data field before it is sent: credential-shaped keys and values are masked with ••••. Numeric telemetry (token counts, cost) survives the mask.
Routes
| Method | Path | Summary |
|---|---|---|
GET | /api/obs/events | Query the orchestration event feed |
GET | /api/obs/traces/:traceId | One reconstructed trace and aggregate metrics |
GET | /api/obs/errors | The error-taxonomy feed |
GET | /api/obs/health | Fleet-health triage (working/idle/stalled/zombie) |
GET | /api/obs/graph | Event-sourced delegation/status/cost graph projection |
GET | /api/obs/stream | SSE live-tail (Server-Sent Events) |
POST | /api/obs/ingest | Mirror client-observed runtime events into the log |
POST | /api/eval/smoke | Run the deterministic eval smoke suite |
GET /api/obs/events
Queries rows from the event log filtered by your parameters, ordered by the monotonic seq cursor. Default order is asc (causal/chronological).
Match events for one team.
Match events for one board task.
Match events for one agent.
Match events sharing a trace id.
Comma-separated list of event kinds to include (e.g.
"cost,error").ts >= (wall-clock ms) — a recent-window read.seq > cursor — strictly monotonic, collision-free. Use for polling.Row cap. Defaults to 500.
"desc" for recent-first. Anything else is asc.Response 200 OK
Matched events with the inner
data field redacted.task_created, task_claimed, status_changed, comment_added, dep_linked, execution_started, execution_completed, tool_call, tool_result, cost, approval_requested, approval_resolved, error, span_start, span_end, session_rotated, routine_fired, routine_dispatched, routine_completed, routine_error, team_chat_post, speaker_selected, turn_bound_hit.
GET /api/obs/traces/:traceId
Reconstructs one trace — every event sharing the traceId, ordered causally (seq ASC). Aggregate metrics are computed from the un-redacted events first, then each event’s data is masked for display, so numeric telemetry in metrics is accurate.
The trace read is capped at 5,000 events. An unknown traceId returns 200 with an empty events array and zeroed metrics.
Response 200 OK
The requested trace id.
All events in this trace,
data field redacted.Aggregate metrics across the trace.
GET /api/obs/errors
The error-taxonomy feed — every error event, recent-first, projected to a compact shape. Pass harnessBug=true to filter to errors whose class is Unknown (a harness bug indicator).
Pass
"true" to filter to harness-bug errors only.ts >= (wall-clock ms) lower bound.Response 200 OK
Error rows, recent-first (capped at 500).
Count of harness-bug errors in the full window, regardless of the
harnessBug filter. Use this to badge an alert count.GET /api/obs/health
Fleet-health triage — a per-agent state folded from the event log, time-sensitive against Date.now(). Capped at 5,000 events.
| State | Condition |
|---|---|
working | Open execution with a recent event (within 5 minutes) |
idle | No open execution |
stalled | Open execution, quiet for more than 5 minutes |
zombie | Open execution, quiet for more than 30 minutes — process almost certainly dead |
Scope to one team.
Response 200 OK
One entry per agent that appears in the event window.
GET /api/obs/graph
Folds the ordered event stream into a delegation/status/cost graph projection. This is a pure projection — replaying the same log always reproduces the same graph. Capped at 5,000 events.
Scope the projection to one team.
Response 200 OK
Task nodes with status, assignee, and cost.
Edges between tasks:
kind is 'delegation' or 'dependency'.Agent nodes with accumulated cost and task ids.
Agent-to-agent delegation edges.
GET /api/obs/stream (SSE)
Live-tail of the event log over Server-Sent Events. The handler polls the log every 750 ms on the monotonic seq cursor and pushes new rows as they arrive. Resume from a known position via the standard EventSource Last-Event-ID header or the ?since=<seq> query param.
This is an SSE route. Use
curl -N or an EventSource client. Each frame carries id: <seq> so the browser can resume automatically on reconnect without replaying from the beginning.Scope the tail to one team.
Scope the tail to one board task.
Scope the tail to one agent.
Resume cursor (
seq). Defaults to 0.SSE frame catalog
| Frame | When | Description |
|---|---|---|
: connected | On open | SSE comment; ignored by EventSource |
data: <json> | Per new log row (poll every 750 ms) | Full event row with data field redacted; id: value is the row’s seq |
: keepalive | Every 20 s | SSE comment to keep the connection warm |
POST /api/obs/ingest
Mirrors client-observed runtime events into the durable log. The OpenClaw runtime is observed in the browser, so the SPA forwards those events here to keep the activity terminal uniform across runtimes. Accepted kinds are whitelisted to tool_call, tool_result, and error — board lifecycle events are never accepted here.
Each event is best-effort: a malformed row is skipped, never failing the batch. Maximum 200 events per call.
Request body
Events to ingest. Non-whitelisted kinds are silently dropped.
Response 200 OK
POST /api/eval/smoke
Runs the deterministic eval smoke suite — the same subset CI runs. Uses no live model, no provider keys, and no network. Each trial gets its own temporary SQLite board disjoint from the real clawboo.db.
Request body
Number of trials per task. Clamped to 1–3. Defaults to
1.The
k in pass@k. Clamped to 1–3. Defaults to trials.Response 200 OK
See also
- Observability concepts — the event log, traces, Ghost Graph projection, fleet-health triage
- Events and errors reference — per-kind
datashapes and the error taxonomy - Observability dashboard — the UI over these endpoints
- REST API overview