Skip to content

ElevenAgents React SDK v1.0

ElevenAgents React SDK v1.0.0: a re-architecture of the JavaScript and React SDK with granular hooks, a unified API across web and React Native, and a stable public API.

Cover with ElevenAgents, React and SDK v1

Version 1.0.0 of the ElevenAgents JavaScript and React SDK is now available. This release is a ground-up re-architecture of the @elevenlabs/client, @elevenlabs/react, and @elevenlabs/react-native packages, focused on render performance, a unified API across web and React Native, and a stable public API. It is a breaking change, but the familiar useConversation hook is preserved, and a coding agent skill is available to automate the upgrade.

Why a new major version

Three problems drove this release.

Different APIs on web and React Native

React and React Native had different APIs, different feature sets, and different configuration options. Code and knowledge didn't transfer between platforms, and AI coding tools frequently suggested APIs that only existed on one platform. React Native also lacked WebSocket connection mode entirely.

Internally, this happened because the React Native SDK wrapped a third-party React Native SDK instead of building on @elevenlabs/client. Features and fixes had to ship twice, and the two platforms drifted further apart with each release.

Poor render performance

Any state change (status, mode, mute, volume) re-rendered every component that consumed conversation state. There was no way to subscribe to just the slice you needed. If your component only cared about connection status, it still re-rendered when the mute state changed.

This was because the SDK used a single context provider spanning all conversation state, with only coarse hooks and callbacks passed through options objects.

Fragile upgrades

Upgrading the SDK risked breaking your code. Internal classes like Input, Output, and Connection were part of the public API, and developers relied on raw browser primitives like conversation.output.gain.gain.value for volume and conversation.input.analyser for audio visualization. Any internal change could break these access patterns.

On our side, an inheritance-based class hierarchy made it difficult to fix this incrementally, so a clean break was needed.

What's new

One API across platforms

@elevenlabs/react-native now re-exports @elevenlabs/react with a thin platform strategy layer: around 40 lines of code, down from over a thousand. The same ConversationProvider, the same hooks, the same methods. Code written for the web works on React Native with only an import path change, knowledge transfers directly between platforms, and AI coding tools no longer hallucinate platform-specific APIs.

1// On React Native, change this import to '@elevenlabs/react-native'.
2import {
3 ConversationProvider,
4 useConversationControls,
5 useConversationStatus,
6} from '@elevenlabs/react';
7
8function App() {
9 return (
10 <ConversationProvider>
11 <Agent />
12 </ConversationProvider>
13 );
14}
15
16function Agent() {
17 const { startSession, endSession } = useConversationControls();
18 const { status } = useConversationStatus();
19
20 if (status === 'connected') {
21 return <button onClick={endSession}>End</button>;
22 }
23
24 return (
25 <button onClick={() => startSession({ agentId: 'agent_7101k5zvyjhmfg983brhmhkd98n6' })}>
26 Start
27 </button>
28 );
29}

Granular hooks for render performance

Six new hooks each subscribe to an individual slice of conversation state. Components only re-render when the data they consume changes.

Hook
Returns
Re-renders on
useConversationControls
Action methods (startSession, endSession, sendUserMessage, ...)
Never (stable references)
useConversationStatus
status, message
Connection status changes
useConversationInput
isMuted, setMuted
Mute state changes
useConversationMode
mode, isSpeaking, isListening
Mode changes
useConversationFeedback
canSendFeedback, sendFeedback
Feedback availability changes
useConversationClientTool
(registers a tool handler)
Never

A status indicator that previously re-rendered on every state change now only re-renders when the connection status itself changes:

1import { useConversationStatus } from '@elevenlabs/react';
2
3function StatusBadge() {
4 const { status } = useConversationStatus();
5 return <span>{status}</span>;
6}

useConversation is still there

The familiar useConversation hook still exists and returns the same shape of data: status, mode, mute state, and all control methods. It is a convenience wrapper over the granular hooks described above. Existing users can migrate to ConversationProvider + useConversation as a first step, then adopt granular hooks incrementally where render performance matters.

1import { useConversation } from '@elevenlabs/react';
2
3function Agent() {
4 const { status, isSpeaking, isMuted, setMuted, startSession, endSession } = useConversation();
5 // Same API shape as before, just requires a ConversationProvider ancestor.
6}

Dynamic client tools

useConversationClientTool lets React components register tools that the agent can invoke. Tools are tied to component lifecycle: they register on mount, unregister on unmount, and always use the latest closure value.

1import { useConversationClientTool } from '@elevenlabs/react';
2import { useState } from 'react';
3
4function MapComponent() {
5 const [location, setLocation] = useState({ lat: 0, lng: 0 });
6
7 useConversationClientTool('getLocation', () => {
8 return `${location.lat},${location.lng}`;
9 });
10
11 useConversationClientTool('setLocation', (params: { lat: number; lng: number }) => {
12 setLocation(params);
13 return 'Location updated';
14 });
15
16 return <Map center={location} />;
17}

This is useful when a tool's handler needs access to component state or props that aren't available at the provider level.

Stable API surface

Internal classes (Input, Output, wake lock) are now private. The public API exposes documented methods instead of raw browser primitives:

  • setVolume({ volume }) replaces conversation.output.gain.gain.value = v
  • getInputByteFrequencyData() replaces conversation.input.analyser.getByteFrequencyData()
  • setMicMuted(true) replaces conversation.input.setMuted(true)

This means the underlying audio implementation can be replaced (for example, swapping transport layers) without breaking user code.

Controlled state

ConversationProvider accepts isMuted and onMutedChange props for external state management. This is useful for persisting mute state across sessions or synchronizing it with application-level state.

1import { ConversationProvider } from '@elevenlabs/react';
2import { useState } from 'react';
3
4function App() {
5 const [muted, setMuted] = useState(false);
6
7 return (
8 <ConversationProvider isMuted={muted} onMutedChange={setMuted}>
9 <YourComponents />
10 </ConversationProvider>
11 );
12}

When these props are omitted, mute state is managed internally as before.

Smart connection type inference

Voice conversations now default to WebRTC and text-only conversations default to WebSocket. There is no need to set connectionType manually in most cases. If you need a specific connection type, you can still pass it explicitly.

Upgrading

This is a breaking change that requires updates to existing integrations. The key changes at a glance:

  • Conversation is now a namespace object and type alias, not a class. instanceof checks and subclassing no longer work.
  • useConversation requires a ConversationProvider ancestor.
  • Input and Output classes are replaced by documented methods on the conversation instance.
  • On React Native, ElevenLabsProvider is replaced by ConversationProvider from @elevenlabs/react-native.

For the full list of breaking changes, see the changelog.

Automated migration with your coding agent

A dedicated skill is available to automate the upgrade. The skill reads your existing integration, applies the necessary API changes, and updates imports. It handles the mechanical work of migrating to ConversationProvider, replacing removed class references, and updating method calls.

The skill is particularly useful for larger codebases where the migration touches multiple files.

1npx skills add elevenlabs/packages

Updated documentation

The SDK documentation has been updated to reflect the new API:

Getting started

Install the package for your platform:

1# React (web)
2npm install @elevenlabs/react
3
4# React Native (Expo)
5npx expo install @elevenlabs/react-native @livekit/react-native @livekit/react-native-webrtc
6
7# Vanilla JavaScript
8npm install @elevenlabs/client

@elevenlabs/react re-exports everything from @elevenlabs/client, so you do not need to install both.

Wrap your app in a ConversationProvider, use the hooks to start a session, and refer to the SDK documentation for the full API reference.

And as we mentioned in the intro, a coding agent skill is available to automate the upgrade:

1npx skills add elevenlabs/packages

Feedback

If you encounter issues or have suggestions, open an issue on GitHub. The SDK is actively maintained and we review every report.

Explore articles by the ElevenLabs team

Create with the highest quality AI Audio