Vercel AI SDK UI
Vercel AI SDK UI gives you client-side React hooks for building chat interfaces. AI Transport implements the transport those hooks use, so the same UI gets durable sessions, multi-device sync, and bidirectional control.
Vercel AI SDK UI is Vercel's React library for building AI chat interfaces. Its useChat hook manages the conversation state, sends user messages, and renders streaming responses. The framework intentionally leaves the transport pluggable through the ChatTransport interface; AI Transport implements that interface and adds the durability that direct HTTP streaming does not provide.
What Vercel AI SDK UI brings
| Feature | Description |
|---|---|
useChat hook | Manages the UIMessage array, the status field (submitted, streaming, ready, error), and the methods sendMessage, regenerate, and stop. |
UIMessage model | Messages with parts (text, reasoning, tool calls, tool results, files, sources). Each part tracks its own streaming state. |
ChatTransport interface | The plug-in point. sendMessages submits messages; reconnectToStream resumes an interrupted stream. The default implementation is HTTP plus Server-Sent Events. |
| UI components | Patterns and primitives for chat layouts, message rendering, and input handling. |
AI Transport composes with these rather than replacing them; it replaces only the transport useChat uses.
What AI Transport adds
Everything below comes from AI Transport rather than the framework.
| Feature | Description | Available with |
|---|---|---|
| Streams that outlive a connection | Tokens flow through a channel rather than one HTTP response, so a client can reconnect and pick up where it left off. | Streaming |
| Multi-device delivery | Every device attached to the conversation receives the same messages in realtime. | Streaming |
| Bidirectional control | Cancel, steer, and interrupt the agent from any client, on the same channel as the response. | Streaming |
| Run tracking | Run lifecycle events say which client started a run and when it ended. view.runs() keeps the tally for you. | Durable session |
| Conversation branching | Edit and regenerate create forks in the conversation tree rather than destructive replacements. | Durable session |
| Approval gates that reach the user anywhere | Pending tool approvals persist on the session until someone acts on them. | Durable session |
| History and replay | Page the channel backwards on reconnect, page refresh, or a new device joining. | Streaming |
| Token compaction | Reconnecting clients receive accumulated responses rather than a replay of every token. | Streaming |
Where they connect
AI Transport implements the ChatTransport interface. On the client, swapping it in is a small change to useChat:
1
2
3
4
5
6
7
// Before: default HTTP transport
const { messages } = useChat();
// After: Ably transport (everything else stays the same)
// Wrap your tree with <ChatTransportProvider channelName={chatId}> first.
const { chatTransport } = useChatTransport();
const { messages } = useChat({ transport: chatTransport });The integration has four parts:
- The Vercel codec (from
createUIMessageSessionCodec()) encodes Vercel'sUIMessageChunkevents as Ably messages. The streamed chunk types (text-delta,reasoning-deltaandtool-input-delta) append to the single Ably message their stream opened, and the discrete types (start,finish,tool-output-available,tool-output-errorand the rest) each publish their own message. Headers carry the metadata for all event types. The codec encodes on the server, decodes on the client, and reassembles chunks into completeUIMessageobjects. ChatTransportProvidercreates the underlyingClientSessionand theChatTransportadapter and makes both available through context.useChatTransportis a context reader that returns{ session, chatTransport }.useMessageSyncsubscribes to the transport's conversation tree and pushes updates intouseChat'ssetMessages. It brings multi-device sync and conversation branching into Vercel's local state, neither of whichuseChatsupports on its own. Pass amessagesseed to hydrate from your own database and reconcile that conversation with the live session.- On the server,
run.pipe(result.toUIMessageStream())pipes the model's output through the codec encoder to the session. The transport reads only the response status, so your route can return any body it likes. Tokens reach every connected client through the session rather than through the HTTP response. The server-side integration covers how the agent pipes it.
Typed messages
createUIMessageSessionCodec, createClientSession, createAgentSession, and createChatTransport are generic over the AI SDK's three UIMessage type parameters: message metadata, custom data parts, and tools. Supply them once and your typed message flows through the session, so view.getMessages() returns messages whose metadata, data parts, and tool parts carry your types instead of the SDK defaults. Omit them and type inference is unchanged.
On the client, that looks like this:
1
2
3
4
5
6
7
8
9
10
import { createClientSession } from '@ably/ai-transport/vercel';
import type * as AI from 'ai';
type Metadata = { userId: string };
type DataParts = AI.UIDataTypes & { chart: { points: number[] } };
type Tools = AI.UITools & { getWeather: { input: { city: string }; output: { tempC: number } } };
const session = createClientSession<Metadata, DataParts, Tools>({ client: ably, channelName: 'ai:demo' });
const [{ message }] = session.view.getMessages();
message.metadata; // typed `Metadata | undefined`, not `unknown`The React provider path (ChatTransportProvider and the hooks from createSessionHooks) stays at the SDK defaults, because those hooks are created once at module scope. To use your own types end-to-end, pass them through the imperative path: createClientSession<Metadata, DataParts, Tools>(), createChatTransport<Metadata, DataParts, Tools>(), and useMessageSync<Metadata, DataParts, Tools>().
Scope and trade-offs
Vercel AI SDK UI is intentionally focused on Vercel's data model. By design, it does not handle multi-device session continuity, branch navigation, or bidirectional control. AI Transport adds all three, and you still use useChat the same way. The same messages array, the same sendMessage and stop methods; the behaviours underneath move from ephemeral HTTP to durable sessions.
If you need direct access to the conversation tree for branch navigation, split-pane views, or custom message construction, use ClientSessionProvider with useView instead of useChat. The useView quickstart builds that path.
Read next
- Get started with Vercel AI SDK: build a working app.
- Vercel AI SDK Core: the server-side integration that pairs with this page.
- Vercel integration API reference: every option and method on the Vercel integration.
- Conversation branching: one of the features
useMessageSyncbrings touseChat.