run.start | agentName: string, agentId?: string | First event of every run. |
step.start | step: number | A model step begins: one model call plus the tool calls it asks for. step counts from 1 (a run resumed from a checkpoint continues the count). |
text.delta | text: string | A chunk of model text, as it arrives. |
text.done | text: string | The step’s complete text: the concatenation of its text.delta events. Only for steps with text. |
reasoning.start | (none) | The model starts reasoning in this step. Only with the reasoning option (or a model that always reasons). Its reasoning.deltas and reasoning.done follow, before the step’s first text.delta or tool.start. |
reasoning.delta | text: string | A chunk of reasoning text (or of its summary). Never part of text.delta / run.done’s text. |
reasoning.done | text: string, tokens?: number | The reasoning ended: text is all of it; tokens when the provider reported reasoning tokens by then. |
tool.start | toolCallId: string, toolName: string, args: Record<string, unknown> | A tool call starts. args are the model’s arguments parsed from JSON ({} when they are not valid JSON). |
tool.done | toolCallId, toolName, result: unknown, durationMs: number | A tool call returned. result is the value as it would be JSON-encoded (undefined becomes null, a Date becomes a string). durationMs counts from its tool.start. |
tool.error | toolCallId, toolName, error: { name: string, message: string }, durationMs: number | A tool call failed: it threw, its arguments did not match its schema (name: 'ToolArgumentsValidationError'), or the tool does not exist. The model gets the error as the call’s result and the run continues. |
approval.requested | approvalId: string, toolCallId, toolName, args: Record<string, unknown>, kind?: 'question', question?: { text, options?, allowFreeText? } | A tool call needs a human decision. The run then stops; resume it with agent.approvals.resolve() or resumeAfterApproval() (see Approvals), or stream the continuation (see Streaming after an approval). An ask_question call carries kind: 'question' and its question; answer it with agent.approvals.answer() (see Asking the user a question). |
permission.decision | toolCallId, toolName, decision: 'allow' | 'deny' | 'ask' | 'default', rule?: { index: number, reason?: string }, args?: Record<string, unknown>, at: string | How a tool call’s permission rules decided it: after its tool.start, before the call’s own tool.done / tool.error / approval.requested. Only when the run sets permissions or onPermissionDecision; args is left out under redactContent. |
step.done | step: number, finishReason: string, usage?: { promptTokens, completionTokens, totalTokens } | A step ends. finishReason is the model’s ('stop', 'tool_calls', 'length', …), or 'awaiting-approval', 'aborted', 'steered' (its model call was aborted by run.steer(), see Steering) or 'error' when the step ended that way (a run that runs out of maxSteps still wanting to continue ends with run.done 'max-steps'). usage is this step’s model call, absent when the call produced no response. |
error | error: { name: string, message: string } | An error. If it ends the run, run.done with finishReason: 'error' follows. A provider error retried under surfaceRetryableProviderErrors is followed by further steps instead. |
provider.retry | attempt: number, maxRetries: number, delayMs: number, error: { message: string, category?: string }, provider: string | A model call failed and is retried after delayMs (createAgent({ retry }) or any withRetry() provider). attempt is the attempt that failed (1 = first); category is 'rate-limit', 'timeout', … and absent when unknown (a 5xx, for example). |
provider.fallback | from: string, to: string, error: { message: string } | A model call still failed after its retries and the next provider takes over (createAgent({ fallbackModels }) or any withFallback() provider). from and to are provider names. |
compaction.start | strategy: string, tokensBefore: number, contextWindow: number, thresholdTokens: number | The compaction hook (createAgent({ compaction })) found the next model request above its threshold and starts compacting it. Exactly one compaction.done follows. See Context compaction. |
compaction.done | strategy: string, tokensBefore: number, tokensAfter: number, prunedToolCallIds: string[], summary?: boolean, error?: { message: string } | A compaction ended. tokensAfter equals tokensBefore when nothing could be compacted; summary is set when old turns were replaced by a summary; error is set when the strategy failed or fell back (the run continues). |
context.cleared | sessionId: string, messagesCleared: number | session.clear() emptied a session’s transcript. Delivered to session.on() listeners, not to a run’s stream. compaction.start / compaction.done from session.compact() also reach session.on() and carry trigger: 'manual'. |
budget.exceeded | limit: string, value: number, max: number, scope: 'run' | 'session' | A limits budget tripped: limit is 'maxTokens', 'maxInputTokens', 'maxOutputTokens', 'maxCostUsd', 'maxDurationMs' or 'maxSteps', value what was spent, max the limit. run.done ('budget-exceeded') follows; with onExceeded: 'throw', error and run.done ('error'). |
input.queued | id: string, text: string | run.enqueue() took an input (id is EnqueueResult.id, text its user text). Can come at any point of the run, also inside a step. See Queued input. |
input.steered | id: string, text: string, mode: 'immediate' | 'queued' | run.steer() took an input (id is SteerResult.id). mode: 'immediate': the in-flight model call was aborted for it, and its step ends with step.done 'steered'; 'queued': it waits for the next safe point like enqueue(). See Steering. |
input.applied | id: string, step: number | The queued (or steered) input joined the transcript, right before the model call of step: the step.start of that step follows. |
guardrail.tripped | name: string, kind: 'input' | 'output' | 'tool', reason: string, toolName?: string | An input, output or tool guardrail blocked: before the first model call (input), before the step’s text.done (output) or after the call’s tool.start (tool). run.done ('guardrail') follows; with onTripped: 'throw', error and run.done ('error'). |
guardrail.rewrote | name, kind, reason, toolName? | A guardrail rewrote the input, the step’s text (before its text.done, which carries the new text) or a tool call’s arguments. The run continues. |
run.done | finishReason: string, text: string, usage?: { promptTokens, completionTokens, totalTokens }, object?: unknown | Last event of every run, exactly once, including aborted, failed and awaiting-approval runs. finishReason and text match run.result ('max-steps' when the maxSteps budget ran out while the model still wanted to continue); a failed run has finishReason: 'error', text: '' and no usage. object is run.result’s validated object for an agent with an output schema (see Structured output), absent otherwise. |