---
title: "useThreads"
description: "React hook for listing, managing, and syncing conversation threads with useThreads. Rename, archive, delete, and paginate threads with realtime updates via WebSocket."
---

## Overview

`useThreads` is a React hook for managing conversation threads on the Enterprise Intelligence Platform. It fetches the thread list for a given agent, keeps it synchronized in realtime via WebSocket, and exposes mutation methods for renaming, archiving, and deleting threads.

<Callout type="warn">
  Thread persistence runs on the Enterprise Intelligence Platform, which is
  accessed with a `publicLicenseKey`. That key is **not yet supported on React
  Native** (see [`CopilotKitProvider`](/reference/react-native/components/CopilotKitProvider)),
  so `useThreads` is documented here for API parity but is not yet usable on
  React Native.
</Callout>

<Callout type="info">
  Re-exported from `@copilotkit/react-core/v2`, identical to the [React (V2) `useThreads`](/reference/v2/hooks/useThreads). The only difference is the import path.
</Callout>

Threads are sorted by most recently updated first. The hook supports cursor-based pagination when a `limit` is provided.

## Signature

```tsx
import { useThreads } from "@copilotkit/react-native";

function useThreads(input: UseThreadsInput): UseThreadsResult
```

## Parameters

<PropertyReference name="input" type="UseThreadsInput">
  Configuration object for the hook.

  <PropertyReference name="agentId" type="string">
    The ID of the agent whose threads to list. Must match an agent configured in your runtime.
  </PropertyReference>

  <PropertyReference name="includeArchived" type="boolean" default="false">
    Whether to include archived threads in the list.
  </PropertyReference>

  <PropertyReference name="limit" type="number" default="undefined">
    Maximum number of threads to fetch per page. When set, enables cursor-based pagination via `fetchMoreThreads()` and `hasMoreThreads`.
  </PropertyReference>
</PropertyReference>

## Return Value

<PropertyReference name="result" type="UseThreadsResult">

  ### State

  <PropertyReference name="threads" type="Thread[]">
    Array of threads for the current user and agent, sorted by most recently updated first. Each `Thread` contains:
    - `id: string`: unique thread identifier
    - `agentId: string`: the agent this thread belongs to
    - `name: string | null`: thread name (auto-generated by the LLM on first run, or set manually via `renameThread`)
    - `archived: boolean`: whether the thread is archived
    - `createdAt: string`: ISO 8601 timestamp
    - `updatedAt: string`: ISO 8601 timestamp
    - `lastRunAt?: string`: ISO 8601 timestamp of the most recent run on this thread. Only present when the thread has had at least one run. Useful for surfacing "last activity" timing distinct from `updatedAt` (which also bumps on metadata changes like rename/archive).
  </PropertyReference>

  <PropertyReference name="isLoading" type="boolean">
    `true` while the initial thread list is being fetched.
  </PropertyReference>

  <PropertyReference name="error" type="Error | null">
    The most recent error from fetching or mutating threads, or `null` if no error has occurred.
  </PropertyReference>

  <PropertyReference name="hasMoreThreads" type="boolean">
    `true` when more threads are available beyond the current page. Only meaningful when `limit` is set.
  </PropertyReference>

  <PropertyReference name="isFetchingMoreThreads" type="boolean">
    `true` while additional threads are being fetched.
  </PropertyReference>

  ### Methods

  <PropertyReference name="fetchMoreThreads" type="() => void">
    Fetch the next page of threads. No-op if `hasMoreThreads` is `false` or a fetch is already in progress.
  </PropertyReference>

  <PropertyReference name="renameThread" type="(threadId: string, name: string) => Promise<void>">
    Rename a thread. The promise resolves when the server confirms the operation, or rejects with an `Error` on failure.
  </PropertyReference>

  <PropertyReference name="archiveThread" type="(threadId: string) => Promise<void>">
    Soft-delete a thread. The thread remains in the database with `archived: true` but is excluded from the list unless `includeArchived` is `true`. Archived threads can be restored via the `unarchived` platform event. The promise resolves on server confirmation, or rejects with an `Error` on failure. There is no built-in confirmation dialog, so implement your own if needed.
  </PropertyReference>

  <PropertyReference name="deleteThread" type="(threadId: string) => Promise<void>">
    Permanently and irreversibly delete a thread. The thread record is removed from the database entirely. The promise resolves on server confirmation, or rejects with an `Error` on failure. There is no built-in confirmation dialog, so implement your own if needed.
  </PropertyReference>
</PropertyReference>

## Usage

```tsx title="ThreadList.tsx"
import { useThreads } from "@copilotkit/react-native"; // [!code highlight]
import { FlatList, Text, TouchableOpacity, View } from "react-native";

function ThreadList() {
  const {
    threads,
    isLoading,
    renameThread,
    archiveThread,
    deleteThread,
  } = useThreads({ agentId: "my-agent" }); // [!code highlight]

  if (isLoading) {
    return (
      <View>
        <Text>Loading threads...</Text>
      </View>
    );
  }

  return (
    <FlatList
      data={threads}
      keyExtractor={(thread) => thread.id}
      renderItem={({ item: thread }) => (
        <View>
          <Text>{thread.name ?? "Untitled"}</Text>
          <TouchableOpacity onPress={() => renameThread(thread.id, "New name")}>
            <Text>Rename</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => archiveThread(thread.id)}>
            <Text>Archive</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => deleteThread(thread.id)}>
            <Text>Delete</Text>
          </TouchableOpacity>
        </View>
      )}
    />
  );
}
```

## Behavior

- On mount, fetches the thread list and establishes a realtime WebSocket subscription.
- Thread creates, renames, archives, and deletes from any client are reflected immediately without polling.
- All mutation methods use **pessimistic updates**: the UI updates only after the server confirms the operation via WebSocket, not immediately on dispatch. Promises resolve on confirmation (15-second timeout) and reject on failure.
- The `error` state updates with the most recent error from any operation.
- The `threads` array stays sorted by `updatedAt` descending (most recent first).
- New threads are **automatically named** by the LLM after their first run (a short title of 2 to 5 words). This is configurable via `generateThreadNames` on the runtime.

## Next steps

- **Understand how it works:** [How Threads & Persistence Work](/premium/threads-explained) covers the architecture, event replay model, and WebSocket sync
- **Step-by-step guide:** [Threads](/threads) walks you through setting up thread management in your app
- **Tutorial:** [Build a Multi-Conversation Chat App](/tutorials/multi-conversation-chat) is an end-to-end walkthrough building a chat app with thread history
- **React (V2) reference:** [`useThreads`](/reference/v2/hooks/useThreads), the web `useThreads` this hook mirrors
