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
| Value | Type | Description |
|---|---|---|
thread | ThreadState | undefined | Current thread state including messages and metadata |
messages | TamboMessage[] | Array of messages in the current thread with computed properties |
currentThreadId | string | ID of the currently active thread |
Streaming Status
| Value | Type | Description |
|---|---|---|
streamingState | StreamingState | Detailed streaming state including status, runId, error |
isStreaming | boolean | true when actively streaming a response |
isWaiting | boolean | true when waiting for server response |
isIdle | boolean | true when no generation is in progress |
Run Control
| Value | Type | Description |
|---|---|---|
cancelRun | () => Promise<void> | Cancel the active run. No-op if there's no active run or thread is a placeholder. |
Thread Management
| Value | Type | Description |
|---|---|---|
initThread | (threadId: string, initialThread?: Partial<TamboThread>) => void | Initialize a thread with optional initial state |
switchThread | (threadId: string) => void | Switch to a different thread by ID |
startNewThread | () => string | Create a new thread and return its ID |
Registry
| Value | Type | Description |
|---|---|---|
registerComponent | (component: TamboComponent) => void | Register a component dynamically |
registerTool | (tool: TamboTool) => void | Register a single tool |
registerTools | (tools: TamboTool[]) => void | Register multiple tools |
componentList | ComponentRegistry | Map of registered components |
toolRegistry | Map<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
| Value | Type | Description |
|---|---|---|
value | string | Current input value |
setValue | Dispatch<SetStateAction<string>> | Update the input value |
submit | (options?: SubmitOptions) => Promise<{ threadId: string | undefined }> | Submit the current input (see SubmitOptions) |
images | StagedImage[] | Array of staged images |
addImage | (file: File) => Promise<void> | Add a single image |
addImages | (files: File[]) => Promise<void> | Add multiple images |
removeImage | (id: string) => void | Remove a staged image |
clearImages | () => void | Clear all staged images |
threadId | string | undefined | Current thread ID |
isPending | boolean | true while submission is in progress |
isError | boolean | true if submission failed |
error | Error | null | Error 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
| Parameter | Type | Description |
|---|---|---|
threadId | string | The thread ID to fetch |
options | UseQueryOptions | Optional 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
| Parameter | Type | Description |
|---|---|---|
listOptions | ThreadListOptions | Optional filtering options |
queryOptions | UseQueryOptions | Optional React Query options |
ThreadListOptions
| Property | Type | Description |
|---|---|---|
userKey | string | User key (defaults to provider context) |
limit | number | Maximum threads to return |
cursor | string | Pagination 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
| Parameter | Type | Default | Description |
|---|---|---|---|
keyName | string | Required | Unique key identifying this state |
initialValue | S | Required | Initial state value |
debounceTime | number | 500 | Milliseconds to debounce server updates |
Return Values
Returns a tuple: [currentState, setState, meta]
| Value | Type | Description |
|---|---|---|
currentState | S | Current state value |
setState | (newState: S | ((prev: S) => S)) => void | State setter (supports functional updates) |
meta.isPending | boolean | true while syncing with server |
meta.error | Error | null | Error if sync failed |
meta.flush | () => void | Immediately 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
| Value | Type | Description |
|---|---|---|
streamStatus | StreamStatus | Overall streaming status for the component |
propStatus | Partial<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
| Value | Type | Description |
|---|---|---|
data | SuggestionsQueryResponse | undefined | Raw query response |
suggestions | Suggestion[] | Array of suggestion objects |
isLoading | boolean | Initial loading state |
isSuccess | boolean | Query succeeded |
isError | boolean | Query failed |
error | Error | null | Query error |
isFetching | boolean | Fetching (includes background refetch) |
generate | () => Promise<SuggestionCreateResponse | undefined> | Generate new suggestions |
isGenerating | boolean | Generation in progress |
generateError | Error | null | Generation error |
accept | (options: AcceptSuggestionOptions) => Promise<void> | Accept a suggestion |
isAccepting | boolean | Accept in progress |
acceptError | Error | null | Accept error |
selectedSuggestionId | string | null | Currently selected suggestion |
AcceptSuggestionOptions
| Property | Type | Description |
|---|---|---|
suggestion | Suggestion | The suggestion to accept |
shouldSubmit | boolean | Submit 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
| Parameter | Type | Description |
|---|---|---|
threadId | string | undefined | Thread 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();