# 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.