Bring your own thread list
The library keeps no threads. The thread list is the runtime’s: give your runtime a thread list adapter, then show it in the panel or in your layout.
Give the runtime a thread list
Section titled “Give the runtime a thread list”The example keeps each user’s threads in a ThreadHub agent on the Worker and feeds them to an ExternalStoreThreadListAdapter. From examples/app/app/assistant.tsx:
export const Assistant = ({ children }: { children?: ReactNode }) => { const hub = useAgent<HubState>({ agent: "ThreadHub", name: user, host }); const [picked, setPicked] = useState<string>(); const threads = useMemo( () => hub.state?.threads.map((thread) => ({ ...thread, status: "regular" as const })), [hub.state], ); const threadId = threads?.find((thread) => thread.id === picked)?.id ?? threads?.[0]?.id; if (!threadId) return null;
const select = (id: string) => startTransition(() => setPicked(id)); const threadList: ExternalStoreThreadListAdapter = { threadId, threads, onSwitchToThread: select, onSwitchToNewThread: async () => select(await hub.call<string>("createThread")), onRename: (id, title) => hub.call<void>("renameThread", [id, title]), onDelete: (id) => hub.call<void>("deleteThread", [id]), }; return ( <Suspense> <Conversation threadList={threadList}>{children}</Conversation> </Suspense> );};Conversation opens the picked thread’s chat and passes the adapter to the runtime. It also gives the runtime a fresh MessageRepository per chat, so a thread switch in place never shows the previous thread’s messages under the new one:
const repository = useMemo(() => new MessageRepository(), [chat.id]);const runtime = useAISDKRuntime(chat as Parameters<typeof useAISDKRuntime>[0], { adapters: { threadList }, unstable_messageRepositoryInstance: repository,});MessageRepository comes from @assistant-ui/core/internal, and the option is unstable. Re-check both when you upgrade assistant-ui.
Threads switch in place, so AssistedProvider stays mounted. The panel stays open and the page keeps what it lends. The Worker side, a RoutedAgents hub with createThread, renameThread and deleteThread, is in examples/agent/src/hub.ts.
Other runtimes bring their own thread list adapters. For example, useChatRuntime takes a cloud option for assistant-ui’s hosted threads.
Show it in the panel
Section titled “Show it in the panel”Set threads on a floating or sheet panel. The header gets a picker over the runtime’s threads and a new-thread button. From examples/app/app/assistant.tsx:
<AssistedPanel mode="floating" threads description={description} />Leave threads off when the runtime has no thread list. Every runtime lists one in-memory thread, so the panel cannot tell on its own.
Or place your own list
Section titled “Or place your own list”In embedded mode the panel has no header. Place assistant-ui’s ThreadList element in your layout beside it. From examples/app/app/assistant.tsx:
<aside className="w-64 shrink-0 border-e p-2"> <ThreadList /></aside>Add ThreadList with assistant-ui’s CLI:
npx assistant-ui@latest add thread-list