# ChatTransport
The Vercel entry point pre-binds the [`UIMessageCodec`](https://ably.com/docs/ai-transport/api/javascript/vercel/codec.md) and exposes a `ChatTransport` adapter that satisfies the contract Vercel AI SDK's `useChat` hook expects. Use these factories whenever you build a chat UI on top of `useChat` so you do not have to wire the codec yourself.
#### Javascript
```
import * as Ably from 'ably';
import { createClientSession, createChatTransport } from '@ably/ai-transport/vercel';
const ably = new Ably.Realtime({ authUrl: '/api/auth/token' });
const session = createClientSession({
client: ably,
channelName: 'conversation-42',
});
await session.connect();
const chatTransport = createChatTransport(session);
```
React-side wiring (`ChatTransportProvider`, `useChatTransport`, `useMessageSync`) lives at [`@ably/ai-transport/vercel/react`](https://ably.com/docs/ai-transport/api/react/vercel/use-chat-transport.md).
## Create a Vercel client session
`function createClientSession(options: VercelClientSessionOptions): ClientSession`
A pre-bound version of the core [`createClientSession`](https://ably.com/docs/ai-transport/api/javascript/core/client-session.md#constructor) with `codec: UIMessageCodec` already supplied. The `api` default is set on [`createChatTransport`](#create-chat-transport), not here.
### Javascript
```
import * as Ably from 'ably';
import { createClientSession } from '@ably/ai-transport/vercel';
const ably = new Ably.Realtime({ authUrl: '/api/auth/token' });
const session = createClientSession({
client: ably,
channelName: 'conversation-42',
clientId: 'user-abc',
});
```
### Parameters
| Parameter | Required | Description | Type |
| --- | --- | --- | --- |
| client | required | The Ably Realtime client. The caller owns its lifecycle. | `Ably.Realtime` |
| channelName | required | The channel to subscribe to and publish cancel signals on. | String |
| clientId | optional | The client's identity, used as the Ably publisher `clientId` on everything this session publishes. | String |
| messages | optional | Initial messages to seed the conversation tree with. | `UIMessage[]` |
| logger | optional | Logger instance for diagnostic output. | `Logger` |
### Returns
`ClientSession`. A client session whose codec is pre-bound to `UIMessageCodec`.
## Create a Vercel agent session
`function createAgentSession(options: VercelAgentSessionOptions): AgentSession`
A pre-bound version of the core [`createAgentSession`](https://ably.com/docs/ai-transport/api/javascript/core/agent-session.md#constructor) with `codec: UIMessageCodec` already supplied. Construct one inside your HTTP handler when the request arrives.
### Javascript
```
import * as Ably from 'ably';
import { Invocation } from '@ably/ai-transport';
import { createAgentSession } from '@ably/ai-transport/vercel';
const ably = new Ably.Realtime({ key: process.env.ABLY_API_KEY });
const invocation = Invocation.fromJSON(await req.json());
const session = createAgentSession({
client: ably,
channelName: invocation.sessionName,
});
```
### Parameters
| Parameter | Required | Description | Type |
| --- | --- | --- | --- |
| client | required | The Ably Realtime client. The caller owns its lifecycle. | `Ably.Realtime` |
| channelName | required | The channel to publish to. | String |
| logger | optional | Logger instance for diagnostic output. | `Logger` |
| onError | optional | Called with non-fatal session-level errors not scoped to any run. | `(error: ErrorInfo) => void` |
| inputEventLookupTimeoutMs | optional | How long `Run.start()` waits for the input event to arrive. Defaults to 30000. | Number |
| inputEventBufferLimit | optional | Max distinct input events that may be buffered while waiting for `Run.start()` to register a lookup listener. Defaults to 200. | Number |
| rewindWindow | optional | Channel rewind applied when the agent attaches. Passed verbatim to Ably's `params.rewind`. Defaults to `"2m"`. | String |
### Returns
`AgentSession`. An agent session whose codec is pre-bound to `UIMessageCodec`.
## Create a chat transport
`function createChatTransport(session: ClientSession, chatOptions?: ChatTransportOptions): ChatTransport`
Wrap a `ClientSession` in a `ChatTransport` adapter that satisfies Vercel AI SDK's `useChat` `transport` option. The adapter maps `useChat`'s `sendMessages` and `reconnectToStream` contract onto the session's `view.send`, `view.regenerate`, and tool-resolution paths.
### Javascript
```
import { useChat } from '@ai-sdk/react';
import { createChatTransport } from '@ably/ai-transport/vercel';
const chatTransport = createChatTransport(session, {
prepareSendMessagesRequest: ({ history }) => ({
body: { history },
}),
});
const chat = useChat({ transport: chatTransport });
```
### Parameters
| Parameter | Required | Description | Type |
| --- | --- | --- | --- |
| session | required | The core client session to wrap. | `ClientSession` |
| chatOptions | optional | Hooks for customising request construction. | |
| Property | Description | Type |
| --- | --- | --- |
| api | Endpoint the transport POSTs the invocation pointer to, to wake the agent. Defaults to `/api/chat`. | String |
| credentials | Fetch credentials mode for the invocation POST (for example `'include'`). | `RequestCredentials` |
| fetch | Custom fetch implementation for the invocation POST. Defaults to `globalThis.fetch`. | `typeof globalThis.fetch` |
| prepareSendMessagesRequest | Customise the POST body and headers before sending. Called by `sendMessages` with the conversation . The returned `body` is merged into the POST body (the run's invocation identifiers always take precedence) and `headers` are added to the request. | `(context: SendMessagesRequestContext) => { body?, headers? }` |
| Property | Description | Type |
| --- | --- | --- |
| chatId | Chat session ID (from `useChat`'s id). Optional; `undefined` when `useChat` is mounted without one. | String or Undefined |
| trigger | What triggered the request. | `'submit-message'` or `'regenerate-message'` |
| messageId | The message ID for edit or regeneration requests. | String |
| history | Previous messages in the conversation (context for the LLM). | `UIMessage[]` |
| messages | The new messages being sent. Empty for regeneration. | `UIMessage[]` |
| forkOf | The codec-message-id of the message being forked. | String |
| parent | The codec-message-id of the predecessor in the conversation thread. | String |
### Returns
[`ChatTransport`](#chat-transport). The adapter to pass to `useChat`'s `transport` option.
## ChatTransport
The transport adapter returned by [`createChatTransport`](#create-chat-transport). Structurally compatible with the AI SDK's internal `ChatTransport` interface, extended with `close()`, `streaming`, and `onStreamingChange` for coordinating with [`useMessageSync`](https://ably.com/docs/ai-transport/api/react/vercel/use-message-sync.md).
### Properties
| Property | Description | Type |
| --- | --- | --- |
| sendMessages | Send messages and return a `ReadableStream` of `UIMessageChunk` events. | `(options) => Promise>` |
| reconnectToStream | Reconnect to an existing streaming response. Returns `null` because observer mode handles in-progress streams automatically. | `(options) => Promise \| null>` |
| close | Close the underlying transport, releasing all resources. | `() => Promise` |
| streaming | Whether an own-run stream is currently being consumed by `useChat`. | Boolean |
| onStreamingChange | Subscribe to streaming state changes. Used by `useMessageSync` to gate `setMessages` calls during active streams. | `(callback: (streaming: boolean) => void) => () => void` |
## Example
End-to-end client-side wiring: open a session, wrap it in a chat transport, and hand it to `useChat`.
### Javascript
```
import * as Ably from 'ably';
import { useChat } from '@ai-sdk/react';
import { createClientSession, createChatTransport } from '@ably/ai-transport/vercel';
const ably = new Ably.Realtime({ authUrl: '/api/auth/token' });
const session = createClientSession({
client: ably,
channelName: 'conversation-42',
});
await session.connect();
const chatTransport = createChatTransport(session, {
prepareSendMessagesRequest: ({ history, messages }) => ({
body: { history, messages },
}),
});
function Chat() {
const { messages, sendMessage } = useChat({ transport: chatTransport });
return (
<>
{messages.map((m) => (
))}
sendMessage({ role: 'user', parts: [{ type: 'text', text }] })} />
>
);
}
```
## Related Topics
- [Codec](https://ably.com/docs/ai-transport/api/javascript/vercel/codec.md): API reference for UIMessageCodec, the pre-built AI Transport codec for the Vercel AI SDK.
- [Run outcome](https://ably.com/docs/ai-transport/api/javascript/vercel/run-outcome.md): API reference for vercelRunOutcome, the helper that maps a Vercel streamText finishReason and Run.pipe result to a RunEndReason or a 'suspend' sentinel.
## 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.