Eventos do cliente

Entenda e processe eventos em tempo real recebidos pelo cliente durante aplicações conversacionais.

Eventos do cliente são eventos de nível de sistema enviados do servidor para o cliente que facilitam a comunicação em tempo real. Esses eventos fornecem áudio, transcrição, respostas do agente e outras informações essenciais à aplicação cliente.

Para saber mais sobre os eventos que você pode enviar do cliente para o servidor, consulte a documentação de eventos do cliente para o servidor.

Visão geral

Os eventos do cliente são essenciais para manter o caráter em tempo real das conversas. Eles fornecem desde metadados de inicialização até áudio processado e respostas do agente.

Esses eventos fazem parte do protocolo de comunicação WebSocket e são processados automaticamente pelos nossos SDKs. Compreendê-los é fundamental para implementações avançadas e depuração.

Tipos de eventos do cliente

  • Enviado automaticamente ao iniciar uma conversa
  • Inicializa as configurações e os parâmetros da conversa
// 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
}
}
  • Enviado apenas para pessoas que ligam e estão na fila de chamadas, enquanto o agente está no limite de simultaneidade
  • waiting é enviado uma vez, após conversation_initiation_metadata e antes de qualquer áudio de espera
  • admitted ou timed_out é enviado uma vez quando a espera termina. Após timed_out, o WebSocket é fechado com o código 4300
  • Sempre enviado para pessoas que estão na fila. Não é necessário ativá-lo na configuração client_events do agente

Enquanto uma pessoa que liga está na fila, o áudio de espera chega como eventos audio regulares. Use este evento para mostrar um estado de espera, em vez de tratar o áudio de espera como fala do 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 verificação de integridade que exige resposta imediata
  • Gerenciado automaticamente pelo SDK
  • Usado para manter a conexão 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');
});
  • Contém áudio codificado em base64 para reprodução
  • Inclui um ID de evento numérico para rastreamento e sequenciamento
  • Processa streaming de saída de voz
  • Inclui dados de alinhamento com informações de tempo no nível dos caracteres

Em conexões WebRTC, o evento audio não é enviado, pois o áudio é processado diretamente pelo 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]);
});
});
  • Contém resultados finalizados de conversão de fala em texto
  • Representa enunciados completos do usuário
  • Usado para o histórico da conversa
// 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);
});
  • Contém a mensagem completa do agente
  • É enviado quando a mensagem termina; por isso, em conversas por voz, geralmente chega depois que o áudio da mensagem já começou a ser transmitido.
  • Usado para exibição e histórico

Para exibir o texto do agente conforme ele é produzido, use o evento agent_chat_response_part descrito abaixo, em vez de esperar por 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);
});
  • Contém a resposta truncada após uma interrupção
  • Atualiza a mensagem exibida
  • Mantém a precisão da conversa
// 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);
});
  • Contém metadados arbitrários de uma resposta de LLM personalizada
  • Enviado apenas ao usar uma LLM personalizada
  • Deve ser explicitamente ativado na configuração client_events do agente

Este evento é específico de integrações com LLMs personalizadas. Ele permite que seu servidor de LLM personalizada transmita metadados adicionais junto com a resposta, que podem ser usados pelo aplicativo 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 uma chamada de função que o agente quer que o cliente execute
  • Contém o nome da ferramenta, o ID da chamada da ferramenta e os parâmetros
  • Exige a execução da função no cliente e o envio do resultado de volta ao servidor

Se você estiver usando o SDK, são fornecidos callbacks para processar o envio do resultado de volta ao 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 quando o agente executou uma função de ferramenta
  • Contém metadados da ferramenta e o status de execução
  • Oferece visibilidade sobre o uso de ferramentas pelo agente durante as conversas
// 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 e também transmite a carga completa do resultado da ferramenta como uma string em full_tool_result.
  • Disponibiliza a saída da ferramenta no cliente para exibição ou processamento posterior.
  • Deve ser explicitamente ativado na configuração client_events do agente.

Este evento expõe o resultado completo da ferramenta ao cliente e pode conter dados sensíveis. Ative-o apenas quando o cliente for confiável para processar a carga. Resultados maiores que 64 KB são truncados automaticamente.

// 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 pontuação de Detecção de Atividade de Voz
  • Indica a probabilidade de o usuário estar falando
  • Os valores variam de 0 a 1, e valores mais altos indicam maior confiança de fala
// Example VAD score event
{
"type": "vad_score",
"vad_score_event": {
"vad_score": 0.95
}
}
  • Indica quando o agente executou uma função de ferramenta MCP
  • Contém o nome da ferramenta, o ID da chamada da ferramenta e os parâmetros
  • Chamado com um de quatro estados: loading, awaiting_approval, success e 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 o texto da resposta do agente conforme ele é gerado, como mensagens start, delta e stop
  • Sempre enviado no modo somente texto; em conversas por voz, deve ser explicitamente ativado na configuração client_events do agente
  • Não é enviado enquanto o agente ou um procedimento ativo usa uma proteção bloqueadora, que precisa avaliar toda a resposta antes que qualquer parte dela seja liberada
  • response_id identifica a mensagem que está sendo transmitida e corresponde ao response_id de agent_response, que a confirma posteriormente
// 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 o raciocínio fornecido pelo modelo durante conversas somente de texto. Ative o evento em client_events e habilite o resumo do raciocínio para o agente. O servidor envia mensagens start, delta e stop. Ele não envia este evento durante conversas por voz nem enquanto o agente ou um procedimento ativo usa proteções bloqueadoras.

Este evento e o callback correspondente do SDK são experimentais. Seu comportamento e formato podem mudar em qualquer lançamento.

Carga do 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
}
}

Eventos de início e parada usam um valor text vazio.

Processar eventos de raciocínio
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();
}
},
});
  • Disparado quando o agente conclui sua resposta, incluindo quaisquer chamadas de ferramenta pendentes. Após este evento, o agente só produzirá mais saída se o usuário fornecer uma nova entrada ou se um tempo limite de turno iniciar um novo turno.
  • Deve ser explicitamente ativado na configuração client_events do 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`);
});
  • Disparado quando uma violação de proteção encerra a conversa. Não é enviado quando uma proteção dispara uma nova tentativa bem-sucedida.
  • O próprio evento é o sinal: ele não carrega nenhuma carga além do campo type.
  • Deve ser explicitamente ativado na configuração client_events do 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.');
},
});

Fluxo de eventos

Veja uma sequência típica de eventos durante uma conversa:

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

Quando um agente está no limite de simultaneidade e a fila de chamadas está ativada, o servidor envia eventos queue_status entre conversation_initiation_metadata e o primeiro evento audio. O áudio de espera é enviado como eventos audio até que a chamada seja admitida.

Boas práticas

  1. Tratamento de erros

    • Implemente o tratamento adequado de erros para cada tipo de evento
    • Registre eventos importantes para depuração
    • Lide adequadamente com interrupções de conexão
  2. Gerenciamento de áudio

    • Armazene os blocos de áudio em buffer adequadamente
    • Implemente uma limpeza adequada em caso de interrupção
    • Gerencie os recursos de áudio
  3. Gerenciamento de conexão

    • Responda prontamente aos eventos PING
    • Implemente a lógica de reconexão
    • Monitore a integridade da conexão

Solução de problemas

  • Garanta uma conexão WebSocket adequada
  • Verifique as respostas PING/PONG
  • Confira as credenciais da API
  • Verifique o tratamento dos blocos de áudio
  • Confira a compatibilidade do formato de áudio
  • Monitore o uso de memória
  • Registre todos os eventos para depuração
  • Implemente limites de erro
  • Verifique o registro dos manipuladores de eventos

Para ver exemplos detalhados de implementação, consulte a documentação do SDK.