Loading...
Loading...
Manages Tambo threads, messages, suggestions, voice input, and image attachments. Use when working with conversations, sending messages, implementing AI suggestions, adding voice input, managing multi-thread UIs, or handling image attachments with useTamboThread, useTamboSuggestions, or useTamboVoice.
npx skill4agent add tambo-ai/tambo threadsconst { thread, sendThreadMessage, isIdle } = useTamboThread();
await sendThreadMessage("Hello", { streamResponse: true });import { useTamboThread } from "@tambo-ai/react";
function Chat() {
const {
thread, // Current thread with messages
sendThreadMessage, // Send user message
isIdle, // True when not generating
generationStage, // Current stage (IDLE, STREAMING_RESPONSE, etc.)
switchCurrentThread, // Switch to different thread
inputValue, // Current input field value
setInputValue, // Update input field
} = useTamboThread();
const handleSend = async () => {
await sendThreadMessage(inputValue, { streamResponse: true });
setInputValue("");
};
return (
<div>
{thread?.messages.map((msg) => (
<div key={msg.id}>
{msg.content.map((part, i) =>
part.type === "text" ? <p key={i}>{part.text}</p> : null,
)}
{msg.renderedComponent}
</div>
))}
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={handleSend} disabled={!isIdle}>
Send
</button>
</div>
);
}| Stage | Description |
|---|---|
| Not generating |
| Selecting which component to use |
| Calling registered tools |
| Generating component props |
| Actively streaming |
| Finished successfully |
| Error occurred |
import { useTamboThread, useTamboThreadList } from "@tambo-ai/react";
function ThreadSidebar() {
const { data: threads, isPending } = useTamboThreadList();
const { thread, switchCurrentThread } = useTamboThread();
if (isPending) return <Skeleton />;
return (
<ul>
{threads?.items.map((t) => (
<li key={t.id}>
<button
onClick={() => switchCurrentThread(t.id)}
className={thread?.id === t.id ? "active" : ""}
>
{t.name || "Untitled"}
</button>
</li>
))}
</ul>
);
}import { useTamboSuggestions } from "@tambo-ai/react";
function Suggestions() {
const { suggestions, isLoading, accept, isAccepting } = useTamboSuggestions({
maxSuggestions: 3, // 1-10, default 3
});
if (isLoading) return <Skeleton />;
return (
<div className="suggestions">
{suggestions.map((s) => (
<button
key={s.id}
onClick={() => accept(s)} // Sets input value
// onClick={() => accept(s, true)} // Sets and auto-submits
disabled={isAccepting}
>
{s.title}
</button>
))}
</div>
);
}const { setCustomSuggestions } = useTamboContextAttachment();
setCustomSuggestions([
{ id: "1", title: "Edit this", detailedSuggestion: "...", messageId: "" },
{ id: "2", title: "Add feature", detailedSuggestion: "...", messageId: "" },
]);
// Clear to return to auto-generated
setCustomSuggestions(null);import { useTamboVoice } from "@tambo-ai/react";
function VoiceButton() {
const {
startRecording,
stopRecording,
isRecording,
isTranscribing,
transcript,
transcriptionError,
mediaAccessError,
} = useTamboVoice();
return (
<div>
<button onClick={isRecording ? stopRecording : startRecording}>
{isRecording ? "Stop" : "Record"}
</button>
{isTranscribing && <span>Transcribing...</span>}
{transcript && <p>{transcript}</p>}
{transcriptionError && <p className="error">{transcriptionError}</p>}
</div>
);
}| Property | Type | Description |
|---|---|---|
| | Start recording, reset transcript |
| | Stop and start transcription |
| | Currently recording |
| | Processing audio |
| | Transcribed text |
| | Transcription error |
| | Mic access error |
import { useMessageImages } from "@tambo-ai/react";
function ImageInput() {
const { images, addImage, addImages, removeImage, clearImages } =
useMessageImages();
const handleFiles = async (files: FileList) => {
await addImages(Array.from(files)); // Only valid images added
};
return (
<div>
<input
type="file"
accept="image/*"
multiple
onChange={(e) => handleFiles(e.target.files!)}
/>
{images.map((img) => (
<div key={img.id}>
<img src={img.preview} alt={img.file.name} />
<button onClick={() => removeImage(img.id)}>Remove</button>
</div>
))}
</div>
);
}| Property | Type | Description |
|---|---|---|
| | Staged images ready to send |
| | Add single image (throws if not image) |
| | Add multiple (only valid images kept) |
| | Remove by ID |
| | Remove all |
userTokenimport { TamboProvider } from "@tambo-ai/react";
function App() {
const userToken = useUserToken(); // From your auth provider (Auth0, Clerk, etc.)
return (
<TamboProvider userToken={userToken}>
<Chat />
</TamboProvider>
);
}userToken