> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.deepgram.com/docs/browser-agent-react/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.deepgram.com/_mcp/server.
# React Hooks & Provider
> API reference for @deepgram/react — AgentProvider, connection state hooks, playback-aware mode tracking, conversation hooks, component-scoped client tools, and standalone useDeepgramAgent for simpler apps.
> **Info**
>
> Looking for pre-built UI components? See [React UI Components](/docs/browser-agent-react-ui). For the core JavaScript SDK, see [JavaScript](/docs/browser-agent-javascript).
## Installation
```shell
npm install @deepgram/react
```
> **Note**
>
> `@deepgram/react` lists `@deepgram/agents` as a dependency and re-exports the SDK types you need (`AgentSessionConfig`, `AgentSettingsObject`, `MicrophoneOptions`, and the rest), so a single `npm install @deepgram/react` is all you need for the React layer. If you want direct access to the SDK classes (`AgentSession`, `AgentMicrophone`, `AgentPlayer`), import them from `@deepgram/agents`.
## Usage
Wrap your component tree in `AgentProvider`, then use focused hooks to access the state and controls your component needs.
```tsx
import {
AgentProvider,
useAgentState,
useAgentConversation,
useAgentMode,
} from "@deepgram/react";
function App() {
return (
fetch("/api/token").then((r) => r.text()) },
agent: "YOUR_AGENT_ID",
}}
>
);
}
function VoiceAgent() {
const { state, start, stop } = useAgentState();
const { conversation } = useAgentConversation();
const { mode } = useAgentMode();
return (
Mode: {mode}
{conversation.map((msg) => (
{msg.role}: {msg.content}
))}
);
}
```
Replace `YOUR_AGENT_ID` with a [Reusable Agent Configuration](/docs/reusable-agent-configurations) UUID, or pass an inline agent config object instead. See [Agent Configuration](/docs/browser-agent-overview#agent-configuration) for both patterns.
## AgentProvider
The provider creates and manages `AgentSession`, `AgentMicrophone`, and `AgentPlayer` instances. All hooks below must be called within an `AgentProvider`.
```tsx
{children}
```
### Props
| Prop | Type | Default | Description |
| -------------------- | ----------------------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config` | `AgentSessionConfig` | required | Session configuration. See [JavaScript SDK](/docs/browser-agent-javascript) for all options. |
| `microphone` | `boolean` | `true` | Enable microphone capture. |
| `microphoneOptions` | `MicrophoneOptions` | `undefined` | Options passed to `AgentMicrophone` (sample rate, echo cancellation, noise suppression, auto gain control). See [JavaScript SDK](/docs/browser-agent-javascript#agentmicrophone). |
| `tts` | `boolean` | `true` | Enable TTS audio playback. |
| `playerSampleRate` | `number` | `24000` | Sample rate for the audio player. |
| `autoStart` | `boolean` | `false` | Connect to the agent immediately on mount. |
| `onFunctionCall` | `(fn: FunctionCallItem) => Promise \| string` | `undefined` | Default handler for agent function call requests. Dynamic tools registered with `useAgentClientTool` take priority over this prop. |
| `onError` | `(message: AgentErrorMessage) => void` | `undefined` | Handler for server-reported agent errors. |
| `onSdkError` | `(error: Error) => void` | `undefined` | Handler for SDK transport errors and automatic-start failures. |
| `onWarning` | `(message: AgentWarningMessage) => void` | `undefined` | Handler for server-reported agent warnings. |
| `onLatencyReport` | `(message: LatencyReportMessage) => void` | `undefined` | Handler for agent latency reports. |
| `onInjectionRefused` | `(message: InjectionRefusedMessage) => void` | `undefined` | Handler when the server rejects an injected message. |
| `onListenUpdated` | `(message: ListenUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updateListen()` request. |
| `onPromptUpdated` | `(message: PromptUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updatePrompt()` request. |
| `onSpeakUpdated` | `(message: SpeakUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updateSpeak()` request. |
| `onThinkUpdated` | `(message: ThinkUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updateThink()` request. |
| `onHistory` | `(message: HistoryMessage) => void` | `undefined` | Handler for conversation history received from the server. |
## Hooks
### useAgentState
Connection state and lifecycle controls.
```tsx
const {
state, // "idle" | "connecting" | "connected" | "reconnecting" | "disconnected"
isIdle, // true when state === "idle"
isConnecting, // true when state === "connecting"
isConnected, // true when state === "connected"
isReconnecting, // true when state === "reconnecting"
isDisconnected, // true when state === "disconnected"
isActive, // true when connected, connecting, or reconnecting
start, // () => Promise — connect session + open mic
stop, // () => void — disconnect + close mic
} = useAgentState();
```
### useAgentConversation
Conversation history and text input.
```tsx
const {
conversation, // ConversationEntry[]
clearConversation, // () => void
sendUserMessage, // (text: string) => void — inject a text message as the user
sendAgentMessage, // (message: string, behavior?: "default" | "queue" | "interrupt") => void
} = useAgentConversation();
```
Each `ConversationEntry` contains:
| Field | Type | Description |
| --------- | ----------------------- | -------------------------------- |
| `id` | `string` | Unique identifier for the entry. |
| `role` | `"user" \| "assistant"` | Who said it. |
| `content` | `string` | The message text. |
### useAgentMode
Tracks the agent's speaking/listening mode with playback awareness. The mode transitions from `"speaking"` to `"listening"` only after all queued audio finishes playing in the browser, not when the server sends the `AgentAudioDone` event. This prevents the UI from showing "listening" while the agent's voice is still audible.
```tsx
const {
mode, // "idle" | "listening" | "thinking" | "speaking"
isSpeaking, // true when mode === "speaking"
isListening, // true when mode === "listening"
isThinking, // true when mode === "thinking"
} = useAgentMode();
```
> **Note**
>
> The playback-aware transition is automatic. The provider measures `AgentPlayer.getRemainingPlaybackTime()` when the server signals audio-done, then delays the mode switch by that duration. No configuration needed.
### useAgentMicrophone
Microphone state, mute controls, and input volume.
```tsx
const {
micActive, // true when hardware is open
micMuted, // true when muted (stream still open, not sending audio)
setMicMuted, // (muted: boolean) => void
toggle, // () => void — toggle mute state
enabled, // false when microphone={false} on provider — mic is fully disabled
getInputVolume, // () => number — returns 0-1, call per animation frame
} = useAgentMicrophone();
```
> **Note**
>
> `getInputVolume()` reads the current microphone level without triggering a re-render. Call it inside `requestAnimationFrame` or a canvas draw loop for smooth audio visualizations.
### useAgentPlayer
Audio playback state, mute controls, and output volume.
```tsx
const {
outputMuted, // true when muted
setOutputMuted, // (muted: boolean) => void
toggle, // () => void — toggle mute state
enabled, // false when tts={false} on provider — playback is fully disabled
getOutputVolume, // () => number — returns 0-1, call per animation frame
} = useAgentPlayer();
```
### useAgentControls
Action methods only, no state. Like the other focused hooks, it consumes `AgentContext`, so its component re-renders when the provider value changes.
Use this for components that dispatch commands but do not display state, such as a toolbar or keyboard shortcut handler.
```tsx
const {
start, // () => Promise
stop, // () => void
sendUserMessage, // (text: string) => void
sendAgentMessage, // (message: string, behavior?: "default" | "queue" | "interrupt") => void
updateListen, // (listen: ListenSettings) => void
updateThink, // (think: ThinkSettings | ThinkSettings[]) => void
updateSpeak, // (speak: SpeakSettings | SpeakSettings[]) => void
updatePrompt, // (prompt: string) => void
clearConversation, // () => void
setMicMuted, // (muted: boolean) => void
setOutputMuted, // (muted: boolean) => void
} = useAgentControls();
```
```tsx
useEffect(() => {
const handleKey = (e: KeyboardEvent) => {
if (e.key === "m") setMicMuted(true);
};
window.addEventListener("keydown", handleKey);
return () => window.removeEventListener("keydown", handleKey);
}, [setMicMuted]);
```
### useAgentClientTool
Register a client-side tool handler scoped to the component lifecycle. The handler is automatically unregistered when the component unmounts, so tools only exist while the component that provides them is mounted.
```tsx
useAgentClientTool(
name: string,
handler: (fn: FunctionCallItem) => Promise | string
): void
```
Dynamic tools registered with this hook take priority over the `onFunctionCall` prop on `AgentProvider`. If no dynamic tool matches the requested function name, the provider falls back to `onFunctionCall`.
```tsx
function WeatherWidget() {
const [weather, setWeather] = useState(null);
useAgentClientTool("get_weather", async (fn) => {
const { city } = JSON.parse(fn.input);
const data = await fetchWeather(city);
setWeather(data);
return JSON.stringify(data);
});
return weather ? : null;
}
```
The handler always captures the latest closure, so referencing component state inside the handler works without stale-state issues.
```tsx
function MapComponent() {
const [location, setLocation] = useState({ lat: 0, lng: 0 });
// Always reads the current location value
useAgentClientTool("getLocation", () => {
return JSON.stringify(location);
});
useAgentClientTool("setLocation", (fn) => {
const coords = JSON.parse(fn.input);
setLocation(coords);
return JSON.stringify({ ok: true });
});
return ;
}
```
### useAgentSession
Raw escape hatch to the underlying `AgentSession` instance. Use for advanced operations not covered by other hooks, such as listening to custom events or calling lower-level session methods.
```tsx
const session = useAgentSession();
useEffect(() => {
const handler = (msg) => console.log("Agent thinking:", msg);
session.on("agent-thinking", handler);
return () => session.off("agent-thinking", handler);
}, [session]);
```
### useAgentContext
Access the full context value. Prefer the focused hooks above for a smaller, purpose-specific API surface. This hook is available when you need several unrelated values without importing multiple hooks.
```tsx
const ctx = useAgentContext();
// ctx.state, ctx.mode, ctx.conversation, ctx.micMuted, etc.
```
## Standalone Hook
For simpler apps that do not need shared state across multiple components, `useDeepgramAgent` manages the session, microphone, and player internally without requiring a provider.
```tsx
import { useDeepgramAgent } from "@deepgram/react";
function VoiceAgent() {
const {
state,
conversation,
micActive,
outputMuted,
start,
stop,
setMicMuted,
setOutputMuted,
sendUserMessage,
interrupt,
} = useDeepgramAgent({
config: {
auth: { tokenFactory: () => fetch("/api/token").then((r) => r.text()) },
agent: "YOUR_AGENT_ID",
},
micOptions: { sampleRate: 16_000 },
playerSampleRate: 24_000,
onFunctionCall: async (fn) => {
return JSON.stringify({ result: "ok" });
},
});
return (
{conversation.map((msg) => (
{msg.role}: {msg.content}
))}
);
}
```
### Options
| Option | Type | Default | Description |
| -------------------- | -------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------ |
| `config` | `AgentSessionConfig` | required | Session configuration (auth, agent ID, settings). |
| `micOptions` | `MicrophoneOptions` | `{}` | Microphone options (sample rate, echo cancellation, noise suppression, auto gain control). |
| `playerSampleRate` | `number` | `24000` | Audio player sample rate. |
| `onFunctionCall` | `(fn) => Promise \| string` | `undefined` | Handler for agent function call requests. |
| `onError` | `(message: AgentErrorMessage) => void` | `undefined` | Handler for server-reported agent errors. |
| `onSdkError` | `(error: Error) => void` | `undefined` | Handler for SDK transport errors. |
| `onWarning` | `(message: AgentWarningMessage) => void` | `undefined` | Handler for server-reported agent warnings. |
| `onLatencyReport` | `(message: LatencyReportMessage) => void` | `undefined` | Handler for agent latency reports. |
| `onInjectionRefused` | `(message: InjectionRefusedMessage) => void` | `undefined` | Handler when the server rejects an injected message. |
| `onListenUpdated` | `(message: ListenUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updateListen()` request. |
| `onPromptUpdated` | `(message: PromptUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updatePrompt()` request. |
| `onSpeakUpdated` | `(message: SpeakUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updateSpeak()` request. |
| `onThinkUpdated` | `(message: ThinkUpdatedMessage) => void` | `undefined` | Handler when the server confirms a `updateThink()` request. |
| `onHistory` | `(message: HistoryMessage) => void` | `undefined` | Handler for conversation history received from the server. |
### Return values
| Value | Type | Description |
| ------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| `state` | `AgentState` | Current connection state. |
| `mode` | `AgentMode` | Current agent mode: `"idle"`, `"listening"`, `"thinking"`, or `"speaking"`. |
| `isSpeaking` | `boolean` | Whether the agent is speaking. |
| `isListening` | `boolean` | Whether the agent is listening. |
| `isThinking` | `boolean` | Whether the agent is preparing a response. |
| `micActive` | `boolean` | Whether the microphone hardware is open. |
| `micMuted` | `boolean` | Whether the microphone is muted. |
| `outputMuted` | `boolean` | Whether agent audio output is muted. |
| `conversation` | `ConversationEntry[]` | Conversation history. |
| `start` | `() => Promise` | Connect session and open microphone. |
| `stop` | `() => void` | Disconnect session and close microphone. |
| `setMicMuted` | `(muted: boolean) => void` | Mute or unmute the microphone. |
| `setOutputMuted` | `(muted: boolean) => void` | Mute or unmute agent audio. |
| `sendUserMessage` | `(text: string) => void` | Inject a text message as the user. |
| `sendAgentMessage` | `(message: string, behavior?: AgentMessageBehavior) => void` | Inject a text message as the agent. `behavior` can be `"default"`, `"queue"`, or `"interrupt"`. |
| `updateListen` | `(listen: ListenSettings) => void` | Update speech-to-text settings during the session. |
| `updateThink` | `(think: ThinkSettings \| ThinkSettings[]) => void` | Update LLM settings during the session. |
| `updateSpeak` | `(speak: SpeakSettings \| SpeakSettings[]) => void` | Update text-to-speech settings during the session. |
| `updatePrompt` | `(prompt: string) => void` | Update the agent system prompt during the session. |
| `clearConversation` | `() => void` | Clear the local conversation history and request that the session clears its history. |
| `interrupt` | `() => void` | Interrupt agent speech immediately. |
> **Note**
>
> `useDeepgramAgent` does not support `useAgentClientTool`. Use the provider pattern if you need per-component tool registration.
> Build voice agent interfaces with React using AgentProvider and granular hooks.