useMessagesWithSeed

useMessagesWithSeed reconciles a persisted conversation seed with the live session and returns the composed conversation, oldest-first: the seed followed by the live tail the seed does not already contain. Use it directly for database-backed hydration, or use the Vercel useMessageSync, which calls it for you.

Pass the view from a resolved session. useClientSession() returns a handle whose session.view is a View.

JavaScript

1

2

3

4

5

6

7

import { useMessagesWithSeed } from '@ably/ai-transport/react';

const messages = useMessagesWithSeed({
  view: session?.view,
  seed,
  getMessageId: (message) => message.id,
});

This hook is typically used within a ClientSessionProvider, which resolves the session whose view you pass in.

The hook takes the newest seed message's id, via getMessageId, as the join point and calls View.loadUntil to page the session back until that id reappears. It then composes the seed followed by the live tail, dropping the single overlapping message at the join point. With no seed (an empty array) it surfaces the live session window unchanged.

Parameters

useMessagesWithSeed accepts a single UseMessagesWithSeedOptions<TMessage> object:

viewrequiredView<TMessage> or Undefined
The view over the live session to reconcile against, for example session.view, or undefined before the session or view resolves. The hook then surfaces the seed as-is.
seedrequiredTMessage[]
The persisted conversation, oldest-first. Compared by content, so passing a fresh array each render, for example data ?? [], is safe. An empty array is a loaded-but-empty conversation, and the hook then surfaces the live session window unchanged. While the seed is still loading, set skip instead of passing [].
getMessageIdrequired(message: TMessage) => string
Returns a message's stable domain id, the join-point key shared between your store and the session. The transport's internal codecMessageId is never persisted.
skipoptionalBoolean
Holds the reconciliation while the seed is still loading, for example during an async store fetch. When true the hook does not page the session and returns []. Clear it once the seed has loaded. Defaults to false.

Returns

TMessage[]. The composed conversation, oldest-first: the seed followed by the live tail newer than the join point. While skip is true the hook returns [].

Example

A component that fetches its seed from a store, reads the view from the resolved session, and renders the composed conversation:

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

import { useClientSession, useMessagesWithSeed } from '@ably/ai-transport/react';

function Conversation({ seed }) {
  const { session } = useClientSession();
  const messages = useMessagesWithSeed({
    view: session?.view,
    seed,
    getMessageId: (message) => message.id,
  });

  return (
    <>
      {messages.map((message) => (
        <Message key={message.id} message={message} />
      ))}
    </>
  );
}

For Vercel AI SDK applications, the pre-typed useMessagesWithSeed from @ably/ai-transport/vercel/react omits getMessageId because it keys on UIMessage.id, and useMessageSync calls it for you and syncs the composed conversation into useChat.