PAIPAI

useThreads()

List, create, rename, and delete threads.

useThreads is the sidebar. It lists saved conversations for the current identity and lets you create, rename, and delete them.

Requires Pai.Provider. Does not require ThreadProvider.

function Sidebar() {
  const threads = Assistant.useThreads();
  const client = Assistant.useClient();

  return (
    <ul>
      {threads.items.map((thread) => (
        <li key={thread.threadId}>
          <a href={`/chat/${thread.threadId}`}>{thread.title ?? "Untitled"}</a>
        </li>
      ))}
      <button
        type="button"
        onClick={() => {
          window.location.assign(`/chat/${client.newThreadId()}`);
        }}
      >
        New chat
      </button>
    </ul>
  );
}

Empty ids are fine. The server row appears on the first send.

Import

const threads = Assistant.useThreads();

Signature

function useThreads(options?: UseThreadsOptions): ThreadsController<TContract>;

Parameters

options?: UseThreadsOptions

List query plus onThreadCreated.

limit?: number

pageToken?: string

category?: string

parentThreadId?: ThreadId

onThreadCreated?: (thread, { refresh }) => void | Promise<void>

Called when a new thread appears in this runtime scope.

Returns

ThreadsController

Includes the current ThreadListResult (items, …).

hasMore: boolean

Another page is available.

loading: boolean

Initial list or a manual refresh() is in flight. Becomes true again on every refresh — unlike useChat().loading.

loadingMore: boolean

Next page is being appended.

deleting: boolean

renaming: boolean

error: Error | null

Last list or mutation error caught by the hook.

watchError: Error | null

Terminal failure from the thread-head watch.

watchStatus: WatchStatus

Head-subscription lifecycle. List reads have their own loading / error.

refresh: () => Promise<ThreadListResult>

loadMore: () => Promise<ThreadListResult | null>

create: (options?) => Thread<TContract>

Fresh local handle. The server row appears on the first send.

rename: (threadId, title) => Promise<ThreadRenameResult>

delete: (threadId) => Promise<void>

newThreadId() on useClient() is the usual “New chat” path.

Learn more

On this page