Skip to main content
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