# Vercel AI SDK integration The Vercel integration provides a pre-built codec and three pre-bound factories for the Vercel AI SDK. It maps Vercel's `UIMessageChunk` events to `UIMessage` objects, so you can use AI Transport with `useChat` without writing a custom codec. #### Javascript ``` import { UIMessageCodec, createClientTransport, createServerTransport, createChatTransport, } from '@ably/ai-transport/vercel'; ``` React-side hooks (`useChatTransport`, `useMessageSync`, `ChatTransportProvider`) live on the [React hooks reference](https://ably.com/docs/ai-transport/api/react/providers.md). ## UIMessageCodec A pre-built `Codec` for the Vercel AI SDK. It handles encoding and decoding of Vercel's message types over Ably channels. You do not need to import `UIMessageCodec` directly if you use the Vercel-pre-bound transport factories or the React hooks; they bind the codec automatically. ### Javascript ``` import { UIMessageCodec } from '@ably/ai-transport/vercel'; ``` ## Create a Vercel client transport `function createClientTransport(options: VercelClientTransportOptions): ClientTransport` Pre-bound version of the core `createClientTransport` with `codec: UIMessageCodec` already supplied and `api` defaulted to `/api/chat`. ### Javascript ``` import * as Ably from 'ably'; import { createClientTransport } from '@ably/ai-transport/vercel'; const ably = new Ably.Realtime({ authUrl: '/auth' }); const channel = ably.channels.get('conversation-42'); const transport = createClientTransport({ channel }); ``` ### Parameters | Parameter | Required | Description | Type | | --- | --- | --- | --- | | options | Required | Vercel client transport configuration. |
|
| Property | Description | Type | | --- | --- | --- | | channel | The Ably channel to receive responses on and publish cancel signals to. | `Ably.RealtimeChannel` | | api | Server endpoint URL for the HTTP POST that triggers a new turn. Defaults to `/api/chat`. | String or Undefined | | clientId | The client's identity. Sent to the server in the POST body. | String or Undefined | | headers | Headers for the HTTP POST. Function form for dynamic values. | `Record` or `() => Record` or Undefined | | body | Additional body fields merged into the HTTP POST. Function form for dynamic values. | `Record` or `() => Record` or Undefined | | credentials | Fetch credentials mode for the HTTP POST. | `RequestCredentials` or Undefined | | fetch | Custom fetch implementation. Defaults to `globalThis.fetch`. | `typeof fetch` or Undefined | | messages | Initial messages to seed the conversation tree with. | `UIMessage[]` or Undefined | | logger | Logger instance for diagnostic output. | `Logger` or Undefined |
### Returns `ClientTransport` A `ClientTransport` typed for Vercel's `UIMessage` content. See [`ClientTransport`](https://ably.com/docs/ai-transport/api/javascript/client-transport.md) for the full surface. ## Create a Vercel server transport `function createServerTransport(options: VercelServerTransportOptions): ServerTransport` Pre-bound version of the core `createServerTransport` with `codec: UIMessageCodec` already supplied. ### Javascript ``` import Ably from 'ably'; import { createServerTransport } from '@ably/ai-transport/vercel'; const ably = new Ably.Realtime({ key: process.env.ABLY_API_KEY }); const channel = ably.channels.get('conversation-42'); const transport = createServerTransport({ channel }); ``` ### Parameters | Parameter | Required | Description | Type | | --- | --- | --- | --- | | options | Required | Vercel server transport configuration. |
|
| Property | Description | Type | | --- | --- | --- | | channel | The Ably channel to publish to. Must match the client's channel. | `Ably.RealtimeChannel` | | logger | Logger instance for diagnostic output. | `Logger` or Undefined | | onError | Called with non-fatal transport-level errors. | `(error: Ably.ErrorInfo) => void` or Undefined |
### Returns `ServerTransport` A `ServerTransport` typed for Vercel's `UIMessage` content. See [`ServerTransport`](https://ably.com/docs/ai-transport/api/javascript/server-transport.md) for the full surface. ## Create a chat transport `function createChatTransport(transport: ClientTransport, chatOptions?: ChatTransportOptions): ChatTransport` Create a `ChatTransport` adapter around an existing `ClientTransport`. The `ChatTransport` is the object you pass to Vercel's `useChat` as `transport`. In most cases you will use the [`ChatTransportProvider`](https://ably.com/docs/ai-transport/api/react/providers.md) and read the adapter via `useChatTransport` rather than calling this factory directly. ### Javascript ``` import { createClientTransport, createChatTransport } from '@ably/ai-transport/vercel'; const clientTransport = createClientTransport({ channel }); const chatTransport = createChatTransport(clientTransport); ``` ### Parameters | Parameter | Required | Description | Type | | --- | --- | --- | --- | | transport | Required | The underlying client transport. | `ClientTransport` | | chatOptions | Optional | Options customising the chat-transport behaviour. |
|
| Property | Description | Type | | --- | --- | --- | | prepareSendMessagesRequest | Hook to customise the HTTP POST body and headers before each send. Called with the conversation context (see
); returns the body and headers to use. Default sends all previous messages as `history`. | `(context: SendMessagesRequestContext) => { body?: Record; headers?: Record }` or Undefined |
| Property | Description | Type | | --- | --- | --- | | chatId | Chat session ID (from `useChat`'s `id`). | String or Undefined | | trigger | What triggered the request: `'submit-message'` for new messages, `'regenerate-message'` for regeneration. | `'submit-message'` or `'regenerate-message'` | | messageId | The message ID for edit or regeneration. For regeneration, the assistant message to regenerate. For edits (`submit-message` with `messageId`), the user message being replaced. Undefined when submitting a new message. | String or Undefined | | history | Previous messages in the conversation (context for the LLM). | `UIMessage[]` | | messages | The new messages being sent. Empty for regeneration. | `UIMessage[]` | | forkOf | The msg-id of the message being forked (regenerated or edited). | String or Undefined | | parent | The msg-id of the predecessor in the conversation thread. | String or Undefined |
### Returns `ChatTransport` A `ChatTransport` adapter that satisfies Vercel's `useChat({ transport })` parameter shape. ## ChatTransport The adapter object Vercel's `useChat` expects as `transport`. Has two methods, both invoked by `useChat` internally; you typically pass the adapter and never call these directly. ### Send messages `sendMessages(options: SendMessagesOptions): Promise>` Send messages and return a streaming response of `UIMessageChunk` events. Called by `useChat` when the user submits a new message or requests a regeneration. ### Reconnect to a stream `reconnectToStream(options: { chatId: string }): Promise | null>` Reconnect to an existing streaming response. Returns `null` if no active stream exists for the specified chat session. ### Close the chat transport `close(options?: CloseOptions): Promise` Close the underlying [`ClientTransport`](https://ably.com/docs/ai-transport/api/javascript/client-transport.md), releasing all resources. Delegates to `ClientTransport.close()`; pass `{ cancel }` to publish a cancel before tearing down. When the `ChatTransportProvider` owns the lifecycle, it calls this automatically on unmount. ### Streaming flag `streaming: boolean` Read-only flag indicating whether an own-turn stream is currently being consumed by `useChat`. Used internally by [`useMessageSync`](https://ably.com/docs/ai-transport/api/react/use-message-sync.md) to gate `setMessages` calls during active streams. ### Subscribe to streaming-state changes `onStreamingChange(callback: (streaming: boolean) => void): () => void` Subscribe to transitions between streaming and idle. The callback fires with `true` when an own-turn stream starts and `false` when it ends. Returns an unsubscribe function. Used by `useMessageSync` to coordinate message-state writes with the streaming gate. ## Example ### Javascript ``` import * as Ably from 'ably'; import { createClientTransport, createChatTransport } from '@ably/ai-transport/vercel'; import { useChat } from '@ai-sdk/react'; const ably = new Ably.Realtime({ authUrl: '/auth' }); const channel = ably.channels.get('conversation-42'); const clientTransport = createClientTransport({ channel }); const chatTransport = createChatTransport(clientTransport, { prepareSendMessagesRequest({ chatId, trigger, history, messages, forkOf, parent }) { return { body: { chatId, trigger, history, messages, forkOf, parent, locale: 'en-GB' }, headers: { 'x-tenant-id': tenantId }, }; }, }); // In a React component: const { messages, sendMessage, stop } = useChat({ id: 'conversation-42', transport: chatTransport, }); ``` ## Related Topics - [Client transport](https://ably.com/docs/ai-transport/api/javascript/client-transport.md): API reference for the AI Transport client transport: options, properties, methods, the View interface, and the ActiveTurn type. - [Server transport](https://ably.com/docs/ai-transport/api/javascript/server-transport.md): API reference for the AI Transport server transport: turn lifecycle, cancel routing, abort hooks, and configuration options. - [Codec](https://ably.com/docs/ai-transport/api/javascript/codec.md): API reference for the AI Transport codec interface. Build custom codecs to integrate any AI framework with Ably channels. ## 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.