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,

    // Authentication
    authState,
    isIdentified,

    // 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
messagesTamboThreadMessage[]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

Authentication

ValueTypeDescription
authStateTamboAuthStateCurrent authentication state as a discriminated union
isIdentifiedbooleanShorthand for authState.status === "identified"

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
updateThreadName(threadId: string, name: string) => Promise<void>Update a thread's display name

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,
    isDisabled,
    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
isDisabledbooleantrue when input should be disabled (pending submission or not authenticated)
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.

Auth-gating

This hook automatically disables the query until the user is identified (authState.status === "identified"). While gated, React Query keeps the query disabled/idle. You can add additional enabled logic via the options parameter — both conditions must be true for the query to run.

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.

Auth-gating

Like useTamboThread, this hook automatically disables the query until the user is identified. You can add additional enabled logic via queryOptions — both conditions must be true for the query to run.

Automatic userKey merging

You don't need to pass userKey in listOptions — the hook automatically uses the userKey from TamboProvider. If you do pass one explicitly, it takes precedence over the provider value.

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

useTamboInteractable

Manages the registry of interactable components — components already placed in your UI that the AI can update. Provides functions to add, remove, update, query, and select interactable components.

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

function InteractableManager() {
  const {
    interactableComponents,
    addInteractableComponent,
    removeInteractableComponent,
    updateInteractableComponentProps,
    getInteractableComponent,
    getInteractableComponentsByName,
    clearAllInteractableComponents,
    setInteractableState,
    getInteractableComponentState,
    setInteractableSelected,
    clearInteractableSelections,
  } = useTamboInteractable();
}

Return Values

ValueTypeDescription
interactableComponentsTamboInteractableComponent[]All registered interactable components
addInteractableComponent(component: Omit<TamboInteractableComponent, "id" | "createdAt">) => stringRegister a component, returns its generated ID
removeInteractableComponent(id: string) => voidRemove a component by ID
updateInteractableComponentProps(id: string, newProps: Record<string, unknown>) => stringPartially update a component's props
getInteractableComponent(id: string) => TamboInteractableComponent | undefinedGet a component by ID
getInteractableComponentsByName(name: string) => TamboInteractableComponent[]Get all components matching a name
clearAllInteractableComponents() => voidRemove all interactable components
setInteractableState(componentId: string, key: string, value: unknown) => voidSet a single state key on a component
getInteractableComponentState(componentId: string) => Record<string, unknown> | undefinedGet a component's state
setInteractableSelected(componentId: string, isSelected: boolean) => voidMark a component as selected for AI interaction
clearInteractableSelections() => voidClear all component selections

Most applications use withTamboInteractable() instead of calling this hook directly. The HOC handles registration and cleanup automatically.

useCurrentInteractablesSnapshot

Returns a cloned snapshot of all currently registered interactable components. The snapshot is safe to mutate without affecting internal state.

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

function InteractablesList() {
  const interactables = useCurrentInteractablesSnapshot();

  return (
    <ul>
      {interactables.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </ul>
  );
}

Returns: TamboInteractableComponent[] (shallow-cloned array with cloned props)

useTamboContextAttachment

Manages context attachments — pieces of context that are automatically included with the next user message and then cleared.

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

function FileAttacher() {
  const {
    attachments,
    addContextAttachment,
    removeContextAttachment,
    clearContextAttachments,
  } = useTamboContextAttachment();

  const attachFile = (fileContent: string, fileName: string) => {
    addContextAttachment({
      context: fileContent,
      displayName: fileName,
      type: "file",
    });
  };
}

Return Values

ValueTypeDescription
attachmentsContextAttachment[]Current context attachments
addContextAttachment(attachment: Omit<ContextAttachment, "id">) => ContextAttachmentAdd an attachment, returns it with its ID
removeContextAttachment(id: string) => voidRemove an attachment by ID
clearContextAttachments() => voidRemove all attachments

ContextAttachment

PropertyTypeDescription
idstringUnique identifier (auto-generated)
contextstringThe context value included in additionalContext
displayNamestringOptional display name for UI rendering
typestringOptional type for grouping (e.g., "file")

useTamboContextHelpers

Accesses the context helpers system for managing dynamic additional context that is included with every message.

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

function ContextManager() {
  const { addContextHelper, removeContextHelper } = useTamboContextHelpers();

  useEffect(() => {
    addContextHelper("appState", () => ({
      currentPage: window.location.pathname,
      theme: "dark",
    }));

    return () => removeContextHelper("appState");
  }, [addContextHelper, removeContextHelper]);
}

Return Values

ValueTypeDescription
getAdditionalContext() => Promise<AdditionalContext[]>Resolve all helpers into additional context entries
getContextHelpers() => ContextHelpersGet the current context helpers map
addContextHelper(name: string, helper: ContextHelperFn) => voidRegister or update a context helper by name
removeContextHelper(name: string) => voidRemove a context helper by name

useTamboCurrentMessage

Returns the current message from the TamboMessageProvider context. Use this inside components rendered via the message pipeline to access the message that triggered the component.

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

function ComponentWithMessage() {
  const message = useTamboCurrentMessage();

  return (
    <div>
      <p>Message ID: {message.id}</p>
      <p>Role: {message.role}</p>
    </div>
  );
}

Returns: TamboThreadMessage — the current message.

Throws if used outside a TamboMessageProvider (i.e., outside the message rendering pipeline).

useTamboCurrentComponent

Returns metadata about the current component from the message context. Works for both AI-generated components and interactable components wrapped with withTamboInteractable.

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

function ComponentInfo() {
  const component = useTamboCurrentComponent();

  if (!component) return null;

  return (
    <div>
      <p>Component: {component.componentName}</p>
      {component.interactableId && <p>ID: {component.interactableId}</p>}
    </div>
  );
}

Return Values

Returns TamboCurrentComponent | null (null if used outside TamboMessageProvider).

PropertyTypeDescription
componentNamestring | undefinedComponent name from the message or interactable metadata
propsRecord<string, unknown>Component props from the message content block
interactableIdstring | undefinedInteractable ID (only for withTamboInteractable components)
descriptionstring | undefinedDescription (only for withTamboInteractable components)
threadIdstring | undefinedThread ID (not available on messages directly, always undefined)

useComponentContent

Returns metadata about the current component instance from the ComponentContentProvider context. This is a lower-level hook — useTamboStreamStatus uses it internally, and useTamboComponentState uses a non-throwing variant of the same context.

Most applications should use useTamboCurrentComponent instead. Use this hook when you need the component's instance ID, thread ID, or message ID directly.

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

function DebugOverlay() {
  const { componentId, threadId, messageId, componentName } =
    useComponentContent();

  return (
    <pre>
      {componentName} ({componentId}) in thread {threadId}
    </pre>
  );
}

Return Values

ValueTypeDescription
componentIdstringUnique instance ID for the component
threadIdstringThread the component belongs to
messageIdstringMessage the component belongs to
componentNamestringRegistered component name

Throws if used outside a component rendered via ComponentRenderer.

useIsTamboTokenUpdating

Returns whether a session token exchange is in progress. Useful for showing loading indicators or disabling UI during authentication token refresh.

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

function AuthGuard({ children }: { children: React.ReactNode }) {
  const isUpdating = useIsTamboTokenUpdating();

  if (isUpdating) return <div>Authenticating...</div>;

  return <>{children}</>;
}

Returns: booleantrue while the session token is being refreshed.

Throws if used outside a TamboClientProvider.

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();