ChatTransport
The Vercel entry point pre-binds the UIMessageCodec 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
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.
Create a Vercel client session
function createClientSession(options: VercelClientSessionOptions): ClientSession<VercelInput, VercelOutput, VercelProjection, UIMessage>A pre-bound version of the core createClientSession with codec: UIMessageCodec already supplied. The api default is set on createChatTransport, not here.
1
2
3
4
5
6
7
8
9
10
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
clientrequiredAbly.RealtimechannelNamerequiredStringclientIdoptionalStringclientId on everything this session publishes.messagesoptionalUIMessage[]loggeroptionalLoggerReturns
ClientSession<VercelInput, VercelOutput, VercelProjection, UIMessage>. A client session whose codec is pre-bound to UIMessageCodec.
Create a Vercel agent session
function createAgentSession(options: VercelAgentSessionOptions): AgentSession<VercelOutput, VercelProjection, UIMessage>A pre-bound version of the core createAgentSession with codec: UIMessageCodec already supplied. Construct one inside your HTTP handler when the request arrives.
1
2
3
4
5
6
7
8
9
10
11
12
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
clientrequiredAbly.RealtimechannelNamerequiredStringloggeroptionalLoggeronErroroptional(error: ErrorInfo) => voidinputEventLookupTimeoutMsoptionalNumberRun.start() waits for the input event to arrive. Defaults to 30000.inputEventBufferLimitoptionalNumberRun.start() to register a lookup listener. Defaults to 200.rewindWindowoptionalStringparams.rewind. Defaults to "2m".Returns
AgentSession<VercelOutput, VercelProjection, UIMessage>. An agent session whose codec is pre-bound to UIMessageCodec.
Create a chat transport
function createChatTransport(session: ClientSession<VercelInput, VercelOutput, VercelProjection, UIMessage>, chatOptions?: ChatTransportOptions): ChatTransportWrap 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.
1
2
3
4
5
6
7
8
9
10
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
sessionrequiredClientSession<VercelInput, VercelOutput, VercelProjection, UIMessage>chatOptionsoptionalChatTransportOptionsReturns
ChatTransport. The adapter to pass to useChat's transport option.
ChatTransport
The transport adapter returned by createChatTransport. Structurally compatible with the AI SDK's internal ChatTransport<UIMessage> interface, extended with close(), streaming, and onStreamingChange for coordinating with useMessageSync.
Properties
sendMessages(options) => Promise<ReadableStream<UIMessageChunk>>ReadableStream of UIMessageChunk events.reconnectToStream(options) => Promise<ReadableStream<UIMessageChunk> | null>null because observer mode handles in-progress streams automatically.close() => Promise<void>streamingBooleanuseChat.onStreamingChange(callback: (streaming: boolean) => void) => () => voiduseMessageSync to gate setMessages calls during active streams.Example
End-to-end client-side wiring: open a session, wrap it in a chat transport, and hand it to useChat.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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) => (
<Message key={m.id} message={m} />
))}
<Composer onSubmit={(text) => sendMessage({ role: 'user', parts: [{ type: 'text', text }] })} />
</>
);
}