Documentation Index
Fetch the complete documentation index at: https://docs.agentium.in/llms.txt
Use this file to discover all available pages before exploring further.
Vercel UI Message Stream Adapter
What it is
Vercel’s AI SDK has become the de-facto standard streaming protocol for AI chat UIs in React. ItsuseChat, useAssistant, and useCompletion hooks consume a specific line-delimited JSON stream over HTTP — the UI Message Stream Protocol v1.
Agentium ships an adapter that converts an agent.stream() async iterable into that exact protocol, so you can:
- Drop an Agentium agent into a Vercel AI Chatbot template with zero React changes
- Reuse any community ChatKit / shadcn AI chat component that targets the Vercel protocol
- Future-proof against the inevitable consolidation of streaming protocols
Architecture
Two entry points
createAgentUIStreamResponse(agent, input, options?) — Web / Edge runtimes
Returns a standard fetch Response whose body streams UI message chunks. Use as the return value of a Next.js Route Handler, Hono handler, Cloudflare Worker, etc.
pipeAgentUIStreamToResponse(agent, input, res, options?) — Node ServerResponse / Express
For Node’s classic http.ServerResponse shape (Express, Fastify with raw mode, etc.):
AgentUIStreamOptions
Both functions accept the same options:
Lower-level: agentUIStream(agent, input, options?)
Returns the raw ReadableStream<Uint8Array> if you want to wrap the response yourself (custom headers, intermediate transforms, multiplex with another stream):
Wire-level protocol
The adapter emits one SSE event per chunk in the form:| Type | When emitted | Payload |
|---|---|---|
start | At the beginning of every run | { messageId } |
text-start | First text chunk in a turn | { id } |
text-delta | Each text token | { id, textDelta } |
text-end | When tool calls interrupt text OR at the end | { id } |
reasoning-delta | Each reasoning / thinking token (Claude, o1) | { id, reasoningDelta } |
tool-input-start | LLM starts a tool call | { toolCallId, toolName } |
tool-input-available | Tool input is finalized | { toolCallId, toolName, input } |
tool-output-available | Tool result is back | { toolCallId, output } |
error | An error occurred mid-stream | { errorText } |
finish-step | At every roundtrip end | { finishReason, usage } |
finish | At the very end of the whole run | (none) |
What chunks does the adapter need from agent.stream?
The adapter is loose about the agent’s internal chunk shape — it handles any of:
| Agent chunk | UI Message output |
|---|---|
{ type: "text", text } | text-start then text-delta |
{ type: "text-delta", delta } | text-delta |
{ type: "reasoning" | "thinking", ... } | reasoning-delta |
{ type: "tool.call" | "tool-call", toolCallId, toolName, arguments } | tool-input-start + tool-input-available |
{ type: "tool.result" | "tool-result", toolCallId, output } | tool-output-available |
{ type: "error", error } | error |
{ type: "finish" | "done", finishReason, usage } | finish-step |
Headers
The adapter sets:x-vercel-ai-ui-message-stream: v1 is what Vercel’s hooks look for to identify the protocol. Don’t strip it in a reverse proxy.
Compose with Resumable SSE
The UI Stream adapter is one-shot — if the client reconnects, they get a fresh stream. For full mobile-grade resumability (Last-Event-ID replay), use the lower-level defaultEventLog + formatSSEEvent instead of the UI stream adapter.
The two can coexist: serve UI-stream-protocol from /api/chat for desktop browsers (Vercel hooks), and a separate /api/run endpoint with resumable SSE for mobile clients.
See also
- Resumable SSE — for mobile / flaky network resilience
- Vercel AI SDK docs — client-side hooks
- @agentium/transport — full transport package overview