Chat - Conversation history
Use adapter-driven conversations, thread loading, and history paging without any structural UI components.
This demo covers the full conversation lifecycle through the adapter:
- loading the conversation list on mount
- loading messages when the active conversation changes
- paging through older history
- sending follow-up messages within a loaded thread
The UI is a plain inbox-and-thread shell built only with React elements and runtime hooks.
Key concepts
Adapter methods for history
Two optional adapter methods enable conversation orchestration:
const adapter: ChatAdapter = {
async listConversations() {
// Called on mount — returns the conversation list
const res = await fetch('/api/conversations');
return { conversations: await res.json() };
},
async listMessages({ conversationId, cursor }) {
// Called when activeConversationId changes — returns thread messages
const res = await fetch(`/api/threads/${conversationId}?cursor=${cursor ?? ''}`);
const { messages, nextCursor, hasMore } = await res.json();
return { messages, cursor: nextCursor, hasMore };
},
async sendMessage(input) {
/* ... */
},
};
Cursor-based pagination
listMessages() returns a cursor and hasMore flag.
When the user scrolls to the top, call loadMoreHistory() to fetch the next page:
const { hasMoreHistory, loadMoreHistory } = useChat();
<button disabled={!hasMoreHistory} onClick={() => loadMoreHistory()}>
Load older messages
</button>;
Switching conversations
Call setActiveConversation(id) to switch threads.
The runtime automatically calls listMessages() for the new conversation:
const { setActiveConversation } = useChat();
<ConversationList onSelect={(id) => setActiveConversation(id)} />;
Key takeaways
listConversations()andlistMessages()are optional adapter methods — the runtime skips them if not implemented- History pagination is driven by cursors and the
hasMoreHistoryflag - Switching conversations triggers automatic thread loading through the adapter
- New messages can still be sent and streamed within a loaded thread
See also
- Adapters for the full adapter interface reference
- Controlled state for externally-owned conversation state
- Streaming lifecycle for send, stop, and retry flows