AgentRunEvent instances that describe what happened during execution. These events form the run’s audit trail — they tell you when the run started, when LLM calls were made, when tools executed, when policy decisions were rendered, and how the run terminated.
Understanding the event contract is essential for building real-time UIs, logging pipelines, eval assertions, and debugging tools. This page documents every event type, explains when each fires, describes the data it carries, and provides patterns for consuming events safely.
Event stream model
Every run begins withrun_started and ends with exactly one terminal event: run_completed, run_failed, run_interrupted, or run_cancelled. Between those boundaries, the runner emits step, LLM, tool, policy, and subagent events in the order they occur.
Event reference
| Event Type | When It Fires | Key Fields in data |
|---|---|---|
run_started | At the beginning of a new or resumed run. | agent_name, resumed (bool) |
step_started | At the start of each step iteration. | step (int), state |
llm_called | Before sending a request to the LLM provider. | model, provider |
llm_completed | After receiving the LLM response. | tool_call_count, finish_reason, text |
tool_batch_started | Before executing a batch of tool calls from one LLM response. | tool_call_count, tool_names, tool_call_ids |
tool_completed | After each individual tool finishes executing. | tool_name, tool_call_id, success (bool), output, error, agent_name, agent_depth, agent_path |
tool_deferred | Tool accepted and moved to background processing. | tool_name, tool_call_id, ticket_id, status, summary, resume_hint |
tool_background_resolved | Deferred tool completed successfully. | tool_name, tool_call_id, ticket_id, output |
tool_background_failed | Deferred tool failed or expired. | tool_name, tool_call_id, ticket_id, error |
policy_decision | After the policy engine evaluates a tool, LLM, or subagent event. | event_type, action, reason, policy_id, matched_rules |
subagent_started | Before dispatching a subagent invocation. | subagent_name, correlation_id |
subagent_completed | After a subagent finishes (success or failure). | subagent_name, success, latency_ms, error (if failed) |
text_delta | During streamed runs when incremental model text arrives. | delta |
warning | When a non-fatal issue occurs (memory fallback, dead letters, etc.). | Varies by warning type |
run_completed | When the run reaches successful terminal state. | None (terminal) |
run_failed | When the run terminates due to an unrecoverable error. | error message in event.message |
run_interrupted | When the run is interrupted by the caller or by timeout. | Interruption reason in event.message |
run_cancelled | When the run is cancelled before completion. | None (terminal) |
AgentRunEvent structure
Each event is anAgentRunEvent dataclass with the following fields:
| Field | Type | Description |
|---|---|---|
type | str | Event type identifier (see table above). |
run_id | str | Unique run identifier. |
thread_id | str | Thread identifier for memory continuity. |
state | str | Current run state when the event was emitted. |
step | int | Current step number (0 if not yet in a step). |
message | str or None | Human-readable description of what happened. |
data | dict or None | Structured payload with event-specific fields. |
Consuming events
The primary way to consume events is through the run handle’sevents async iterator:
Pattern: event-type branching
The recommended consumption pattern is a simpleif/elif chain that branches on event.type. This is explicit, readable, and easy to extend:
Forward compatibility
The event contract is append-only. New event types may be added in future releases, but existing event types will not be removed or have theirdata fields changed.
Your event consumer should always handle unknown event types gracefully. The simplest approach is a default branch that logs or ignores unknown types: