# How to Use `useTamboThreadList` and `useTamboThread` Hooks in Tambo AI

> Master `useTamboThreadList` and `useTamboThread` hooks for seamless React data fetching. Tambo AI SDK simplifies conversation thread management with loading states, cached data, and error handling.

- Repository: [tambo ai/tambo](https://github.com/tambo-ai/tambo)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The `useTamboThreadList` and `useTamboThread` hooks from the `@tambo-ai/react` SDK provide React-Query-style data fetching for conversation threads, returning loading states, cached data, and error handling while automatically managing context keys and API authentication.**

The `tambo-ai/tambo` repository provides a comprehensive React SDK that abstracts thread management into composable hooks. When building AI chat interfaces with Tambo AI, understanding how to leverage `useTamboThreadList` for fetching thread catalogs and `useTamboThread` for retrieving individual conversation histories is essential for performant, type-safe applications.

## Understanding the Tambo AI Thread Hooks Architecture

The React SDK implements a layered architecture where hooks consume context from the `TamboStreamProvider` and interact with the Tambo AI backend API at `/api/v1/threads`.

### The TamboStreamProvider Context Layer

At [`react-sdk/src/v1/providers/tambo-v1-stream-context.tsx`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/providers/tambo-v1-stream-context.tsx), the `TamboStreamProvider` maintains the current thread ID and streaming state. All thread-related hooks—including `useTamboThreadList`, `useTamboThread`, and `useThreadManagement`—must be used within this provider to access the shared context and authentication headers.

### Thread List vs. Single Thread Data Flow

The `useTamboThreadList` hook (located at [`react-sdk/src/v1/hooks/use-tambo-v1-thread-list.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1-thread-list.ts)) fetches the complete thread catalog via an internal `fetcher` utility. It automatically injects the `projectId` and `userKey` from the provider context unless explicitly overridden.

The `useTamboThread` hook (at [`react-sdk/src/v1/hooks/use-tambo-v1-thread.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1-thread.ts)) implements a caching optimization: it first attempts to extract the requested thread from the list cache populated by `useTamboThreadList`. Only if the thread is missing does it trigger a fresh fetch, minimizing redundant network requests.

## Fetching Thread Lists with useTamboThreadList

The `useTamboThreadList` hook returns a React-Query-style result object containing `data`, `isLoading`, `isError`, and `refetch` properties. This pattern enables declarative UI rendering based on fetch state.

In [`react-sdk/src/v1/hooks/use-tambo-v1-thread-list.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1-thread-list.ts), the hook constructs the API request using the context key from `TamboStreamProvider`, ensuring authenticated access to the `/api/v1/threads` endpoint.

```typescript
import { useTamboThreadList } from "@tambo-ai/react";

export function ThreadList() {
  const {
    data: threads,
    isLoading,
    isError,
    refetch,
  } = useTamboThreadList();

  if (isLoading) return <p>Loading threads…</p>;
  if (isError) return <p>Failed to load threads. <button onClick={() => refetch()}>Retry</button></p>;

  return (
    <ul>
      {threads?.threads.map((t) => (
        <li key={t.id}>{t.name}</li>
      ))}
    </ul>
  );
}

```

## Retrieving Individual Threads with useTamboThread

When you need to display a specific conversation history, `useTamboThread` accepts a `threadId` string and returns the corresponding thread object, including its message array.

As implemented in [`react-sdk/src/v1/hooks/use-tambo-v1-thread.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1-thread.ts), this hook leverages the SWR-style caching from `useTamboThreadList`. If the thread exists in the cached list data, it returns immediately without an additional network request.

```typescript
import { useTamboThread } from "@tambo-ai/react";

export function ThreadViewer({ threadId }: { threadId: string }) {
  const { data: thread, isLoading } = useTamboThread(threadId);

  if (isLoading) return <p>Loading thread…</p>;
  if (!thread) return <p>No thread found.</p>;

  return (
    <div>
      <h2>{thread.name}</h2>
      <ul>
        {thread.messages.map((msg) => (
          <li key={msg.id}>
            <strong>{msg.role}:</strong> {msg.content}
          </li>
        ))}
      </ul>
    </div>
  );
}

```

## Managing Thread State with useThreadManagement

Navigation between threads and thread creation is handled by the `useThreadManagement` hook, defined in [`react-sdk/src/v1/providers/tambo-v1-stream-context.tsx`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/providers/tambo-v1-stream-context.tsx). This hook must be used inside a `TamboStreamProvider` and provides imperative actions to modify the current thread state.

### Switching Between Existing Threads

The `switchThread(threadId)` function updates the provider's `currentThreadId` state. This change propagates to all dependent hooks, causing `useTamboThread` and message-related hooks to re-render with the new thread's data.

```typescript
import {
  useTamboThreadList,
  useThreadManagement,
} from "@tambo-ai/react";

export function ThreadSwitcher() {
  const { data } = useTamboThreadList();
  const { switchThread } = useThreadManagement();

  return (
    <select
      onChange={(e) => switchThread(e.target.value)}
      defaultValue=""
    >
      <option value="" disabled>
        Select a thread…
      </option>
      {data?.threads.map((t) => (
        <option key={t.id} value={t.id}>
          {t.name}
        </option>
      ))}
    </select>
  );
}

```

### Creating New Threads Programmatically

The `startNewThread()` function initiates a fresh conversation by calling the Tambo AI API to create a new thread, then automatically selects it as the current thread.

```typescript
import { useThreadManagement } from "@tambo-ai/react";

export function NewThreadButton() {
  const { startNewThread } = useThreadManagement();

  return <button onClick={startNewThread}>New Thread</button>;
}

```

## Complete Integration Example

Combining these hooks creates a fully functional thread management interface. The following example demonstrates the composition pattern used in the SDK's own UI components like `ThreadDropdown` and `ThreadHistory` (located in `packages/ui-registry/src/components/`).

```typescript
import {
  TamboProvider,
  TamboStreamProvider,
  useTamboThreadList,
  useTamboThread,
  useThreadManagement,
} from "@tambo-ai/react";

function ThreadManager() {
  const { data: listData, isLoading: listLoading } = useTamboThreadList();
  const { currentThreadId, switchThread, startNewThread } = useThreadManagement();
  const { data: currentThread } = useTamboThread(currentThreadId);

  if (listLoading) return <div>Loading threads...</div>;

  return (
    <div>
      <div className="thread-list">
        <button onClick={startNewThread}>+ New Thread</button>
        <ul>
          {listData?.threads.map((thread) => (
            <li 
              key={thread.id}
              onClick={() => switchThread(thread.id)}
              className={currentThreadId === thread.id ? 'active' : ''}
            >
              {thread.name}
            </li>
          ))}
        </ul>
      </div>
      
      <div className="thread-content">
        {currentThread ? (
          <div>
            <h2>{currentThread.name}</h2>
            <div className="messages">
              {currentThread.messages.map((msg) => (
                <div key={msg.id} className={`message ${msg.role}`}>
                  {msg.content}
                </div>
              ))}
            </div>
          </div>
        ) : (
          <p>Select a thread to view messages</p>
        )}
      </div>
    </div>
  );
}

export default function App() {
  return (
    <TamboProvider apiKey={process.env.TAMBO_API_KEY}>
      <TamboStreamProvider>
        <ThreadManager />
      </TamboStreamProvider>
    </TamboProvider>
  );
}

```

## Summary

- **`useTamboThreadList`** fetches the complete thread catalog from `/api/v1/threads`, returning a React-Query-style object with `data`, `isLoading`, `isError`, and `refetch` properties.

- **`useTamboThread`** retrieves a single thread by ID, intelligently caching data from `useTamboThreadList` to avoid redundant network requests when the thread already exists in the list cache.

- **`useThreadManagement`** provides imperative actions (`switchThread` and `startNewThread`) to navigate between conversations and create new ones, but requires wrapping components in `TamboStreamProvider`.

- All hooks automatically handle authentication by reading the `projectId` and `userKey` from the `TamboStreamProvider` context, eliminating manual header management.

- The hooks are implemented in `react-sdk/src/v1/hooks/` and exported through [`react-sdk/src/v1/hooks/use-tambo-v1.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1.ts) for public consumption.

## Frequently Asked Questions

### What is the difference between `useTamboThreadList` and `useTamboThread`?

`useTamboThreadList` fetches the entire catalog of threads for the current user or project from the `/api/v1/threads` endpoint, returning an array of thread metadata. In contrast, `useTamboThread` accepts a specific `threadId` parameter and returns the full thread object including its message history. Additionally, `useTamboThread` implements a caching optimization where it first checks the existing cache from `useTamboThreadList` before making a new network request.

### How does `useTamboThread` handle caching?

According to the implementation in [`react-sdk/src/v1/hooks/use-tambo-v1-thread.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1-thread.ts), the hook first attempts to extract the requested thread from the cache populated by `useTamboThreadList`. If the thread exists in the list data already loaded in memory, it returns immediately without triggering an additional HTTP request. Only when the thread is missing from the cache does it initiate a fresh fetch, minimizing network overhead and improving UI responsiveness when switching between recently loaded threads.

### Can I use these hooks outside of `TamboStreamProvider`?

No, both `useTamboThreadList` and `useTamboThread` depend on the context provided by `TamboStreamProvider` (defined in [`react-sdk/src/v1/providers/tambo-v1-stream-context.tsx`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/providers/tambo-v1-stream-context.tsx)). The provider supplies the necessary authentication context (`projectId` and `userKey`) and the current thread state. Attempting to use these hooks outside the provider will result in runtime errors due to missing context. You must wrap your component tree with both `TamboProvider` (for API configuration) and `TamboStreamProvider` (for thread state management).

### How do I create a new thread programmatically?

To create a new thread programmatically, use the `useThreadManagement` hook exported from `@tambo-ai/react`. This hook provides a `startNewThread()` function that calls the Tambo AI API to create a new thread and automatically updates the provider's `currentThreadId` to select the newly created thread. Unlike `useTamboThreadList` and `useTamboThread`, `useThreadManagement` is defined in [`react-sdk/src/v1/providers/tambo-v1-stream-context.tsx`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/providers/tambo-v1-stream-context.tsx) and provides imperative actions rather than data fetching capabilities.