React SDK
Loading...

React SDK Hooks

Complete reference for @tambo-ai/react hooks - thread management, messaging, suggestions, and component state.

The @tambo-ai/react package provides hooks for building AI-powered applications with explicit thread management and React Query integration.

useTambo

The primary hook for the React SDK. Provides access to thread state, messages, streaming status, and registry functions.

import { useTambo } from "@tambo-ai/react";

function Chat() {
  const {
    // Thread state
    thread,
    messages,
    currentThreadId,

    // Streaming status
    streamingState,
    isStreaming,
    isWaiting,
    isIdle,

    // Thread management
    initThread,
    switchThread,
    startNewThread,

    // Run control
    cancelRun,

    // Registry
    registerComponent,
    registerTool,
    registerTools,
    componentList,
    toolRegistry,

    // API client
    client,
    dispatch,
  } = useTambo();
}

Return Values

Thread State

ValueTypeDescription
threadThreadState | undefinedCurrent thread state including messages and metadata
messagesTamboMessage[]Array of messages in the current thread with computed properties
currentThreadIdstringID of the currently active thread

Streaming Status

ValueTypeDescription
streamingStateStreamingStateDetailed streaming state including status, runId, error
isStreamingbooleantrue when actively streaming a response
isWaitingbooleantrue when waiting for server response
isIdlebooleantrue when no generation is in progress

Run Control

ValueTypeDescription
cancelRun() => Promise<void>Cancel the active run. No-op if there's no active run or thread is a placeholder.

Thread Management

ValueTypeDescription
initThread(threadId: string, initialThread?: Partial<TamboThread>) => voidInitialize a thread with optional initial state
switchThread(threadId: string) => voidSwitch to a different thread by ID
startNewThread() => stringCreate a new thread and return its ID

Registry

ValueTypeDescription
registerComponent(component: TamboComponent) => voidRegister a component dynamically
registerTool(tool: TamboTool) => voidRegister a single tool
registerTools(tools: TamboTool[]) => voidRegister multiple tools
componentListComponentRegistryMap of registered components
toolRegistryMap<string, TamboTool>Map of registered tools

Example: Basic Chat

import { useTambo, useTamboThreadInput } from "@tambo-ai/react";

function ChatInterface() {
  const { messages, isStreaming, startNewThread } = useTambo();
  const { value, setValue, submit } = useTamboThreadInput();

  return (
    <div>
      <button onClick={() => startNewThread()}>New Chat</button>

      <div className="messages">
        {messages.map((msg) => (
          <MessageBubble key={msg.id} message={msg} />
        ))}
        {isStreaming && <LoadingIndicator />}
      </div>

      <input
        value={value}
        onChange={(e) => setValue(e.target.value)}
        onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && submit()}
        disabled={isStreaming}
      />
    </div>
  );
}

useTamboThreadInput

Provides shared input state management across components. Input state is shared via the TamboThreadInputProvider, allowing features like suggestions to update the input directly.

import { useTamboThreadInput } from "@tambo-ai/react";

function MessageInput() {
  const {
    value,
    setValue,
    submit,
    images,
    addImage,
    addImages,
    removeImage,
    clearImages,
    threadId,
    isPending,
    isError,
    error,
  } = useTamboThreadInput();
}

Return Values

ValueTypeDescription
valuestringCurrent input value
setValueDispatch<SetStateAction<string>>Update the input value
submit(options?: SubmitOptions) => Promise<{ threadId: string | undefined }>Submit the current input (see SubmitOptions)
imagesStagedImage[]Array of staged images
addImage(file: File) => Promise<void>Add a single image
addImages(files: File[]) => Promise<void>Add multiple images
removeImage(id: string) => voidRemove a staged image
clearImages() => voidClear all staged images
threadIdstring | undefinedCurrent thread ID
isPendingbooleantrue while submission is in progress
isErrorbooleantrue if submission failed
errorError | nullError details if submission failed

Example: Input with Images

function RichInput() {
  const { value, setValue, submit, images, addImage, removeImage, isPending } =
    useTamboThreadInput();

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const files = Array.from(e.target.files || []);
    for (const file of files) {
      await addImage(file);
    }
  };

  return (
    <div>
      <div className="staged-images">
        {images.map((img) => (
          <div key={img.id}>
            <img src={img.dataUrl} alt={img.name} />
            <button onClick={() => removeImage(img.id)}>Remove</button>
          </div>
        ))}
      </div>

      <input type="file" accept="image/*" onChange={handleFileChange} />

      <textarea
        value={value}
        onChange={(e) => setValue(e.target.value)}
        disabled={isPending}
      />

      <button onClick={() => submit()} disabled={isPending || !value.trim()}>
        Send
      </button>
    </div>
  );
}

useTamboThread

React Query hook to fetch a single thread by ID.

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

function ThreadLoader({ threadId }: { threadId: string }) {
  const { data, isLoading, isError, error } = useTamboThread(threadId);

  if (isLoading) return <Loading />;
  if (isError) return <Error message={error.message} />;

  return <ThreadView thread={data} />;
}

Parameters

ParameterTypeDescription
threadIdstringThe thread ID to fetch
optionsUseQueryOptionsOptional React Query options

Return Values

Returns a standard React Query UseQueryResult<ThreadRetrieveResponse>.

The query has a staleTime of 1000ms by default for real-time data freshness.

useTamboThreadList

React Query hook to list threads for the current user.

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

function ThreadSidebar() {
  const { data, isLoading } = useTamboThreadList();

  if (isLoading) return <Loading />;

  return (
    <ul>
      {data?.threads.map((thread) => (
        <li key={thread.id}>{thread.name || "Untitled"}</li>
      ))}
    </ul>
  );
}

Parameters

ParameterTypeDescription
listOptionsThreadListOptionsOptional filtering options
queryOptionsUseQueryOptionsOptional React Query options

ThreadListOptions

PropertyTypeDescription
userKeystringUser key (defaults to provider context)
limitnumberMaximum threads to return
cursorstringPagination cursor

Return Values

Returns a standard React Query UseQueryResult<ThreadListResponse>.

The query has a staleTime of 5000ms by default.

useTamboComponentState

Bidirectional state synchronization between component and server. Similar to React's useState, but syncs state changes with the Tambo server.

import { useTamboComponentState } from "@tambo-ai/react";

function Counter() {
  const [count, setCount, { isPending, error, flush }] = useTamboComponentState(
    "count",
    0,
  );

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => setCount((c) => c + 1)} disabled={isPending}>
        Increment
      </button>
    </div>
  );
}

Parameters

ParameterTypeDefaultDescription
keyNamestringRequiredUnique key identifying this state
initialValueSRequiredInitial state value
debounceTimenumber500Milliseconds to debounce server updates

Return Values

Returns a tuple: [currentState, setState, meta]

ValueTypeDescription
currentStateSCurrent state value
setState(newState: S | ((prev: S) => S)) => voidState setter (supports functional updates)
meta.isPendingbooleantrue while syncing with server
meta.errorError | nullError if sync failed
meta.flush() => voidImmediately flush pending updates

This hook only works within components rendered via ComponentRenderer or components that are part of the message rendering pipeline.

Example: Editable Card

function EditableCard({ title: initialTitle }: { title: string }) {
  const [title, setTitle, { isPending }] = useTamboComponentState(
    "title",
    initialTitle,
    300, // debounce 300ms
  );

  return (
    <div>
      <input
        value={title}
        onChange={(e) => setTitle(e.target.value)}
        className={isPending ? "saving" : ""}
      />
      {isPending && <span>Saving...</span>}
    </div>
  );
}

useTamboStreamStatus

Track streaming status for components rendered via ComponentRenderer. Provides both overall stream status and per-prop granularity.

Important: Props update repeatedly during streaming and may be partial. Use propStatus.<field>?.isSuccess before treating a prop as complete.

import { useTamboStreamStatus } from "@tambo-ai/react";

function MyComponent(props: MyProps) {
  const { streamStatus, propStatus } = useTamboStreamStatus<MyProps>();

  if (streamStatus.isPending) return <Skeleton />;

  return (
    <div>
      <h2 className={propStatus.title?.isStreaming ? "animate-pulse" : ""}>
        {props.title}
      </h2>
      {streamStatus.isSuccess && <p>Stream complete</p>}
    </div>
  );
}

Return Values

ValueTypeDescription
streamStatusStreamStatusOverall streaming status for the component
propStatusPartial<Record<keyof Props, PropStatus>>Per-prop streaming status. Keys are absent until the prop receives its first token. See PropStatus.

This hook only works inside components rendered via ComponentRenderer. The renderer provides the necessary context for tracking streaming state.

useTamboSuggestions

Generate and manage AI-powered message suggestions.

import { useTamboSuggestions } from "@tambo-ai/react";

function SuggestionChips() {
  const {
    suggestions,
    accept,
    generate,
    isLoading,
    isGenerating,
    isAccepting,
  } = useTamboSuggestions();

  return (
    <div>
      {suggestions.map((suggestion) => (
        <button
          key={suggestion.id}
          onClick={() => accept({ suggestion, shouldSubmit: true })}
          disabled={isAccepting}
        >
          {suggestion.text}
        </button>
      ))}

      <button onClick={() => generate()} disabled={isGenerating}>
        Refresh Suggestions
      </button>
    </div>
  );
}

Options

const result = useTamboSuggestions({
  maxSuggestions: 3, // 1-10, default 3
  autoGenerate: true, // auto-generate on mount, default true
  queryOptions: {}, // React Query options
});

Return Values

ValueTypeDescription
dataSuggestionsQueryResponse | undefinedRaw query response
suggestionsSuggestion[]Array of suggestion objects
isLoadingbooleanInitial loading state
isSuccessbooleanQuery succeeded
isErrorbooleanQuery failed
errorError | nullQuery error
isFetchingbooleanFetching (includes background refetch)
generate() => Promise<SuggestionCreateResponse | undefined>Generate new suggestions
isGeneratingbooleanGeneration in progress
generateErrorError | nullGeneration error
accept(options: AcceptSuggestionOptions) => Promise<void>Accept a suggestion
isAcceptingbooleanAccept in progress
acceptErrorError | nullAccept error
selectedSuggestionIdstring | nullCurrently selected suggestion

AcceptSuggestionOptions

PropertyTypeDescription
suggestionSuggestionThe suggestion to accept
shouldSubmitbooleanSubmit immediately after accepting

useTamboSendMessage

Low-level hook for sending messages with streaming. Most applications should use useTamboThreadInput instead.

import { useTamboSendMessage } from "@tambo-ai/react";

function CustomSendButton({ threadId }: { threadId: string }) {
  const { mutate, isPending } = useTamboSendMessage(threadId);

  const handleSend = () => {
    mutate({
      message: {
        role: "user",
        content: [{ type: "text", text: "Hello!" }],
      },
      userMessageText: "Hello!", // For optimistic UI
    });
  };

  return (
    <button onClick={handleSend} disabled={isPending}>
      Send
    </button>
  );
}

Parameters

ParameterTypeDescription
threadIdstring | undefinedThread to send to (creates new if undefined)

Return Values

Returns a React Query UseMutationResult.

Re-exported Hooks

The following hooks are re-exported from the base SDK for convenience:

useTamboClient

Access the Tambo API client directly.

import { useTamboClient } from "@tambo-ai/react";

function ApiExample() {
  const client = useTamboClient();

  const fetchData = async () => {
    const threads = await client.beta.threads.list();
    // ...
  };
}

useMessageImages

Manage staged images for message input.

import { useMessageImages } from "@tambo-ai/react";

const { images, addImage, addImages, removeImage, clearImages } =
  useMessageImages();

useTamboVoice

Record and transcribe speech.

import { useTamboVoice } from "@tambo-ai/react";

const {
  startRecording,
  stopRecording,
  isRecording,
  isTranscribing,
  transcript,
  transcriptionError,
  mediaAccessError,
} = useTamboVoice();