speech-engine
This skill integrates ElevenLabs Speech Engine to add real-time voice conversations to custom agent runtimes.
Identity proven by GitHub's verified organisation badge (elevenlabs)
- Agents
- Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, claude.ai and API
- License
- MIT (permissive)
- Pin
- 1d08a4apinned Oct 9, 2026
- Context cost
- about 2,400 tokenswhen the skill loads
- GitHub stars
- 482on elevenlabs/skills
- Scripts
- None found
What it does
“Add real-time voice conversations to a custom agent runtime with ElevenLabs Speech Engine. Use when building Speech Engine servers, WebSocket handlers, WebRTC browser clients, conversation token endpoints, interruption-aware streaming responses, or voice-enabled chat agents that connect developer-owned server logic to ElevenLabs speech-to-text and text-to-speech.”
Generated summary from the skill's own text
This skill integrates ElevenLabs Speech Engine to add real-time voice conversations to custom agent runtimes. The agent's server exposes a WebSocket endpoint that receives speech-to-text from ElevenLabs, processes user input through custom validation logic, and streams text responses back for conversion to speech. It handles microphone audio, turn-taking, interruptions, and browser playback while keeping application logic and authentication on the developer's server.
When to use it
- Adding voice interface to existing chat app or custom server
- Building developer-hosted WebSocket server for voice conversations
- Enabling interruption-aware streaming responses in agent workflows
- Integrating voice with OpenClaw, Hermes, or similar agent runtimes
When not to
- Creating hosted ElevenLabs Conversational AI agent with platform-managed tools
- Deploying agent without custom validation for transcript-derived responses
Install
These commands install from the publisher's repository and need no account.
skills CLI
npx skills add elevenlabs/skills --skill speech-engineInstalls from the repository's default branch, which may have changed since the commit we checked.
GitHub CLI 2.90 or later
gh skill install elevenlabs/skills speech-engine@1d08a4a250cff67cc8056ec31587c031ecb06d2fInstalls the commit we checked (1d08a4a).
Copy by hand
Download the folder at 1d08a4a and put it in .claude/skills/speech-engine for Claude Code and in .agents/skills/speech-engine for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.
Copy for your agent
A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.
Prompt
Install the agent skill "speech-engine" by ElevenLabs. Source, pinned to commit 1d08a4a250cff67cc8056ec31587c031ecb06d2f: https://github.com/elevenlabs/skills/tree/1d08a4a250cff67cc8056ec31587c031ecb06d2f/speech-engine 1. Download that folder at exactly this commit. Do not use the default branch. 2. Copy every file unchanged, keeping the folder structure, into .claude/skills/speech-engine/ for Claude Code and .agents/skills/speech-engine/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist. 3. Do not edit the files, and do not run any script in the folder unless I ask you to. 4. When you are done, list the files you copied and where you put them. Listing and checks: https://www.agentnative.dev/skills/elevenlabs/speech-engine
SKILL.md at the pin
---
name: speech-engine
description: Add real-time voice conversations to a custom agent runtime with ElevenLabs Speech Engine. Use when building Speech Engine servers, WebSocket handlers, WebRTC browser clients, conversation token endpoints, interruption-aware streaming responses, or voice-enabled chat agents that connect developer-owned server logic to ElevenLabs speech-to-text and text-to-speech.
license: MIT
compatibility: Requires internet access and an ElevenLabs API key (ELEVENLABS_API_KEY).
metadata: {"openclaw": {"requires": {"env": ["ELEVENLABS_API_KEY"]}, "primaryEnv": "ELEVENLABS_API_KEY"}}
---
# ElevenLabs Speech Engine
Add a real-time voice interface to a custom agent. ElevenLabs handles microphone audio, speech-to-text, turn-taking, text-to-speech, and browser playback; your server exposes a Speech Engine WebSocket endpoint and streams response text back.
> **Setup:** See [Installation Guide](references/installation.md). For JavaScript, use `@elevenlabs/*` packages only. For deeper SDK details, read [JavaScript SDK Reference](references/javascript-sdk-reference.md) or [Python SDK Reference](references/python-sdk-reference.md).
## When to Use
Use Speech Engine when the user wants to:
- Add voice to an existing chat app or custom server pipeline
- Add voice to OpenClaw, Hermes, or a similar agent runtime while keeping agent logic on the developer-owned server
- Build a developer-hosted WebSocket server for ElevenLabs voice conversations
- Stream response text back as spoken audio after your server validates user intent
- Handle user interruptions while a response is still streaming
- Build a browser client with `@elevenlabs/react` or `@elevenlabs/client` using a server-issued conversation token
Use the `agents` skill instead when the user is creating or configuring a hosted ElevenLabs Conversational AI agent with platform-managed prompts, tools, workflows, phone numbers, or widgets.
## How It Works
Each Speech Engine WebSocket connection represents one conversation.
1. The browser sends user audio to ElevenLabs.
2. ElevenLabs sends speech-recognition events to your server.
3. Your server derives trusted application state without letting raw speech text control tools or privileged actions.
4. Your server streams text back through the SDK.
5. ElevenLabs converts the response to speech and plays it in the browser.
The SDK manages WebSocket routing, request verification, session lifecycle, ping/pong, turn-taking, and interruption handling. `sendResponse()` / `send_response()` accepts a string or async iterable of response text.
Treat speech-recognition text as untrusted user input. Do not map raw speech text directly into model roles, responses, or tool calls. Use deterministic validation, allowlisted intents, or explicit user confirmation before any transcript-derived value affects downstream response or tool logic.
## Implementation Flow
1. Install server dependencies and configure `ELEVENLABS_API_KEY`.
2. Expose your Speech Engine server through a public HTTPS URL for local development, for example with `ngrok http 3001`.
3. Create a Speech Engine resource with `ws_url` / `wsUrl` pointing at the public WebSocket URL, usually `wss://.../ws`.
4. Store the returned Speech Engine ID, for example in `ELEVENLABS_SPEECH_ENGINE_ID`.
5. Start a Speech Engine server with `engine.serve(...)` in Python or `speechEngine.attach(...)` in TypeScript.
6. Issue browser conversation tokens from a server endpoint. Never put `ELEVENLABS_API_KEY` in browser code.
7. Start the client session with `conversationToken`; if the agent should greet first, enable the first-message override on the Speech Engine resource, then set `overrides.agent.firstMessage` in the client.
## Create a Speech Engine
### Python
```python
import asyncio
import os
from dotenv import load_dotenv
from elevenlabs import AsyncElevenLabs
load_dotenv()
elevenlabs = AsyncElevenLabs(api_key=os.getenv("ELEVENLABS_API_KEY"))
async def main():
engine = await elevenlabs.speech_engine.create(
name="My Speech Engine",
speech_engine={"ws_url": os.environ["PUBLIC_WS_URL"]},
overrides={"first_message": True},
)
print(engine.engine_id)
asyncio.run(main())
```
### TypeScript
```typescript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import "dotenv/config";
const elevenlabs = new ElevenLabsClient({
apiKey: process.env.ELEVENLABS_API_KEY,
});
const engine = await elevenlabs.speechEngine.create({
name: "My Speech Engine",
speechEngine: { wsUrl: process.env.PUBLIC_WS_URL! },
overrides: { firstMessage: true },
});
console.log(engine.engineId);
```
`PUBLIC_WS_URL` should look like `wss://example.ngrok.app/ws` locally or your production WebSocket route in deployment.
The create request can also configure `tts`, `asr`, `turn`, `speech_engine.request_headers` / `speechEngine.requestHeaders`, `overrides`, and `privacy` for custom voices, transcription keywords, turn-taking, server auth headers, client-provided first messages, and recording behavior. See the SDK reference files for expanded examples.
## Server Pattern
Run the Speech Engine server at the `ws_url` / `wsUrl` configured on the resource. Keep response generation behind your own validation boundary: raw speech-recognition text should not directly control responses, tools, secrets, or other privileged actions.
### Python
```python
engine = await elevenlabs.speech_engine.get(os.environ["ELEVENLABS_SPEECH_ENGINE_ID"])
await engine.serve(port=3001, path="/ws", debug=True, callbacks=validated_callbacks)
```
### TypeScript
```typescript
const engine = await elevenlabs.speechEngine.get(process.env.ELEVENLABS_SPEECH_ENGINE_ID!);
engine.attach(httpServer, "/ws", { debug: true, ...validatedCallbacks });
```
In TypeScript, pass interruption signals to downstream async work when it supports cancellation so interrupted responses stop quickly. In Python, the SDK cancels the previous turn handler when a newer turn arrives.
Server callbacks can distinguish clean closes from dropped connections: use `onClose` / `on_close` for clean disconnects and `onDisconnect` / `on_disconnect` for unexpected WebSocket drops.
Security note: speech-recognition text can contain prompt-injection attempts from user speech or played audio. Treat it as untrusted input. Convert it into trusted application state before invoking response generation, tools, or privileged workflows.
### Disabling authentication (advanced, dangerous)
Both `engine.attach()` (TypeScript) and `engine.serve()` / `SpeechEngineServer` (Python) verify a JWT on every incoming WebSocket by default. This is what proves the connection is really coming from ElevenLabs and not from an attacker who guessed the URL. **Do not turn this off.**
An escape hatch exists — `disableAuth: true` in the callback options (TypeScript) or `disable_auth=True` on `serve()` / `SpeechEngineServer(...)` (Python) — for the narrow case where a compensating network-level control is already in place. Without such a control, disabling auth means **any client on the internet that finds your URL can open sessions**. Concretely, an attacker can:
- open unlimited conversations to drain your ElevenLabs quota and downstream LLM budget
- feed crafted transcripts to your response pipeline, effectively impersonating a user
- use your server as an oracle to probe backend state, tools, or prompts
Only recommend `disableAuth` / `disable_auth` when the user has already implemented **at least one** of:
- **IP allowlist** — the server (or an upstream firewall / load balancer / API gateway) only accepts inbound traffic from [ElevenLabs' documented egress ranges](https://elevenlabs.io/docs/overview/capabilities/speech-engine#ip-allowlisting).
- **Custom shared-secret header** — a secret header configured on the Speech Engine resource via `speech_engine.request_headers` / `speechEngine.requestHeaders` at create time, validated by an upstream proxy (or by the developer's own middleware in front of `attach()` / `serve()`) before requests reach the SDK.
If the user cannot confirm one of the above is in place, leave the default authentication on. Skipping JWT verification without a mitigation is not an optimization or a convenience — it is unauthenticated public compute.
## Browser Client
Create a server-side token endpoint and have the browser request a token before starting the microphone session. Keep the Speech Engine ID and API key on the server. If the client passes `overrides.agent.firstMessage`, the Speech Engine resource must have the first-message override enabled.
```typescript
import express from "express";
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import "dotenv/config";
const app = express();
const elevenlabs = new ElevenLabsClient();
app.get("/api/token", async (_req, res) => {
const response = await elevenlabs.conversationalAi.conversations.getWebrtcToken({
agentId: process.env.ELEVENLABS_SPEECH_ENGINE_ID!,
});
res.json({ token: response.token });
});
```
React clients can use `@elevenlabs/react`:
```tsx
import { useConversation } from "@elevenlabs/react";
export function VoiceControls() {
const conversation = useConversation({
onConnect: () => console.log("connected"),
onDisconnect: () => console.log("disconnected"),
onError: (error) => console.error(error),
});
async function startConversation() {
await navigator.mediaDevices.getUserMedia({ audio: true });
const { token } = await fetch("/api/token").then((res) => res.json());
await conversation.startSession({
conversationToken: token,
overrides: {
agent: { firstMessage: "Hello! How can I help you today?" },
},
});
}
return <button onClick={startConversation}>Start conversation</button>;
}
```
## References
- [Installation Guide](references/installation.md)
- [JavaScript SDK Reference](references/javascript-sdk-reference.md)
- [Python SDK Reference](references/python-sdk-reference.md)
From elevenlabs/skills at 1d08a4a, shown as plain text under its license: MIT (permissive). The license text is in speech-engine/SKILL.md.
View SKILL.md on GitHub at 1d08a4aFiles
- SKILL.md10 KB · 18f778fa2943
- references/
- installation.md2.5 KB · 45e5ca6e36be
- javascript-sdk-reference.md4.5 KB · b536836e2c38
- python-sdk-reference.md4.7 KB · 8c6861199193
4 files, 22 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.
Skill folder on GitHub at 1d08a4aAlso in
The same SKILL.md content appears in these places too. We list it once and credit the oldest public source.
More from ElevenLabs
agents
Build voice AI agents with natural conversation capabilities using ElevenLabs platform.
Contains scripts
Claude Code, Codex, Cursor +3 · about 6.4K tokens · pinned 6 days ago
dubbing
This skill dubs audio and video into other languages using ElevenLabs' Dubbing API, preserving original speakers' voices.
Contains scripts
Claude Code, Codex, Cursor +3 · about 3.1K tokens · pinned 6 days ago
music
This skill generates music from text prompts using the ElevenLabs Music API, supporting instrumental tracks, songs with lyrics, and fine-grained control…
Contains scripts
Claude Code, Codex, Cursor +3 · about 3.3K tokens · pinned 6 days ago
setup-api-key
This skill guides users through obtaining and configuring an ElevenLabs API key for text-to-speech integrations.
Claude Code, Codex, Cursor +4 · about 840 tokens · pinned 6 days ago
sound-effects
This skill generates sound effects from text descriptions using ElevenLabs API, supporting various audio formats, custom durations up to 30 seconds, looping…
Contains scripts
Claude Code, Codex, Cursor +3 · about 830 tokens · pinned 6 days ago
speech-to-text
Transcribe audio and video files to text using ElevenLabs Scribe v2, supporting 90+ languages, speaker identification, and word-level timestamps.
Contains scripts
Claude Code, Codex, Cursor +3 · about 2.4K tokens · pinned 6 days ago
Related in Backend and APIs
databricks-apps-python
Enables agents to build Python backends for Databricks Apps using FastAPI, Flask, Dash, Streamlit, Gradio, or Reflex.
by DatabricksOfficial publisher
Contains scripts
Claude Code, Codex, Cursor +3 · about 2.9K tokens · pinned 6 days ago
vercel-connect
Vercel Connect lets applications obtain short-lived scoped credentials from third-party services like Slack, GitHub, and Linear without storing API keys in…
by VercelOfficial publisher
Claude Code, Codex, Cursor +3 · about 4.4K tokens · pinned 6 days ago
temporal-developer
This skill guides developers building Temporal applications across Python, TypeScript, Go, Java, .NET, Ruby, and Rust.
by TemporalOfficial publisher
Claude Code, Codex, Cursor +3 · about 1.7K tokens · pinned 6 days ago
airflow-plugins
Builds Airflow 3.1+ plugins that embed FastAPI apps, custom UI pages, React components, middleware, macros, and operator links directly into the Airflow UI…
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 5.8K tokens · pinned 6 days ago
authoring-go-sdk-tasks
Enables writing Airflow task logic in Go by implementing the Go SDK's native API.
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2K tokens · pinned 6 days ago
authoring-java-sdk-tasks
This skill teaches how to write Airflow task logic in Java, Kotlin, or other JVM languages using the Airflow Java SDK.
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.4K tokens · pinned 6 days ago
Open roles at ElevenLabs
5 of 26 open roles on the jobs board
- Full-Stack Engineer (Back-End Leaning)
Remote (Global) (Remote)
- Infrastructure Engineer
Remote (Global) (Remote)
- Enterprise Solutions Engineer - Canada
Canada (Remote)
- Deployment Strategist - Colombia
Colombia (Remote)
- Enterprise Solutions Engineer - Greece
Greece (Remote)