AgentEvent stream
appctl emits structured AgentEvents from the agent loop. They are the single source of truth for UIs (CLI renderer, VS Code panel, web UI) and for the WebSocket and POST /run transports.
Serialization
Section titled “Serialization”Each event is a JSON object with a kind discriminator:
{ "kind": "<variant>", /* fields */ }Variants
Section titled “Variants”user_prompt
Section titled “user_prompt”Emitted once when the user submits a prompt.
{ "kind": "user_prompt", "text": "list widgets" }assistant_delta
Section titled “assistant_delta”Incremental assistant text. Emitted by providers that support streaming; absent otherwise.
{ "kind": "assistant_delta", "text": "Looking " }assistant_message
Section titled “assistant_message”A complete assistant message. Always emitted at the end of an assistant turn.
{ "kind": "assistant_message", "text": "Here are your widgets." }tool_call
Section titled “tool_call”The agent chose a tool and is about to call it.
{ "kind": "tool_call", "id": "call_01HV...", "name": "list_widgets", "arguments": { "limit": 10 }}id correlates with the matching tool_result.
tool_result
Section titled “tool_result”The tool returned.
{ "kind": "tool_result", "id": "call_01HV...", "result": { "items": [ /* ... */ ] }, "status": "ok", "duration_ms": 120}status is ok or error.
Unrecoverable error during the loop.
{ "kind": "error", "message": "max iterations reached" }Loop finished. No more events will be emitted for this turn.
{ "kind": "done" }Ordering guarantees
Section titled “Ordering guarantees”- Exactly one
user_promptstarts the stream. - Zero or more
tool_call/tool_resultpairs interleave withassistant_delta/assistant_message. - Every
tool_callis followed by atool_resultwith the sameid(unless the loop errors first). - Exactly one
doneterminates the stream.
Consuming events
Section titled “Consuming events”From POST /run
Section titled “From POST /run”The response body buffers every event in the events array plus a final result object. Good for synchronous callers.
From WS /chat
Section titled “From WS /chat”Frames stream live. Good for UIs.
From the CLI
Section titled “From the CLI”appctl chat and appctl run use the same stream internally. The terminal renderer is in crates/appctl/src/term.rs if you want to see how they are formatted.