Real-time token and event streaming with agent.stream() and agent.runStreamEvents() - text deltas, tool call visibility, and progressive structured output.
Vibes provides two streaming APIs. agent.stream() is the simpler option: it returns a StreamResult that you can iterate over for text tokens and await for the final output. agent.runStreamEvents() gives you granular event-level control: every turn start, text delta, tool call, and tool result is emitted as a typed event.Use agent.stream() for most cases. Reach for agent.runStreamEvents() when you need full observability, custom progress indicators, or real-time tool call logging.
agent.stream() returns a StreamResult<TOutput> immediately. The async iterables deliver data in real time; the promises resolve when the run completes.
import { Agent } from "@vibesjs/sdk";import { anthropic } from "@ai-sdk/anthropic";const agent = new Agent({ model: anthropic("claude-sonnet-4-6"), systemPrompt: "You are a helpful assistant.",});const stream = agent.stream("Tell me a story.");// Stream tokens as they arrivefor await (const chunk of stream.textStream) { process.stdout.write(chunk);}// Await final values after consuming textStreamconst output = await stream.output; // Promise<TOutput>const messages = await stream.messages; // Promise<ModelMessage[]>const newMessages = await stream.newMessages; // Promise<ModelMessage[]>const usage = await stream.usage; // Promise<Usage>
For progressive structured output (only when outputMode: "tool"):
for await (const partial of stream.partialOutput) { console.log("Partial output:", partial);}
agent.runStreamEvents() returns an AsyncIterable<AgentStreamEvent<TOutput>>. Switch on event.kind to handle each event type.
import type { AgentStreamEvent } from "@vibesjs/sdk";for await (const event of agent.runStreamEvents("What is 2 + 2?")) { switch (event.kind) { // NOTE: .kind not .type case "turn-start": console.log(`Turn ${event.turn} started`); break; case "text-delta": process.stdout.write(event.delta); break; case "tool-call-start": console.log(`Calling ${event.toolName}`, event.args); break; case "tool-call-result": console.log(`Result from ${event.toolName}:`, event.result); break; case "partial-output": console.log("Partial output:", event.partial); break; case "usage-update": console.log("Usage:", event.usage); break; case "final-result": console.log("Done:", event.output); break; case "error": console.error("Error:", event.error); break; }}
The event discriminant is event.kind, not event.type. Always use event.kind when switching on stream events.