Skip to content

Runtime Events

Event kinds workers receive via @worker.on_event, with payload fields and lifecycle ordering.

Workers subscribe to runtime events with @worker.on_event(kind). The runtime publishes thirteen kinds across turn lifecycle, prompts, transport, sessions, components, and capability reloads.

@worker.on_event("turn.completed")
async def on_turn(event, client) -> None:
print(event.kind, event.payload["duration_ms"])

Each handler receives an EventEnvelope. event.kind is always set; event.session_id is set for session-scoped events and None for runtime-scope. event.payload is a dict[str, Any] with the fields listed below.

A turn always emits accepted first, started once it leaves the queue, and exactly one terminal event (completed, failed, or cancelled). Subscribe to the terminal kinds when you want one event per turn — they carry the full result.

KindPayloadWhen
turn.acceptedagent, model, reset, message_length, queue_depthThe turn was queued for processing.
turn.startedagent, modelThe turn left the queue and the model call is about to start.
turn.completedturn_id, response_text, tool_calls, usage, duration_ms, agent, message_countTerminal — successful completion.
turn.failedturn_id, error: {type, message}, partial_response, tool_calls_attempted, duration_msTerminal — error before completion.
turn.cancelledturn_id, reason, partial_response, duration_msTerminal — cancelled by the user or runtime.
KindPayload
prompt.requiredevent_type, raw_event — permission requests and human-input requests

Respond with client.send_permission_response(...) or client.send_human_input_response(...).

KindPayloadNotes
session.createdsession_idA new session opened on the runtime.
session.deletedsession_idA session was removed.
session.warningcode, message, sync_statusOperational warning for a session — currently used for platform-sync degradation.
KindPayload
capabilities.reloadedcapability_count

Fires after the runtime re-discovers capabilities on disk.

KindPayloadNotes
component.state_changedcapability, kind, name, status, error, detailAny worker, MCP server, or tool health transition (start, stop, restart, crash).

Two kinds fire at very high rates and exist primarily for the runtime’s own clients (the TUI, transport bridges). Subscribe sparingly.

KindPayloadNotes
turn.eventevent_type, raw_eventEvery granular event inside a turn — model deltas, tool starts, generation chunks.
transport.heartbeatevent_type, raw_eventPeriodic keepalive emitted by the runtime transport layer.

If you only care about completed turns, subscribe to turn.completed instead of filtering turn.event — the terminal envelope already aggregates everything you need.

turn.*, prompt.*, session.*, transport.*, capabilities.*, and component.* are reserved for the runtime. client.publish(...) rejects custom kinds in those namespaces — use your own prefix (myapp.*, bridge.*, or capability.<name>.*) for events you emit.

await client.publish(
kind="myapp.report_ready",
payload={"report_id": "abc123", "url": "https://..."},
session_id=event.session_id,
)

Subscribed workers and external clients receive the event. Use client.notify(...) instead when the audience is the human operator — notifications surface in the TUI rather than flowing through the event bus.