React
The samai-sdk/react subpath exports useAgent(client, agent): a thin hook wrapping runAgentStream(). It owns no agent-loop logic of its own, so behavior matches calling runAgentStream() directly from Node — it just gives you React state to render.
SupportChat.tsx
import { createClient, anthropic, defineAgent } from "samai-sdk";
import { useAgent } from "samai-sdk/react";
const client = createClient({ provider: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }) });
const supportAgent = defineAgent({ name: "support_agent", instructions: "...", model: "claude-sonnet-4-6" });
function SupportChat() {
const { run, isRunning, text, events, result, error } = useAgent(client, supportAgent);
return (
<div>
<button onClick={() => run("How do I add a handoff?")} disabled={isRunning}>Ask</button>
<p>{text}</p> {/* streams in live as text-delta events arrive */}
{error && <p>Error: {error.message}</p>}
{result && <p>Done — final agent: {result.finalAgent}</p>}
</div>
);
}| Field | Type | Notes |
|---|---|---|
run(input, opts?) | (string, RunAgentOptions?) => Promise<RunResult> | Starts a run; safe to call again once the previous one finishes |
isRunning | boolean | True while a run is in progress |
text | string | Accumulates live from text-delta events |
events | AgentEvent[] | Full ordered event log — tool calls, handoffs, retries/fallbacks/timeouts, guardrail trips |
result / error | RunResult | null / Error | null | Populated once the run finishes |
reset() | () => void | Resets state back to idle |
Optional peer dependency
react is an optional peer dependency — nothing else in the SDK requires it. See examples/react-usage.tsx for the full version.Voice: useVoiceAgent
samai-sdk/react-voice exports useVoiceAgent(provider, agent) — same shape as useAgent but for voice sessions. It exposes isConnected / isSpeaking / isListening / transcript plus connect() / disconnect() / sendAudio() / interrupt(), and subscribes to VoiceSession events internally. The underlying transport (pipelineVoice or openaiRealtime) is interchangeable — the hook doesn't care.
useVoiceAgent.tsx
import { useVoiceAgent } from "samai-sdk/react-voice";
import { pipelineVoice } from "samai-sdk/voice";
const { isConnected, isSpeaking, transcript, connect, disconnect, sendAudio, interrupt } =
useVoiceAgent(provider, agent);