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.

JavaScript

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.

JavaScript

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.Realtime
The Ably Realtime client. The caller owns its lifecycle.
channelNamerequiredString
The channel to subscribe to and publish cancel signals on.
clientIdoptionalString
The client's identity, used as the Ably publisher clientId on everything this session publishes.
messagesoptionalUIMessage[]
Initial messages to seed the conversation tree with.
loggeroptionalLogger
Logger instance for diagnostic output.

Returns

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.

JavaScript

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.Realtime
The Ably Realtime client. The caller owns its lifecycle.
channelNamerequiredString
The channel to publish to.
loggeroptionalLogger
Logger instance for diagnostic output.
onErroroptional(error: ErrorInfo) => void
Called with non-fatal session-level errors not scoped to any run.
inputEventLookupTimeoutMsoptionalNumber
How long Run.start() waits for the input event to arrive. Defaults to 30000.
inputEventBufferLimitoptionalNumber
Max distinct input events that may be buffered while waiting for Run.start() to register a lookup listener. Defaults to 200.
rewindWindowoptionalString
Channel rewind applied when the agent attaches. Passed verbatim to Ably's params.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): 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

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>
The core client session to wrap.
chatOptionsoptionalChatTransportOptions
Hooks for customising request construction.

Returns

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>>
Send messages and return a ReadableStream of UIMessageChunk events.
reconnectToStream(options) => Promise<ReadableStream<UIMessageChunk> | null>
Reconnect to an existing streaming response. Returns null because observer mode handles in-progress streams automatically.
close() => Promise<void>
Close the underlying transport, releasing all resources.
streamingBoolean
Whether an own-run stream is currently being consumed by useChat.
onStreamingChange(callback: (streaming: boolean) => void) => () => void
Subscribe to streaming state changes. Used by useMessageSync 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.

JavaScript

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 }] })} />
    </>
  );
}