ElevenLabs Conversational AI can power realtime voice experiences. orb-ui turns those sessions into
a React voice orb UI with visible listening and speaking states, audio-reactive feedback, and
accessible call controls.
Install
Install both orb-ui and the ElevenLabs client package used by the adapter:
Use the adapter
For private agents, pass the server-generated signedUrl or conversationToken option that your app already gives to Conversation.startSession().
Choose the session credential
The adapter accepts the same mutually exclusive session shapes that the ElevenLabs client uses:
agentId for a public agent, with an optional connectionType
signedUrl for a private WebSocket session
conversationToken for a private WebRTC session
Create private session credentials on your server. Do not expose a standard provider API key in
browser code. The adapter passes other supported startSession options through to the client, but
text-only sessions are intentionally outside orb-ui’s voice UI contract.
Create the adapter with a fresh credential when that credential is single-use or expires. Your
application remains responsible for authenticating and rate-limiting the server endpoint that
mints it.
ElevenLabs voice orb state mapping
The ElevenLabs adapter is responsible for normalizing provider events into orb-ui states. Keep the UI language simple:
- connecting
- listening
- thinking
- speaking
- error
ElevenLabs input levels are emitted as inputVolume while listening, and output levels are emitted as outputVolume while speaking.
The ElevenLabs mode surface does not expose a separate thinking event through this adapter, so the
normal transition is listening to speaking. If your application has an authoritative processing
state from another source, use controlled mode and include it in the signal you pass to Orb.
Session ownership
createElevenLabsAdapter owns Conversation.startSession() and endSession(). When an interactive
theme is activated, Orb calls the adapter’s start() or stop() method. The adapter installs the
required callbacks, polls both volume directions during the active turn, and clears that polling
when the session ends or the subscriber is removed.
If your product already has permanent call controls, use a passive orb and invoke the adapter from
those controls:
Theming
The circle theme works well for assistant-style voice interfaces. The bars theme is useful when you want a waveform-adjacent feel.
Clickable themes render as <button type="button"> controls, so they work with keyboard activation and accept forwarded attributes like id, data-*, and aria-label.
Controlled mode
If your app owns more of the ElevenLabs session lifecycle, pass a signal directly.
Controlled mode is also useful when the same product-level state combines ElevenLabs events with
tool calls, human handoff, or transcript activity. Normalize those sources once and keep the orb
independent of provider-specific event names.
Troubleshooting
The orb stays on connecting. Confirm that Conversation.startSession() resolves and that the
browser can reach the agent. For private agents, mint a fresh credential and verify that its
connection type matches the credential shape.
The orb moves for only one side. Input volume is read while the normalized state is listening;
output volume is read while it is speaking. Confirm that ElevenLabs mode-change callbacks are
arriving and that the browser granted microphone access.
A stopped session still updates the UI. Keep one adapter instance per active configuration and
let React remove its subscription on unmount. If a credential or agent changes, stop the old
adapter before replacing it.
Production checklist
- Private credentials are minted on an authenticated, rate-limited server endpoint.
- The adapter is created with exactly one of
agentId, signedUrl, or conversationToken.
- Microphone denial and session errors have visible recovery copy outside the orb.
- Separate call controls use
interactive={false} on the visualization.
- Start, stop, and restart are tested without leaked listeners or volume polling.
- A text status or transcript makes the conversation understandable without animation.
Last modified on July 29, 2026