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