Hoppa till navigering

Klienthändelser

Förstå och hantera realtidshändelser som klienten tar emot i konversationsapplikationer.

Klienthändelser är händelser på systemnivå som skickas från servern till klienten och möjliggör kommunikation i realtid. Dessa händelser levererar ljud, transkribering, agentsvar och annan viktig information till klientapplikationen.

Information om händelser som du kan skicka från klienten till servern finns i dokumentationen för händelser från klient till server.

Översikt

Klienthändelser är viktiga för att upprätthålla konversationernas realtidskaraktär. De tillhandahåller allt från initialiseringsmetadata till bearbetat ljud och agentsvar.

Dessa händelser är en del av WebSocket-kommunikationsprotokollet och hanteras automatiskt av våra SDK:er. Det är avgörande att förstå dem för avancerade implementationer och felsökning.

Typer av klienthändelser

  • Skickas automatiskt när en konversation startas
  • Initierar konversationsinställningar och parametrar
// 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
}
}
  • Skickas endast till uppringare som hålls i samtalskön medan agenten är vid sin samtidighetsgräns
  • waiting skickas en gång, efter conversation_initiation_metadata och före vänteljud
  • admitted eller timed_out skickas en gång när väntan avslutas. Efter timed_out stängs WebSocket med kod 4300
  • Skickas alltid till uppringare i kö. Den behöver inte aktiveras i agentens client_events-konfiguration

När en uppringare står i kö kommer vänteljud som vanliga audio-händelser. Använd den här händelsen för att visa ett vänteläge i stället för att behandla vänteljudet som agentspråk.

// 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();
}
});
  • Hälsokontrollhändelse som kräver omedelbart svar
  • Hanteras automatiskt av SDK
  • Används för att upprätthålla WebSocket-anslutningen
// 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');
});
  • Innehåller base64-kodat ljud för uppspelning
  • Inkluderar numeriskt händelse-ID för spårning och sekvensering
  • Hanterar strömning av röstutdata
  • Inkluderar justeringsdata med timinginformation på teckennivå

Via WebRTC-anslutningar skickas inte audio-händelsen eftersom ljud hanteras direkt av LiveKit.

// 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]);
});
});
  • Innehåller slutförda resultat från tal-till-text
  • Representerar kompletta användaryttranden
  • Används för konversationshistorik
// 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);
});
  • Innehåller agentens kompletta meddelande
  • Skickas när meddelandet är klart, så i röstkonversationer kommer det vanligtvis efter att meddelandets ljud redan har börjat strömma.
  • Används för visning och historik

Om du vill visa agentens text medan den skapas använder du händelsen agent_chat_response_part som beskrivs nedan i stället för att vänta på denna händelse.

// 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);
});
  • Innehåller avkortat svar efter avbrott
  • Uppdaterar det visade meddelandet
  • Bevarar konversationens noggrannhet
// 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);
});
  • Innehåller godtyckliga metadata från ett anpassat LLM-svar
  • Skickas endast när du använder en anpassad LLM
  • Måste uttryckligen aktiveras i agentens client_events-konfiguration

Den här händelsen är specifik för anpassade LLM-integreringar. Den låter din anpassade LLM-server skicka ytterligare metadata tillsammans med svaret som kan användas av klientapplikationen.

// 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);
});
  • Representerar ett funktionsanrop som agenten vill att klienten ska köra
  • Innehåller verktygsnamn, verktygsanrops-ID och parametrar
  • Kräver att funktionen körs på klientsidan och att resultatet skickas tillbaka till servern

Om du använder SDK tillhandahålls callbacks för att hantera att resultatet skickas tillbaka till servern.

// 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
});
}
});
  • Anger när agenten har kört en verktygsfunktion
  • Innehåller verktygsmetadata och körningsstatus
  • Ger insyn i agentens verktygsanvändning under konversationer
// 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}`);
}
});
  • Speglar agent_tool_response och strömmar dessutom verktygets fullständiga resultatinnehåll som en sträng i full_tool_result.
  • Visar verktygsutdata i klienten för visning eller vidare bearbetning.
  • Måste uttryckligen aktiveras i agentens client_events-konfiguration.

Den här händelsen exponerar hela verktygsresultatet för klienten och kan innehålla känsliga data. Aktivera den endast när klienten är betrodd att hantera innehållet. Resultat större än 64 KB avkortas automatiskt.

// 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>
);
}
  • Poänghändelse för röstaktivitetsdetektering
  • Anger sannolikheten att användaren talar
  • Värden sträcker sig från 0 till 1, där högre värden anger större säkerhet på att tal förekommer
// Example VAD score event
{
"type": "vad_score",
"vad_score_event": {
"vad_score": 0.95
}
}
  • Anger när agenten har kört en MCP-verktygsfunktion
  • Innehåller verktygsnamn, verktygsanrops-ID och parametrar
  • Anropas med ett av fyra tillstånd: loading, awaiting_approval, success och 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
}
}
  • Strömmar agentens svarstext medan den genereras, som meddelandena start, delta och stop
  • Skickas alltid i läget med endast text; i röstkonversationer måste den uttryckligen aktiveras i agentens client_events-konfiguration
  • Skickas inte medan agenten eller en aktiv procedur använder ett blockerande skyddsräcke, som måste utvärdera hela svaret innan någon del av det släpps
  • response_id identifierar meddelandet som strömmas och matchar response_id för det agent_response som senare bekräftar det
// 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 strömmar resonemang från modellen under konversationer med endast text. Aktivera händelsen i client_events och slå på Sammanfattning av resonemang för agenten. Servern skickar meddelandena start, delta och stop. Den skickar inte denna händelse under röstkonversationer eller medan agenten eller en aktiv procedur använder blockerande skyddsräcken.

Denna händelse och motsvarande SDK-callback är experimentella. Deras beteende och struktur kan ändras i vilken version som helst.

Händelsens innehåll
{
"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- och stopphändelser använder ett tomt text-värde.

Hantera resonemangshändelser
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();
}
},
});
  • Utlöses när agenten har avslutat sitt svar, inklusive väntande verktygsanrop. Efter denna händelse producerar agenten bara ytterligare utdata om användaren ger ny inmatning eller om en turtimeout utlöser en ny tur.
  • Måste uttryckligen aktiveras i agentens client_events-konfiguration
// 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`);
});
  • Utlöses när en överträdelse av ett skyddsräcke avslutar konversationen. Skickas inte när ett skyddsräcke utlöser ett återförsök som lyckas.
  • Händelsen i sig är signalen – den har inget innehåll utöver fältet type.
  • Måste uttryckligen aktiveras i agentens client_events-konfiguration.
// 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.');
},
});

Händelseflöde

Här är en typisk händelsesekvens under en konversation:

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

När en agent har nått sin samtidighetsgräns och samtalsköer är aktiverade skickar servern queue_status-händelser mellan conversation_initiation_metadata och den första audio-händelsen. Kömusik levereras som audio-händelser tills uppringaren släpps in.

Rekommenderade metoder

  1. Felhantering

    • Implementera korrekt felhantering för varje händelsetyp
    • Logga viktiga händelser för felsökning
    • Hantera anslutningsavbrott på ett smidigt sätt
  2. Ljudhantering

    • Buffra ljudsegment på lämpligt sätt
    • Implementera korrekt rensning vid avbrott
    • Hantera ljudresurser
  3. Anslutningshantering

    • Svara snabbt på PING-händelser
    • Implementera logik för återanslutning
    • Övervaka anslutningens status

Felsökning

  • Kontrollera att WebSocket-anslutningen är korrekt
  • Kontrollera PING/PONG-svar
  • Verifiera API-autentiseringsuppgifter
  • Kontrollera hanteringen av ljudsegment
  • Verifiera kompatibiliteten för ljudformat
  • Övervaka minnesanvändningen
  • Logga alla händelser för felsökning
  • Implementera felgränser
  • Kontrollera registreringen av händelsehanterare

Se vår SDK- dokumentation för detaljerade implementationsexempel.