Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · AgentEvent Union Type and Event Streaming
page:docs-agent-mux-reference-04-agent-eventsa5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
II.
Page JSON

page:docs-agent-mux-reference-04-agent-events

Structured · live

AgentEvent Union Type and Event Streaming json

Inspect the normalized record payload exactly as the atlas UI reads it.

File · wiki/docs/agent-mux/reference/04-agent-events.mdCluster · wiki
Record JSON
{
  "id": "page:docs-agent-mux-reference-04-agent-events",
  "_kind": "Page",
  "_file": "wiki/docs/agent-mux/reference/04-agent-events.md",
  "_cluster": "wiki",
  "attributes": {
    "nodeKind": "Page",
    "sourcePath": "docs/agent-mux/reference/04-agent-events.md",
    "sourceKind": "repo-docs",
    "title": "AgentEvent Union Type and Event Streaming",
    "displayName": "AgentEvent Union Type and Event Streaming",
    "slug": "docs/agent-mux/reference/04-agent-events",
    "articlePath": "wiki/docs/agent-mux/reference/04-agent-events.md",
    "article": "\n# AgentEvent Union Type and Event Streaming\n\n**Specification v1.0** | `@a5c-ai/agent-mux`\n\n> **Note:** hermes-agent is included as a 10th supported agent per project requirements, extending the original scope's 9 agents. All ten built-in agents (claude, codex, gemini, copilot, cursor, opencode, pi, omp, openclaw, hermes) share the same event contract.\n\nLast refreshed: 2026-04-25\n\n---\n\n## 1. Overview\n\nThis specification defines the complete `AgentEvent` union type -- 67 event types across 18 categories -- the streaming model that controls how events are emitted, event ordering guarantees, correlation keys for grouping related events, and the per-agent event support matrix.\n\nEvery agent run produces a stream of `AgentEvent` values. Regardless of the underlying agent's output format (JSON streaming, line-buffered text, PTY raw output, structured API responses), each adapter parses native output into the normalized event types defined here. Consumers never see agent-specific output formats.\n\n### 1.1 Cross-References\n\n| Type / Concept | Spec | Section |\n|---|---|---|\n| `AgentName`, `BuiltInAgentName` | `01-core-types-and-client.md` | 1.4 |\n| `AgentMuxClient`, `createClient()` | `01-core-types-and-client.md` | 5 |\n| `RunOptions`, `stream` option | `02-run-options-and-profiles.md` | 2, 5 |\n| `RunHandle`, `AsyncIterable<AgentEvent>` | `03-run-handle-and-interaction.md` | 2 |\n| `RunResult` | `03-run-handle-and-interaction.md` | 3 |\n| `CostRecord` | `01-core-types-and-client.md` | 4.2.3 |\n| `AgentCapabilities` | `06-capabilities-and-models.md` | 2 |\n| `ErrorCode`, `AgentMuxError` | `01-core-types-and-client.md` | 3.1 |\n| `InteractionChannel` | `03-run-handle-and-interaction.md` | 5 |\n\n### 1.2 Design Principles\n\n1. **Uniform shape.** Every event extends `BaseEvent`. Consumers can always access `type`, `runId`, `agent`, and `timestamp` without type narrowing.\n2. **Additive-only.** New event types may be added in minor versions; existing types are never removed or changed in breaking ways.\n3. **Same types in all modes.** Whether `stream` is `'auto'`, `true`, or `false`, the consumer always receives the same set of event types. The mode only controls granularity and timing.\n4. **Correlation by key.** Related events share a correlation key (`toolCallId`, `subagentId`, `interactionId`, `pluginId`) so consumers can group them without position-based logic.\n5. **No agent-specific events.** The union is closed for agent-specific data. The `raw` field on `BaseEvent` and the `debug` event provide escape hatches for agent-specific diagnostics.\n\n---\n\n## 2. BaseEvent Interface\n\n```typescript\n/**\n * Shared fields present on every AgentEvent.\n *\n * All 67 event types extend this interface. Consumers can read these\n * fields without narrowing to a specific event type.\n */\ninterface BaseEvent {\n  /**\n   * Discriminant field. Uniquely identifies the event type within the\n   * AgentEvent union. Always a lowercase, underscore-separated string\n   * literal (e.g., 'text_delta', 'tool_call_start').\n   */\n  type: string;\n\n  /**\n   * The ULID of the run that produced this event. Matches\n   * `RunHandle.runId`. Format: 26-character Crockford Base32 string.\n   *\n   * @see RunHandle.runId in 03-run-handle-and-interaction.md, Section 2.\n   */\n  runId: string;\n\n  /**\n   * The agent that produced this event.\n   *\n   * @see AgentName in 01-core-types-and-client.md, Section 1.4.\n   */\n  agent: AgentName;\n\n  /**\n   * Unix epoch timestamp in milliseconds when this event was created\n   * by the adapter. Uses `Date.now()` at event construction time.\n   *\n   * Events are emitted in causal order; timestamps are monotonically\n   * non-decreasing within a single run.\n   */\n  timestamp: number;\n\n  /**\n   * The raw, unparsed output from the agent subprocess that produced\n   * this event. Present only when the client was created with\n   * `ClientOptions.debug: true` (see `01-core-types-and-client.md` §5.1.1).\n   *\n   * Format is agent-specific (JSON line, PTY escape sequence, etc.).\n   * Intended for debugging adapter implementations, not for\n   * production consumption.\n   */\n  raw?: string;\n}\n```\n\n### 2.1 BaseEvent Field Constraints\n\n| Field | Type | Required | Constraints |\n|---|---|---|---|\n| `type` | `string` (literal) | Yes | One of the 67 defined event type literals. |\n| `runId` | `string` | Yes | ULID format, 26 characters, Crockford Base32. |\n| `agent` | `AgentName` | Yes | One of the 10 built-in agents or a registered plugin adapter name. |\n| `timestamp` | `number` | Yes | Positive integer, Unix epoch milliseconds, monotonically non-decreasing within a run. |\n| `raw` | `string` | No | Present only in debug mode. Arbitrary string from the agent subprocess. |\n\n---\n\n## 3. CostRecord Type\n\nUsed by `session_end`, `turn_end`, `subagent_result`, `cost`, and `RunResult`. Defined canonically in `01-core-types-and-client.md` Section 4.2.3; reproduced here for reference.\n\n```typescript\n/**\n * Aggregated cost and token usage for a run, turn, or subagent invocation.\n *\n * All token counts are integers. Cost is a floating-point estimate in USD.\n * Fields are optional when the agent does not report the corresponding data.\n *\n * @see 01-core-types-and-client.md, Section 4.2.3.\n */\ninterface CostRecord {\n  /** Total estimated cost in US dollars. */\n  totalUsd: number;\n\n  /** Input tokens consumed. */\n  inputTokens: number;\n\n  /** Output tokens generated. */\n  outputTokens: number;\n\n  /** Thinking/reasoning tokens consumed (if the model supports thinking). */\n  thinkingTokens?: number;\n\n  /** Cached input tokens reused from a previous turn or session (if applicable). */\n  cachedTokens?: number;\n}\n```\n\n### 3.1 CostRecord Field Constraints\n\n| Field | Type | Required | Constraints |\n|---|---|---|---|\n| `totalUsd` | `number` | Yes | Non-negative. `0` when cost data is unavailable. |\n| `inputTokens` | `number` | Yes | Non-negative integer. |\n| `outputTokens` | `number` | Yes | Non-negative integer. |\n| `thinkingTokens` | `number` | No | Non-negative integer. Omitted when thinking was not used. |\n| `cachedTokens` | `number` | No | Non-negative integer. Omitted when caching is unsupported. |\n\n---\n\n## 4. AgentEvent Union Type\n\nThe `AgentEvent` type is a discriminated union of 67 event interfaces grouped into 18 categories. The `type` field is the discriminant.\n\n```typescript\ntype AgentEvent =\n  // Session lifecycle (5)\n  | SessionStartEvent\n  | SessionResumeEvent\n  | SessionForkEvent\n  | SessionCheckpointEvent\n  | SessionEndEvent\n  // Turn / step lifecycle (4)\n  | TurnStartEvent\n  | TurnEndEvent\n  | StepStartEvent\n  | StepEndEvent\n  // Text / message streaming (3)\n  | MessageStartEvent\n  | TextDeltaEvent\n  | MessageStopEvent\n  // Thinking / reasoning (3)\n  | ThinkingStartEvent\n  | ThinkingDeltaEvent\n  | ThinkingStopEvent\n  // Tool calling (5)\n  | ToolCallStartEvent\n  | ToolInputDeltaEvent\n  | ToolCallReadyEvent\n  | ToolResultEvent\n  | ToolErrorEvent\n  // File operations (5)\n  | FileReadEvent\n  | FileWriteEvent\n  | FileCreateEvent\n  | FileDeleteEvent\n  | FilePatchEvent\n  // Shell operations (4)\n  | ShellStartEvent\n  | ShellStdoutDeltaEvent\n  | ShellStderrDeltaEvent\n  | ShellExitEvent\n  // MCP tool calling (3)\n  | McpToolCallStartEvent\n  | McpToolResultEvent\n  | McpToolErrorEvent\n  // Subagent dispatch (3)\n  | SubagentSpawnEvent\n  | SubagentResultEvent\n  | SubagentErrorEvent\n  // Plugin events (3)\n  | PluginLoadedEvent\n  | PluginInvokedEvent\n  | PluginErrorEvent\n  // Skill / agent doc loading (3)\n  | SkillLoadedEvent\n  | SkillInvokedEvent\n  | AgentdocReadEvent\n  // Multimodal (2)\n  | ImageOutputEvent\n  | ImageInputAckEvent\n  // Cost and tokens (2)\n  | CostEvent\n  | TokenUsageEvent\n  // Interaction / waiting (4)\n  | InputRequiredEvent\n  | ApprovalRequestEvent\n  | ApprovalGrantedEvent\n  | ApprovalDeniedEvent\n  // Rate / context limits (4)\n  | RateLimitedEvent\n  | ContextLimitWarningEvent\n  | ContextCompactedEvent\n  | RetryEvent\n  // Run lifecycle / control (7)\n  | InterruptedEvent\n  | AbortedEvent\n  | PausedEvent\n  | ResumedEvent\n  | TimeoutEvent\n  | TurnLimitEvent\n  | StreamFallbackEvent\n  // Errors (5)\n  | AuthErrorEvent\n  | RateLimitErrorEvent\n  | ContextExceededEvent\n  | CrashEvent\n  | ErrorEvent\n  // Debug (2)\n  | DebugEvent\n  | LogEvent;\n```\n\n---\n\n## 5. Session Lifecycle Events (5 events)\n\nSession lifecycle events mark the creation, resumption, forking, checkpointing, and completion of an agent session. A session maps to the agent's native persistent conversation record.\n\n### 5.1 SessionStartEvent\n\nEmitted once at the beginning of every run. Always the first domain event (after any `debug` or `log` events from subprocess startup).\n\n```typescript\ninterface SessionStartEvent extends BaseEvent {\n  type: 'session_start';\n\n  /**\n   * The agent's native session identifier. Format is agent-dependent:\n   * - Claude Code: UUID v4\n   * - Codex CLI: session directory name\n   * - Gemini CLI: conversation ID\n   * - OpenCode: session file stem\n   * - hermes: session UUID\n   *\n   * When `RunOptions.noSession` is true, this is a synthetic transient\n   * ID generated by the adapter, prefixed with 'transient-'.\n   */\n  sessionId: string;\n\n  /**\n   * Whether this session is a continuation of a prior conversation.\n   * True when `RunOptions.sessionId` was provided and the session\n   * already existed. False for new sessions.\n   */\n  resumed: boolean;\n\n  /**\n   * When this session was created by forking another, the source\n   * session's ID. Only present when `RunOptions.forkSessionId` was\n   * set and the agent supports forking.\n   *\n   * @capability Requires `AgentCapabilities.canFork: true`.\n   */\n  forkedFrom?: string;\n}\n```\n\n### 5.2 SessionResumeEvent\n\nEmitted when an existing session is resumed. Provides context about the prior conversation state. Only emitted when `resumed` on `SessionStartEvent` is `true`.\n\n```typescript\ninterface SessionResumeEvent extends BaseEvent {\n  type: 'session_resume';\n\n  /** The session being resumed. Matches `SessionStartEvent.sessionId`. */\n  sessionId: string;\n\n  /**\n   * Number of turns in the session before this run's first turn.\n   * Useful for UIs that display turn numbering.\n   */\n  priorTurnCount: number;\n}\n```\n\n### 5.3 SessionForkEvent\n\nEmitted when a session is created by forking an existing one. The new session inherits the conversation history of the source up to the fork point.\n\n```typescript\ninterface SessionForkEvent extends BaseEvent {\n  type: 'session_fork';\n\n  /** The newly created session ID. */\n  sessionId: string;\n\n  /** The source session that was forked. */\n  forkedFrom: string;\n}\n```\n\n### 5.4 SessionCheckpointEvent\n\nEmitted when the agent creates a checkpoint within a session. Checkpoints are agent-specific save points that can be restored later.\n\n```typescript\ninterface SessionCheckpointEvent extends BaseEvent {\n  type: 'session_checkpoint';\n\n  /** The session that was checkpointed. */\n  sessionId: string;\n\n  /**\n   * Agent-specific checkpoint identifier. Can be passed to future\n   * runs to restore state to this point.\n   */\n  checkpointId: string;\n}\n```\n\n### 5.5 SessionEndEvent\n\nEmitted when the session completes. Always the last session lifecycle event. Contains optional aggregated cost data for the entire session.\n\n```typescript\ninterface SessionEndEvent extends BaseEvent {\n  type: 'session_end';\n\n  /** The session that ended. */\n  sessionId: string;\n\n  /** Total number of turns completed in this session (including prior turns if resumed). */\n  turnCount: number;\n\n  /**\n   * Aggregated cost for all turns in this run (not including prior\n   * sessions if resumed). May be absent if the agent does not\n   * report cost data.\n   *\n   * @see CostRecord in Section 3.\n   */\n  cost?: CostRecord;\n}\n```\n\n### 5.6 Session Event Ordering\n\n```\nsession_start\n  -> session_resume?        (only if resumed)\n  -> session_fork?          (only if forked)\n  -> [turn events...]\n  -> session_checkpoint*    (zero or more, at any point during turns)\n  -> session_end\n```\n\n`session_start` is guaranteed before any turn, tool, text, or thinking events. `session_end` is guaranteed after all turn events have completed.\n\n---\n\n## 6. Turn / Step Lifecycle Events (4 events)\n\nTurns represent complete request-response cycles with the agent. Steps are sub-units within a turn (e.g., thinking, generating text, calling a tool). Not all agents expose step-level granularity; adapters that lack step data emit turns without steps.\n\n### 6.1 TurnStartEvent\n\nEmitted at the beginning of each turn. Turn indices are zero-based within the current run.\n\n```typescript\ninterface TurnStartEvent extends BaseEvent {\n  type: 'turn_start';\n\n  /**\n   * Zero-based turn index within this run. The first turn is 0,\n   * the second is 1, etc. Does not account for prior turns in\n   * a resumed session.\n   */\n  turnIndex: number;\n}\n```\n\n### 6.2 TurnEndEvent\n\nEmitted when a turn completes. Contains optional per-turn cost data.\n\n```typescript\ninterface TurnEndEvent extends BaseEvent {\n  type: 'turn_end';\n\n  /** Zero-based turn index. Matches the corresponding `TurnStartEvent.turnIndex`. */\n  turnIndex: number;\n\n  /**\n   * Cost for this specific turn. Absent if the agent does not\n   * provide per-turn cost breakdown.\n   *\n   * @see CostRecord in Section 3.\n   */\n  cost?: CostRecord;\n}\n```\n\n### 6.3 StepStartEvent\n\nEmitted at the beginning of a step within a turn. Steps represent distinct phases of agent processing.\n\n```typescript\ninterface StepStartEvent extends BaseEvent {\n  type: 'step_start';\n\n  /** The turn this step belongs to. */\n  turnIndex: number;\n\n  /** Zero-based step index within the turn. */\n  stepIndex: number;\n\n  /**\n   * The kind of step. Common values:\n   * - 'thinking' -- reasoning/planning phase\n   * - 'generation' -- text generation phase\n   * - 'tool_use' -- tool execution phase\n   * - 'review' -- agent reviewing its own output\n   *\n   * Agent-specific step types may appear; consumers should handle\n   * unknown values gracefully.\n   */\n  stepType: string;\n}\n```\n\n### 6.4 StepEndEvent\n\nEmitted when a step within a turn completes.\n\n```typescript\ninterface StepEndEvent extends BaseEvent {\n  type: 'step_end';\n\n  /** The turn this step belongs to. */\n  turnIndex: number;\n\n  /** Zero-based step index. Matches the corresponding `StepStartEvent.stepIndex`. */\n  stepIndex: number;\n}\n```\n\n### 6.5 Turn/Step Event Ordering\n\n```\nturn_start(turnIndex=0)\n  -> step_start(turnIndex=0, stepIndex=0)?\n  -> [thinking/text/tool events...]\n  -> step_end(turnIndex=0, stepIndex=0)?\n  -> step_start(turnIndex=0, stepIndex=1)?\n  -> [more events...]\n  -> step_end(turnIndex=0, stepIndex=1)?\n  -> turn_end(turnIndex=0)\nturn_start(turnIndex=1)\n  -> ...\n  -> turn_end(turnIndex=1)\n```\n\nSteps are optional. A turn always has exactly one `turn_start` followed by exactly one `turn_end`. Step events, when present, are always properly nested within their enclosing turn and never overlap.\n\n---\n\n## 7. Text / Message Streaming Events (3 events)\n\nText streaming events deliver the agent's textual response. In streaming mode, `text_delta` events arrive incrementally. In buffered mode, a single `text_delta` with the full text arrives before `message_stop`.\n\n### 7.1 MessageStartEvent\n\nEmitted when the agent begins generating a textual response. Precedes the first `text_delta` in the current generation.\n\n```typescript\ninterface MessageStartEvent extends BaseEvent {\n  type: 'message_start';\n}\n```\n\n### 7.2 TextDeltaEvent\n\nEmitted for each chunk of generated text. In streaming mode, `delta` contains a small fragment. In buffered mode (`stream: false`), a single `text_delta` is emitted with `delta` equal to the complete text.\n\n```typescript\ninterface TextDeltaEvent extends BaseEvent {\n  type: 'text_delta';\n\n  /**\n   * The new text fragment. In streaming mode, typically 1-50 characters.\n   * In buffered mode, the complete response text.\n   */\n  delta: string;\n\n  /**\n   * All text generated so far in this message, including this delta.\n   * Consumers can use this instead of manually concatenating deltas.\n   */\n  accumulated: string;\n}\n```\n\n### 7.3 MessageStopEvent\n\nEmitted when the agent finishes generating a textual response. The `text` field contains the complete generated text.\n\n```typescript\ninterface MessageStopEvent extends BaseEvent {\n  type: 'message_stop';\n\n  /** The complete generated text for this message. */\n  text: string;\n}\n```\n\n### 7.4 Text Streaming Event Ordering\n\n```\nmessage_start\n  -> text_delta+      (one or more)\n  -> message_stop\n```\n\n`message_start` always precedes any `text_delta` events. `message_stop` always follows the last `text_delta` and contains the same text as the final `text_delta.accumulated`. Multiple message sequences can occur within a single turn (e.g., when the agent generates text, calls a tool, then generates more text).\n\n---\n\n## 8. Thinking / Reasoning Events (3 events)\n\nThinking events expose the agent's internal reasoning process. Only emitted when the agent and model support thinking and the user has enabled it via `RunOptions.thinkingEffort` or the model defaults to thinking.\n\n### 8.1 ThinkingStartEvent\n\nEmitted when the agent begins a thinking/reasoning phase.\n\n```typescript\ninterface ThinkingStartEvent extends BaseEvent {\n  type: 'thinking_start';\n\n  /**\n   * The effective thinking effort level for this invocation.\n   * Absent if the agent does not report effort level.\n   */\n  effort?: string;\n}\n```\n\n### 8.2 ThinkingDeltaEvent\n\nEmitted for each chunk of thinking content. Follows the same streaming/buffered pattern as `text_delta`.\n\n```typescript\ninterface ThinkingDeltaEvent extends BaseEvent {\n  type: 'thinking_delta';\n\n  /** The new thinking text fragment. */\n  delta: string;\n\n  /** All thinking text generated so far, including this delta. */\n  accumulated: string;\n}\n```\n\n### 8.3 ThinkingStopEvent\n\nEmitted when the thinking phase completes.\n\n```typescript\ninterface ThinkingStopEvent extends BaseEvent {\n  type: 'thinking_stop';\n\n  /** The complete thinking/reasoning text. */\n  thinking: string;\n}\n```\n\n### 8.4 Thinking Event Ordering\n\n```\nthinking_start\n  -> thinking_delta+    (one or more)\n  -> thinking_stop\n```\n\nThinking events always precede the corresponding text generation events within the same step. When thinking is used, the sequence within a turn is:\n\n```\nthinking_start -> thinking_delta+ -> thinking_stop -> message_start -> text_delta+ -> message_stop\n```\n\n---\n\n## 9. Tool Calling Events (5 events)\n\nTool calling events track the lifecycle of native tool invocations (as opposed to MCP tools, which have their own event group). Events are correlated by `toolCallId`.\n\n### 9.1 Correlation Key: `toolCallId`\n\nAll tool calling events for a single invocation share the same `toolCallId`. This is a unique identifier generated by the adapter, typically derived from the agent's native tool call ID. Format is adapter-dependent but guaranteed unique within a run.\n\n### 9.2 ToolCallStartEvent\n\nEmitted when the agent begins constructing a tool call. In streaming mode, the input may still be accumulating.\n\n```typescript\ninterface ToolCallStartEvent extends BaseEvent {\n  type: 'tool_call_start';\n\n  /** Unique identifier for this tool call. Correlates all events for this invocation. */\n  toolCallId: string;\n\n  /** The name of the tool being called. */\n  toolName: string;\n\n  /**\n   * The tool input accumulated so far. In streaming mode, this may be\n   * a partial JSON string. In buffered mode, this is the complete input.\n   */\n  inputAccumulated: string;\n}\n```\n\n### 9.3 ToolInputDeltaEvent\n\nEmitted for each chunk of tool input as it streams in. Only emitted in streaming mode when the agent supports tool call streaming.\n\n```typescript\ninterface ToolInputDeltaEvent extends BaseEvent {\n  type: 'tool_input_delta';\n\n  /** Correlates to the `ToolCallStartEvent` for this tool call. */\n  toolCallId: string;\n\n  /** The new input fragment. */\n  delta: string;\n\n  /** All input accumulated so far, including this delta. */\n  inputAccumulated: string;\n}\n```\n\n### 9.4 ToolCallReadyEvent\n\nEmitted when the tool input is fully assembled and the tool is ready to execute (or is executing). The `input` field contains the parsed, complete input.\n\n```typescript\ninterface ToolCallReadyEvent extends BaseEvent {\n  type: 'tool_call_ready';\n\n  /** Correlates to the `ToolCallStartEvent` for this tool call. */\n  toolCallId: string;\n\n  /** The name of the tool being called. */\n  toolName: string;\n\n  /**\n   * The complete, parsed tool input. Type depends on the tool's schema;\n   * typically a plain object but may be any JSON-serializable value.\n   */\n  input: unknown;\n}\n```\n\n### 9.5 ToolResultEvent\n\nEmitted when a tool call completes successfully.\n\n```typescript\ninterface ToolResultEvent extends BaseEvent {\n  type: 'tool_result';\n\n  /** Correlates to the `ToolCallStartEvent` for this tool call. */\n  toolCallId: string;\n\n  /** The name of the tool that was called. */\n  toolName: string;\n\n  /**\n   * The tool's output. Type depends on the tool; typically a string\n   * or plain object. May be any JSON-serializable value.\n   */\n  output: unknown;\n\n  /** Wall-clock duration of the tool execution in milliseconds. */\n  durationMs: number;\n}\n```\n\n### 9.6 ToolErrorEvent\n\nEmitted when a tool call fails.\n\n```typescript\ninterface ToolErrorEvent extends BaseEvent {\n  type: 'tool_error';\n\n  /** Correlates to the `ToolCallStartEvent` for this tool call. */\n  toolCallId: string;\n\n  /** The name of the tool that failed. */\n  toolName: string;\n\n  /** Human-readable error message. */\n  error: string;\n}\n```\n\n### 9.7 Tool Event Ordering\n\n```\ntool_call_start(toolCallId='tc-1')\n  -> tool_input_delta(toolCallId='tc-1')*    (zero or more, streaming only)\n  -> tool_call_ready(toolCallId='tc-1')\n  -> tool_result(toolCallId='tc-1')          (success path)\n     OR tool_error(toolCallId='tc-1')        (failure path)\n```\n\nA tool call always begins with `tool_call_start` and terminates with exactly one of `tool_result` or `tool_error`. `tool_call_ready` is guaranteed between the last `tool_input_delta` and the result/error. Parallel tool calls may interleave events from different `toolCallId` values, but events for a single `toolCallId` are always in order.\n\n---\n\n## 10. File Operations Events (5 events)\n\nFile operation events are emitted when the agent reads, writes, creates, deletes, or patches files. These are high-level semantic events; the underlying tool call events are emitted separately.\n\n```typescript\ninterface FileReadEvent extends BaseEvent {\n  type: 'file_read';\n\n  /** Absolute or workspace-relative path of the file that was read. */\n  path: string;\n}\n\ninterface FileWriteEvent extends BaseEvent {\n  type: 'file_write';\n\n  /** Absolute or workspace-relative path of the file that was written. */\n  path: string;\n\n  /** Number of bytes written to the file. */\n  byteCount: number;\n}\n\ninterface FileCreateEvent extends BaseEvent {\n  type: 'file_create';\n\n  /** Absolute or workspace-relative path of the newly created file. */\n  path: string;\n\n  /** Number of bytes in the newly created file. */\n  byteCount: number;\n}\n\ninterface FileDeleteEvent extends BaseEvent {\n  type: 'file_delete';\n\n  /** Absolute or workspace-relative path of the deleted file. */\n  path: string;\n}\n\ninterface FilePatchEvent extends BaseEvent {\n  type: 'file_patch';\n\n  /** Absolute or workspace-relative path of the patched file. */\n  path: string;\n\n  /**\n   * Unified diff of the changes applied. Format follows the standard\n   * unified diff format (--- a/file, +++ b/file, @@ hunks).\n   */\n  diff: string;\n}\n```\n\n### 10.1 File Event Ordering\n\nFile events are emitted after the corresponding `tool_result` or `tool_call_ready` event. They are informational projections of tool activity, not a separate execution stream. A single tool call may produce multiple file events (e.g., a multi-file edit tool).\n\n```\ntool_call_ready(toolName='file_write') -> tool_result -> file_write\ntool_call_ready(toolName='edit_file')  -> tool_result -> file_patch\n```\n\n---\n\n## 11. Shell Operations Events (4 events)\n\nShell events track command execution by the agent. The `shell_start` event identifies the command; stdout/stderr deltas stream the output; `shell_exit` marks completion.\n\n### 11.1 ShellStartEvent\n\n```typescript\ninterface ShellStartEvent extends BaseEvent {\n  type: 'shell_start';\n\n  /** The command string as executed by the agent. */\n  command: string;\n\n  /** The working directory for the command. */\n  cwd: string;\n}\n```\n\n### 11.2 ShellStdoutDeltaEvent\n\n```typescript\ninterface ShellStdoutDeltaEvent extends BaseEvent {\n  type: 'shell_stdout_delta';\n\n  /** A chunk of stdout output from the running command. */\n  delta: string;\n}\n```\n\n### 11.3 ShellStderrDeltaEvent\n\n```typescript\ninterface ShellStderrDeltaEvent extends BaseEvent {\n  type: 'shell_stderr_delta';\n\n  /** A chunk of stderr output from the running command. */\n  delta: string;\n}\n```\n\n### 11.4 ShellExitEvent\n\n```typescript\ninterface ShellExitEvent extends BaseEvent {\n  type: 'shell_exit';\n\n  /**\n   * The exit code of the command. 0 indicates success; non-zero\n   * indicates failure. -1 indicates the process was killed by a signal.\n   */\n  exitCode: number;\n\n  /** Wall-clock duration of the command execution in milliseconds. */\n  durationMs: number;\n}\n```\n\n### 11.5 Shell Event Ordering\n\n```\nshell_start\n  -> shell_stdout_delta*     (zero or more, interleaved with stderr)\n  -> shell_stderr_delta*     (zero or more, interleaved with stdout)\n  -> shell_exit\n```\n\n`shell_start` always precedes any stdout/stderr deltas. `shell_exit` is always the final shell event for a given command. Stdout and stderr deltas may interleave in any order. Shell events are nested within the corresponding tool call events (the shell execution is a tool invocation).\n\n---\n\n## 12. MCP Tool Calling Events (3 events)\n\nMCP (Model Context Protocol) tool events track invocations of tools provided by MCP servers configured via `RunOptions.mcpServers`. They are distinct from native tool events to allow consumers to differentiate between built-in and MCP-provided tools.\n\n### 12.1 Correlation Key: `toolCallId`\n\nMCP tool events share the `toolCallId` correlation key with native tool events. The `server` field distinguishes MCP tool calls from native ones.\n\n```typescript\ninterface McpToolCallStartEvent extends BaseEvent {\n  type: 'mcp_tool_call_start';\n\n  /** Unique identifier for this tool call. */\n  toolCallId: string;\n\n  /** The name of the MCP server providing the tool. */\n  server: string;\n\n  /** The tool name within the MCP server's namespace. */\n  toolName: string;\n\n  /** The complete parsed input for the tool call. */\n  input: unknown;\n}\n\ninterface McpToolResultEvent extends BaseEvent {\n  type: 'mcp_tool_result';\n\n  /** Correlates to the `McpToolCallStartEvent`. */\n  toolCallId: string;\n\n  /** The MCP server name. */\n  server: string;\n\n  /** The tool name. */\n  toolName: string;\n\n  /** The tool's output value. */\n  output: unknown;\n}\n\ninterface McpToolErrorEvent extends BaseEvent {\n  type: 'mcp_tool_error';\n\n  /** Correlates to the `McpToolCallStartEvent`. */\n  toolCallId: string;\n\n  /** The MCP server name. */\n  server: string;\n\n  /** The tool name. */\n  toolName: string;\n\n  /** Human-readable error message from the MCP server or transport layer. */\n  error: string;\n}\n```\n\n### 12.2 MCP Tool Event Ordering\n\n```\nmcp_tool_call_start(toolCallId='mcp-1')\n  -> mcp_tool_result(toolCallId='mcp-1')     (success path)\n     OR mcp_tool_error(toolCallId='mcp-1')   (failure path)\n```\n\nMCP tool events do not have input delta streaming. The full input is available at `mcp_tool_call_start`. Each MCP tool call produces exactly one start event followed by exactly one result or error event.\n\n---\n\n## 13. Subagent Dispatch Events (3 events)\n\nSubagent events track when the primary agent spawns a secondary agent to handle a subtask. These events are emitted by agents that support parallel or delegated execution.\n\n### 13.1 Correlation Key: `subagentId`\n\nAll subagent events for a single spawned agent share the same `subagentId`. This is generated by the adapter and is unique within the parent run.\n\n```typescript\ninterface SubagentSpawnEvent extends BaseEvent {\n  type: 'subagent_spawn';\n\n  /** Unique identifier for this subagent invocation. */\n  subagentId: string;\n\n  /** The name of the agent being spawned as a subagent. */\n  agentName: string;\n\n  /** The prompt/task delegated to the subagent. */\n  prompt: string;\n}\n\ninterface SubagentResultEvent extends BaseEvent {\n  type: 'subagent_result';\n\n  /** Correlates to the `SubagentSpawnEvent`. */\n  subagentId: string;\n\n  /** The agent name. */\n  agentName: string;\n\n  /** A summary of the subagent's result. */\n  summary: string;\n\n  /**\n   * Cost incurred by the subagent invocation.\n   *\n   * @see CostRecord in Section 3.\n   */\n  cost?: CostRecord;\n}\n\ninterface SubagentErrorEvent extends BaseEvent {\n  type: 'subagent_error';\n\n  /** Correlates to the `SubagentSpawnEvent`. */\n  subagentId: string;\n\n  /** The agent name. */\n  agentName: string;\n\n  /** Human-readable error message from the subagent. */\n  error: string;\n}\n```\n\n### 13.2 Subagent Event Ordering\n\n```\nsubagent_spawn(subagentId='sa-1')\n  -> subagent_result(subagentId='sa-1')    (success path)\n     OR subagent_error(subagentId='sa-1')  (failure path)\n```\n\nSubagent events do not stream intermediate results from the subagent. The parent adapter collects the subagent's output and emits a single result or error. Multiple subagents may run concurrently; their events may interleave but are correlated by `subagentId`.\n\n---\n\n## 14. Plugin Events (3 events)\n\nPlugin events track the loading, invocation, and failure of agent plugins (skills, extensions, channel plugins, MCP servers managed as plugins).\n\n### 14.1 Correlation Key: `pluginId`\n\nAll plugin events for a specific plugin share the same `pluginId`. The `pluginId` is the plugin's unique identifier as registered with the agent.\n\n```typescript\ninterface PluginLoadedEvent extends BaseEvent {\n  type: 'plugin_loaded';\n\n  /** Unique identifier for the plugin (e.g., npm package name). */\n  pluginId: string;\n\n  /** Human-readable plugin name. */\n  pluginName: string;\n\n  /** Semantic version string of the loaded plugin. */\n  version: string;\n}\n\ninterface PluginInvokedEvent extends BaseEvent {\n  type: 'plugin_invoked';\n\n  /** The plugin being invoked. */\n  pluginId: string;\n\n  /** Human-readable plugin name. */\n  pluginName: string;\n}\n\ninterface PluginErrorEvent extends BaseEvent {\n  type: 'plugin_error';\n\n  /** The plugin that errored. */\n  pluginId: string;\n\n  /** Human-readable plugin name. */\n  pluginName: string;\n\n  /** Human-readable error message. */\n  error: string;\n}\n```\n\n### 14.2 Plugin Event Ordering\n\n```\nplugin_loaded(pluginId='p-1')             (during session startup)\n  -> plugin_invoked(pluginId='p-1')*      (zero or more, during turns)\n  -> plugin_error(pluginId='p-1')*        (zero or more, on failure)\n```\n\n`plugin_loaded` events are emitted during session initialization, before the first turn. `plugin_invoked` and `plugin_error` events occur during turn processing. A `plugin_error` does not necessarily terminate the run; the agent may continue with remaining plugins.\n\n---\n\n## 15. Skill / Agent Doc Loading Events (3 events)\n\nSkill and agent doc events track the loading and invocation of skills (reusable prompt/tool bundles) and AGENTS.md-style documentation files.\n\n```typescript\ninterface SkillLoadedEvent extends BaseEvent {\n  type: 'skill_loaded';\n\n  /** The name of the skill that was loaded. */\n  skillName: string;\n\n  /**\n   * The source of the skill. Common values:\n   * - File path for file-based skills\n   * - npm package name for package skills\n   * - 'built-in' for agent-native skills\n   */\n  source: string;\n}\n\ninterface SkillInvokedEvent extends BaseEvent {\n  type: 'skill_invoked';\n\n  /** The name of the skill that was invoked. */\n  skillName: string;\n}\n\ninterface AgentdocReadEvent extends BaseEvent {\n  type: 'agentdoc_read';\n\n  /**\n   * Path to the agent documentation file that was read.\n   * Typically AGENTS.md or similar.\n   */\n  path: string;\n}\n```\n\n### 15.1 Skill/Agentdoc Event Ordering\n\n`skill_loaded` events are emitted during session initialization. `skill_invoked` events occur during turn processing. `agentdoc_read` events occur during session initialization, after `session_start` but before the first `turn_start`.\n\n---\n\n## 16. Multimodal Events (2 events)\n\nMultimodal events handle image input acknowledgement and image output generation.\n\n```typescript\ninterface ImageOutputEvent extends BaseEvent {\n  type: 'image_output';\n\n  /**\n   * MIME type of the image (e.g., 'image/png', 'image/jpeg', 'image/svg+xml').\n   */\n  mimeType: string;\n\n  /**\n   * Base64-encoded image data. Present when the image is delivered inline.\n   * Mutually exclusive with `filePath` in typical usage, though both may\n   * be present if the adapter provides both.\n   */\n  base64?: string;\n\n  /**\n   * Absolute path to the generated image file on disk. Present when the\n   * agent writes the image to a file rather than streaming it inline.\n   */\n  filePath?: string;\n}\n\ninterface ImageInputAckEvent extends BaseEvent {\n  type: 'image_input_ack';\n\n  /**\n   * MIME type of the acknowledged input image.\n   */\n  mimeType: string;\n}\n```\n\n---\n\n## 17. Cost and Token Events (2 events)\n\nCost and token events provide real-time cost tracking and token usage telemetry. These are emitted independently of `turn_end` cost data and may arrive at different granularities.\n\n### 17.1 CostEvent\n\nEmitted when the agent reports cumulative or incremental cost data. May be emitted multiple times per run as cost information becomes available.\n\n```typescript\ninterface CostEvent extends BaseEvent {\n  type: 'cost';\n\n  /**\n   * The cost record. Whether this is cumulative (total run cost so far)\n   * or incremental (cost of the latest operation) is adapter-dependent.\n   * Consumers should treat the final `cost` event as the authoritative\n   * total, and the `session_end` cost as the canonical aggregate.\n   *\n   * @see CostRecord in Section 3.\n   */\n  cost: CostRecord;\n}\n```\n\n### 17.2 TokenUsageEvent\n\nEmitted when the agent reports token usage for a specific API call or turn.\n\n```typescript\ninterface TokenUsageEvent extends BaseEvent {\n  type: 'token_usage';\n\n  /** Number of input tokens consumed in this API call. */\n  inputTokens: number;\n\n  /** Number of output tokens generated in this API call. */\n  outputTokens: number;\n\n  /** Number of thinking/reasoning tokens consumed (if applicable). */\n  thinkingTokens?: number;\n\n  /** Number of cached input tokens reused (if applicable). */\n  cachedTokens?: number;\n}\n```\n\n### 17.3 Cost/Token Event Ordering\n\nCost and token events are not ordered relative to text or tool events. They may arrive at any point during a turn, typically after the API call that generated the usage completes. The last `cost` event in a run contains the most up-to-date cumulative cost.\n\n---\n\n## 18. Interaction / Waiting Events (4 events)\n\nInteraction events implement the bidirectional communication channel between the agent and the consumer. They enable approval workflows and free-form input prompts.\n\n### 18.1 Correlation Key: `interactionId`\n\nAll interaction events for a single interaction share the same `interactionId`. This ID is used with `InteractionChannel.respond()` on the `RunHandle` to send a response back to the agent.\n\n```typescript\ninterface InputRequiredEvent extends BaseEvent {\n  type: 'input_required';\n\n  /** Unique identifier for this interaction. Used with `RunHandle.interaction.respond()`. */\n  interactionId: string;\n\n  /** The question or prompt the agent is asking the user. */\n  question: string;\n\n  /** Additional context for the question (e.g., what the agent is trying to do). */\n  context?: string;\n\n  /**\n   * Whether the input request originated from the agent itself or from\n   * a tool the agent is using.\n   */\n  source: 'agent' | 'tool';\n}\n\ninterface ApprovalRequestEvent extends BaseEvent {\n  type: 'approval_request';\n\n  /** Unique identifier for this approval interaction. */\n  interactionId: string;\n\n  /** Short description of the action requiring approval (e.g., 'Execute shell command'). */\n  action: string;\n\n  /** Detailed description of what will be done (e.g., the full command). */\n  detail: string;\n\n  /** The tool requesting approval, if applicable. */\n  toolName?: string;\n\n  /**\n   * Assessed risk level of the action:\n   * - 'low': read-only operations, safe transformations\n   * - 'medium': file writes, non-destructive commands\n   * - 'high': destructive operations, network access, privileged commands\n   */\n  riskLevel: 'low' | 'medium' | 'high';\n}\n\ninterface ApprovalGrantedEvent extends BaseEvent {\n  type: 'approval_granted';\n\n  /** Correlates to the `ApprovalRequestEvent`. */\n  interactionId: string;\n}\n\ninterface ApprovalDeniedEvent extends BaseEvent {\n  type: 'approval_denied';\n\n  /** Correlates to the `ApprovalRequestEvent`. */\n  interactionId: string;\n\n  /** The reason the approval was denied, if provided. */\n  reason?: string;\n}\n```\n\n### 18.2 Interaction Event Ordering\n\n```\napproval_request(interactionId='ia-1')\n  -> approval_granted(interactionId='ia-1')    (approved path)\n     OR approval_denied(interactionId='ia-1')  (denied path)\n\ninput_required(interactionId='ia-2')\n  -> [consumer responds via InteractionChannel]\n```\n\nAn `approval_request` is always followed by exactly one `approval_granted` or `approval_denied`. When `RunOptions.approvalMode` is `'yolo'`, no `approval_request` events are emitted; tools execute without approval. When `approvalMode` is `'deny'`, every tool call is auto-denied and an `approval_denied` event is emitted.\n\nAn `input_required` event pauses the run until the consumer responds. If `RunOptions.onInputRequired` is set, it is called automatically; otherwise the event is surfaced on `RunHandle.interaction.pending` for manual response.\n\n---\n\n## 19. Rate / Context Limit Events (4 events)\n\nThese events surface rate limiting, context window pressure, automatic compaction, and retry behavior.\n\n```typescript\ninterface RateLimitedEvent extends BaseEvent {\n  type: 'rate_limited';\n\n  /**\n   * Suggested delay before retrying, in milliseconds. Absent if the\n   * agent/API did not provide retry-after guidance.\n   */\n  retryAfterMs?: number;\n}\n\ninterface ContextLimitWarningEvent extends BaseEvent {\n  type: 'context_limit_warning';\n\n  /** Number of tokens currently used in the context window. */\n  usedTokens: number;\n\n  /** Maximum context window size in tokens for the current model. */\n  maxTokens: number;\n\n  /**\n   * Percentage of context window used (0-100). Warnings are typically\n   * emitted when this exceeds 80%.\n   */\n  pctUsed: number;\n}\n\ninterface ContextCompactedEvent extends BaseEvent {\n  type: 'context_compacted';\n\n  /**\n   * A human-readable summary of what was removed or compressed\n   * during compaction.\n   */\n  summary: string;\n\n  /** Number of tokens freed by compaction. */\n  tokensSaved: number;\n}\n\ninterface RetryEvent extends BaseEvent {\n  type: 'retry';\n\n  /** The current retry attempt number (1-based). */\n  attempt: number;\n\n  /** The maximum number of retry attempts configured. */\n  maxAttempts: number;\n\n  /** Human-readable reason for the retry (e.g., 'rate_limited', 'transient_error'). */\n  reason: string;\n\n  /** Delay in milliseconds before the retry will be attempted. */\n  delayMs: number;\n}\n```\n\n### 19.1 Rate/Context Event Ordering\n\n`rate_limited` may occur at any point during a run, typically between API calls. A `retry` event follows a `rate_limited` event when auto-retry is enabled. `context_limit_warning` may occur at any point during a turn. `context_compacted` follows a `context_limit_warning` when the agent automatically compacts its context.\n\n---\n\n## 20. Run Lifecycle / Control Events (7 events)\n\nRun lifecycle events reflect state transitions triggered by consumer control methods (`interrupt()`, `abort()`, `pause()`, `resume()`) or by system limits.\n\n```typescript\ninterface InterruptedEvent extends BaseEvent {\n  type: 'interrupted';\n}\n\ninterface AbortedEvent extends BaseEvent {\n  type: 'aborted';\n}\n\ninterface PausedEvent extends BaseEvent {\n  type: 'paused';\n}\n\ninterface ResumedEvent extends BaseEvent {\n  type: 'resumed';\n}\n\ninterface TimeoutEvent extends BaseEvent {\n  type: 'timeout';\n\n  /**\n   * Which timeout was hit:\n   * - 'run': the overall run timeout (`RunOptions.timeout`)\n   * - 'inactivity': the inactivity timeout (`RunOptions.inactivityTimeout`)\n   */\n  kind: 'run' | 'inactivity';\n}\n\ninterface TurnLimitEvent extends BaseEvent {\n  type: 'turn_limit';\n\n  /** The maximum number of turns that was configured via `RunOptions.maxTurns`. */\n  maxTurns: number;\n}\n\ninterface StreamFallbackEvent extends BaseEvent {\n  type: 'stream_fallback';\n\n  /**\n   * The streaming capability that fell back to buffered mode:\n   * - 'text': text generation streaming\n   * - 'tool_calls': tool input streaming\n   * - 'thinking': thinking/reasoning streaming\n   */\n  capability: 'text' | 'tool_calls' | 'thinking';\n\n  /** Human-readable reason for the fallback. */\n  reason: string;\n}\n```\n\n### 20.1 Run Lifecycle Event Ordering\n\n`interrupted`, `aborted`, and `timeout` are terminal control events. After any of these, no further turn/text/tool events are emitted. The run transitions to a terminal state and emits `session_end`.\n\n```\n[running events...] -> interrupted -> session_end\n[running events...] -> aborted -> session_end\n[running events...] -> timeout -> session_end\n[running events...] -> turn_limit -> session_end\n```\n\n`paused` and `resumed` are non-terminal. Events stop flowing after `paused` and resume after `resumed`.\n\n```\n[running events...] -> paused -> resumed -> [running events...]\n```\n\n`stream_fallback` is informational and non-terminal. It is emitted once per capability per run, at the point the adapter first detects that the capability must fall back to buffered mode.\n\n---\n\n## 21. Error Events (5 events)\n\nError events represent failures of varying severity. Some are recoverable (the run continues); others are terminal (the run ends).\n\n```typescript\ninterface AuthErrorEvent extends BaseEvent {\n  type: 'auth_error';\n\n  /** Human-readable error message describing the auth failure. */\n  message: string;\n\n  /**\n   * Actionable guidance for the user to resolve the auth issue.\n   * E.g., 'Run \"claude login\" to authenticate' or 'Set OPENAI_API_KEY'.\n   */\n  guidance: string;\n}\n\ninterface RateLimitErrorEvent extends BaseEvent {\n  type: 'rate_limit_error';\n\n  /** Human-readable error message. */\n  message: string;\n\n  /** Suggested retry delay in milliseconds, if provided by the API. */\n  retryAfterMs?: number;\n}\n\ninterface ContextExceededEvent extends BaseEvent {\n  type: 'context_exceeded';\n\n  /** Number of tokens used when the context was exceeded. */\n  usedTokens: number;\n\n  /** Maximum context window size in tokens. */\n  maxTokens: number;\n}\n\ninterface CrashEvent extends BaseEvent {\n  type: 'crash';\n\n  /** Exit code from the agent subprocess. */\n  exitCode: number;\n\n  /** Captured stderr output from the crashed subprocess. */\n  stderr: string;\n}\n\ninterface ErrorEvent extends BaseEvent {\n  type: 'error';\n\n  /**\n   * Machine-readable error code from the ErrorCode enum.\n   *\n   * @see ErrorCode in 01-core-types-and-client.md, Section 3.1.\n   */\n  code: ErrorCode;\n\n  /** Human-readable error message. */\n  message: string;\n\n  /**\n   * Whether the run can continue after this error.\n   * When false, the run will terminate after this event.\n   */\n  recoverable: boolean;\n}\n```\n\n### 21.1 Error Event Ordering and Terminality\n\n| Event | Terminal | Followed By |\n|---|---|---|\n| `auth_error` | Yes | `session_end` (if session was started) |\n| `rate_limit_error` | No (if retries remain) / Yes (if exhausted) | `retry` (if retrying) or `session_end` |\n| `context_exceeded` | Yes | `session_end` |\n| `crash` | Yes | Nothing (subprocess is gone) |\n| `error` (`recoverable: true`) | No | Normal event flow continues |\n| `error` (`recoverable: false`) | Yes | `session_end` |\n\nTerminal error events halt the run. After a terminal error, no further text, tool, or turn events are emitted. `session_end` follows when possible; `crash` events may not have a `session_end` if the subprocess died before session state could be finalized.\n\n---\n\n## 22. Debug Events (2 events)\n\nDebug events provide adapter-level diagnostic information. They are emitted regardless of the `debug` flag, but the `raw` field on other events is only populated when `debug` is enabled.\n\n```typescript\ninterface DebugEvent extends BaseEvent {\n  type: 'debug';\n\n  /**\n   * Severity level:\n   * - 'verbose': detailed tracing information (high volume)\n   * - 'info': notable adapter-level information\n   * - 'warn': potential issues that do not prevent operation\n   */\n  level: 'verbose' | 'info' | 'warn';\n\n  /** Human-readable debug message. */\n  message: string;\n}\n\ninterface LogEvent extends BaseEvent {\n  type: 'log';\n\n  /**\n   * Which output stream the line came from:\n   * - 'stdout': standard output from the agent subprocess\n   * - 'stderr': standard error from the agent subprocess\n   */\n  source: 'stdout' | 'stderr';\n\n  /** A single line of output from the agent subprocess. */\n  line: string;\n}\n```\n\n### 22.1 Debug Event Ordering\n\nDebug and log events may appear at any point in the event stream. They do not affect the ordering guarantees of other event categories. `log` events with `source: 'stderr'` during subprocess startup may appear before `session_start`.\n\n---\n\n## 23. Complete Correlation Key Reference\n\nCorrelation keys allow consumers to group related events across the stream. Each key is unique within a single run.\n\n| Correlation Key | Events Using It | Purpose |\n|---|---|---|\n| `toolCallId` | `tool_call_start`, `tool_input_delta`, `tool_call_ready`, `tool_result`, `tool_error`, `mcp_tool_call_start`, `mcp_tool_result`, `mcp_tool_error` | Groups all events for a single tool invocation (native or MCP). |\n| `subagentId` | `subagent_spawn`, `subagent_result`, `subagent_error` | Groups all events for a single subagent invocation. |\n| `interactionId` | `input_required`, `approval_request`, `approval_granted`, `approval_denied` | Groups all events for a single interaction prompt/approval cycle. |\n| `pluginId` | `plugin_loaded`, `plugin_invoked`, `plugin_error` | Groups all events for a specific plugin. |\n| `sessionId` | `session_start`, `session_resume`, `session_fork`, `session_checkpoint`, `session_end` | Groups all session lifecycle events. |\n\n> **Note:** `turnIndex` is a positional index used for turn/step scoping (present on `turn_start`, `turn_end`, `step_start`, `step_end`) but is not a correlation identifier — it does not uniquely identify a resource across events the way the keys above do.\n\n### 23.1 Key Format Conventions\n\n| Key | Format | Example |\n|---|---|---|\n| `toolCallId` | Adapter-dependent; typically `toolu_` prefix (Claude), UUID (Codex), or numeric ID | `toolu_01ABcD`, `tc-a1b2c3` |\n| `subagentId` | ULID or UUID generated by the adapter | `01HXYZ...` |\n| `interactionId` | ULID generated by the adapter | `01HABC...` |\n| `pluginId` | Plugin package name or adapter-assigned ID | `@scope/plugin-name`, `skill-file-hash` |\n| `sessionId` | Agent-native format | `uuid-v4` (Claude), `session-dirname` (Codex) |\n\n---\n\n## 24. Streaming Model\n\nThe streaming model controls how events are emitted by adapters. It is configured via `RunOptions.stream` (or `ClientOptions.stream` for the default).\n\n### 24.1 Streaming Modes\n\n#### `stream: 'auto'` (default)\n\nThe adapter uses streaming for each output type that the agent and model support. For unsupported output types, the adapter silently falls back to buffered emission.\n\n**Behavior per capability:**\n\n| Capability | Supported | Not Supported |\n|---|---|---|\n| Text streaming (`supportsTextStreaming`) | Multiple `text_delta` events with small fragments | Single `text_delta` with complete text |\n| Tool call streaming (`supportsToolCallStreaming`) | `tool_input_delta` events for tool input | `tool_call_start` with complete input, no `tool_input_delta` events |\n| Thinking streaming (`supportsThinkingStreaming`) | Multiple `thinking_delta` events | Single `thinking_delta` with complete thinking text |\n\nWhen fallback activates, a `stream_fallback` event is emitted once per capability. This event is informational; the consumer still receives the same event types with the same ordering guarantees.\n\n#### `stream: true`\n\nRequires text streaming. If the adapter has `supportsTextStreaming: false`, `mux.run()` throws `CapabilityError` synchronously before spawning the subprocess.\n\nTool call and thinking streaming still fall back silently (same as `'auto'`), because these are supplementary capabilities that should not block the run.\n\n#### `stream: false`\n\nAll output is buffered. The adapter waits for the agent to complete its response, then emits events in rapid succession:\n\n1. `message_start`\n2. A single `text_delta` with `delta` equal to the complete text and `accumulated` equal to the complete text\n3. `message_stop`\n\nTool events are emitted after all text. Tool call streaming never occurs. Thinking events, if present, are emitted as a single `thinking_delta` with the complete thinking text.\n\n### 24.2 Stream Fallback Behavior\n\nWhen `stream: 'auto'` detects that a capability is unsupported, the adapter:\n\n1. Emits a `stream_fallback` event identifying the capability and reason.\n2. Buffers the corresponding output internally.\n3. Emits the buffered output as a single delta event when the agent completes that output segment.\n\nThe `stream_fallback` event is emitted at most once per capability per run. Multiple capabilities may fall back independently.\n\n```typescript\n// Example: adapter detects thinking streaming is not supported\n// Emitted once when first thinking output arrives:\n{\n  type: 'stream_fallback',\n  capability: 'thinking',\n  reason: 'Model gpt-4o does not support thinking streaming',\n  runId: '01HXYZ...',\n  agent: 'codex',\n  timestamp: 1712345678901\n}\n// Then a single thinking_delta with accumulated text:\n{\n  type: 'thinking_delta',\n  delta: '<complete thinking text>',\n  accumulated: '<complete thinking text>',\n  ...\n}\n```\n\n### 24.3 Backpressure\n\nThe event stream implements backpressure through the async iterator protocol. When a consumer is slow to consume events:\n\n1. **AsyncIterable consumption** (`for await...of`): The adapter buffers events in an internal queue. The queue has no hard limit; extremely slow consumers may cause memory growth. Consumers should avoid blocking in event handlers.\n\n2. **EventEmitter consumption** (`on`/`off`): Events are delivered synchronously to all listeners. No backpressure is applied. Listeners that perform async work should queue internally.\n\n3. **Promise consumption** (`await`): No streaming occurs from the consumer's perspective. All events are processed internally by the `RunHandle` to build the `RunResult`.\n\n**Adapter-side buffering:** Each adapter maintains an internal ring buffer for subprocess stdout/stderr. The buffer size is 64 KB per stream. When the buffer fills, the oldest data is discarded and a `debug` event with `level: 'warn'` is emitted indicating data loss. This situation indicates the consumer is not draining events fast enough.\n\n### 24.4 Streaming Mode Summary\n\n| Behavior | `'auto'` | `true` | `false` |\n|---|---|---|---|\n| Text streaming | If supported | Required (throws if not) | Buffered |\n| Tool call streaming | If supported | If supported | Buffered |\n| Thinking streaming | If supported | If supported | Buffered |\n| `stream_fallback` emitted | Yes, per unsupported capability | Yes, for tool/thinking only | No |\n| `CapabilityError` thrown | Never | Yes, if text streaming unsupported | Never |\n| Event types received | All 67 | All 67 | All 67 |\n\n---\n\n## 25. Event Ordering Contracts\n\nThis section formally specifies the ordering guarantees that consumers can rely on.\n\n### 25.1 Global Ordering\n\n1. `session_start` is the first domain event in every run. Only `debug` and `log` events may precede it (from subprocess startup).\n2. `session_end` is the last domain event in every successful run. Only `debug` and `log` events may follow it.\n3. All turn events occur between `session_start` and `session_end`.\n4. Events within a run are totally ordered. The async iterator yields them in emission order.\n\n### 25.2 Turn-Level Ordering\n\n1. `turn_start(N)` always precedes `turn_end(N)`.\n2. `turn_end(N)` always precedes `turn_start(N+1)`.\n3. All thinking, text, tool, file, shell, MCP, and subagent events for turn N occur between `turn_start(N)` and `turn_end(N)`.\n4. Steps, when present, are properly nested: `step_start` precedes `step_end` and both are within the enclosing turn.\n\n### 25.3 Within-Turn Ordering\n\n1. Thinking events precede text events within the same generation cycle.\n2. Text events and tool events may interleave across generation cycles (e.g., text -> tool call -> more text).\n3. File events follow their corresponding tool result events.\n4. Shell events are nested within their corresponding tool call events.\n\n### 25.4 Interaction Ordering\n\n1. `approval_request` always precedes `approval_granted` or `approval_denied` for the same `interactionId`.\n2. The run pauses after emitting `input_required` or `approval_request` (when not auto-handled) until the consumer responds.\n3. Tool execution events follow `approval_granted` for the approved tool call.\n\n### 25.5 Error and Terminal Ordering\n\n1. Terminal errors (`auth_error`, `context_exceeded`, `crash`, non-recoverable `error`) are followed only by `session_end` (when possible) and `debug`/`log` events.\n2. `interrupted`, `aborted`, `timeout`, and `turn_limit` are followed by `session_end`.\n3. After any terminal event, no further turn/text/tool events are emitted.\n\n### 25.6 Complete Run Event Sequence\n\n```\n[debug/log]*                           -- subprocess startup noise\nsession_start                          -- always first domain event\n  [session_resume]?                    -- if resuming\n  [session_fork]?                      -- if forking\n  [plugin_loaded]*                     -- zero or more during init\n  [skill_loaded]*                      -- zero or more during init\n  [agentdoc_read]*                     -- zero or more during init\n  turn_start(0)\n    [stream_fallback]*                 -- zero or more, when adapter first detects capability fallback\n    [step_start(0,0)]?\n      [thinking_start -> thinking_delta+ -> thinking_stop]?\n      [message_start -> text_delta+ -> message_stop]*\n      [tool_call_start -> tool_input_delta* -> tool_call_ready\n        -> (tool_result | tool_error)\n        -> (file_read | file_write | file_create | file_delete | file_patch)*\n      ]*\n      [mcp_tool_call_start -> (mcp_tool_result | mcp_tool_error)]*\n      [shell_start -> shell_stdout_delta* -> shell_stderr_delta* -> shell_exit]*\n      [subagent_spawn -> (subagent_result | subagent_error)]*\n      [approval_request -> (approval_granted | approval_denied)]*\n      [input_required]*\n      [plugin_invoked | plugin_error]*\n      [skill_invoked]*\n      [image_output | image_input_ack]*\n      [cost | token_usage]*\n      [rate_limited -> retry?]*\n      [context_limit_warning -> context_compacted?]*\n    [step_end(0,0)]?\n    [step_start(0,N) -> ... -> step_end(0,N)]*\n    [session_checkpoint]?\n  turn_end(0)\n  [turn_start(N) -> ... -> turn_end(N)]*\n  [interrupted | aborted | timeout | turn_limit]?    -- terminal control\n  [auth_error | rate_limit_error | context_exceeded | crash | error]?\nsession_end                            -- always last domain event\n[debug/log]*                           -- subprocess teardown noise\n```\n\n---\n\n## 26. Per-Agent Event Support Matrix\n\nEach built-in adapter emits a subset of the 67 event types based on the agent's capabilities and output format. This matrix shows which event categories each adapter supports.\n\n### 26.1 Category Support\n\n| Category | claude | codex | gemini | copilot | cursor | opencode | pi | omp | openclaw | hermes |\n|---|---|---|---|---|---|---|---|---|---|---|\n| Session lifecycle | Full | Partial | Partial | Minimal | Partial | Full | Full | Full | Full | Full |\n| Turn / step | Full | Full | Full | Turn only | Turn only | Full | Full | Full | Full | Full |\n| Text streaming | Full | Full | Full | Full | Full | Full | Full | Full | Full | Full |\n| Thinking | Full | Full | Full | No | No | Full | Full | Full | Full | Full |\n| Tool calling | Full | Full | Full | Partial | Full | Full | Full | Full | Full | Full |\n| File operations | Full | Full | Full | Full | Partial | Full | Full | Full | Full | Full |\n| Shell operations | Full | Full | Full | No | Partial | Full | Full | Full | Full | Full |\n| MCP | Full | No | Partial | No | Full | Full | Full | Full | Full | Full |\n| Subagent dispatch | Full | No | No | No | No | No | Partial | Partial | Full | No |\n| Plugin events | Partial | No | No | No | Full | Full | Full | Full | Full | No |\n| Skill / agentdoc | Full | No | No | No | Full | Full | Full | Full | Full | No |\n| Multimodal | Full | Partial | Full | No | Full | Partial | Partial | Partial | Full | Partial |\n| Cost / tokens | Full | Full | Full | No | No | Full | Full | Full | Full | Full |\n| Interaction | Full | Full | Full | Partial | Full | Full | Full | Full | Full | Full |\n| Rate / context | Full | Full | Full | Partial | Partial | Full | Full | Full | Full | Full |\n| Run lifecycle | Full | Full | Full | Full | Full | Full | Full | Full | Full | Full |\n| Errors | Full | Full | Full | Full | Full | Full | Full | Full | Full | Full |\n| Debug | Full | Full | Full | Full | Full | Full | Full | Full | Full | Full |\n\n### 26.2 Support Level Definitions\n\n| Level | Meaning |\n|---|---|\n| **Full** | All events in the category are emitted with all fields populated. |\n| **Partial** | Some events in the category are emitted, or some fields may be absent. See per-agent notes below. |\n| **Minimal** | Only the bare minimum events are emitted (e.g., `session_start` and `session_end` with synthetic data). |\n| **Turn only** | Only turn-level events are emitted; step events are not available. |\n| **No** | No events in this category are emitted by this adapter. |\n\n### 26.3 Per-Agent Notes\n\n**claude:** Full support across all categories. Claude Code provides the richest event data of any adapter. Subagent dispatch maps to Claude Code's built-in Agent tool. Plugin events are partial because Claude Code's skill system does not emit explicit load/invoke signals; the adapter synthesizes these from tool call patterns.\n\n**codex:** No MCP, subagent, plugin, or skill support. Session lifecycle is partial: no fork or checkpoint support. Multimodal is partial: supports image input acknowledgement but not image output.\n\n**gemini:** No subagent, plugin, or skill support. MCP is partial: Gemini CLI has experimental MCP support with limited error reporting. Session lifecycle is partial: no fork support.\n\n**copilot:** Minimal session lifecycle (no resume, fork, or checkpoint). No thinking, shell, MCP, subagent, plugin, skill, multimodal, or cost support. Interaction is partial: supports approval but not free-form input. Tool calling is partial: tool input streaming is not available.\n\n**cursor:** No thinking, subagent, or cost/token support. Turn-level only (no steps). Shell operations are partial: command output is captured but cwd is not always available. File operations are partial: byte counts may be estimated.\n\n**opencode:** Full support across most categories. No subagent dispatch. Multimodal is partial: image input only. MCP and plugin support depend on OpenCode version.\n\n**pi:** Full support across most categories. Subagent dispatch is partial: limited to Pi's task delegation feature. Multimodal is partial: image input only, no image output.\n\n**omp:** Same as Pi with additional support through oh-my-pi extensions. Subagent dispatch is partial: same as Pi.\n\n**openclaw:** Full support across all categories including its multi-channel plugin system. The richest plugin event data among all adapters.\n\n**hermes:** Full support for session, turn/step, text, thinking, tool calling, file ops, shell ops, interaction, rate/context, cost/tokens, run lifecycle, errors, debug, and MCP (both client and server mode via the `hermes-acp` entry point). No subagent, plugin, or skill support. Multimodal is partial: image input only. hermes-agent is installed via `pip install hermes-agent` (Python >= 3.11) and its output is parsed from JSON-lines format.\n\n### 26.4 Unsupported Event Behavior\n\nWhen an adapter does not support a category, it simply never emits those events. Consumers should not assume any event type will be present. The recommended pattern is:\n\n```typescript\nconst handle = mux.run({ agent: 'copilot', prompt: 'Hello' });\n\nfor await (const event of handle) {\n  switch (event.type) {\n    case 'text_delta':\n      // Always safe -- all adapters emit text events\n      process.stdout.write(event.delta);\n      break;\n    case 'thinking_delta':\n      // Only some adapters emit this; simply not reached for copilot\n      displayThinking(event.delta);\n      break;\n    case 'cost':\n      // Only emitted by adapters that track cost; absent for copilot\n      updateCostDisplay(event.cost);\n      break;\n  }\n}\n```\n\n---\n\n## 27. Event Type Literal Constants\n\nFor convenience, the package exports a frozen object containing all event type literals:\n\n```typescript\n/**\n * All 67 event type string literals as a const object.\n * Useful for programmatic iteration and exhaustiveness checks.\n */\nconst AgentEventType = {\n  // Session lifecycle\n  SESSION_START: 'session_start',\n  SESSION_RESUME: 'session_resume',\n  SESSION_FORK: 'session_fork',\n  SESSION_CHECKPOINT: 'session_checkpoint',\n  SESSION_END: 'session_end',\n\n  // Turn / step\n  TURN_START: 'turn_start',\n  TURN_END: 'turn_end',\n  STEP_START: 'step_start',\n  STEP_END: 'step_end',\n\n  // Text / message streaming\n  MESSAGE_START: 'message_start',\n  TEXT_DELTA: 'text_delta',\n  MESSAGE_STOP: 'message_stop',\n\n  // Thinking / reasoning\n  THINKING_START: 'thinking_start',\n  THINKING_DELTA: 'thinking_delta',\n  THINKING_STOP: 'thinking_stop',\n\n  // Tool calling\n  TOOL_CALL_START: 'tool_call_start',\n  TOOL_INPUT_DELTA: 'tool_input_delta',\n  TOOL_CALL_READY: 'tool_call_ready',\n  TOOL_RESULT: 'tool_result',\n  TOOL_ERROR: 'tool_error',\n\n  // File operations\n  FILE_READ: 'file_read',\n  FILE_WRITE: 'file_write',\n  FILE_CREATE: 'file_create',\n  FILE_DELETE: 'file_delete',\n  FILE_PATCH: 'file_patch',\n\n  // Shell operations\n  SHELL_START: 'shell_start',\n  SHELL_STDOUT_DELTA: 'shell_stdout_delta',\n  SHELL_STDERR_DELTA: 'shell_stderr_delta',\n  SHELL_EXIT: 'shell_exit',\n\n  // MCP tool calling\n  MCP_TOOL_CALL_START: 'mcp_tool_call_start',\n  MCP_TOOL_RESULT: 'mcp_tool_result',\n  MCP_TOOL_ERROR: 'mcp_tool_error',\n\n  // Subagent dispatch\n  SUBAGENT_SPAWN: 'subagent_spawn',\n  SUBAGENT_RESULT: 'subagent_result',\n  SUBAGENT_ERROR: 'subagent_error',\n\n  // Plugin events\n  PLUGIN_LOADED: 'plugin_loaded',\n  PLUGIN_INVOKED: 'plugin_invoked',\n  PLUGIN_ERROR: 'plugin_error',\n\n  // Skill / agent doc\n  SKILL_LOADED: 'skill_loaded',\n  SKILL_INVOKED: 'skill_invoked',\n  AGENTDOC_READ: 'agentdoc_read',\n\n  // Multimodal\n  IMAGE_OUTPUT: 'image_output',\n  IMAGE_INPUT_ACK: 'image_input_ack',\n\n  // Cost / tokens\n  COST: 'cost',\n  TOKEN_USAGE: 'token_usage',\n\n  // Interaction / waiting\n  INPUT_REQUIRED: 'input_required',\n  APPROVAL_REQUEST: 'approval_request',\n  APPROVAL_GRANTED: 'approval_granted',\n  APPROVAL_DENIED: 'approval_denied',\n\n  // Rate / context limits\n  RATE_LIMITED: 'rate_limited',\n  CONTEXT_LIMIT_WARNING: 'context_limit_warning',\n  CONTEXT_COMPACTED: 'context_compacted',\n  RETRY: 'retry',\n\n  // Run lifecycle / control\n  INTERRUPTED: 'interrupted',\n  ABORTED: 'aborted',\n  PAUSED: 'paused',\n  RESUMED: 'resumed',\n  TIMEOUT: 'timeout',\n  TURN_LIMIT: 'turn_limit',\n  STREAM_FALLBACK: 'stream_fallback',\n\n  // Errors\n  AUTH_ERROR: 'auth_error',\n  RATE_LIMIT_ERROR: 'rate_limit_error',\n  CONTEXT_EXCEEDED: 'context_exceeded',\n  CRASH: 'crash',\n  ERROR: 'error',\n\n  // Debug\n  DEBUG: 'debug',\n  LOG: 'log',\n} as const;\n\ntype AgentEventTypeLiteral = typeof AgentEventType[keyof typeof AgentEventType];\n```\n\n---\n\n## 28. Type Guard Utilities\n\nThe package exports type guard functions for narrowing `AgentEvent` to specific types or categories:\n\n```typescript\n/**\n * Narrow an AgentEvent to a specific type.\n */\nfunction isEventType<T extends AgentEvent['type']>(\n  event: AgentEvent,\n  type: T\n): event is Extract<AgentEvent, { type: T }> {\n  return event.type === type;\n}\n\n/**\n * Check if an event belongs to a category.\n */\nfunction isSessionEvent(event: AgentEvent): event is\n  SessionStartEvent | SessionResumeEvent | SessionForkEvent |\n  SessionCheckpointEvent | SessionEndEvent {\n  return event.type.startsWith('session_');\n}\n\nfunction isTurnEvent(event: AgentEvent): event is\n  TurnStartEvent | TurnEndEvent | StepStartEvent | StepEndEvent {\n  return event.type === 'turn_start' || event.type === 'turn_end'\n    || event.type === 'step_start' || event.type === 'step_end';\n}\n\nfunction isTextEvent(event: AgentEvent): event is\n  MessageStartEvent | TextDeltaEvent | MessageStopEvent {\n  return event.type === 'message_start' || event.type === 'text_delta'\n    || event.type === 'message_stop';\n}\n\nfunction isThinkingEvent(event: AgentEvent): event is\n  ThinkingStartEvent | ThinkingDeltaEvent | ThinkingStopEvent {\n  return event.type.startsWith('thinking_');\n}\n\nfunction isToolEvent(event: AgentEvent): event is\n  ToolCallStartEvent | ToolInputDeltaEvent | ToolCallReadyEvent |\n  ToolResultEvent | ToolErrorEvent {\n  return event.type.startsWith('tool_');\n}\n\nfunction isFileEvent(event: AgentEvent): event is\n  FileReadEvent | FileWriteEvent | FileCreateEvent |\n  FileDeleteEvent | FilePatchEvent {\n  return event.type.startsWith('file_');\n}\n\nfunction isShellEvent(event: AgentEvent): event is\n  ShellStartEvent | ShellStdoutDeltaEvent | ShellStderrDeltaEvent |\n  ShellExitEvent {\n  return event.type.startsWith('shell_');\n}\n\nfunction isMcpEvent(event: AgentEvent): event is\n  McpToolCallStartEvent | McpToolResultEvent | McpToolErrorEvent {\n  return event.type.startsWith('mcp_');\n}\n\nfunction isSubagentEvent(event: AgentEvent): event is\n  SubagentSpawnEvent | SubagentResultEvent | SubagentErrorEvent {\n  return event.type.startsWith('subagent_');\n}\n\nfunction isPluginEvent(event: AgentEvent): event is\n  PluginLoadedEvent | PluginInvokedEvent | PluginErrorEvent {\n  return event.type.startsWith('plugin_');\n}\n\nfunction isSkillEvent(event: AgentEvent): event is\n  SkillLoadedEvent | SkillInvokedEvent | AgentdocReadEvent {\n  return event.type === 'skill_loaded' || event.type === 'skill_invoked'\n    || event.type === 'agentdoc_read';\n}\n\nfunction isMultimodalEvent(event: AgentEvent): event is\n  ImageOutputEvent | ImageInputAckEvent {\n  return event.type === 'image_output' || event.type === 'image_input_ack';\n}\n\nfunction isCostEvent(event: AgentEvent): event is\n  CostEvent | TokenUsageEvent {\n  return event.type === 'cost' || event.type === 'token_usage';\n}\n\nfunction isInteractionEvent(event: AgentEvent): event is\n  InputRequiredEvent | ApprovalRequestEvent |\n  ApprovalGrantedEvent | ApprovalDeniedEvent {\n  return event.type === 'input_required' || event.type === 'approval_request'\n    || event.type === 'approval_granted' || event.type === 'approval_denied';\n}\n\nfunction isRateLimitEvent(event: AgentEvent): event is\n  RateLimitedEvent | ContextLimitWarningEvent |\n  ContextCompactedEvent | RetryEvent {\n  return event.type === 'rate_limited' || event.type === 'context_limit_warning'\n    || event.type === 'context_compacted' || event.type === 'retry';\n}\n\nfunction isRunLifecycleEvent(event: AgentEvent): event is\n  InterruptedEvent | AbortedEvent | PausedEvent | ResumedEvent |\n  TimeoutEvent | TurnLimitEvent | StreamFallbackEvent {\n  return event.type === 'interrupted' || event.type === 'aborted'\n    || event.type === 'paused' || event.type === 'resumed'\n    || event.type === 'timeout' || event.type === 'turn_limit'\n    || event.type === 'stream_fallback';\n}\n\nfunction isErrorEvent(event: AgentEvent): event is\n  AuthErrorEvent | RateLimitErrorEvent | ContextExceededEvent |\n  CrashEvent | ErrorEvent {\n  return event.type === 'auth_error' || event.type === 'rate_limit_error'\n    || event.type === 'context_exceeded' || event.type === 'crash'\n    || event.type === 'error';\n}\n\nfunction isDebugEvent(event: AgentEvent): event is\n  DebugEvent | LogEvent {\n  return event.type === 'debug' || event.type === 'log';\n}\n\n/**\n * Check if an event is terminal (the run will end after this event).\n */\nfunction isTerminalEvent(event: AgentEvent): boolean {\n  return event.type === 'interrupted'\n    || event.type === 'aborted'\n    || event.type === 'timeout'\n    || event.type === 'turn_limit'\n    || event.type === 'auth_error'\n    || event.type === 'context_exceeded'\n    || event.type === 'crash'\n    || (event.type === 'error' && !(event as ErrorEvent).recoverable);\n}\n\n/**\n * Check if an event carries a correlation key.\n */\nfunction hasCorrelationKey(event: AgentEvent, key: string): boolean {\n  return key in event;\n}\n```\n\n---\n\n## 29. Event Count Verification\n\nTotal event types by category:\n\n| # | Category | Count | Event Types |\n|---|---|---|---|\n| 1 | Session lifecycle | 5 | `session_start`, `session_resume`, `session_fork`, `session_checkpoint`, `session_end` |\n| 2 | Turn / step | 4 | `turn_start`, `turn_end`, `step_start`, `step_end` |\n| 3 | Text / message streaming | 3 | `message_start`, `text_delta`, `message_stop` |\n| 4 | Thinking / reasoning | 3 | `thinking_start`, `thinking_delta`, `thinking_stop` |\n| 5 | Tool calling | 5 | `tool_call_start`, `tool_input_delta`, `tool_call_ready`, `tool_result`, `tool_error` |\n| 6 | File operations | 5 | `file_read`, `file_write`, `file_create`, `file_delete`, `file_patch` |\n| 7 | Shell operations | 4 | `shell_start`, `shell_stdout_delta`, `shell_stderr_delta`, `shell_exit` |\n| 8 | MCP tool calling | 3 | `mcp_tool_call_start`, `mcp_tool_result`, `mcp_tool_error` |\n| 9 | Subagent dispatch | 3 | `subagent_spawn`, `subagent_result`, `subagent_error` |\n| 10 | Plugin events | 3 | `plugin_loaded`, `plugin_invoked`, `plugin_error` |\n| 11 | Skill / agent doc | 3 | `skill_loaded`, `skill_invoked`, `agentdoc_read` |\n| 12 | Multimodal | 2 | `image_output`, `image_input_ack` |\n| 13 | Cost / tokens | 2 | `cost`, `token_usage` |\n| 14 | Interaction / waiting | 4 | `input_required`, `approval_request`, `approval_granted`, `approval_denied` |\n| 15 | Rate / context limits | 4 | `rate_limited`, `context_limit_warning`, `context_compacted`, `retry` |\n| 16 | Run lifecycle / control | 7 | `interrupted`, `aborted`, `paused`, `resumed`, `timeout`, `turn_limit`, `stream_fallback` |\n| 17 | Errors | 5 | `auth_error`, `rate_limit_error`, `context_exceeded`, `crash`, `error` |\n| 18 | Debug | 2 | `debug`, `log` |\n| | **Total** | **67** | |\n\n---\n\n## Implementation Status (2026-04-12)\n\nThe event union and parse-context contract are implemented as specified. The stream is produced by `StreamAssembler` and consumed by `RunHandleImpl.events()`. Adapters emit events by returning `AgentEvent | AgentEvent[] | null` from `parseEvent(line, context)`, driven by line buffering in `spawn-runner.ts`. No changes to the wire shape.\n",
    "documents": []
  },
  "outgoingEdges": [],
  "incomingEdges": [
    {
      "from": "page:docs-agent-mux-reference",
      "to": "page:docs-agent-mux-reference-04-agent-events",
      "kind": "contains_page"
    }
  ]
}

Shortcuts

Back to overview
Open graph tab