@elevenlabs/client
1.30.0 · 21 Oct 2026MIT696k / weekRepositoryHomepagenpmAtom feed
84 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
- 1.x · latest line
1.30.0
21 Oct 20263855a41: Add an opt-in
stripAudioTagssession option that removes expressive audio tags such as[laughs]from agent messages passed toonMessageandonAgentResponseCorrection, and export thestripAudioTagshelper. Stripped text no longer lines up character-for-character withonAudioAlignmenttimings, so leave the option off if you rely on them.
1.28.0
13 Oct 2026bac5c96: Add the experimental
persistentSessionsession option for resumable text conversations over WebSocket, and theonConversationHistorycallback for the transcript rows the server replays on resume. WebSocket sessions now also emitonConversationMetadata.
Minor Changes
bac5c96: Add the experimental
persistentSessionsession option for resumable text conversations over WebSocket, and theonConversationHistorycallback for the transcript rows the server replays on resume. WebSocket sessions now also emitonConversationMetadata.
1.27.0
6 Oct 2026050aeea: Add a
previousTextoption toScribe.connect()anduseScribe()in microphone mode. It is sent with the first microphone audio chunk to give the model context, such as existing document text, for casing, punctuation and sentence continuation.7f316ec: Pass
libsampleratePathtoMediaDeviceOutputso output resampling uses the custom libsamplerate bundle path, matchingMediaDeviceInput.
1.26.0
29 Sep 202633a5042: Add the
transcriptEditoption toScribe.connect()and dispatch the newedited_transcriptserver message:32358cc: Export the
MessagePayloadtype from the package root so consumers can typeonMessagehandlers.e2d1ac7: Expose stable response IDs for agent messages and use them to prevent a reply
from rendering twice when it is resent during a turn, while retaining
compatibility with older orchestrators.
Minor Changes
33a5042: Add the
transcriptEditoption toScribe.connect()and dispatch the newedited_transcriptserver message:transcriptEdit: a natural-language instruction applied to each committed transcript (max 2000 characters), sent as thetranscript_editquery param. Cannot be combined withentityDetection.edited_transcript(RealtimeEvents.EDITED_TRANSCRIPT), carrying the committedtextand itsedited_text(EditedTranscriptMessage).edited_textequalstextwhen the instruction changed nothing.useScribe()accepts the sametranscriptEditoption, exposes anonEditedTranscriptcallback and attaches the edited text to the matching entry incommittedTranscriptsaseditedText.
Patch Changes
1.24.0
4 Sep 2026afd2170: Forward the optional
attachmentsfield (url, name, mime_type) from theagent_responseclient event into theonMessagepayload, so consumers can render files attached to agent messages, e.g. relayed from a human agent reply.aad288c: Add an optional
webRtc.singlePeerConnectionsession option for WebRTC connections. Set it tofalseto force LiveKit's dual peer connection path, which restores the microphone request timing used before livekit-client began defaulting to the v1 join protocol. Leaving it unset keeps livekit-client's own default.
Minor Changes
afd2170: Forward the optional
attachmentsfield (url, name, mime_type) from theagent_responseclient event into theonMessagepayload, so consumers can render files attached to agent messages, e.g. relayed from a human agent reply.aad288c: Add an optional
webRtc.singlePeerConnectionsession option for WebRTC connections. Set it tofalseto force LiveKit's dual peer connection path, which restores the microphone request timing used before livekit-client began defaulting to the v1 join protocol. Leaving it unset keeps livekit-client's own default.
1.22.0
25 Aug 2026b60d460: Draw rich content alongside the first message, and echo button taps back to the
server.A
first_message_rich_contententry on the widget config is painted with the
first message before any connection exists, so a text-only widget shows its
buttons on a cold start. Tapping one starts the conversation with that button's
message, the same way typing into the input does — previously a button was
disabled until connected, which left a first-message button waiting for the
session it would itself begin.A row the customer has already answered is retired rather than left sitting in
the transcript. Whether a component does this is per-component, so display
components can later stay and merely de-emphasise instead of disappearing.sendUserMessageaccepts an optional attribution (richContentId) that rides
theuser_messageevent asrich_content_id; the widget sends it automatically
when a button is tapped, on both the mid-conversation and conversation-starting
paths. It names the row the button belonged to rather than the button itself
given the row, the message text says which button was pressed. Purely additive:
servers that predate the field ignore it, and the message text alone remains
what the agent acts on.be9cb0c: Add support for the
external_agent_disconnectedclient event. The client SDK exposes a newonExternalAgentDisconnectedcallback, and the widget leaves external-agent mode (and clears the typing indicator) when the external human agent disconnects and the AI agent resumes control.dce9815: Add an
onMCPToolApprovalRequesthandler option, which decides MCP tool calls that arrive in theawaiting_approvalstate and sends the approval result for you. Eachtool_call_idis answered at most once; a handler that rejects or resolves to a non-boolean is reported throughonErrorand denied, and a decision that arrives after the call leftawaiting_approvalor the session ended is dropped rather than sent. The handler receives anAbortSignalso approval UI can dismiss itself when that happens.
Minor Changes
b60d460: Draw rich content alongside the first message, and echo button taps back to the
server.A
first_message_rich_contententry on the widget config is painted with the
first message before any connection exists, so a text-only widget shows its
buttons on a cold start. Tapping one starts the conversation with that button's
message, the same way typing into the input does — previously a button was
disabled until connected, which left a first-message button waiting for the
session it would itself begin.A row the customer has already answered is retired rather than left sitting in
the transcript. Whether a component does this is per-component, so display
components can later stay and merely de-emphasise instead of disappearing.sendUserMessageaccepts an optional attribution (richContentId) that rides
theuser_messageevent asrich_content_id; the widget sends it automatically
when a button is tapped, on both the mid-conversation and conversation-starting
paths. It names the row the button belonged to rather than the button itself
given the row, the message text says which button was pressed. Purely additive:
servers that predate the field ignore it, and the message text alone remains
what the agent acts on.be9cb0c: Add support for the
external_agent_disconnectedclient event. The client SDK exposes a newonExternalAgentDisconnectedcallback, and the widget leaves external-agent mode (and clears the typing indicator) when the external human agent disconnects and the AI agent resumes control.dce9815: Add an
onMCPToolApprovalRequesthandler option, which decides MCP tool calls that arrive in theawaiting_approvalstate and sends the approval result for you. Eachtool_call_idis answered at most once; a handler that rejects or resolves to a non-boolean is reported throughonErrorand denied, and a decision that arrives after the call leftawaiting_approvalor the session ended is dropped rather than sent. The handler receives anAbortSignalso approval UI can dismiss itself when that happens.
Patch Changes
ce34dbc: Publish the configured
inputDeviceIdwhen a WebRTC session starts, instead of the browser's default microphone. The mic was enabled with LiveKit'ssetMicrophoneEnabled(true), which always captures the default device, so the selected device only drove the local level meter while the agent received a wrong or silent track.changeInputDevicenow also acquires the new track before stopping the old one, so a failed re-acquire leaves the current microphone live instead of tearing it down.ce34dbc: Keep a muted WebRTC session muted across an input device change.
changeInputDevicepublished the newly captured track without reapplying the session's mute state, so a user who switched microphones while muted kept sending audio to the agent whileisMuted()and the volume meter still reported muted. The new track is now muted before it is published.79a9d4f: Fail WebRTC session setup when the conversation initiation payload cannot be
published, instead of resolving onto a session the server never initialized.WebRTCConnection.create()sentconversation_initiation_client_datathrough
the same best-effort path as ordinary messages, which returns early when the
room is no longer connected and swallows apublishData()rejection. Setup
could therefore succeed, andonConnectfire, while the room and microphone
stayed live for a conversation that was never initialized. The mandatory
initiation send now surfaces those failures so the existingcreate()error
path disconnects the room and reports the failure to the caller. Mid-session
sends remain best effort.
1.21.0
19 Aug 2026eea19d2: Add support for the
context_usageserver event via a newonContextUsagecallback. The event is emitted after each completed agent turn and reports{ event_id, model, context_tokens, context_limit_tokens }, wherecontext_tokensis the prompt size of the turn's last LLM generation andcontext_limit_tokensis that model's maximum context window — useful for surfacing how close a long conversation is to the context limit.e3d1c40: Resolve React Native via the
react-nativeexport condition instead of sniffing globals, and let platform entry points inject the setup guidance shown when nothing is registered.
Minor Changes
eea19d2: Add support for the
context_usageserver event via a newonContextUsagecallback. The event is emitted after each completed agent turn and reports{ event_id, model, context_tokens, context_limit_tokens }, wherecontext_tokensis the prompt size of the turn's last LLM generation andcontext_limit_tokensis that model's maximum context window — useful for surfacing how close a long conversation is to the context limit.
Patch Changes
e3d1c40: Resolve React Native via the
react-nativeexport condition instead of sniffing globals, and let platform entry points inject the setup guidance shown when nothing is registered.
1.19.1
17 Aug 2026a82a0c5: Point React Native users at
@elevenlabs/react-nativewhen no voice session setup strategy is registered, instead of suggesting the browser entry point.118fd04: Pass
workletPathsthrough on the WebRTC connection path, so self-hosted AudioWorklet files are used for output capture instead of falling back toblob:/data:URLs under a strict CSP.f4c5588: Key the worklet module cache by the requested source as well as the worklet name, so a self-hosted
workletPathsentry is no longer served an inlinedblob:URL cached by an earlier load.
1.19.0
17 Aug 2026880edd2: Expose missing realtime speech-to-text options on
Scribe.connect(), matching elevenlabs-js#436:New server messages are now dispatched instead of being dropped:
Also fixes
vadSilenceThresholdSecs,minSpeechDurationMs, andminSilenceDurationMslower-bound validation to treat the bound as inclusive, matching the API (e.g.vadSilenceThresholdSecs: 0.3is now accepted instead of being rejected client-side).The
scribe.asyncapi.yamlschema (and the generatedWord/CommittedTranscriptWithTimestampsMessage/FinalTranscriptWithTimestampsMessagetypes) was cross-checked against the live contract athttps://api.elevenlabs.io/speech-to-text-asyncapi.yml. Thewordsshape is identical betweencommitted_transcript_with_timestampsandfinal_transcript_with_timestampson that contract (both support"audio_event", per-character timings, andchannel_index), so both messages now share a singleWordtype instead of the narrower shapecommitted_transcript_with_timestampspreviously used.Configalso gainedtimestamps_granularityandmax_tokens_to_recomputeto match the session config the server echoes back.@elevenlabs/react'suseScribe().committedTranscripts.words(WordTimestamp) is updated to match:typenow includes"audio_event",charactersis nowWordTimestampCharacter(each with its ownstart/end) instead ofstring, and achannel_indexfield was added.a068144: Fix a microphone-setup failure wedging
useScribe, so a denied or dismissed
permission prompt can be retried without remounting.A microphone-mode session whose
getUserMediacall rejects can never send
audio, but the socket was left open holding that session.useScribekept its
connection ref, and every laterconnect()short-circuited on"Already connected". The failed setup now closes the connection, which releases the
stranded socket and lets the hook's existing close handling clear the ref.
onErrorstill fires first; the session then ends asdisconnectedwith the
error preserved.The hook's close handler also nulled its ref for whichever connection reported
a close, so a late close from a replaced socket tore down the session that had
replaced it — the race a consumer hit when working around the above with
disconnect-then-reconnect. A close is now ignored when a newer connection owns
the ref, while an explicitdisconnect()still reports normally.
Minor Changes
880edd2: Expose missing realtime speech-to-text options on
Scribe.connect(), matching elevenlabs-js#436:secondaryLanguages: additional language codes that may be present in the audio, sent as repeatedsecondary_languagesquery params.entityDetection: detect entities (PII, PHI, PCI, offensive language, or specific types) on committed transcripts. Accepts a single value or a list.filterBackgroundAudio: enable background speech filtering to reduce false activations from nearby conversations and ambient noise.
New server messages are now dispatched instead of being dropped:
final_transcriptandfinal_transcript_with_timestamps(RealtimeEvents.FINAL_TRANSCRIPT/FINAL_TRANSCRIPT_WITH_TIMESTAMPS)committed_transcript_entities, carryingDetectedEntity(RealtimeEvents.COMMITTED_TRANSCRIPT_ENTITIES)invalid_request, sent when the server rejects the connection parameters (RealtimeEvents.INVALID_REQUEST), emitted alongside the genericERRORevent
Also fixes
vadSilenceThresholdSecs,minSpeechDurationMs, andminSilenceDurationMslower-bound validation to treat the bound as inclusive, matching the API (e.g.vadSilenceThresholdSecs: 0.3is now accepted instead of being rejected client-side).The
scribe.asyncapi.yamlschema (and the generatedWord/CommittedTranscriptWithTimestampsMessage/FinalTranscriptWithTimestampsMessagetypes) was cross-checked against the live contract athttps://api.elevenlabs.io/speech-to-text-asyncapi.yml. Thewordsshape is identical betweencommitted_transcript_with_timestampsandfinal_transcript_with_timestampson that contract (both support"audio_event", per-character timings, andchannel_index), so both messages now share a singleWordtype instead of the narrower shapecommitted_transcript_with_timestampspreviously used.Configalso gainedtimestamps_granularityandmax_tokens_to_recomputeto match the session config the server echoes back.@elevenlabs/react'suseScribe().committedTranscripts.words(WordTimestamp) is updated to match:typenow includes"audio_event",charactersis nowWordTimestampCharacter(each with its ownstart/end) instead ofstring, and achannel_indexfield was added.
Patch Changes
a068144: Fix a microphone-setup failure wedging
useScribe, so a denied or dismissed
permission prompt can be retried without remounting.A microphone-mode session whose
getUserMediacall rejects can never send
audio, but the socket was left open holding that session.useScribekept its
connection ref, and every laterconnect()short-circuited on"Already connected". The failed setup now closes the connection, which releases the
stranded socket and lets the hook's existing close handling clear the ref.
onErrorstill fires first; the session then ends asdisconnectedwith the
error preserved.The hook's close handler also nulled its ref for whichever connection reported
a close, so a late close from a replaced socket tore down the session that had
replaced it — the race a consumer hit when working around the above with
disconnect-then-reconnect. A close is now ignored when a newer connection owns
the ref, while an explicitdisconnect()still reports normally.
1.18.0
14 Aug 202693cf08c: Add the experimental
rich_contentevent types and anonRichContentcallback,
called when the agent sends a component for the client to display, such as an
item card. The callback receives{ rich_content_id, component, props, event_id }
and nothing is sent back, so the agent's turn does not wait on the client.This backs the embedded widget, which is the only client the server offers
components to today, so the callback does not fire for other consumers. Treatpropsas agent-authored and untrusted when rendering it into a document.1a1f440: Add
workletPaths.scribeAudioProcessortoScribe.connect({ microphone })so the Scribe audio worklet can be self-hosted, matching the existingConversationworkletPathsoption. This lets strict CSPs (script-src/script-src-elemwithoutblob:/data:) load the worklet from a same-origin URL instead of falling back to a blob or data URL.The generated worklet processors (including
scribeAudioProcessor.js) are now also published as static assets under@elevenlabs/client/worklets/*, so bundlers can copy them into your own static assets and serve them underscript-src 'self'.fb06e12: Add self-hosted orchestrator session support. Passing
orchestratorConfigtoConversation.startSessionroutes the conversation WebSocket to a self-hosted (private deployment) orchestrator and sends the agent configuration at connection time, mirroring the Python SDK'sOnPremInitiationData.
Minor Changes
93cf08c: Add the experimental
rich_contentevent types and anonRichContentcallback,
called when the agent sends a component for the client to display, such as an
item card. The callback receives{ rich_content_id, component, props, event_id }
and nothing is sent back, so the agent's turn does not wait on the client.This backs the embedded widget, which is the only client the server offers
components to today, so the callback does not fire for other consumers. Treatpropsas agent-authored and untrusted when rendering it into a document.1a1f440: Add
workletPaths.scribeAudioProcessortoScribe.connect({ microphone })so the Scribe audio worklet can be self-hosted, matching the existingConversationworkletPathsoption. This lets strict CSPs (script-src/script-src-elemwithoutblob:/data:) load the worklet from a same-origin URL instead of falling back to a blob or data URL.The generated worklet processors (including
scribeAudioProcessor.js) are now also published as static assets under@elevenlabs/client/worklets/*, so bundlers can copy them into your own static assets and serve them underscript-src 'self'.fb06e12: Add self-hosted orchestrator session support. Passing
orchestratorConfigtoConversation.startSessionroutes the conversation WebSocket to a self-hosted (private deployment) orchestrator and sends the agent configuration at connection time, mirroring the Python SDK'sOnPremInitiationData.
Patch Changes
92e70c6: Fix conversation state consistency through disconnect:
BaseConversationnow always reaches thedisconnectedstatus and firesonDisconnect, even when session teardown throws.ConversationProviderno longer lets a lateonDisconnectfrom a previous session clear a newer session's state, and no longer leaks unhandled rejections fromendSession().useConversationStatusnow reportsdisconnectedas soon as teardown starts, instead of holdingconnectedwhile the conversation was already released — consumers guarding conversation access withstatus === "connected"could previously crash during disconnect.
1.17.0
30 Jul 2026a96f220: Add
enableLoggingoption (boolean) to the Scribe realtime API, available onScribe.connectand theuseScribehook. Setting it tofalsesendsenable_logging=falseon the WebSocket URL, which runs the session in zero retention mode so history features are unavailable for it. Zero retention mode may only be used by enterprise customers.
Minor Changes
a96f220: Add
enableLoggingoption (boolean) to the Scribe realtime API, available onScribe.connectand theuseScribehook. Setting it tofalsesendsenable_logging=falseon the WebSocket URL, which runs the session in zero retention mode so history features are unavailable for it. Zero retention mode may only be used by enterprise customers.
1.16.0
27 Jul 2026139ed79: Add
onAgentReasoningResponsePartcallback to receive streaming reasoning response
events from the agent. The callback receives{ text, type, event_id }where type
is one of "start", "delta", or "stop".
Minor Changes
139ed79: Add
onAgentReasoningResponsePartcallback to receive streaming reasoning response
events from the agent. The callback receives{ text, type, event_id }where type
is one of "start", "delta", or "stop".
1.15.2
22 Jul 2026Reading the note…
1.15.1
16 Jul 2026Reading the note…
1.15.0
10 Jul 2026Reading the note…
1.14.1
7 Jul 2026Reading the note…
1.14.0
25 Jun 2026Reading the note…
1.13.0
24 Jun 2026Reading the note…
1.12.1
23 Jun 2026Reading the note…
1.12.0
18 Jun 2026Reading the note…
1.11.2
17 Jun 2026Reading the note…
1.11.1
12 Jun 2026Reading the note…
1.11.0
11 Jun 2026Reading the note…
1.10.0
9 Jun 2026Reading the note…
1.9.0
27 May 2026Reading the note…
1.8.1
22 May 2026Reading the note…
1.8.0
20 May 2026Reading the note…
1.7.1
19 May 2026Reading the note…
1.7.0
8 May 2026Reading the note…
1.6.0
8 May 2026Reading the note…
1.5.0
5 May 2026Reading the note…
1.4.0
29 Apr 2026Reading the note…
1.3.1
23 Apr 2026Reading the note…
1.3.0
22 Apr 2026Reading the note…
1.2.1
14 Apr 2026Reading the note…
1.2.0
10 Apr 2026Reading the note…
1.1.2
6 Apr 2026Reading the note…
1.1.1
3 Apr 2026Reading the note…
1.1.0
30 Mar 2026Reading the note…
1.0.0
27 Mar 2026Reading the note…
- 0.16.x
0.16.0
25 Mar 2026Reading the note…
- 0.15.x
0.15.2
17 Mar 2026Reading the note…
0.15.1
10 Mar 2026Reading the note…
0.15.0
24 Feb 2026Reading the note…
- 0.14.x
0.14.0
4 Feb 2026Reading the note…
- 0.13.x
0.13.1
27 Jan 2026Reading the note…