Canal personalizado

Conecta un canal de texto externo a un agente de ElevenLabs mediante webhooks

Descripción general

Canal personalizado conecta un sistema de mensajería externo con un agente de ElevenLabs. Envía mensajes de usuarios a un webhook de ElevenLabs y recibe las respuestas del agente en tu propia ruta HTTPS.

Canal personalizado está en fase alfa.
Canal personalizado no está disponible para agentes o espacios de trabajo que usen el modo de retención cero.

Funcionalidades

FuncionalidadCompatibilidad
Modo de retención cero (ZRM)No compatible — no disponible para espacios de trabajo ni agentes con ZRM
Archivos adjuntos en mensajesNo compatible — los mensajes solo admiten texto

Configuración

1

Abre Canal personalizado

Abre tu agente, selecciona Canales, elige Canal personalizado y haz clic en Añadir activador.

2

Configura el activador

Selecciona una conexión existente o crea una y, a continuación, introduce la URL del webhook de respuesta.

3

Copia las credenciales

Haz clic en Añadir y copia la URL del webhook entrante, el secreto entrante y el secreto de firma saliente.

4

Configura tu servicio

Envía mensajes de usuarios a la URL del webhook entrante con el secreto entrante en X-Webhook-Secret. Usa el secreto de firma saliente para verificar cada respuesta.

Envía un mensaje

Envía una solicitud POST a la URL de webhook generada:

POST /v1/convai/api-integrations/custom_channel/triggers/{trigger_connection_id}/async_message
X-Webhook-Secret: <inbound-secret>
Content-Type: application/json
{
"data": {
"type": "user_message",
"text": "Where is my order?",
"user_identifier": "customer_8427"
},
"user_message_id": "msg_01k1e6z3f4t8n9c2",
"dynamic_variables": {
"order_id": "order_72491"
}
}
CampoObligatorioDescripción
data.typeSíDebe ser user_message.
data.textSíMensaje de usuario no vacío.
data.user_identifierNoIdentificador del usuario externo.
user_message_idSíClave de idempotencia no vacía proporcionada por tu sistema.
conversation_idNoIncluye el ID devuelto para continuar una conversación. Omítelo para iniciar una nueva conversación.
dynamic_variablesNoVariables dinámicas proporcionadas al agente para este turno.

ElevenLabs devuelve 202 Accepted antes de procesar el turno:

{
"conversation_id": "conv_01k1e72d4x8p6v3m",
"status": "queued"
}

Para continuar la conversación, envía otra solicitud con ese conversation_id y un nuevo user_message_id.

Recibe respuestas

ElevenLabs envía una solicitud POST a la URL del webhook de respuesta después de cada turno:

{
"version": "1",
"conversation_id": "conv_01k1e72d4x8p6v3m",
"user_message_ids": ["msg_01k1e6z3f4t8n9c2"],
"status": "completed",
"data": [
{
"type": "agent_response",
"event": {
"agent_response": "Your order is scheduled to arrive tomorrow.",
"response_id": "9f2c1a7e-4b3d-4e8a-9c1f-2d6b8e0a5f31",
"event_id": 4
}
},
{
"type": "agent_tool_response",
"event": {
"tool_name": "end_call",
"tool_call_id": "toolu_01k1e70r4b8y",
"tool_type": "system",
"event_id": 4,
"is_called": true,
"is_error": false,
"is_blocked": false,
"status": "success"
}
}
],
"error": null
}

Si el procesamiento falla, status es failed, data es [] y error contiene una descripción.

data enumera los eventos en el orden del turno. Cada elemento tiene un type y un event:

  • agent_response contiene una intervención del agente. response_id identifica la intervención de forma única, mientras que event_id la asocia a un turno. Une los valores de agent_response si tu canal muestra una burbuja de texto por turno.
  • agent_tool_response informa del resultado de una herramienta y comparte el event_id del turno. Su status puede ser success, error, blocked o skipped. Una respuesta con tool_type: "system", tool_name: "end_call" y status: "success" significa que el agente ha finalizado la conversación.

Varios mensajes entrantes pueden combinarse en un único turno. user_message_ids enumera los ID de los mensajes de usuario a los que responde esta respuesta.

Verifica las firmas de las respuestas

Cada respuesta incluye una cabecera ElevenLabs-Signature:

t=1753876800,v0=<hex-digest>

El resumen es una firma HMAC-SHA256 sobre {timestamp}.{raw_request_body} que usa el secreto de firma saliente. Verifica el cuerpo sin procesar antes de analizar el JSON y rechaza marcas de tiempo obsoletas.

import hashlib
import hmac
import time
def verify_signature(raw_body: bytes, header: str, secret: str) -> None:
values = dict(part.split("=", 1) for part in header.split(","))
timestamp = values["t"]
if abs(time.time() - int(timestamp)) > 30 * 60:
raise ValueError("Stale webhook signature")
expected = hmac.new(
secret.encode(),
timestamp.encode() + b"." + raw_body,
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, values["v0"]):
raise ValueError("Invalid webhook signature")

Comportamiento de entrega

ElevenLabs realiza tres intentos de entrega durante el proceso aproximadamente a los 0, 0,5 y 2 segundos. Una respuesta 2xx marca la entrega como correcta.

Los cuerpos de las solicitudes están limitados a 256 KiB.