# Ai Provider Elevenlabs

> ElevenLabs voice AI SDK patterns for TypeScript/Node.js -- text-to-speech, streaming, voice cloning, speech-to-speech, pronunciation control, and conversational AI

- **Type:** Skill
- **Install:** `agentstack add skill-agents-inc-skills-ai-provider-elevenlabs`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [agents-inc](https://agentstack.voostack.com/s/agents-inc)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [agents-inc](https://github.com/agents-inc)
- **Source:** https://github.com/agents-inc/skills/tree/main/dist/plugins/ai-provider-elevenlabs/skills/ai-provider-elevenlabs

## Install

```sh
agentstack add skill-agents-inc-skills-ai-provider-elevenlabs
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# ElevenLabs Patterns

> **Quick Guide:** Use the official `@elevenlabs/elevenlabs-js` package to interact with the ElevenLabs API. Use `client.textToSpeech.convert()` for full audio generation or `client.textToSpeech.stream()` for low-latency streaming. Voice settings (`stability`, `similarityBoost`, `style`) control output character. Use `eleven_v3` for best quality, `eleven_flash_v2_5` for lowest latency, or `eleven_multilingual_v2` for stable long-form content. The SDK returns `ReadableStream` -- pipe to files or HTTP responses. Use `@elevenlabs/client` for real-time conversational AI agents.

---

## CRITICAL: Before Using This Skill

> **All code must follow project conventions in CLAUDE.md** (kebab-case, named exports, import ordering, `import type`, named constants)

**(You MUST use `@elevenlabs/elevenlabs-js` for server-side TTS, voice management, and speech-to-speech -- use `@elevenlabs/client` only for conversational AI agents)**

**(You MUST never hardcode API keys -- always use environment variables via `process.env.ELEVENLABS_API_KEY` which the SDK reads automatically)**

**(You MUST consume the `ReadableStream` returned by `convert()` and `stream()` -- unconsumed streams leak resources)**

**(You MUST choose the correct model for your use case -- `eleven_v3` for quality, `eleven_flash_v2_5` for speed, `eleven_multilingual_v2` for long-form stability)**

**(You MUST pass `voiceId` as the first positional argument to all `textToSpeech` methods -- it is NOT inside the options object)**

---

**Auto-detection:** ElevenLabs, elevenlabs, ElevenLabsClient, textToSpeech.convert, textToSpeech.stream, eleven_multilingual_v2, eleven_flash_v2_5, eleven_v3, speechToSpeech, voices.search, voice cloning, ELEVENLABS_API_KEY, @elevenlabs/elevenlabs-js, @elevenlabs/client, text-to-speech, TTS, voice synthesis

**When to use:**

- Generating speech audio from text (narration, audiobooks, announcements)
- Streaming audio in real-time for low-latency playback
- Cloning voices from audio samples (instant or professional voice cloning)
- Converting speech from one voice to another (speech-to-speech)
- Building real-time conversational AI agents with voice interaction
- Controlling pronunciation with SSML or pronunciation dictionaries
- Generating audio with character-level timestamp alignment

**Key patterns covered:**

- Client initialization and configuration (retries, timeouts, API key)
- Text-to-speech conversion and streaming (`convert`, `stream`, timestamps)
- Voice settings (`stability`, `similarityBoost`, `style`, `speed`)
- Voice selection and management (`voices.search`, `voices.get`)
- Voice cloning (instant via `voices.ivc.create`)
- Speech-to-speech voice conversion
- WebSocket input streaming for real-time text-to-speech
- Pronunciation dictionaries and SSML
- Conversational AI agents (`@elevenlabs/client`)
- Model selection, output formats, error handling

**When NOT to use:**

- You need multi-provider voice AI (multiple TTS vendors) -- use a unified abstraction
- You only need browser-side audio playback without generation -- use the Web Audio API
- You need speech-to-text transcription only -- ElevenLabs has this, but it is a separate concern

---

## Examples Index

- [Core: Setup, TTS, Streaming & Voice Settings](examples/core.md) -- Client init, convert, stream, timestamps, voice settings, output formats
- [Voices & Cloning](examples/voices.md) -- Voice search, selection, instant voice cloning, speech-to-speech
- [WebSocket & Conversational AI](examples/websocket.md) -- WebSocket input streaming, conversational AI agents, real-time patterns
- [Quick API Reference](reference.md) -- Model IDs, method signatures, output formats, error types, voice settings

---

## Philosophy

The ElevenLabs SDK provides **direct access to the most advanced voice AI API** available. It wraps the ElevenLabs REST API with full TypeScript types, streaming support, and automatic retries.

**Core principles:**

1. **Streams everywhere** -- All audio methods return `ReadableStream`. You pipe them to files, HTTP responses, or audio players. The SDK never buffers entire audio files in memory.
2. **Voice settings are the primary control surface** -- `stability`, `similarityBoost`, `style`, and `speed` shape every generation. Learn these four knobs well.
3. **Model selection drives the quality/latency tradeoff** -- `eleven_v3` for best quality, `eleven_flash_v2_5` for sub-75ms latency, `eleven_multilingual_v2` for stable long-form.
4. **Two packages for two use cases** -- `@elevenlabs/elevenlabs-js` for server-side TTS/voice management, `@elevenlabs/client` for browser-side conversational AI agents.
5. **Built-in resilience** -- The SDK retries on 408, 409, 429, and 5xx errors (2 retries by default) with configurable timeouts.

---

## Core Patterns

### Pattern 1: Client Setup

Initialize the ElevenLabs client. It auto-reads `ELEVENLABS_API_KEY` from the environment.

```typescript
// lib/elevenlabs.ts -- basic setup
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const client = new ElevenLabsClient();
export { client };
```

```typescript
// lib/elevenlabs.ts -- production configuration
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const TIMEOUT_SECONDS = 60;
const MAX_RETRIES = 3;

const client = new ElevenLabsClient({
  apiKey: process.env.ELEVENLABS_API_KEY,
  timeoutInSeconds: TIMEOUT_SECONDS,
  maxRetries: MAX_RETRIES,
});

export { client };
```

**Why good:** Minimal setup, env var auto-detected, named constants for production settings

```typescript
// BAD: Hardcoded API key
const client = new ElevenLabsClient({
  apiKey: "sk-1234567890abcdef",
});
```

**Why bad:** Hardcoded API key is a security breach risk, will leak in version control

**See:** [examples/core.md](examples/core.md) for per-request overrides, error handling

---

### Pattern 2: Text-to-Speech (Convert)

Generate complete audio from text. Returns `ReadableStream`.

```typescript
import { createWriteStream } from "node:fs";
import { Readable } from "node:stream";

const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb"; // George

const audio = await client.textToSpeech.convert(VOICE_ID, {
  text: "Welcome to the application.",
  modelId: "eleven_multilingual_v2",
  outputFormat: "mp3_44100_128",
});

// Pipe to file
const readable = Readable.fromWeb(audio);
const fileStream = createWriteStream("output.mp3");
readable.pipe(fileStream);
```

**Why good:** `voiceId` as first arg (required), model and format explicit, stream piped to file without buffering

```typescript
// BAD: voiceId inside options object
const audio = await client.textToSpeech.convert({
  voiceId: VOICE_ID, // WRONG: voiceId is a positional argument
  text: "Hello",
});
```

**Why bad:** `voiceId` is the first positional argument, not an options field -- this will throw a type error

**See:** [examples/core.md](examples/core.md) for timestamps, HTTP response piping

---

### Pattern 3: Text-to-Speech (Stream)

Stream audio for real-time playback with lower latency than `convert()`.

```typescript
const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";
const LATENCY_OPTIMIZATION = 2;

const audioStream = await client.textToSpeech.stream(VOICE_ID, {
  text: "This streams with lower latency for real-time playback.",
  modelId: "eleven_flash_v2_5",
  optimizeStreamingLatency: LATENCY_OPTIMIZATION,
  outputFormat: "mp3_44100_128",
});

// Consume the stream
for await (const chunk of audioStream) {
  process.stdout.write(chunk); // Or pipe to audio player / HTTP response
}
```

**Why good:** Uses `stream()` for lower latency, `eleven_flash_v2_5` for speed, `optimizeStreamingLatency` reduces first-byte time

```typescript
// BAD: Stream created but never consumed
const audioStream = await client.textToSpeech.stream(VOICE_ID, {
  text: "This audio is lost",
  modelId: "eleven_flash_v2_5",
});
// Stream never consumed -- resources leaked
```

**Why bad:** Unconsumed streams leak resources and the audio data is silently lost

**See:** [examples/core.md](examples/core.md) for streaming to HTTP responses

---

### Pattern 4: Voice Settings

Control voice characteristics with `voiceSettings`.

```typescript
const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";

const audio = await client.textToSpeech.convert(VOICE_ID, {
  text: "Emotional and expressive delivery.",
  modelId: "eleven_v3",
  voiceSettings: {
    stability: 0.3, // Lower = more expressive/variable
    similarityBoost: 0.8, // Higher = closer to original voice
    style: 0.5, // Higher = more style exaggeration
    useSpeakerBoost: true, // Enhanced speaker similarity (adds latency)
    speed: 1.0, // 0.7-1.3 range typical
  },
});
```

**Why good:** All settings explicit with clear purpose, stability lowered for expressive content

```typescript
// BAD: Using extreme values without understanding
const audio = await client.textToSpeech.convert(VOICE_ID, {
  text: "Extreme settings cause artifacts.",
  modelId: "eleven_v3",
  voiceSettings: {
    stability: 0.0, // Too unstable -- garbled output
    similarityBoost: 1.0, // Combined with low stability = artifacts
    style: 1.0, // Maximum exaggeration -- unnatural
  },
});
```

**Why bad:** Extreme values produce artifacts; `stability: 0.0` with high `similarityBoost` is unstable. Start with defaults and adjust incrementally.

**See:** [reference.md](reference.md) for voice settings ranges and recommended starting values

---

### Pattern 5: Voice Selection and Management

Find and select voices from the ElevenLabs voice library.

```typescript
// Search all available voices
const { voices } = await client.voices.search();

for (const voice of voices) {
  console.log(`${voice.name} (${voice.voiceId}) - ${voice.category}`);
}

// Get a specific voice by ID
const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";
const voice = await client.voices.get(VOICE_ID);
console.log(voice.name, voice.settings);
```

**Why good:** Uses `voices.search()` to discover available voices, `voices.get()` for details

**See:** [examples/voices.md](examples/voices.md) for filtering, voice cloning, speech-to-speech

---

### Pattern 6: Voice Cloning (Instant)

Create an instant voice clone from audio samples.

```typescript
import { createReadStream } from "node:fs";

const voice = await client.voices.ivc.create({
  name: "My Custom Voice",
  files: [createReadStream("sample1.mp3"), createReadStream("sample2.mp3")],
  removeBackgroundNoise: true,
});

console.log(`Created voice: ${voice.voiceId}`);

// Use the cloned voice for TTS
const audio = await client.textToSpeech.convert(voice.voiceId, {
  text: "Speaking in the cloned voice.",
  modelId: "eleven_multilingual_v2",
});
```

**Why good:** `removeBackgroundNoise` improves quality, multiple samples improve accuracy, immediately usable

**See:** [examples/voices.md](examples/voices.md) for professional voice cloning, sample validation

---

### Pattern 7: Speech-to-Speech

Convert speech from one voice to another while preserving emotion and cadence.

```typescript
import { createReadStream } from "node:fs";

const TARGET_VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";

const convertedAudio = await client.speechToSpeech.convert(TARGET_VOICE_ID, {
  audio: createReadStream("input-speech.mp3"),
  modelId: "eleven_multilingual_sts_v2",
  voiceSettings: {
    stability: 0.5,
    similarityBoost: 0.75,
  },
});
```

**Why good:** Uses STS-specific model, preserves source emotion, voice settings control output fidelity

**See:** [examples/voices.md](examples/voices.md) for streaming STS, English-only model

---

### Pattern 8: Error Handling

Catch SDK errors and handle specific failure modes.

```typescript
import {
  ElevenLabsError,
  ElevenLabsTimeoutError,
} from "@elevenlabs/elevenlabs-js";

const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";

try {
  const audio = await client.textToSpeech.convert(VOICE_ID, {
    text: "Hello, world.",
    modelId: "eleven_multilingual_v2",
  });
} catch (error) {
  if (error instanceof ElevenLabsTimeoutError) {
    console.error("Request timed out -- increase timeoutInSeconds or retry");
  } else if (error instanceof ElevenLabsError) {
    console.error(`ElevenLabs API error: ${error.message}`);
    console.error(`Status: ${error.statusCode}`);
    console.error(`Body: ${JSON.stringify(error.body)}`);
  } else {
    throw error; // Re-throw non-ElevenLabs errors
  }
}
```

**Why good:** Catches specific error types, logs status code and body for debugging, re-throws unknown errors

**See:** [examples/core.md](examples/core.md) for stream error handling, retry patterns

---

## Performance Optimization

### Model Selection for Latency/Quality

```
Best quality + expressiveness  -> eleven_v3 (70+ languages)
Long-form stability            -> eleven_multilingual_v2 (29 languages, 10K char limit)
Lowest latency ( eleven_flash_v2_5 (32 languages, 40K char limit)
English-only low latency       -> eleven_flash_v2 (English only, 30K char limit)
Voice design from text prompt  -> eleven_ttv_v3 (70+ languages)
```

### Key Optimization Patterns

- **Use `stream()` instead of `convert()`** for user-facing audio -- playback starts before generation completes
- **Set `optimizeStreamingLatency`** (0-4) on `stream()` calls -- higher values reduce latency but may affect text normalization
- **Use `eleven_flash_v2_5`** for real-time applications -- sub-75ms latency at 50% lower cost
- **Use `previous_request_ids`** for multi-part generation -- maintains voice consistency across segments
- **Batch multiple short texts** into single requests when possible -- reduces API call overhead
- **Cache generated audio** for static content -- avoid re-generating identical text
- **Use `outputFormat: "pcm_16000"`** for server-side processing pipelines -- lower bandwidth than MP3

---

## Decision Framework

### Which Model to Choose

```
What is your priority?
+-- Best quality / expressiveness -> eleven_v3
+-- Lowest latency ( eleven_flash_v2_5
+-- Long-form stability (audiobooks) -> eleven_multilingual_v2
+-- English-only speed -> eleven_flash_v2
+-- Voice design from text description -> eleven_ttv_v3
+-- Speech-to-speech conversion -> eleven_multilingual_sts_v2 (or eleven_english_sts_v2)
```

### convert() vs stream()

```
Is the audio user-facing with real-time playback?
+-- YES -> Use stream() for progressive playback
|   +-- Need timestamps? -> streamWithTimestamps()
+-- NO -> Use convert() for complete audio
    +-- Need timestamps? -> convertWithTimestamps()
    +-- Saving to file? -> convert() and pipe to WriteStream
```

### Which Package to Use

```
What are you building?
+-- Server-side TTS, voice management, STS -> @elevenlabs/elevenlabs-js
+-- Browser conversational AI agent -> @elevenlabs/client
+-- React conversational AI agent -> @elevenlabs/react
+-- WebSocket text input streaming -> @elevenlabs/elevenlabs-js (or raw WebSocket)
```

### Output Format Selection

```
What is the audio destination?
+-- Web browser playback -> mp3_44100_128 (universal compatibility)
+-- Low-bandwidth streaming -> opus_48000_64 (smaller files)
+-- Audio processing pipeline -> pcm_16000 or pcm_44100 (raw audio)
+-- Telephony / IVR -> ulaw_8000 or alaw_8000 (legacy codecs)
+-- High-quality archival -> wav_44100 or mp3_44100_192
```

---

## RED FLAGS

**High Priority Issues:**

- Hardcoding API keys instead of using `process.env.ELEVENLABS_API_KEY` (security breach risk)
- Not consuming streams returned by `convert()` or `stream()` (resources leaked, audio lost)
- Passing `voiceId` inside the options object instead of as the first positional argument (type error)
- Using deprecated `eleven_turbo_v2_5` instead of `eleven_flash_v2_5` (migrate to Flash models)
- Using deprecated `eleven_monolingual_v1` or `eleven_multilingual_v1` (use v2+ models)

**Medium Priority Issues:**

- Not setting `timeoutInSeconds` for production (default is 240 seconds -- may be too long or too short)
- Using `stability: 0.0` or extreme voice settings without testing (produces artifacts)
- Not using `optimizeStre

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [agents-inc](https://github.com/agents-inc)
- **Source:** [agents-inc/skills](https://github.com/agents-inc/skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-agents-inc-skills-ai-provider-elevenlabs
- Seller: https://agentstack.voostack.com/s/agents-inc
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
