Client-Ereignisse

Echtzeitereignisse verstehen und verarbeiten, die der Client während konversationeller Anwendungen empfängt.

Client-Ereignisse sind Ereignisse auf Systemebene, die vom Server an den Client gesendet werden und die Echtzeitkommunikation ermöglichen. Diese Ereignisse übermitteln Audio, Transkriptionen, Agentenantworten und weitere wichtige Informationen an die Client-Anwendung.

Informationen zu Ereignissen, die Sie vom Client an den Server senden können, finden Sie in der Dokumentation zu Client-zu-Server-Ereignissen.

Überblick

Client-Ereignisse sind entscheidend, um den Echtzeitcharakter von Gesprächen aufrechtzuerhalten. Sie liefern alles von Initialisierungsmetadaten bis hin zu verarbeitetem Audio und Agentenantworten.

Diese Ereignisse sind Teil des WebSocket-Kommunikationsprotokolls und werden automatisch von unseren SDKs verarbeitet. Ihr Verständnis ist entscheidend für erweiterte Implementierungen und das Debugging.

Client-Ereignistypen

  • Wird beim Start einer Unterhaltung automatisch gesendet
  • Initialisiert Unterhaltungseinstellungen und -parameter
// Example initialization metadata
{
"type": "conversation_initiation_metadata",
"conversation_initiation_metadata_event": {
"conversation_id": "conv_123",
"agent_output_audio_format": "pcm_44100", // TTS output format
"user_input_audio_format": "pcm_16000" // ASR input format
}
}
  • Wird nur an Anrufer in der Anrufwarteschlange gesendet, während der Agent sein Parallelitätslimit erreicht hat
  • waiting wird einmal gesendet, nach conversation_initiation_metadata und vor Wartemusik
  • admitted oder timed_out wird einmal gesendet, wenn die Wartezeit endet. Auf timed_out folgt das Schließen des WebSockets mit Code 4300
  • Wird immer an wartende Anrufer gesendet. Es muss nicht in der client_events-Konfiguration des Agents aktiviert werden

Während ein Anrufer wartet, wird Wartemusik als reguläres audio-Ereignis empfangen. Verwenden Sie dieses Ereignis, um einen Wartestatus anzuzeigen, statt die Wartemusik als Agentensprache zu behandeln.

// Example queue status event structure
{
"type": "queue_status",
"queue_status_event": {
"status": "waiting" // "waiting" | "admitted" | "timed_out"
}
}
// Example queue status handler
websocket.on('queue_status', (event) => {
const { status } = event.queue_status_event;
if (status === 'waiting') {
showWaitingState();
} else if (status === 'admitted') {
hideWaitingState();
} else if (status === 'timed_out') {
showAllAgentsBusyMessage();
}
});
  • Zustandsprüfungsereignis, das eine sofortige Antwort erfordert
  • Wird automatisch vom SDK verarbeitet
  • Dient zur Aufrechterhaltung der WebSocket-Verbindung
// Example ping event structure
{
"ping_event": {
"event_id": 123456,
"ping_ms": 50 // Optional, estimated latency in milliseconds
},
"type": "ping"
}
// Example ping handler
websocket.on('ping', () => {
websocket.send('pong');
});
  • Enthält Base64-codiertes Audio zur Wiedergabe
  • Enthält eine numerische Ereignis-ID zur Nachverfolgung und Sequenzierung
  • Verarbeitet das Streaming der Sprachausgabe
  • Enthält Ausrichtungsdaten mit Timing-Informationen auf Zeichenebene

Bei WebRTC-Verbindungen wird das audio-Ereignis nicht gesendet, da Audio direkt von LiveKit verarbeitet wird.

// Example audio event structure
{
"audio_event": {
"audio_base_64": "base64_encoded_audio_string",
"event_id": 12345,
"alignment": { // Character-level timing data
"chars": ["H", "e", "l", "l", "o"],
"char_durations_ms": [50, 30, 40, 40, 60],
"char_start_times_ms": [0, 50, 80, 120, 160]
}
},
"type": "audio"
}
// Example audio event handler
websocket.on('audio', (event) => {
const { audio_event } = event;
const { audio_base_64, event_id, alignment } = audio_event;
audioPlayer.play(audio_base_64);
// Use alignment data for synchronized text display
const { chars, char_start_times_ms } = alignment;
chars.forEach((char, i) => {
setTimeout(() => highlightCharacter(char, i), char_start_times_ms[i]);
});
});
  • Enthält abgeschlossene Speech-to-Text-Ergebnisse
  • Stellt vollständige Äußerungen des Nutzers dar
  • Dient dem Unterhaltungsverlauf
// Example transcript event structure
{
"type": "user_transcript",
"user_transcription_event": {
"user_transcript": "Hello, how can you help me today?"
}
}
// Example transcript handler
websocket.on('user_transcript', (event) => {
const { user_transcription_event } = event;
const { user_transcript } = user_transcription_event;
updateConversationHistory(user_transcript);
});
  • Enthält die vollständige Agentennachricht
  • Wird gesendet, sobald die Nachricht abgeschlossen ist. In Sprachunterhaltungen trifft es daher meist ein, nachdem das Audio der Nachricht bereits gestreamt wird.
  • Dient zur Anzeige und für den Verlauf

Um den Text des Agents während seiner Generierung anzuzeigen, verwenden Sie das unten beschriebene Ereignis agent_chat_response_part, statt auf dieses Ereignis zu warten.

// Example response event structure
{
"type": "agent_response",
"agent_response_event": {
"agent_response": "Hello, how can I assist you today?"
}
}
// Example response handler
websocket.on('agent_response', (event) => {
const { agent_response_event } = event;
const { agent_response } = agent_response_event;
displayAgentMessage(agent_response);
});
  • Enthält die gekürzte Antwort nach einer Unterbrechung
  • Aktualisiert die angezeigte Nachricht
  • Erhält die Genauigkeit der Unterhaltung
// Example response correction event structure
{
"type": "agent_response_correction",
"agent_response_correction_event": {
"original_agent_response": "Let me tell you about the complete history...",
"corrected_agent_response": "Let me tell you about..." // Truncated after interruption
}
}
// Example response correction handler
websocket.on('agent_response_correction', (event) => {
const { agent_response_correction_event } = event;
const { corrected_agent_response } = agent_response_correction_event;
displayAgentMessage(corrected_agent_response);
});
  • Enthält beliebige Metadaten aus einer benutzerdefinierten LLM-Antwort
  • Wird nur bei Verwendung eines benutzerdefinierten LLM gesendet
  • Muss ausdrücklich in der client_events-Konfiguration des Agents aktiviert werden

Dieses Ereignis gilt speziell für benutzerdefinierte LLM-Integrationen. Es ermöglicht Ihrem benutzerdefinierten LLM-Server, zusätzliche Metadaten zusammen mit der Antwort zu übergeben, die von der Client-Anwendung genutzt werden können.

// Example agent response metadata event structure
{
"type": "agent_response_metadata",
"agent_response_metadata_event": {
"metadata": {
// Any key-value pairs returned by your custom LLM
"key": "value"
},
"event_id": 12345
}
}
// Example metadata handler
websocket.on('agent_response_metadata', (event) => {
const { agent_response_metadata_event } = event;
const { metadata, event_id } = agent_response_metadata_event;
// Use metadata for UI updates, logging, or analytics
console.log(`Response ${event_id} metadata:`, metadata);
updateResponseDetails(metadata);
});
  • Stellt einen Funktionsaufruf dar, den der Agent vom Client ausführen lassen möchte
  • Enthält Toolname, Tool-Call-ID und Parameter
  • Erfordert die clientseitige Ausführung der Funktion und das Zurücksenden des Ergebnisses an den Server

Wenn Sie das SDK verwenden, stehen Callbacks zur Verfügung, um das Ergebnis an den Server zurückzusenden.

// Example tool call event structure
{
"type": "client_tool_call",
"client_tool_call": {
"tool_name": "search_database",
"tool_call_id": "call_123456",
"parameters": {
"query": "user information",
"filters": {
"date": "2024-01-01"
}
}
}
}
// Example tool call handler
websocket.on('client_tool_call', async (event) => {
const { client_tool_call } = event;
const { tool_name, tool_call_id, parameters } = client_tool_call;
try {
const result = await executeClientTool(tool_name, parameters);
// Send success response back to continue conversation
websocket.send({
type: "client_tool_result",
tool_call_id: tool_call_id,
result: result,
is_error: false
});
} catch (error) {
// Send error response if tool execution fails
websocket.send({
type: "client_tool_result",
tool_call_id: tool_call_id,
result: error.message,
is_error: true
});
}
});
  • Gibt an, wann der Agent eine Tool-Funktion ausgeführt hat
  • Enthält Tool-Metadaten und Ausführungsstatus
  • Ermöglicht Einblick in die Tool-Nutzung des Agents während Unterhaltungen
// Example agent tool response event structure
{
"type": "agent_tool_response",
"agent_tool_response": {
"tool_name": "skip_turn",
"tool_call_id": "skip_turn_c82ca55355c840bab193effb9a7e8101",
"tool_type": "system",
"is_error": false
}
}
// Example agent tool response handler
websocket.on('agent_tool_response', (event) => {
const { agent_tool_response } = event;
const { tool_name, tool_call_id, tool_type, is_error } = agent_tool_response;
if (is_error) {
console.error(`Agent tool ${tool_name} failed:`, tool_call_id);
} else {
console.log(`Agent executed ${tool_type} tool: ${tool_name}`);
}
});
  • Entspricht agent_tool_response und streamt zusätzlich die vollständige Ergebnis-Payload des Tools als String in full_tool_result.
  • Stellt die Tool-Ausgabe im Client zur Anzeige oder Weiterverarbeitung bereit.
  • Muss ausdrücklich in der client_events-Konfiguration des Agents aktiviert werden.

Dieses Ereignis legt das vollständige Tool-Ergebnis im Client offen und kann sensible Daten enthalten. Aktivieren Sie es nur, wenn der Client die Payload vertrauenswürdig verarbeiten kann. Ergebnisse über 64 KB werden automatisch gekürzt.

// Example agent tool response full payload event structure
{
"type": "agent_tool_response_full_payload",
"agent_tool_response_full_payload": {
"tool_name": "lookup_order",
"tool_call_id": "lookup_order_c82ca55355c840bab193effb9a7e8101",
"tool_type": "webhook",
"is_error": false,
"full_tool_result": "{\"order_id\": \"ORD-789\", \"status\": \"shipped\"}",
"truncated": false
}
}
// Example agent tool response full payload handler (using @elevenlabs/react)
import { ConversationProvider } from '@elevenlabs/react';
function App() {
return (
<ConversationProvider
onAgentToolResponse={(response) => {
if (!('full_tool_result' in response)) return;
const { tool_name, tool_call_id, is_error, full_tool_result, truncated } = response;
if (is_error) {
console.error(`Agent tool ${tool_name} failed:`, tool_call_id);
} else {
console.log(`Tool ${tool_name} returned:`, full_tool_result);
}
if (truncated) {
console.warn(`Tool ${tool_name} result was truncated (exceeded 64 KB).`);
}
}}
>
<Agent />
</ConversationProvider>
);
}
  • Ereignis mit Voice-Activity-Detection-Score
  • Gibt die Wahrscheinlichkeit an, dass der Nutzer spricht
  • Werte reichen von 0 bis 1, wobei höhere Werte eine höhere Sprechsicherheit anzeigen
// Example VAD score event
{
"type": "vad_score",
"vad_score_event": {
"vad_score": 0.95
}
}
  • Gibt an, wann der Agent eine MCP-Tool-Funktion ausgeführt hat
  • Enthält Toolname, Tool-Call-ID und Parameter
  • Wird mit einem von vier Status aufgerufen: loading, awaiting_approval, success und failure.
{
"type": "mcp_tool_call",
"mcp_tool_call": {
"service_id": "xJ8kP2nQ7sL9mW4vR6tY",
"tool_call_id": "call_123456",
"tool_name": "search_database",
"tool_description": "Search the database for user information",
"parameters": {
"query": "user information",
},
"timestamp": "2024-09-30T14:23:45.123456+00:00",
"state": "loading",
"approval_timeout_secs": 10
}
}
  • Streamt den Antworttext des Agents während seiner Generierung als Nachrichten start, delta und stop
  • Wird im reinen Textmodus immer gesendet. In Sprachunterhaltungen muss es ausdrücklich in der client_events-Konfiguration des Agents aktiviert werden
  • Wird nicht gesendet, während der Agent oder eine aktive Prozedur eine blockierende Guardrail verwendet, die die gesamte Antwort bewerten muss, bevor ein Teil davon freigegeben wird
  • response_id identifiziert die gestreamte Nachricht und entspricht der response_id von agent_response, die sie später bestätigt
// Example start event
{
"type": "agent_chat_response_part",
"text_response_part": {
"type": "start",
"text": "",
"event_id": 12345,
"response_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
}
// Example delta event with text chunk
{
"type": "agent_chat_response_part",
"text_response_part": {
"type": "delta",
"text": "Hello, how can I",
"event_id": 12345,
"response_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
}
// Example stop event
{
"type": "agent_chat_response_part",
"text_response_part": {
"type": "stop",
"text": "",
"event_id": 12345,
"response_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
}
// Example handler
websocket.on('agent_chat_response_part', (event) => {
const { text_response_part } = event;
const { type: partType, text, response_id } = text_response_part;
if (partType === 'start') {
initializeResponseBuffer(response_id);
} else if (partType === 'delta') {
appendToResponseBuffer(response_id, text);
} else if (partType === 'stop') {
finalizeResponse(response_id);
}
});

agent_reasoning_response_part streamt vom Modell bereitgestellte Begründungen während reiner Textunterhaltungen. Aktivieren Sie das Ereignis in client_events und die Zusammenfassung der Begründung für den Agenten. Der Server sendet start-, delta- und stop-Nachrichten. Während Sprachunterhaltungen oder wenn der Agent oder eine aktive Prozedur blockierende Guardrails verwendet, wird dieses Ereignis nicht gesendet.

Dieses Ereignis und der entsprechende SDK-Callback sind experimentell. Ihr Verhalten und ihre Struktur können sich in jeder Version ändern.

Ereignis-Payload
{
"type": "agent_reasoning_response_part",
"reasoning_response_part": {
"type": "delta",
"text": "The user asked to cancel, so I should verify the account before continuing.",
"event_id": 123456
}
}

Start- und Stopp-Ereignisse verwenden einen leeren text-Wert.

Begründungsereignisse verarbeiten
import { Conversation } from '@elevenlabs/client';
const conversation = await Conversation.startSession({
agentId: 'agent_7101k5zvyjhmfg983brhmhkd98n6',
textOnly: true,
onAgentReasoningResponsePart: ({ type, text, event_id }) => {
if (type === 'start') {
initializeReasoningBuffer(event_id);
} else if (type === 'delta') {
appendToReasoningBuffer(text);
} else if (type === 'stop') {
finalizeReasoning();
}
},
});
  • Wird ausgelöst, wenn der Agent seine Antwort einschließlich ausstehender Tool-Aufrufe abgeschlossen hat. Nach diesem Ereignis erzeugt der Agent nur weitere Ausgaben, wenn der Nutzer neue Eingaben bereitstellt oder ein Turn-Timeout einen neuen Turn auslöst.
  • Muss ausdrücklich in der client_events-Konfiguration des Agents aktiviert werden
// Example agent response complete event structure
{
"type": "agent_response_complete",
"agent_response_complete_event": {
"event_id": 12345
}
}
// Example handler
websocket.on('agent_response_complete', (event) => {
const { agent_response_complete_event } = event;
const { event_id } = agent_response_complete_event;
console.log(`Agent response ${event_id} complete`);
});
  • Wird ausgelöst, wenn eine Verletzung einer Guardrail die Unterhaltung beendet. Wird nicht gesendet, wenn eine Guardrail einen erfolgreichen Wiederholungsversuch auslöst.
  • Das Ereignis selbst ist das Signal – es enthält keine Payload außer dem Feld type.
  • Muss ausdrücklich in der client_events-Konfiguration des Agents aktiviert werden.
// Example guardrail triggered event structure
{
"type": "guardrail_triggered"
}
// Example guardrail triggered handler (using @elevenlabs/client)
import { Conversation } from '@elevenlabs/client';
const conversation = await Conversation.startSession({
agentId: 'agent_7101k5zvyjhmfg983brhmhkd98n6',
onGuardrailTriggered: () => {
console.warn('Guardrail triggered — conversation will end.');
},
});

Ereignisablauf

Hier ist eine typische Ereignisabfolge während einer Unterhaltung:

conversation_initiation_metadata ping pong audio user_transcript audio agent_response client_tool_call client_tool_result audio agent_response agent_response_correction Connection established Playing audio User responds Client tool runs Playing audio Interruption detected Client Server

Wenn ein Agent sein Parallelitätslimit erreicht hat und Warteschlangen für Anrufe aktiviert ist, sendet der Server zwischen conversation_initiation_metadata und dem ersten audio-Ereignis queue_status-Ereignisse. Wartemusik wird als audio-Ereignisse bereitgestellt, bis der Anrufer zugelassen wird.

Best Practices

  1. Fehlerbehandlung

    • Implementieren Sie eine korrekte Fehlerbehandlung für jeden Ereignistyp.
    • Protokollieren Sie wichtige Ereignisse zur Fehlerbehebung.
    • Behandeln Sie Verbindungsunterbrechungen zuverlässig.
  2. Audioverwaltung

    • Puffern Sie Audio-Chunks angemessen.
    • Implementieren Sie eine korrekte Bereinigung bei Unterbrechungen.
    • Verwalten Sie Audioressourcen korrekt.
  3. Verbindungsverwaltung

    • Reagieren Sie zeitnah auf PING-Ereignisse.
    • Implementieren Sie eine Logik für Wiederverbindungen.
    • Überwachen Sie den Verbindungsstatus.

Fehlerbehebung

  • Stellen Sie eine korrekte WebSocket-Verbindung sicher.
  • Prüfen Sie PING/PONG-Antworten.
  • Überprüfen Sie die API-Anmeldedaten.
  • Prüfen Sie die Verarbeitung von Audio-Chunks.
  • Überprüfen Sie die Kompatibilität des Audioformats.
  • Überwachen Sie die Speichernutzung.
  • Protokollieren Sie alle Ereignisse zur Fehlerbehebung.
  • Implementieren Sie Fehlergrenzen.
  • Prüfen Sie die Registrierung der Ereignishandler.

Detaillierte Implementierungsbeispiele finden Sie in unserer SDK- Dokumentation.