Wire AI Transport message updates into Vercel's useChat message state. Subscribes to the transport view's update event and replaces useChat's messages with the view's authoritative list. Use this when useChat's message array needs to reflect messages from other devices, browser tabs, or observer participants on the same session.
Without useMessageSync, useChat only renders messages from its own sends. The hook bridges the gap by feeding the view's authoritative list into useChat's state.
This hook must be used within a ChatTransportProvider.
1
2
3
4
5
6
7
8
9
import { useChatTransport, useMessageSync } from '@ably/ai-transport/vercel/react';
import { useChat } from '@ai-sdk/react';
function Chat({ chatId }) {
const { chatTransport } = useChatTransport();
const { messages, setMessages, sendMessage } = useChat({ id: chatId, transport: chatTransport });
useMessageSync({ setMessages });
// messages now includes sends from other devices.
}Parameters
setMessagesrequired(updater: (prev: UIMessage[]) => UIMessage[]) => voidsetMessages updater from useChat(). Called with an updater function that replaces the previous message list with the view's authoritative list.channelNameoptionalStringChatTransportProvider to observe. Omit to use the nearest provider in the tree.skipoptionalBooleantrue, skip all subscriptions and do nothing. Use when the hook's dependencies are not yet resolved (for example, auth pending).Returns
The hook returns void. The sync is set up as a side-effect inside useEffect.
When a ChatTransport is provided (resolved from the nearest ChatTransportProvider), setMessages calls are gated during active own-turn streams. This prevents the push/replace ID mismatch in useChat's internal write function. When the stream finishes, the gate opens and an immediate sync fires to pick up any observer messages that arrived during the stream.
Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { useChatTransport, useMessageSync } from '@ably/ai-transport/vercel/react';
import { useChat } from '@ai-sdk/react';
function Chat({ chatId }) {
const { chatTransport } = useChatTransport();
const { messages, setMessages, sendMessage, stop } = useChat({
id: chatId,
transport: chatTransport,
});
useMessageSync({ setMessages });
return (
<div>
{messages.map((m) => <Message key={m.id} message={m} />)}
<Composer onSend={(text) => sendMessage({ text })} onStop={stop} />
</div>
);
}