API & Event Protocol¶
Full interactive API documentation is served live by your own instance at
http://localhost:8000/docs — that's the authoritative, always-current
reference for request/response shapes. This page covers the one thing that
doesn't show up well in an OpenAPI viewer: the WebSocket event protocol.
One request path, two transports¶
POST /api/chat and WS /ws/chat both call the same underlying
orchestrator — the transport only translates internal events into frames.
Anything true of one is true of the other; the WebSocket just makes each
step visible as it happens instead of returning once at the end.
Event frames¶
| Frame | What it carries |
|---|---|
session |
Session identity, sent once at connection start. |
status |
High-level state changes. |
step_start / step_end |
Bounds around one sub-task. |
reasoning_delta |
Streamed manager "thinking," if the model exposes it. |
plan_delta |
Streamed plan content — split from reasoning by tracking the reasoning-tag boundary as it streams in, so the UI can switch from a thinking panel to a plan view at the right moment. |
content_delta |
Streamed final-answer text. |
code |
Generated code for the current step. |
stdout |
Real execution output. |
artifact |
A file produced by execution (a chart, an export). |
approval_required |
The turn is paused, not ended — carries an id you reply to. This is the one frame that distinguishes "waiting for you" from "done." |
warning / error |
Non-fatal and fatal problems respectively. |
final |
The synthesized answer, plus any trust-layer annotations. |
Investigation frames (the agentic loop made visible)¶
| Frame | What it carries |
|---|---|
iteration_start |
A new loop iteration has begun. |
action |
Which action the manager chose (code/consult/reflect/parallel/inspect/answer). |
observation |
The result of the most recently opened action — closes the most recent one without an observation yet, rather than being matched by an id. |
finding |
Something the agent learned worth surfacing directly. |
plan_revised |
The plan changed mid-run in response to real output. |
assumption |
A silent decision in the generated code (dropped nulls, an inner join, etc.), surfaced alongside the answer. |
verification |
The result of re-deriving the headline number by a different route. |
skill |
Names which installed skill informed this turn, if any. |
skill_candidate |
An offer to save a recurring analysis as a skill — nothing is written unless you confirm. |
usage |
What the turn cost, emitted only when a cloud model actually ran. Under local-only this frame never appears — there's nothing to meter. |
A client that ignores the newer frames still works¶
Every frame listed above is additive. A client built against an earlier
version of the protocol that only understands content_delta/stdout/
final degrades gracefully rather than breaking — it just doesn't render
the richer investigation view.
Subagent branches¶
When a step fans out into parallel sub-investigations, each branch's own
activity reuses the same frame types (action, observation, code,
stdout, …), just additionally tagged with a branch identifier. There's
no separate frame vocabulary for subagent activity to learn.