Design for Sessions/Run views, three new query-api endpoints, and schema validation at ingest-gateway. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.2 KiB
UI, Query API, and Schema Validation Design
Date: 2026-01-17
Overview
This design covers three related improvements to agentmon:
- Web UI — Sessions list, session detail, and run detail views
- Query API — New endpoints to support the UI
- 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 frameworkhost— filter by source hostlimit— max results (default 50, max 200)cursor— pagination token (opaque, timestamp-based)
Response:
{
"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:
{
"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:
{
"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
- Query API endpoints (sessions, session detail, run detail)
- Schema validation at ingest-gateway
- Frontend pages (sessions list, session detail, run detail)
- 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