The Vercel AI SDK Mental Model: Streaming UI Meets Agent Loops
The Vercel AI SDK is the TypeScript stack for full-stack web agents: a streaming chat surface in the browser, a model loop on the server, and a shared protocol that keeps both sides honest.
Most agent frameworks stop at "call tools until done."
The AI SDK starts from the product you ship: a Next.js (or similar) UI that shows tokens, tool cards, and approvals as they happen.
Pair AI SDK UI (useChat and friends) with AI SDK Core (streamText, tools, agents) so a multi-step agent loop streams into typed message parts the React tree can render.
Insight: Users judge agents by latency, transparency, and control. Streaming text without tool UI feels incomplete; tool loops without a stream protocol force custom glue that breaks on every major version.
When to Use: Product chat agents in Next.js, generative UI dashboards, human-in-the-loop tools in the browser, and hybrid stacks where Python agents stream into an AI SDK frontend.
Limitations/Trade-offs: The SDK is TypeScript-first for the UI path. Heavy graph orchestration may still live in LangGraph or Pydantic AI behind the stream. Edge runtimes constrain Node-only APIs.
Gateway string ids, @ai-sdk/* providers, OpenRouter, etc.
UI messages are what the client stores and paints.
They carry id, role, and an ordered parts array (text, tool calls, tool results, data, approvals).
Model messages are what the model API expects: content without UI-only metadata.
Routes convert with helpers such as convertToModelMessages before calling streamText (names verify at build).
The stream is not "just tokens."
It is a sequence of events that rebuilds assistant message parts: text chunks, tool-input streaming, tool outputs, finish markers, and (in AI SDK 6+) tool-approval states.
That is why rendering message.parts is the default path, not a single content string.
User submits text; useChat appends a user message and POSTs history to your API (via DefaultChatTransport or equivalent).
Route reads UIMessage[], converts to model messages, runs streamText with tools and stopWhen (or an agent class).
The model may emit tool calls; the SDK executes server tools or defers to the client.
Each step streams as UI parts; the hook updates messages and status (submitted → streaming → ready / error).
If tools or approvals need another model step, the client or server continues until the stop condition.
// Shape only - verify imports and response helpers at build (AI SDK 6+)import { streamText, convertToModelMessages, type UIMessage } from "ai";export async function POST(req: Request) { const { messages }: { messages: UIMessage[] } = await req.json(); const result = streamText({ model: "openai/gpt-4o-mini", // or gateway / provider instance messages: await convertToModelMessages(messages), // tools, stopWhen, toolApproval / needsApproval... }); return result.toUIMessageStreamResponse(); // or createUIMessageStreamResponse + toUIMessageStream}
Agent loop meets UI loop:
The agent loop is model → tool → observe → model, bounded by stopWhen (step count, conditions) or agent defaults.
The UI loop is user send → stream → render parts → optional tool output / approval → auto-resubmit when configured.
Generative UI is the decision that a tool result should become a React component (weather card, table, form), not only prose.
Tool parts use typed names such as tool-displayWeather with states like input-available and output-available so the tree can show loading, result, or error without ad-hoc string parsing.
Human-in-the-loop sits on the same part model: approval-requested states pause execution until the client sends an approval response and the server runs the second pass.
Cross-language stacks keep the UI half and swap the Core half: a Pydantic AI or LangGraph backend can emit the same (or adapted) UI message stream so useChat stays unchanged.
"The SDK is only a React chat widget." Core generation, tools, structured output, and workflow patterns work without React; UI is the high-leverage product layer.
"Streaming is optional polish." For multi-step agents, streaming is how users see progress and intervene (stop, approve, correct).
"content is enough to render." Prefer parts so tools, reasoning, and data stay first-class.
"Edge is always faster and always better." Edge helps cold start and geography; Node is often required for native modules, long work, or certain SDKs.
"A free tool loop replaces architecture." Routing, evaluation, and approval policies still need explicit design.
What is the difference between UIMessage and ModelMessage?
UIMessage is the client/UI shape with parts and metadata. ModelMessage is the provider-facing conversation format. Convert at the boundary of each generation.
Does useChat require Next.js?
No. Next.js App Router is the common full-stack host. The same UI hooks work with other frameworks that can host a compatible chat API.
Where does the agent loop actually run?
Usually on the server inside streamText or an agent class during the request. Client-side tools can also run in the browser when you omit server execute and handle onToolCall.
What does status mean on useChat?
Typical values include submitted (waiting for stream), streaming (chunks arriving), ready (idle for next send), and error. Use them to disable submit and show stop/retry.
How do tools become UI?
Stream tool parts to the client, then map part.type === 'tool-yourToolName' and part.state to React components. That mapping is generative UI.
What stops a runaway tool loop?
Configure stopWhen (for example step count helpers), timeouts, and product-level max steps. Never rely on the model alone to stop.
Can I use OpenRouter or non-Vercel models?
Yes. Providers are pluggable. Gateway string model ids, OpenRouter, and first-party packages all sit under the same Core APIs.
How does AI SDK 6 change approvals?
AI SDK 6 introduces first-class tool-approval states in the language model / UI stream path so sensitive tools can pause for user or policy decisions. Exact property names (needsApproval vs toolApproval) evolve - verify at build.
When should I put LangGraph behind the UI?
When you need durable graphs, complex branching, or Python-native tooling, keep AI SDK UI in front and stream through an adapter or custom mapper.
Is AI SDK RSC required?
No. Modern chat agents typically use AI SDK UI + route handlers. RSC streaming is a separate path for some server-component patterns.
How do I debug a blank chat after deploy?
Check CORS/auth, stream response helper mismatch, missing env keys, runtime edge incompatibilities, and that the client transport points at the real API path.
Do I need to persist messages?
Hooks hold in-memory chat state by default. Production products usually persist UI messages server-side and rehydrate by chat id.