Vercel AI SDK UI

Vercel AI SDK UI gives you client-side React hooks for building chat interfaces. AI Transport swaps in underneath them as the transport, 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

FeatureDescription
useChat hookManages the UIMessage array, the status field (submitted, streaming, ready, error), and the methods sendMessage, regenerate, and stop.
UIMessage modelMessages with parts (text, reasoning, tool calls, tool results, files, sources). Each part tracks its own streaming state.
ChatTransport interfaceThe plug-in point. sendMessages submits messages; reconnectToStream resumes an interrupted stream. The default implementation is HTTP plus Server-Sent Events.
UI componentsPatterns and primitives for chat layouts, message rendering, and input handling.

AI Transport composes with these rather than replacing them; what it replaces is the transport underneath.

What AI Transport adds

FeatureDescription
Durable sessionsTokens flow through a session that outlives any single connection. A client reconnects and resumes from where it left off.
Multi-device syncEvery device subscribed to the session sees the same conversation in realtime.
Bidirectional controlCancel, steer, and interrupt the agent from any client. No separate control channel.
Active run trackingview.runs() exposes which clients have runs streaming and which runs are in progress.
Conversation branchingEdit and regenerate create forks in the conversation tree rather than destructive replacements.
Approval gates that reach the user anywherePending tool approvals persist on the session until someone acts on them.
History and replayLoad the full conversation on reconnect, page refresh, or new device join.
Token compactionReconnecting clients receive accumulated responses rather than a replay of every token.

Where they connect

AI Transport implements the ChatTransport interface. On the client, swapping it in is a small change to useChat:

JavaScript

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:

  1. The Vercel codec (from createUIMessageCodec()) encodes Vercel's UIMessageChunk events as Ably messages. Every chunk type (text-delta, tool-input, finish, and others) maps to an Ably message with headers that track its metadata. The codec encodes on the server, decodes on the client, and reassembles chunks into complete UIMessage objects.
  2. ChatTransportProvider creates the underlying ClientSession and the ChatTransport adapter and makes both available through context. useChatTransport is a context reader that returns { session, chatTransport }.
  3. useMessageSync subscribes to the transport's conversation tree and pushes updates into useChat's setMessages. This is what brings multi-device sync and conversation branching into Vercel's local state without useChat natively supporting them. Pass a messages seed to hydrate from your own database and reconcile that conversation with the live session.
  4. On the server, run.pipe(result.toUIMessageStream()) pipes the model's output through the codec encoder to the session. The HTTP response returns status 200 with an empty body. 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

createUIMessageCodec, 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 inference is unchanged.

On the client, that looks like this:

JavaScript

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 fills that gap without changing how you use useChat. 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 (branch navigation, split-pane views, custom message construction), work against Vercel AI SDK Core instead.