
eDreams ODIGEO scales agentic AI with ElevenLabs to power the future of conversational travel
Achieving double-digit improvements in resolution speed and transfer rates across five languages
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.
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.
Three problems drove this release.
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.
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.
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.
@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'. |
| 2 | import { |
| 3 | ConversationProvider, |
| 4 | useConversationControls, |
| 5 | useConversationStatus, |
| 6 | } from '@elevenlabs/react'; |
| 7 | |
| 8 | function App() { |
| 9 | return ( |
| 10 | <ConversationProvider> |
| 11 | <Agent /> |
| 12 | </ConversationProvider> |
| 13 | ); |
| 14 | } |
| 15 | |
| 16 | function 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 | } |
Six new hooks each subscribe to an individual slice of conversation state. Components only re-render when the data they consume changes.
A status indicator that previously re-rendered on every state change now only re-renders when the connection status itself changes:
| 1 | import { useConversationStatus } from '@elevenlabs/react'; |
| 2 | |
| 3 | function StatusBadge() { |
| 4 | const { status } = useConversationStatus(); |
| 5 | return <span>{status}</span>; |
| 6 | } |
useConversation is still thereThe 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.
| 1 | import { useConversation } from '@elevenlabs/react'; |
| 2 | |
| 3 | function Agent() { |
| 4 | const { status, isSpeaking, isMuted, setMuted, startSession, endSession } = useConversation(); |
| 5 | // Same API shape as before, just requires a ConversationProvider ancestor. |
| 6 | } |
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.
| 1 | import { useConversationClientTool } from '@elevenlabs/react'; |
| 2 | import { useState } from 'react'; |
| 3 | |
| 4 | function 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.
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 = vgetInputByteFrequencyData() 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.
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.
| 1 | import { ConversationProvider } from '@elevenlabs/react'; |
| 2 | import { useState } from 'react'; |
| 3 | |
| 4 | function 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.
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.
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.ElevenLabsProvider is replaced by ConversationProvider from @elevenlabs/react-native.For the full list of breaking changes, see the changelog.
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.
| 1 | npx skills add elevenlabs/packages |
The SDK documentation has been updated to reflect the new API:
Install the package for your platform:
| 1 | # React (web) |
| 2 | npm install @elevenlabs/react |
| 3 | |
| 4 | # React Native (Expo) |
| 5 | npx expo install @elevenlabs/react-native @livekit/react-native @livekit/react-native-webrtc |
| 6 | |
| 7 | # Vanilla JavaScript |
| 8 | npm 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:
| 1 | npx skills add elevenlabs/packages |
If you encounter issues or have suggestions, open an issue on GitHub. The SDK is actively maintained and we review every report.

Achieving double-digit improvements in resolution speed and transfer rates across five languages
.webp&w=3840&q=95)
ElevenLabs' integration with IBM watsonx Orchestrate will help businesses to deliver natural, multilingual conversational experiences at scale