Eventos del cliente

Conoce y gestiona los eventos en tiempo real que recibe el cliente durante las aplicaciones conversacionales.

Los eventos del cliente son eventos de nivel de sistema enviados del servidor al cliente que facilitan la comunicación en tiempo real. Estos eventos entregan audio, transcripciones, respuestas del agente y otra información crítica a la aplicación cliente.

Para obtener información sobre los eventos que puedes enviar del cliente al servidor, consulta la documentación de eventos del cliente al servidor.

Descripción general

Los eventos del cliente son esenciales para mantener la naturaleza en tiempo real de las conversaciones. Proporcionan desde metadatos de inicialización hasta audio procesado y respuestas del agente.

Estos eventos forman parte del protocolo de comunicación WebSocket y nuestros SDK los gestionan automáticamente. Comprenderlos es fundamental para implementaciones avanzadas y depuración.

Tipos de eventos de cliente

  • Se envía automáticamente al iniciar una conversación
  • Inicializa la configuración y los parámetros de la conversación
// 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
}
}
  • Se envía solo a quienes llaman y permanecen en la cola de llamadas mientras el agente está en su límite de simultaneidad
  • waiting se envía una vez, después de conversation_initiation_metadata y antes de cualquier audio de espera
  • admitted o timed_out se envía una vez cuando termina la espera. Después de timed_out, se cierra el WebSocket con el código 4300
  • Siempre se envía a quienes llaman y están en cola. No es necesario activarlo en la configuración client_events del agente

Mientras quien llama está en cola, el audio de espera llega como eventos audio normales. Usa este evento para mostrar un estado de espera en lugar de tratar el audio de espera como habla del agente.

// 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();
}
});
  • Evento de comprobación de estado que requiere una respuesta inmediata
  • El SDK lo gestiona automáticamente
  • Se utiliza para mantener la conexión WebSocket
// 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');
});
  • Contiene audio codificado en base64 para su reproducción
  • Incluye un ID de evento numérico para seguimiento y secuenciación
  • Gestiona el streaming de la salida de voz
  • Incluye datos de alineación con información de tiempo a nivel de carácter

En conexiones WebRTC, el evento audio no se envía, ya que LiveKit gestiona el audio directamente.

// 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]);
});
});
  • Contiene resultados finalizados de voz a texto
  • Representa intervenciones completas del usuario
  • Se utiliza para el historial de la conversación
// 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);
});
  • Contiene el mensaje completo del agente
  • Se envía cuando el mensaje ha terminado, por lo que en las conversaciones de voz suele llegar después de que el audio del mensaje haya empezado a transmitirse.
  • Se utiliza para mostrar información y para el historial

Para mostrar el texto del agente a medida que se genera, usa el evento agent_chat_response_part descrito a continuación en lugar de esperar a este evento.

// 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);
});
  • Contiene la respuesta truncada tras una interrupción
  • Actualiza el mensaje mostrado
  • Mantiene la precisión de la conversación
// 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);
});
  • Contiene metadatos arbitrarios de una respuesta de LLM personalizada
  • Solo se envía al usar una LLM personalizada
  • Debe activarse explícitamente en la configuración client_events del agente

Este evento es específico de las integraciones de LLM personalizadas. Permite que tu servidor de LLM personalizada transfiera metadatos adicionales junto con la respuesta que puede utilizar la aplicación cliente.

// 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);
});
  • Representa una llamada de función que el agente quiere que ejecute el cliente
  • Contiene el nombre de la herramienta, el ID de llamada de herramienta y los parámetros
  • Requiere ejecutar la función en el lado cliente y enviar el resultado de vuelta al servidor

Si usas el SDK, se proporcionan callbacks para gestionar el envío del resultado de vuelta al servidor.

// 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
});
}
});
  • Indica cuándo el agente ha ejecutado una función de herramienta
  • Contiene metadatos de la herramienta y el estado de ejecución
  • Ofrece visibilidad sobre el uso de herramientas del agente durante las conversaciones
// 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}`);
}
});
  • Replica agent_tool_response y, además, transmite la carga útil completa del resultado de la herramienta como una cadena en full_tool_result.
  • Expone la salida de la herramienta en el cliente para mostrarla o procesarla posteriormente.
  • Debe activarse explícitamente en la configuración client_events del agente.

Este evento expone el resultado completo de la herramienta al cliente y puede contener datos sensibles. Actívalo solo si el cliente es de confianza para gestionar la carga útil. Los resultados de más de 64 KB se truncan automáticamente.

// 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>
);
}
  • Evento de puntuación de detección de actividad de voz
  • Indica la probabilidad de que el usuario esté hablando
  • Los valores van de 0 a 1; los valores más altos indican una mayor certeza de habla
// Example VAD score event
{
"type": "vad_score",
"vad_score_event": {
"vad_score": 0.95
}
}
  • Indica cuándo el agente ha ejecutado una función de herramienta MCP
  • Contiene el nombre de la herramienta, el ID de llamada de herramienta y los parámetros
  • Se llama con uno de cuatro estados: loading, awaiting_approval, success y 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
}
}
  • Transmite el texto de la respuesta del agente a medida que se genera, como mensajes start, delta y stop
  • Siempre se envía en modo de solo texto; en las conversaciones de voz debe activarse explícitamente en la configuración client_events del agente
  • No se envía mientras el agente o un procedimiento activo usan una barrera de protección bloqueante, que debe evaluar toda la respuesta antes de publicar cualquier parte
  • response_id identifica el mensaje que se transmite y coincide con el response_id de agent_response que posteriormente lo confirma
// 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 transmite el razonamiento proporcionado por el modelo durante conversaciones de solo texto. Activa el evento en client_events y la resumen de razonamiento para el agente. El servidor envía mensajes start, delta y stop. No envía este evento durante conversaciones de voz ni mientras el agente o un procedimiento activo usan barreras de protección bloqueantes.

Este evento y el callback de SDK correspondiente son experimentales. Su comportamiento y estructura pueden cambiar en cualquier versión.

Carga útil del evento
{
"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
}
}

Los eventos de inicio y parada usan un valor text vacío.

Gestionar eventos de razonamiento
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();
}
},
});
  • Se activa cuando el agente ha terminado su respuesta, incluidas las llamadas de herramientas pendientes. Tras este evento, el agente solo generará más salida si el usuario proporciona una nueva entrada o si un tiempo de espera de turno activa un nuevo turno.
  • Debe activarse explícitamente en la configuración client_events del agente
// 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`);
});
  • Se activa cuando una infracción de una barrera de protección termina la conversación. No se envía cuando una barrera de protección activa un reintento que tiene éxito.
  • El evento en sí es la señal: no contiene ninguna carga útil más allá del campo type.
  • Debe activarse explícitamente en la configuración client_events del agente.
// 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.');
},
});

Flujo de eventos

Esta es una secuencia típica de eventos durante una conversación:

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

Cuando un agente alcanza su límite de concurrencia y está activada la cola de llamadas, el servidor envía eventos queue_status entre conversation_initiation_metadata y el primer evento audio. El audio de espera se envía como eventos audio hasta que se admite a la persona que llama.

Buenas prácticas

  1. Gestión de errores

    • Implementa una gestión de errores adecuada para cada tipo de evento.
    • Registra los eventos importantes para facilitar la depuración.
    • Gestiona las interrupciones de conexión correctamente.
  2. Gestión de audio

    • Almacena en búfer los fragmentos de audio de forma adecuada.
    • Implementa una limpieza adecuada cuando haya una interrupción.
    • Gestiona los recursos de audio.
  3. Gestión de conexiones

    • Responde rápidamente a los eventos PING.
    • Implementa una lógica de reconexión.
    • Supervisa el estado de la conexión.

Resolución de problemas

  • Asegúrate de que la conexión WebSocket sea correcta.
  • Comprueba las respuestas PING/PONG.
  • Verifica las credenciales de la API.
  • Comprueba la gestión de los fragmentos de audio.
  • Verifica la compatibilidad del formato de audio.
  • Supervisa el uso de memoria.
  • Registra todos los eventos para facilitar la depuración.
  • Implementa límites de error.
  • Comprueba el registro de los gestores de eventos.

Para ver ejemplos detallados de implementación, consulta la documentación del SDK.