createAgentUIStreamResponse
The createAgentUIStreamResponse function executes an Agent, runs its streaming output as a UI message stream, and returns an HTTP Response object whose body is the live, streaming UI message output. This is designed for API routes that deliver real-time agent results, such as chat endpoints or streaming tool-use operations.
Import
import { createAgentUIStreamResponse } from "ai"Usage
import { ToolLoopAgent, createAgentUIStreamResponse } from 'ai';
const agent = new ToolLoopAgent({
model: 'anthropic/claude-sonnet-5.5',
instructions: 'You are a helpful assistant.',
tools: { weather: weatherTool, calculator: calculatorTool },
});
export async function POST(request: Request) {
const { messages } = await request.json();
return createAgentUIStreamResponse({
agent,
uiMessages: messages,
abortSignal: request.signal, // optional: aborts when the client disconnects
// experimental_sandbox, // optional: passed through to tool execution
// ...other UIMessageStreamOptions like sendSources, experimental_transform, etc.
});
}Parameters
agent(Agent): The agent instance to stream responses from. Must implement.stream({ prompt, ... })and define thetoolsproperty.uiMessages(unknown[]): Array of input UI messages provided to the agent (e.g., user and assistant messages).convertDataPart((part: DataUIPart) => TextPart | FilePart | undefined): Converts custom UI data parts into text or file parts for the model. Data parts are ignored when this callback is omitted or returns undefined.abortSignal(AbortSignal): Optional abort signal to cancel streaming, e.g., on client disconnect. This should be anAbortSignalinstance.timeout(number | { totalMs?: number }): Timeout in milliseconds. Can be specified as a number or as an object with a totalMs property. The call will be aborted if it takes longer than the specified timeout. Can be used alongside abortSignal.experimental_sandbox(Experimental_SandboxSession): Optional experimental sandbox environment that is passed through to tool execution. Tools can access it from their execution context.options(CALL_OPTIONS): Optional agent call options, for agents with generic parameterCALL_OPTIONS.experimental_transform(StreamTextTransform | StreamTextTransform[]): Optional stream transforms to post-process text output—the same as in lower-level streaming APIs.onStepEnd(GenerateTextOnStepEndCallback): Callback invoked after each agent step (LLM/tool call) completes. Useful for tracking token usage or logging intermediate steps.onStepFinish(GenerateTextOnStepFinishCallback): Deprecated. UseonStepEndinstead. This alias is only used as a fallback whenonStepEndis not provided.onUIMessageStepEnd(UIMessageStreamOnStepEndCallback): Callback invoked after each UI message step is assembled. It receivesmessages,isContinuation, and the accumulatedresponseMessagefor intermediate persistence....UIMessageStreamOptions(UIMessageStreamOptions): Other UI message output options, including message IDs, metadata, final callbacks, sources, and reasoning.headers(HeadersInit): Optional HTTP headers to include in the Response object.status(number): Optional HTTP status code.statusText(string): Optional HTTP status text.consumeSseStream((options: { stream: ReadableStream<string> }) => PromiseLike<void> | void): Optional function to consume the SSE stream. When provided, this function will be called with the SSE stream to handle consumption.
Returns
A Promise<Response> whose body is a streaming UI message output from the agent. Use this as the return value of API/server handlers in serverless, Next.js, Express, Hono, or edge runtime contexts.
Use onUIMessageStepEnd to persist the accumulated UI response after every agent step. The callback is awaited before the corresponding finish-step chunk continues. Use idempotent writes and protect model output, reasoning, tool inputs, and tool outputs as sensitive conversation data. The existing onStepEnd callback remains the low-level generation callback for usage, finish reasons, and raw step details.
Example: Next.js API Route Handler
import { createAgentUIStreamResponse } from 'ai';
import { MyCustomAgent } from '@/agent/my-custom-agent';
export async function POST(request: Request) {
const { messages } = await request.json();
return createAgentUIStreamResponse({
agent: MyCustomAgent,
uiMessages: messages,
// experimental_sandbox, // optional
sendSources: true, // (optional)
// headers, status, abortSignal, and other UIMessageStreamOptions also supported
});
}How It Works
-
- UI Message Validation: Validates the incoming
uiMessagesarray according to the agent's specified tools and requirements.
- UI Message Validation: Validates the incoming
-
- Model Message Conversion: Converts validated UI messages into the internal model message format for the agent.
-
- Streaming Agent Output: Invokes the agent’s
.stream({ prompt, ... })to get a stream of chunks (steps/UI messages), passing through options such asexperimental_sandbox.
- Streaming Agent Output: Invokes the agent’s
-
- HTTP Response Creation: Wraps the output stream as a readable HTTP
Responseobject that streams UI message chunks to the client.
- HTTP Response Creation: Wraps the output stream as a readable HTTP
Notes
- Your agent must implement
.stream({ prompt, ... })and define atoolsproperty (even if it's just{}) to work with this function. - Server Only: This API should only be called in backend/server-side contexts (API routes, edge/serverless/server route handlers, etc.). Not for browser use.
- Pass
experimental_sandboxwhen your agent tools need an experimental sandbox environment during execution. - Additional options (
headers,status, UI stream options, transforms, etc.) are available for advanced scenarios. - This leverages ReadableStream so your platform/client must support HTTP streaming consumption.