Vercel AI SDK integration

Open in

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

1

2

3

4

5

6

import {
  UIMessageCodec,
  createClientTransport,
  createServerTransport,
  createChatTransport,
} from '@ably/ai-transport/vercel';

React-side hooks (useChatTransport, useMessageSync, ChatTransportProvider) live on the React hooks reference.

UIMessageCodec

A pre-built Codec<UIMessageChunk, UIMessage> 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

1

import { UIMessageCodec } from '@ably/ai-transport/vercel';

Create a Vercel client transport

function createClientTransport(options: VercelClientTransportOptions): ClientTransport<UIMessageChunk, UIMessage>

Pre-bound version of the core createClientTransport with codec: UIMessageCodec already supplied and api defaulted to /api/chat.

JavaScript

1

2

3

4

5

6

7

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

optionsrequiredVercelClientTransportOptions
Vercel client transport configuration.

Returns

ClientTransport<UIMessageChunk, UIMessage>

A ClientTransport typed for Vercel's UIMessage content. See ClientTransport for the full surface.

Create a Vercel server transport

function createServerTransport(options: VercelServerTransportOptions): ServerTransport<UIMessageChunk, UIMessage>

Pre-bound version of the core createServerTransport with codec: UIMessageCodec already supplied.

JavaScript

1

2

3

4

5

6

7

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

optionsrequiredVercelServerTransportOptions
Vercel server transport configuration.

Returns

ServerTransport<UIMessageChunk, UIMessage>

A ServerTransport typed for Vercel's UIMessage content. See ServerTransport for the full surface.

Create a chat transport

function createChatTransport(transport: ClientTransport<UIMessageChunk, UIMessage>, 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 and read the adapter via useChatTransport rather than calling this factory directly.

JavaScript

1

2

3

4

import { createClientTransport, createChatTransport } from '@ably/ai-transport/vercel';

const clientTransport = createClientTransport({ channel });
const chatTransport = createChatTransport(clientTransport);

Parameters

transportrequiredClientTransport<UIMessageChunk, UIMessage>
The underlying client transport.
chatOptionsoptionalChatTransportOptions
Options customising the chat-transport behaviour.

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<ReadableStream<UIMessageChunk>>

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<ReadableStream<UIMessageChunk> | 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<void>

Close the underlying ClientTransport, 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 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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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,
});