From d748033851ae5451e114fe45922a2223011eef86 Mon Sep 17 00:00:00 2001 From: William Valentin Date: Sat, 17 Jan 2026 01:43:04 -0800 Subject: [PATCH] docs: add UI, query API, and validation design Design for Sessions/Run views, three new query-api endpoints, and schema validation at ingest-gateway. Co-Authored-By: Claude Opus 4.5 --- .../2026-01-17-ui-query-validation-design.md | 228 ++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 docs/plans/2026-01-17-ui-query-validation-design.md diff --git a/docs/plans/2026-01-17-ui-query-validation-design.md b/docs/plans/2026-01-17-ui-query-validation-design.md new file mode 100644 index 0000000..5b2d25c --- /dev/null +++ b/docs/plans/2026-01-17-ui-query-validation-design.md @@ -0,0 +1,228 @@ +# UI, Query API, and Schema Validation Design + +Date: 2026-01-17 + +## Overview + +This design covers three related improvements to agentmon: + +1. **Web UI** — Sessions list, session detail, and run detail views +2. **Query API** — New endpoints to support the UI +3. **Schema Validation** — Required field validation at ingest-gateway + +## URL Structure + +| URL | View | Description | +|-----|------|-------------| +| `/` | Redirect | Redirects to `/sessions` | +| `/sessions` | Sessions List | Recent sessions, filterable | +| `/sessions/:session_id` | Session Detail | Runs within a session | +| `/runs/:run_id` | Run Detail | Spans within a run | + +Query parameters for filtering: + +- `/sessions?from=2026-01-17&to=2026-01-18` — time range +- `/sessions?framework=opencode` — filter by framework +- `/sessions?host=willlaptop` — filter by host +- Parameters combine: `/sessions?framework=claude-code&host=willlaptop` + +## Query API Endpoints + +### GET /v1/sessions + +List sessions with filters. + +Query params: + +- `from`, `to` — ISO timestamps (default: last 24h) +- `framework` — filter by source framework +- `host` — filter by source host +- `limit` — max results (default 50, max 200) +- `cursor` — pagination token (opaque, timestamp-based) + +Response: + +```json +{ + "sessions": [ + { + "session_id": "s1", + "started_at": "2026-01-17T08:00:00Z", + "ended_at": "2026-01-17T09:30:00Z", + "framework": "claude-code", + "host": "willlaptop", + "run_count": 5 + } + ], + "next_cursor": "..." +} +``` + +### GET /v1/sessions/:session_id + +Session detail with runs. + +Response: + +```json +{ + "session": { + "session_id": "...", + "started_at": "...", + "ended_at": "...", + "framework": "...", + "host": "..." + }, + "runs": [ + { + "run_id": "r1", + "started_at": "...", + "ended_at": "...", + "status": "success", + "span_count": 12 + } + ] +} +``` + +### GET /v1/runs/:run_id + +Run detail with spans. + +Response: + +```json +{ + "run": { + "run_id": "...", + "session_id": "...", + "started_at": "...", + "ended_at": "...", + "status": "..." + }, + "spans": [ + { + "span_id": "sp1", + "name": "Bash", + "kind": "tool", + "started_at": "...", + "duration_ms": 1234, + "status": "success", + "payload": {} + } + ] +} +``` + +## UI Views + +### Sessions List + +Default view showing last 24 hours, most recent first. + +Layout: + +- Filter bar: time range (from/to), framework dropdown, host dropdown +- Table columns: Session ID, Framework, Host, Run Count, Time (relative) +- Click row to navigate to session detail +- "Load more" button for pagination + +### Session Detail + +Shows session metadata and all runs within it. + +Layout: + +- Header: Session ID, framework, host, start time, total duration +- Back link to sessions list +- Runs table: Run ID, Status, Span Count, Duration, Start Time +- Click row to navigate to run detail + +Status indicators: + +- Green checkmark for success +- Red X for error +- Yellow circle for running/unknown + +### Run Detail + +Shows run metadata and all spans within it. + +Layout: + +- Header: Run ID, status, start time, duration +- Back link to session detail +- Spans table: Name, Kind, Status, Duration +- Click row to expand/collapse details + +Expanded span shows: + +- Model name, tokens, cost (for LLM spans) +- Error details (for failed spans) +- Raw payload JSON + +## Schema Validation + +Validation performed at ingest-gateway before publishing to NATS. + +### Required Fields + +All events must include: + +``` +schema.name = "agentmon.event" +schema.version = 1 +event.id — non-empty string +event.type — one of: session.start, session.end, run.start, + run.end, span.start, span.end, error, metric.snapshot +event.ts — valid timestamp (RFC3339 or unix-ms) +event.source.framework — non-empty string +event.source.client_id — non-empty string +event.source.host — non-empty string +``` + +### Validation Responses + +| Scenario | HTTP | WebSocket | +|----------|------|-----------| +| Valid | 202 Accepted | `{"ack": {"seq": N}}` | +| Missing field | 400 + error | `{"error": "missing_field", "field": "..."}` | +| Invalid type | 400 + error | `{"error": "invalid_type", "value": "..."}` | +| Unknown fields | Allow | Allow | + +Non-strict mode: unknown fields in `correlation`, `attributes`, and `payload` are stored as-is. + +## Frontend Implementation + +Technology: Vanilla JavaScript (no framework, no build step). + +File structure: + +``` +cmd/web-ui/static/ +├── index.html # Shell + router +├── app.js # Router + page loader +├── pages/ +│ ├── sessions.js +│ ├── session.js +│ └── run.js +└── style.css +``` + +Routing: History API with catch-all handler serving index.html for all routes. + +Data fetching: Native fetch() to query-api endpoints via /api proxy. + +## Implementation Order + +1. Query API endpoints (sessions, session detail, run detail) +2. Schema validation at ingest-gateway +3. Frontend pages (sessions list, session detail, run detail) +4. Rebuild and deploy + +## Future Considerations + +- Waterfall visualization for spans (SVG/canvas) +- Token/cost aggregations in session/run summaries +- Free-text search across sessions +- Real-time updates via WebSocket subscription