> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# WebSocket mit mehreren Kontexten

> **Fortgeschritten**
>
> Die Orchestrierung von Sprachagenten mit dieser WebSocket-API für mehrere Kontexte ist komplex und wird
> fortgeschrittenen Entwicklern empfohlen. Als stärker verwaltete Lösung können Sie unser [Produkt Agents Platform ](/docs/de/eleven-agents/overview) nutzen, das viele dieser Herausforderungen vereinfacht.

## Überblick

Reaktionsschnelle Sprachagenten erfordern die Fähigkeit, Audiostreams dynamisch zu verwalten, Unterbrechungen zuverlässig zu verarbeiten und über Gesprächswechsel hinweg natürlich klingende Sprache beizubehalten. Unsere WebSocket-API für mehrere Kontexte für Text to Speech (TTS) wurde speziell für diese Szenarien entwickelt.

Diese API erweitert unsere [standardmäßige TTS-WebSocket-Funktionalität](/docs/de/eleven-api/guides/how-to/websockets/realtime-tts) um das Konzept der „Kontexte“. Jeder Kontext arbeitet als unabhängiger Audiogenerierungsstream innerhalb einer einzelnen WebSocket-Verbindung. So können Sie:

* Mehrere Sprachsequenzen gleichzeitig verwalten, etwa wenn der Agent spricht und gleichzeitig eine Antwort auf eine Nutzerunterbrechung vorbereitet.
* Nutzereinwürfe nahtlos verarbeiten, indem Sie einen bestehenden Sprachkontext schließen und einen neuen starten.
* Prosodische Konsistenz für Äußerungen innerhalb desselben logischen Kontexts bewahren.
* Ressourcen effizient nutzen, indem Sie nicht mehr benötigte Kontexte gezielt schließen.

> **Warning**
>
> Die WebSocket-API für mehrere Kontexte ist für Sprachanwendungen optimiert und nicht dafür vorgesehen,
> mehrere unabhängige Audiostreams gleichzeitig zu generieren. Daher ist jede Verbindung auf 5
> gleichzeitige Kontexte begrenzt.

Dieser Leitfaden führt Sie durch die Verbindung mit dem WebSocket für mehrere Kontexte, die Verwaltung von Kontexten und Best Practices für überzeugende Sprachagenten.

### Best Practices

> **Note**
>
> Diese Best Practices sind entscheidend, um mit unserer WebSocket-API für mehrere Kontexte reaktionsschnelle
> und effiziente Sprachagenten zu erstellen.

#### Eine einzelne WebSocket-Verbindung nutzen

Stellen Sie für jede Endnutzer-Sitzung eine WebSocket-Verbindung her. Das reduziert im Vergleich zum
Aufbau mehrerer Verbindungen den Overhead und die Latenz. Innerhalb dieser Verbindung können Sie
mehrere Kontexte für verschiedene Teile des Gesprächs verwalten.

#### Antworten in Blöcken streamen, Sätze generieren

Streamen Sie bei langen Antworten den Text in kleineren Blöcken und verwenden Sie das Flag `flush: true`
am Ende vollständiger Sätze. Das verbessert die Qualität des generierten Audios und die
Reaktionsfähigkeit.

#### Unterbrechungen zuverlässig verarbeiten

Streamen Sie Text in einen Kontext, bis eine Unterbrechung erfolgt. Erstellen Sie dann einen neuen Kontext
und schließen Sie den bestehenden. Dieser Ansatz gewährleistet reibungslose Übergänge, wenn sich der Gesprächsfluss ändert.

#### Kontextlebenszyklus verwalten

Schließen Sie ungenutzte Kontexte zeitnah. Der Server kann pro Verbindung bis zu 5 gleichzeitige Kontexte
verwalten, Sie sollten Kontexte jedoch schließen, sobald sie nicht mehr benötigt werden.

#### Kontext-Timeouts verhindern

Kontexte laufen standardmäßig nach 20 Sekunden ab und werden automatisch geschlossen. Das Inaktivitäts-
Timeout ist ein Parameter auf WebSocket-Ebene, der für alle Kontexte gilt und bei Bedarf bis zu 180 Sekunden
betragen kann. Senden Sie eine leere Textnachricht an einen Kontext, um die Timeout-Uhr zurückzusetzen.

### Unterbrechungen verarbeiten

Wenn ein Nutzer Ihren Agenten unterbricht, sollten Sie den [aktuellen Kontext schließen](/docs/de/api-reference/text-to-speech/v-1-text-to-speech-voice-id-multi-stream-input#send.Close-Context) und [einen neuen erstellen](/docs/de/api-reference/text-to-speech/v-1-text-to-speech-voice-id-multi-stream-input#send.Initialise-Context):

```python
async def handle_interruption(websocket, old_context_id, new_context_id, new_response):
    # Close the existing context that was interrupted
    await websocket.send(json.dumps({
        "context_id": old_context_id,
        "close_context": True
    }))
    print(f"Closed interrupted context '{old_context_id}'")

    # Create a new context for the new response
    await send_text_in_context(websocket, new_response, new_context_id)
```

```javascript
function handleInterruption(websocket: WebSocket, oldContextId: string, newContextId: string, newResponse: string) {
  // Close the existing context that was interrupted
  websocket.send(JSON.stringify({
    context_id: oldContextId,
    close_context: true
  }));
  console.log(`Closed interrupted context '${oldContextId}'`);

  // Create a new context for the new response
  sendTextInContext(websocket, newResponse, newContextId);
}
```

### Einen Kontext aktiv halten

Kontexte laufen nach [standardmäßig 20 Sekunden Inaktivität](/docs/de/api-reference/text-to-speech/v-1-text-to-speech-voice-id-multi-stream-input#request.query.inactivity_timeout) automatisch ab. Wenn Sie einen Kontext ohne Textgenerierung aktiv halten müssen, etwa während einer Verarbeitungsverzögerung, können Sie eine leere Textnachricht senden, um die Timeout-Uhr zurückzusetzen.

```python
async def keep_context_alive(websocket, context_id):
    await websocket.send(json.dumps({
        "context_id": context_id,
        "text": ""
    }))
```

```javascript
function handleInterruption(websocket: WebSocket, contextId: string) {
  // Close the existing context that was interrupted
  websocket.send(JSON.stringify({
    context_id: oldContextId,
    text: ""
  }));
}
```

### Die WebSocket-Verbindung schließen

Wenn Ihr Gespräch endet, können Sie alle Kontexte bereinigen, indem Sie [den Socket schließen](/docs/de/api-reference/text-to-speech/v-1-text-to-speech-voice-id-multi-stream-input#send.Close-Socket):

```python
async def end_conversation(websocket):
    # This will close all contexts and close the connection
    await websocket.send(json.dumps({
        "close_socket": True
    }))
    print("Ending conversation and closing WebSocket")`
```

```javascript
function endConversation(websocket: WebSocket) {
  // This will close all contexts and close the connection
  websocket.send(JSON.stringify({
    close_socket: true
  }));
  console.log("Ending conversation and closing WebSocket");
}
```

## Vollständiges Beispiel für einen Gesprächsagenten

### Voraussetzungen

* Ein ElevenLabs-Konto mit API-Schlüssel (erfahren Sie, wie Sie [Ihren API-Schlüssel finden](/docs/de/api-reference/authentication)).
* Python oder Node.js (oder eine andere JavaScript-Runtime), installiert auf Ihrem Computer.
* Kenntnisse der WebSocket-Kommunikation. Für grundlegende Konzepte empfehlen wir unseren [Leitfaden zum standardmäßigen WebSocket-Streaming](/docs/de/eleven-api/guides/how-to/websockets/realtime-tts).

### Einrichtung

Installieren Sie die erforderlichen Abhängigkeiten für die von Ihnen gewählte Sprache:

```python
pip install python-dotenv websockets
```

```javascript
npm install dotenv ws
for TypeScript, you might also want types:
npm install @types/dotenv @types/ws --save-dev
```

Erstellen Sie im Verzeichnis Ihres Projekts eine .env-Datei, um Ihren API-Schlüssel zu speichern:

**`.env`**

```python .env
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here
```

### Beispiel für einen Sprachagenten

> **Note**
>
> Dieser Code dient als Beispiel und ist nicht für den Produktionseinsatz gedacht

```python maxLines=100
import os
import json
import asyncio
import websockets
from dotenv import load_dotenv

load_dotenv()
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
VOICE_ID = "your_voice_id"
MODEL_ID = "eleven_flash_v2_5"

WEBSOCKET_URI = f"wss://api.elevenlabs.io/v1/text-to-speech/{VOICE_ID}/multi-stream-input?model_id={MODEL_ID}"

async def send_text_in_context(websocket, text, context_id, voice_settings=None):
    """Send text to be synthesized in the specified context."""
    message = {
        "text": text,
        "context_id": context_id,
    }

    # Only include voice_settings for the first message in a context
    if voice_settings:
        message["voice_settings"] = voice_settings

    await websocket.send(json.dumps(message))

async def continue_context(websocket, text, context_id):
    """Add more text to an existing context."""
    await websocket.send(json.dumps({
        "text": text,
        "context_id": context_id
    }))

async def flush_context(websocket, context_id):
    """Force generation of any buffered audio in the context."""
    await websocket.send(json.dumps({
        "context_id": context_id,
        "flush": True
    }))

async def handle_interruption(websocket, old_context_id, new_context_id, new_response):
    """Handle user interruption by closing current context and starting a new one."""
    # Close the existing context that was interrupted
    await websocket.send(json.dumps({
        "context_id": old_context_id,
        "close_context": True
    }))

    # Create a new context for the new response
    await send_text_in_context(websocket, new_response, new_context_id)

async def end_conversation(websocket):
    """End the conversation and close the WebSocket connection."""
    await websocket.send(json.dumps({
        "close_socket": True
    }))

async def receive_messages(websocket):
    """Process incoming WebSocket messages."""
    context_audio = {}
    try:
        async for message in websocket:
            data = json.loads(message)
            context_id = data.get("contextId", "default")

            if data.get("audio"):
                print(f"Received audio for context '{context_id}'")

            if data.get("is_final"):
                print(f"Context '{context_id}' completed")
    except (websockets.exceptions.ConnectionClosed, asyncio.CancelledError):
        print("Message receiving stopped")

async def conversation_agent_demo():
    """Run a complete conversational agent demo."""
    # Connect with API key in headers
    async with websockets.connect(
        WEBSOCKET_URI,
        max_size=16 * 1024 * 1024,
        additional_headers={"xi-api-key": ELEVENLABS_API_KEY}
    ) as websocket:
        # Start receiving messages in background
        receive_task = asyncio.create_task(receive_messages(websocket))

        # Initial agent response
        await send_text_in_context(
            websocket,
            "Hello! I'm your virtual assistant. I can help you with a wide range of topics. What would you like to know about today?",
            "greeting"
        )

        # Wait a bit (simulating user listening)
        await asyncio.sleep(2)

        # Simulate user interruption
        print("USER INTERRUPTS: 'Can you tell me about the weather?'")

        # Handle the interruption by closing current context and starting new one
        await handle_interruption(
            websocket,
            "greeting",
            "weather_response",
            "I'd be happy to tell you about the weather. Currently in your area, it's 72 degrees and sunny with a slight chance of rain later this afternoon."
        )

        # Add more to the weather context
        await continue_context(
            websocket,
            " If you're planning to go outside, you might want to bring a light jacket just in case.",
            "weather_response"
        )

        # Flush at the end of this turn to ensure all audio is generated
        await flush_context(websocket, "weather_response")

        # Wait a bit (simulating user listening)
        await asyncio.sleep(3)

        # Simulate user asking another question
        print("USER: 'What about tomorrow?'")

        # Create a new context for this response
        await send_text_in_context(
            websocket,
            "Tomorrow's forecast shows temperatures around 75 degrees with partly cloudy skies. It should be a beautiful day overall!",
            "tomorrow_weather"
        )

        # Flush and close this context
        await flush_context(websocket, "tomorrow_weather")
        await websocket.send(json.dumps({
            "context_id": "tomorrow_weather",
            "close_context": True
        }))

        # End the conversation
        await asyncio.sleep(2)
        await end_conversation(websocket)

        # Cancel the receive task
        receive_task.cancel()
        try:
            await receive_task
        except asyncio.CancelledError:
            pass

if __name__ == "__main__":
    asyncio.run(conversation_agent_demo())

```

```javascript maxLines=100
// Import required modules
import dotenv from "dotenv";
import fs from "fs";
import WebSocket from "ws";

// Load environment variables
dotenv.config();
const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY;
const VOICE_ID = "your_voice_id";
const MODEL_ID = "eleven_flash_v2_5";

const WEBSOCKET_URI = `wss://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}/multi-stream-input?model_id=${MODEL_ID}`;

// Function to send text in a specific context
function sendTextInContext(websocket, text, contextId, voiceSettings = null) {
  const message = {
    text: text,
    context_id: contextId,
  };

  // Only include voice_settings for the first message in a context
  if (voiceSettings) {
    message.voice_settings = voiceSettings;
  }

  websocket.send(JSON.stringify(message));
}

// Function to continue an existing context with more text
function continueContext(websocket, text, contextId) {
  websocket.send(
    JSON.stringify({
      text: text,
      context_id: contextId,
    })
  );
}

// Function to flush a context, forcing generation of buffered audio
function flushContext(websocket, contextId) {
  websocket.send(
    JSON.stringify({
      context_id: contextId,
      flush: true,
    })
  );
}

// Function to handle user interruption
function handleInterruption(websocket, oldContextId, newContextId, newResponse) {
  // Close the existing context that was interrupted
  websocket.send(
    JSON.stringify({
      context_id: oldContextId,
      close_context: true,
    })
  );

  // Create a new context for the new response
  sendTextInContext(websocket, newResponse, newContextId);
}

// Function to end the conversation and close the connection
function endConversation(websocket) {
  websocket.send(
    JSON.stringify({
      close_socket: true,
    })
  );
}

// Function to run the conversation agent demo
async function conversationAgentDemo() {
  // Connect to WebSocket with API key in headers
  const websocket = new WebSocket(WEBSOCKET_URI, {
    headers: {
      "xi-api-key": ELEVENLABS_API_KEY,
    },
    maxPayload: 16 * 1024 * 1024,
  });

  // Set up event handlers
  websocket.on("open", () => {
    // Initial agent response
    sendTextInContext(
      websocket,
      "Hello! I'm your virtual assistant. I can help you with a wide range of topics. What would you like to know about today?",
      "greeting"
    );

    // Simulate wait time (user listening)
    setTimeout(() => {
      // Simulate user interruption
      console.log("USER INTERRUPTS: 'Can you tell me about the weather?'");

      // Handle the interruption
      handleInterruption(
        websocket,
        "greeting",
        "weather_response",
        "I'd be happy to tell you about the weather. Currently in your area, it's 72 degrees and sunny with a slight chance of rain later this afternoon."
      );

      // Add more to the weather context
      setTimeout(() => {
        continueContext(
          websocket,
          " If you're planning to go outside, you might want to bring a light jacket just in case.",
          "weather_response"
        );

        // Flush at the end of this turn
        flushContext(websocket, "weather_response");

        // Simulate wait time (user listening)
        setTimeout(() => {
          // Simulate user asking another question
          console.log("USER: 'What about tomorrow?'");

          // Create a new context for this response
          sendTextInContext(
            websocket,
            "Tomorrow's forecast shows temperatures around 75 degrees with partly cloudy skies. It should be a beautiful day overall!",
            "tomorrow_weather"
          );

          // Flush and close this context
          flushContext(websocket, "tomorrow_weather");
          websocket.send(
            JSON.stringify({
              context_id: "tomorrow_weather",
              close_context: true,
            })
          );

          // End the conversation
          setTimeout(() => {
            endConversation(websocket);
          }, 2000);
        }, 3000);
      }, 500);
    }, 2000);
  });

  // Handle incoming messages
  websocket.on("message", (message) => {
    try {
      const data = JSON.parse(message);
      const contextId = data.contextId || "default";

      if (data.audio) {
        //do stuff
      }

      if (data.is_final) {
        console.log(`Context '${contextId}' completed`);
      }
    } catch (error) {
      console.error("Error parsing message:", error);
    }
  });

  // Handle WebSocket closure
  websocket.on("close", () => {
    console.log("WebSocket connection closed");
  });

  // Handle WebSocket errors
  websocket.on("error", (error) => {
    console.error("WebSocket error:", error);
  });
}

// Run the demo
conversationAgentDemo();
```

## Nächste Schritte

#### [ElevenAgents](/docs/de/eleven-agents/quickstart)

Erstellen Sie produktionsreife Sprachagenten mit der vollständigen ElevenAgents-Plattform.

#### [Audio-Streaming verstehen](/docs/de/eleven-api/concepts/audio-streaming)

Erfahren Sie, wie WebSocket-Streaming im Hintergrund funktioniert und was die Latenz beeinflusst.