Files
William Valentin 3434db3c59 feat: complete agent monitoring - hook, UI, and backend filter
- Add event_type and framework filters to events query endpoint
- Add /agents SPA route to web-ui server
- Add Agents nav link and route in frontend
- Add agents page CSS (timeline, VM pills, stats panel)
- Build VM status strip, activity timeline, and real-time stats
- Add agentmon hook for OpenClaw (HOOK.md + handler.ts)
- Add docker-compose, Dockerfile, and supporting infra files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 00:26:42 -07:00

4.8 KiB

AGENTS.md

This file provides guidelines for agentic coding agents working on the agentmon repository.

Build/Lint/Test Commands

# Run all tests
go test ./...

# Run tests for a specific package
go test ./internal/event

# Run a single test
go test ./internal/event -run TestValidate_ValidEvent

# Run tests with verbose output
go test -v ./...

# Tidy dependencies
go mod tidy

# Run services via Makefile
make tidy
make test
make run-ingest      # Ingest gateway (requires NATS_URL, NATS_TOPIC)
make run-query       # Query API (requires DATABASE_URL)
make run-ui          # Web UI
make run-processor   # Event processor (requires DATABASE_URL, NATS_URL, NATS_TOPIC)

# Build executables
go build -o ingest-gateway ./cmd/ingest-gateway
go build -o query-api ./cmd/query-api
go build -o web-ui ./cmd/web-ui

Code Style Guidelines

Imports

  • Order: stdlib, internal packages, external packages
  • Group by blank line between each section
  • No unused imports

Example:

import (
    "context"
    "database/sql"

    "agentmon/internal/event"
    "agentmon/internal/httpx"

    "github.com/go-chi/chi/v5"
    "github.com/jackc/pgx/v5"
)

Formatting

  • Use go fmt or enable auto-formatting
  • Standard Go formatting rules apply
  • No inline comments unless necessary

Types

  • Use any for generic types (not interface{})
  • Use pointer types (*int64) for optional JSON fields
  • Struct tags for JSON serialization: json:"field_name,omitempty"
  • Use sql.ErrNoRows for "not found" database errors

Naming Conventions

  • Exported: CamelCase (e.g., ValidationError, Publish)
  • Unexported: camelCase (e.g., db, validate)
  • Acronyms: keep uppercase (e.g., DB, NATS, URL)
  • Constants: CamelCase (e.g., validTypes)
  • Test functions: Test<Function>_<Scenario>

Error Handling

  • Always check errors, don't ignore
  • Use log.Fatalf for startup errors (main package only)
  • Use errors.As() for type assertions: errors.As(err, &ve)
  • Custom error types must implement Error() string method
  • Return errors from functions, handle at call site
  • HTTP errors: return JSON with error field, appropriate status code

Example:

if err != nil {
    return nil, fmt.Errorf("operation failed: %w", err)
}

if ve, ok := err.(ValidationError); ok {
    return ValidationError{Field: "field", Message: "message"}
}

Database

  • Use context.Context for all DB operations
  • Use pgx/v5 via stdlib interface: sql.Open("pgx", url)
  • Check sql.ErrNoRows explicitly for not-found cases
  • Always defer db.Close() in main functions

HTTP

  • Use chi router with middleware
  • Standard middleware chain: RequestID, RealIP, Logger, Recoverer
  • Health check endpoint: GET /healthz returns 200 with "ok"
  • JSON responses: use httpx.WriteJSON(w, status, data)
  • Get path params: chi.URLParam(r, "paramName")
  • Get query params: r.URL.Query().Get("key")

Configuration

  • Use environment variables for configuration
  • Helper pattern: envDefault(key, defaultValue) function
  • Required env vars: log.Fatal if missing
  • Optional env vars: provide sensible defaults

Validation

  • Validate all input (HTTP, events)
  • Return structured errors with field path and message
  • Type assertion with comma-ok for error type checking
  • Valid event types: session.start, session.end, run.start, run.end, span.start, span.end, error, metric.snapshot

Testing

  • Use standard testing package
  • Test file naming: *_test.go
  • Test function naming: Test<Function>_<Scenario>
  • Use t.Fatalf for setup failures
  • Use t.Fatal for assertion failures (not t.Error)
  • Minimal test structure: setup, act, assert

Example:

func TestValidate_ValidEvent(t *testing.T) {
    raw := `{"schema": {"name": "agentmon.event", "version": 1}}`
    var m map[string]any
    _ = json.Unmarshal([]byte(raw), &m)

    err := Validate(m)
    if err != nil {
        t.Fatalf("expected no error, got %v", err)
    }
}

Context Usage

  • Pass context.Context to functions that do I/O or external calls
  • Use context.WithTimeout for operations with deadlines
  • Defer cancel functions
  • Example: ctx, cancel := context.WithTimeout(ctx, 5*time.Second)

Package Structure

  • cmd/: Executable entry points (main packages)
  • internal/: Internal packages not imported by external code
  • internal/event/: Event schema and validation
  • internal/httpx/: HTTP utilities
  • internal/store/postgres/: Database operations
  • internal/queue/nats/: NATS publishing

JSON Handling

  • Decode to map[string]any for flexible event processing
  • Type assertions: if v, ok := m["key"].(string); ok {}
  • Use json.RawMessage for buffering JSON data
  • JSON encoder/decoder for I/O

Logging

  • Use log.Printf for general logging
  • Use log.Fatalf for unrecoverable errors in main
  • Minimal logging in packages (prefer returning errors)