Skip to main content
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.

Streaming event timeline

agent.stream() - simple streaming

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 arrive
for await (const chunk of stream.textStream) {
  process.stdout.write(chunk);
}

// Await final values after consuming textStream
const 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() - event stream

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.

AgentStreamEvent reference

event.kindExtra FieldsWhen Emitted
"turn-start"turn: numberBeginning of each model turn
"text-delta"delta: stringEach text token from the model
"tool-call-start"toolName, toolCallId, argsModel requests a tool call
"tool-call-result"toolCallId, toolName, resultTool finished executing
"partial-output"partial: unknownProgressive structured output (tool mode only)
"usage-update"usage: UsageAfter each turn completes
"final-result"output: TOutputRun completed successfully
"error"error: unknownUnrecoverable error - stream ends

When to use which

Use CaseAPI
Stream text to user UIagent.stream() + textStream
Await final structured outputagent.stream() + output
Observe tool calls in real timeagent.runStreamEvents()
Build custom progress indicatorsagent.runStreamEvents()
Log every turn and tool for debuggingagent.runStreamEvents()
Persist new messages from this runEither + newMessages

StreamResult interface

For reference, the complete StreamResult<TOutput> interface:
FieldTypeDescription
textStreamAsyncIterable<string>Token-by-token text stream
partialOutputAsyncIterable<TOutput>Progressive structured output (tool mode only)
outputPromise<TOutput>Final structured output
messagesPromise<ModelMessage[]>Full conversation history
newMessagesPromise<ModelMessage[]>Messages added during this run
usagePromise<Usage>Accumulated token usage