React SDK

Agents Platform SDK: deploy customized, interactive voice agents in minutes.

Refer to the Agents Platform overview for an explanation of how Agents Platform works.

Installation

Install the package in your project through package manager.

$npm install @elevenlabs/react
># or
>yarn add @elevenlabs/react
># or
>pnpm install @elevenlabs/react

Usage

useConversation

A React hook for managing connection and audio usage for ElevenLabs Agents.

Initialize conversation

First, initialize the Conversation instance.

1import { useConversation } from '@elevenlabs/react';
2
3const conversation = useConversation();

Note that Agents Platform requires microphone access. Consider explaining and allowing access in your app’s UI before the Conversation starts.

1// call after explaining to the user why the microphone access is needed
2await navigator.mediaDevices.getUserMedia({ audio: true });

Options

The Conversation can be optionally initialized with certain parameters.

1const conversation = useConversation({
2 /* options object */
3});

Options include:

  • clientTools - object definition for client tools that can be invoked by agent. See below for details.
  • overrides - object definition conversations settings overrides. See below for details.
  • textOnly - whether the conversation should run in text-only mode. See below for details.
  • serverLocation - specify the server location ("us", "eu-residency", "in-residency", "global"). Defaults to "us".

Callbacks Overview

  • onConnect - handler called when the conversation websocket connection is established.
  • onDisconnect - handler called when the conversation websocket connection is ended.
  • onMessage - handler called when a new message is received. These can be tentative or final transcriptions of user voice, replies produced by LLM, or debug message when a debug option is enabled.
  • onError - handler called when a error is encountered.
  • onAudio - handler called when audio data is received.
  • onModeChange - handler called when the conversation mode changes (speaking/listening).
  • onStatusChange - handler called when the connection status changes.
  • onCanSendFeedbackChange - handler called when the ability to send feedback changes.
  • onDebug - handler called when debug information is available.
  • onUnhandledClientToolCall - handler called when an unhandled client tool call is encountered.
  • onVadScore - handler called when voice activity detection score changes.
Client Tools

Client tools are a way to enable agent to invoke client-side functionality. This can be used to trigger actions in the client, such as opening a modal or doing an API call on behalf of the user.

Client tools definition is an object of functions, and needs to be identical with your configuration within the ElevenLabs UI, where you can name and describe different tools, as well as set up the parameters passed by the agent.

1const conversation = useConversation({
2 clientTools: {
3 displayMessage: (parameters: { text: string }) => {
4 alert(text);
5
6 return 'Message displayed';
7 },
8 },
9});

In case function returns a value, it will be passed back to the agent as a response.

Note that the tool needs to be explicitly set to be blocking conversation in ElevenLabs UI for the agent to await and react to the response, otherwise agent assumes success and continues the conversation.

Conversation overrides

You may choose to override various settings of the conversation and set them dynamically based other user interactions.

We support overriding various settings. These settings are optional and can be used to customize the conversation experience.

The following settings are available:

1const conversation = useConversation({
2 overrides: {
3 agent: {
4 prompt: {
5 prompt: 'My custom prompt',
6 },
7 firstMessage: 'My custom first message',
8 language: 'en',
9 },
10 tts: {
11 voiceId: 'custom voice id',
12 },
13 conversation: {
14 textOnly: true,
15 },
16 },
17});
Text only

If your agent is configured to run in text-only mode, i.e. it does not send or receive audio messages, you can use this flag to use a lighter version of the conversation. In that case, the user will not be asked for microphone permissions and no audio context will be created.

1const conversation = useConversation({
2 textOnly: true,
3});
Controlled State

You can control certain aspects of the conversation state directly through the hook options:

1const [micMuted, setMicMuted] = useState(false);
2const [volume, setVolume] = useState(0.8);
3
4const conversation = useConversation({
5 micMuted,
6 volume,
7 // ... other options
8});
9
10// Update controlled state
11setMicMuted(true); // This will automatically mute the microphone
12setVolume(0.5); // This will automatically adjust the volume
Data residency

You can specify which ElevenLabs server region to connect to. For more information see the data residency guide.

1const conversation = useConversation({
2 serverLocation: 'eu-residency', // or "us", "in-residency", "global"
3});

Methods

startSession

The startConversation method kicks off the WebSocket or WebRTC connection and starts using the microphone to communicate with the ElevenLabs Agents agent. The method accepts an options object, with the signedUrl, conversationToken or agentId option being required.

The Agent ID can be acquired through ElevenLabs UI.

We also recommended passing in your own end user IDs to map conversations to your users.

1const conversation = useConversation();
2
3// For public agents, pass in the agent ID and the connection type
4const conversationId = await conversation.startSession({
5 agentId: '<your-agent-id>',
6 connectionType: 'webrtc', // either "webrtc" or "websocket"
7 userId: '<your-end-user-id>', // optional field
8});

For public agents (i.e. agents that don’t have authentication enabled), only the agentId is required.

In case the conversation requires authorization, use the REST API to generate signed links for a WebSocket connection or a conversation token for a WebRTC connection.

startSession returns a promise resolving a conversationId. The value is a globally unique conversation ID you can use to identify separate conversations.

1// Node.js server
2
3app.get("/signed-url", yourAuthMiddleware, async (req, res) => {
4 const response = await fetch(
5 `https://api.elevenlabs.seobdtools.com/v1/convai/conversation/get-signed-url?agent_id=${process.env.AGENT_ID}`,
6 {
7 headers: {
8 // Requesting a signed url requires your ElevenLabs API key
9 // Do NOT expose your API key to the client!
10 "xi-api-key": process.env.ELEVENLABS_API_KEY,
11 },
12 }
13 );
14
15 if (!response.ok) {
16 return res.status(500).send("Failed to get signed URL");
17 }
18
19 const body = await response.json();
20 res.send(body.signed_url);
21});
1// Client
2
3const response = await fetch("/signed-url", yourAuthHeaders);
4const signedUrl = await response.text();
5
6const conversation = await Conversation.startSession({
7 signedUrl,
8 connectionType: "websocket",
9});
endSession

A method to manually end the conversation. The method will disconnect and end the conversation.

1await conversation.endSession();
setVolume

Sets the output volume of the conversation. Accepts an object with a volume field between 0 and 1.

1await conversation.setVolume({ volume: 0.5 });
status

A React state containing the current status of the conversation.

1const { status } = useConversation();
2console.log(status); // "connected" or "disconnected"
isSpeaking

A React state containing information on whether the agent is currently speaking. This is useful for indicating agent status in your UI.

1const { isSpeaking } = useConversation();
2console.log(isSpeaking); // boolean
sendUserMessage

Sends a text message to the agent.

Can be used to let the user type in the message instead of using the microphone. Unlike sendContextualUpdate, this will be treated as a user message and will prompt the agent to take its turn in the conversation.

1const { sendUserMessage, sendUserActivity } = useConversation();
2const [value, setValue] = useState("");
3
4return (
5 <>
6 <input
7 value={value}
8 onChange={e => {
9 setValue(e.target.value);
10 sendUserActivity();
11 }}
12 />
13 <button
14 onClick={() => {
15 sendUserMessage(value);
16 setValue("");
17 }}
18 >
19 SEND
20 </button>
21 </>
22);
sendContextualUpdate

Sends contextual information to the agent that won’t trigger a response.

1const { sendContextualUpdate } = useConversation();
2
3sendContextualUpdate(
4 "User navigated to another page. Consider it for next response, but don't react to this contextual update."
5);
sendFeedback

Provide feedback on the conversation quality. This helps improve the agent’s performance.

1const { sendFeedback } = useConversation();
2
3sendFeedback(true); // positive feedback
4sendFeedback(false); // negative feedback
sendUserActivity

Notifies the agent about user activity to prevent interruptions. Useful for when the user is actively using the app and the agent should pause speaking, i.e. when the user is typing in a chat.

The agent will pause speaking for ~2 seconds after receiving this signal.

1const { sendUserActivity } = useConversation();
2
3// Call this when user is typing to prevent interruption
4sendUserActivity();
canSendFeedback

A React state indicating whether feedback can be submitted for the current conversation.

1const { canSendFeedback } = useConversation();
2
3// Use this to conditionally show feedback UI
4{
5 canSendFeedback && (
6 <FeedbackButtons
7 onLike={() => conversation.sendFeedback(true)}
8 onDislike={() => conversation.sendFeedback(false)}
9 />
10 );
11}
changeInputDevice

Switch the audio input device during an active voice conversation. This method is only available for voice conversations.

1// Change to a specific input device
2await conversation.changeInputDevice({
3 sampleRate: 16000,
4 format: 'pcm',
5 preferHeadphonesForIosDevices: true,
6 inputDeviceId: 'your-device-id', // Optional: specific device ID
7});
changeOutputDevice

Switch the audio output device during an active voice conversation. This method is only available for voice conversations.

1// Change to a specific output device
2await conversation.changeOutputDevice({
3 sampleRate: 16000,
4 format: 'pcm',
5 outputDeviceId: 'your-device-id', // Optional: specific device ID
6});

Device switching only works for voice conversations. If no specific deviceId is provided, the browser will use its default device selection. You can enumerate available devices using the MediaDevices.enumerateDevices() API.

getId

Returns the current conversation ID.

1const { getId } = useConversation();
2const conversationId = getId();
3console.log(conversationId); // e.g., "conv_abc123"
getInputVolume / getOutputVolume

Methods that return the current input/output volume levels (0-1 scale).

1const { getInputVolume, getOutputVolume } = useConversation();
2const inputLevel = getInputVolume();
3const outputLevel = getOutputVolume();
getInputByteFrequencyData / getOutputByteFrequencyData

Methods that return Uint8Arrays containing the current input/output frequency data. See AnalyserNode.getByteFrequencyData for more information.

1const { getInputByteFrequencyData, getOutputByteFrequencyData } = useConversation();
2const inputFrequencyData = getInputByteFrequencyData();
3const outputFrequencyData = getOutputByteFrequencyData();

These methods are only available for voice conversations. In WebRTC mode the audio is hardcoded to use pcm_48000, meaning any visualization using the returned data might show different patterns to WebSocket connections.

sendMCPToolApprovalResult

Sends approval result for MCP (Model Context Protocol) tool calls.

1const { sendMCPToolApprovalResult } = useConversation();
2
3// Approve a tool call
4sendMCPToolApprovalResult('tool_call_id_123', true);
5
6// Reject a tool call
7sendMCPToolApprovalResult('tool_call_id_123', false);