Skip to main content
agent.streamEvents() yields a typed union — text tokens, tool calls, tool results, and terminal events — in the exact order the agent produced them, so a UI can show tool activity instead of inferring it from prose.

Quick Start

1

Consume the event stream

One agent, one tool, one for await — switch on event.type.

The Event Union

streamEvents() yields the AgentEvent discriminated union — five variants, keyed on type.
Never infer success from a non-empty output. A tool that failed with a message is byte-identical to one that succeeded with a message. ok: false is emitted on both failure paths — a thrown error and an approval-gate denial. If your UI treats “we got a string back” as a green checkmark, a silently-broken tool will look like a normal answer.

Pairing Calls to Results with callId

callId is the provider’s id for the invocation and is the only key that may pair a tool_result to its tool_call. Matching by position holds only while exactly one call is in flight, and silently attributes the wrong output the moment that stops being true.

Order Matters

Structured events share the same queue as the text, which keeps a tool call in its true position. On a separate channel a call could arrive before the sentence introducing it, and a reader cannot tell a reordered transcript from a model that genuinely said things in that order.

stream() vs streamEvents()

Use stream() for text-only output; use streamEvents() when the UI must render tool activity. stream() filters on type === 'text' internally, so widening the AgentEvent union does not affect it — text-only consumers are unaffected by this change.

Upgrading an Exhaustive switch

Widening a union is source-breaking for an exhaustive switch. A consumer that handled text/finish/error and treated everything else as an error will now see tool_call/tool_result on the default branch. Add cases (or ignore the new variants explicitly) before upgrading.

Cancelling a Stream

Pass an AbortSignal through AgentStreamOptions.signal to stop generation when the user leaves the screen.
Breaking out of the for await loop also aborts automatically — the iterator’s return() stops the in-flight provider request so no further tokens are generated or billed.

Best Practices

The whole point of ok is that output length is not a signal. Render a checkmark or an error state from event.ok, never from whether event.output is non-empty.
tool_call is emitted before the tool runs. Render a call-in-progress row the moment it arrives so the user knows work is happening.
Position-matching works right up until the day two calls are in flight at once, then it silently attributes the wrong output. Key a Map on callId from the start.
Pass an AbortSignal via AgentStreamOptions.signal when the user leaves the screen, or break the for await loop. Both stop the provider request so tokens are no longer generated or billed.

Streaming

Stream text token-by-token

Mobile Entry

Webview-safe bundle from praisonai/mobile

Events (listener API)

The agent.on(…) listener style

Agent

Full agent configuration