AbortSignal — see Cancellation.
Which Mode Do I Want?
Pick the surface that matches where the answer renders.Quick Start
1
Iterate tokens with stream()
Render tokens live anywhere — the
for await loop pulls them at its own pace.2
Terminal default (start / chat)
On the CLI, streaming is already on — tokens print to the terminal.
3
Structured events with streamEvents()
Same agent, structured events — handle text, finish, and error.
4
Streaming with Tools
Tool calls are woven into the same stream — text the model speaks before the tool (Iterate
"Let me check."), the tool call itself, and the answer after it all arrive as they happen. This holds on every provider: OpenAI, Anthropic, Google, xAI, Groq, and any AI-SDK backend. Pre-tool commentary is delivered as tokens, not held back until the tool finishes.agent.stream() to observe the pre-tool text in a non-console caller — each chunk is a token string.5
Consume Tokens Yourself
Consume tokens yourself with
agent.stream() — an async iterator over chunks.6
Stop a Stream
Break the loop to stop the request — the provider stops generating and billing immediately.For a UI Stop button, pass an
AbortSignal:Cancellation
Break out of the loop to stop the stream cleanly — no more tokens are queued and the in-flight provider request is aborted.AbortSignal to cancel a turn from outside the loop.
How It Works
When tools are configured, the round routes throughstreamText on every provider — text spoken before the tool call streams as tokens, then the tool runs, then the answer after it streams too.
Streaming with Tools
Text deltas, tool calls, and tool results interleave on a single loop — the stream never stops just because the agent needs a tool.Bounding the loop
Two knobs bound the run when the model chains many tools.Stop a stream
Two ways to cancel a streaming turn — both stop the upstream provider request so no further tokens are generated or billed.Which one should I use?
opts.signal is turn-scoped and independent of the agent-level SimpleAgentConfig.signal. Aborting one turn does not disable the agent; the next stream() call runs normally.Tell a Stop from a real error
agent.lastStopReason reports why the last run ended:
AgentEvent Reference
streamEvents() yields a discriminated union. Switch on event.type.
Match a
tool_result to its tool_call by callId — it is the only reliable pairing key. plain stream() skips tool events and yields text only.AgentStreamOptions Reference
Bothstream() and streamEvents() accept an optional second argument.
Configuration Options
Thestream config option controls the terminal default and whether token deltas are produced.
When the run does not stream tokens (
stream: false, tools in use, or a structured outputSchema), stream() still yields the full response as a single token — callers never silently receive nothing.Common Patterns
Stream to a Server-Sent Events endpoint
Log the full text once with streamEvents()
Terminal default (unchanged)
Seeing Tool Activity
If your UI needs to render tool calls and their results — not just the streamed text — useagent.streamEvents() instead of agent.chat(). It yields a typed union (text, tool_call, tool_result, finish, error) in the order the agent produced them, so a call is announced before it runs and its result carries an explicit ok field.
Best Practices
Use stream() for UI hosts
Use stream() for UI hosts
Anywhere tokens must land in a DOM, SSE, WebSocket, or React Native view,
for await (const token of agent.stream(...)) gives you each token to route yourself.Use streamEvents() when you need finish/error semantics
Use streamEvents() when you need finish/error semantics
Switch to
streamEvents() to close a socket, log the full text once, react to tool activity, or fall back on error — the finish, error, tool_call, and tool_result events carry that context.Break the loop to cancel
Break the loop to cancel
No separate
AbortController is needed for the streaming surface itself — breaking out of the for await loop detaches the token sink and aborts the in-flight request. Pass opts.signal only when you need to cancel from outside the loop.Streaming works with all providers — including with tools
Streaming works with all providers — including with tools
Every supported provider streams — OpenAI, Anthropic, Google, xAI, Groq, and any AI-SDK backend. That includes streaming while tools are running: text the model speaks before a
tool_call is delivered as tokens, not held back until the tool finishes. Setting stream: false still works and collapses the round into a single non-streaming call.Keep stream: true when you use tools on non-OpenAI providers
Keep stream: true when you use tools on non-OpenAI providers
On Anthropic, Google, xAI, Groq, and any AI-SDK backend,
stream: true gives you pre-tool commentary as tokens. Setting stream: false collapses the round into one non-streaming call and delivers the same text at the end in one lump.Break or abort — both stop billing
Break or abort — both stop billing
Agent.stream() owns the upstream request and cancels it in the iterator’s finally. Breaking a for await loop, or aborting a signal you passed via agent.stream(prompt, { signal }), both stop provider tokens from being generated. Use agent.lastStopReason === 'cancelled' to distinguish a user Stop from a real failure in your error handler.Non-streaming paths still work with stream()
Non-streaming paths still work with stream()
Even when tools or
outputSchema disable token deltas, stream() yields the full response as a single item, so callers always receive an answer.Keep the CLI default alone
Keep the CLI default alone
Omitting the token sink (i.e. calling
start() or chat()) still writes to process.stdout, so existing CLI scripts don’t change.Beyond Text: Structured Events
For UIs that need to show tool activity live, usestreamEvents() — it yields typed AgentEvents instead of just tokens.
Streaming Events
Stream tool calls, tool results, and text as structured events
Related
Stream Events
Structured text and tool events
Agent
Full agent configuration
Providers
LLM provider setup

