# 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](https://ai-sdk.dev/docs/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; what it replaces is the transport underneath. ## What AI Transport adds | Feature | Description | | --- | --- | | Durable sessions | Tokens flow through a session that outlives any single connection. A client reconnects and resumes from where it left off. | | Multi-device sync | Every device subscribed to the session sees the same conversation in realtime. | | Bidirectional control | Cancel, steer, and interrupt the agent from any client. No separate control channel. | | Active run tracking | `view.runs()` exposes which clients have runs streaming and which runs are in progress. | | Conversation branching | Edit and regenerate create forks in the conversation tree rather than destructive replacements. | | Approval gates that reach the user anywhere | Pending tool approvals persist on the session until someone acts on them. | | History and replay | Load the full conversation on reconnect, page refresh, or new device join. | | Token compaction | Reconnecting 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 ``` // Before: default HTTP transport const { messages } = useChat(); // After: Ably transport (everything else stays the same) // Wrap your tree with 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](https://ably.com/docs/ai-transport/features/database-hydration.md) 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](https://ably.com/docs/ai-transport/frameworks/vercel-ai-sdk-core.md) 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 ``` 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({ 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()`, `createChatTransport()`, and `useMessageSync()`. ## 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](https://ably.com/docs/ai-transport/frameworks/vercel-ai-sdk-core.md) instead. ## Read next - [Get started with Vercel AI SDK](https://ably.com/docs/ai-transport/getting-started/vercel-ai-sdk.md): build a working app. - [Vercel AI SDK Core](https://ably.com/docs/ai-transport/frameworks/vercel-ai-sdk-core.md): the server-side integration that pairs with this page. - [Vercel integration API reference](https://ably.com/docs/ai-transport/api/javascript/vercel/chat-transport.md): every option and method on the Vercel integration. - [Conversation branching](https://ably.com/docs/ai-transport/features/branching.md): one of the features `useMessageSync` brings to `useChat`. ## Related Topics - [OpenAI](https://ably.com/docs/ai-transport/frameworks/openai.md): How Ably AI Transport integrates with the OpenAI Responses API. The ResponsesCodec encodes the Responses event stream onto an Ably channel, and toResponsesInput feeds the conversation back to the model. - [Vercel AI SDK Core](https://ably.com/docs/ai-transport/frameworks/vercel-ai-sdk-core.md): How Ably AI Transport integrates with Vercel AI SDK Core (the `ai` library) on the server. Codec, streamText, and the UI message stream. - [Vercel WDK](https://ably.com/docs/ai-transport/frameworks/vercel-wdk.md): How Ably AI Transport composes with Vercel Workflow Development Kit. Open the run and each model call as their own WDK steps, WDK step ids as AI Transport step ids, retries supersede on the session, and cancels route through Ably rather than workflow signals. - [Temporal](https://ably.com/docs/ai-transport/frameworks/temporal.md): How Ably AI Transport composes with Temporal. One activity per step, activity ids as stepIds, retry supersedes on the session, cancels routed through Ably rather than Temporal signals. ## Documentation Index To discover additional Ably documentation: 1. Fetch [llms.txt](https://ably.com/llms.txt) for the canonical list of available pages. 2. Identify relevant URLs from that index. 3. Fetch target pages as needed. Avoid using assumed or outdated documentation paths.