Azure Communication Services
Permite que usuarios llamen a un número de teléfono al que responde tu agente de ElevenLabs mediante ACS Call Automation.
Descripción general
Este enfoque proporciona a tu agente un número de teléfono. Quien llama lo marca, Azure Communication Services (ACS) responde con streaming multimedia bidireccional, y un pequeño puente transmite audio PCM entre ACS y el agente de ElevenLabs mediante el protocolo WebSocket de agentes estándar. Es el patrón de centro de contacto/IVR, la misma arquitectura que una implementación de trunking SIP, con ACS como operador.
También se conecta a Teams de dos formas: un usuario de Teams con un plan de llamadas puede marcar directamente el número de ACS, o puedes poner delante del número Teams Phone Extensibility para que las llamadas a una cuenta de recursos de Teams se dirijan a ACS.
ACS aprovisiona números de PSTN solo en un conjunto limitado de países. Si no hay un número disponible en tu región, utiliza un proveedor SIP con trunking SIP o el bot de llamadas de Graph.
Cómo funciona
El audio es PCM mono de 16 kHz en ambos extremos (el formato de entrada/salida del agente es pcm_16000), por lo que se transmite como base64 sin remuestreo.
El puente expone estas rutas:
Requisitos
- Una suscripción de Azure de pago (MCA / EA / Pay-As-You-Go); las suscripciones gratuitas, de prueba o patrocinadas no pueden comprar números.
- Un recurso de Azure Communication Services.
- Un host HTTPS para el puente con un WebSocket público (Azure Container Apps, App Service o una VM).
- Un agente de ElevenLabs configurado en PCM 16000 Hz en ambos extremos: formato de salida TTS en la pestaña Voz y formato de audio de entrada de usuario en la pestaña Avanzado.
Permisos y roles
Con el rol Colaborador (no Propietario), az containerapp up no puede crear la asignación del rol de
extracción de ACR de identidad administrada. Activa el usuario administrador del registro y asígnalo en su lugar; consulta la advertencia del paso 2.
Paso 1: aprovisiona el recurso y el número de ACS
Compra un número en el recurso (Portal → tu recurso ACS → Números de teléfono → Obtener, o el SDK de phone-numbers). Para un agente que responde llamadas, basta con un número con llamadas entrantes; añade la capacidad saliente si también quieres usar /api/outboundCall.

Para verificarlo desde la CLI (requiere az extension add --name communication) y obtener la cadena de conexión que el puente utiliza como ACS_CONNECTION_STRING:
Paso 2: despliega el puente
El puente es una pequeña aplicación Flask + flask-sock que utiliza azure-communication-callautomation. El núcleo del flujo entrante:
En el socket /ws, transmite PCM16 en ambos sentidos: reenvía los frames AudioData de ACS a ElevenLabs como {"user_audio_chunk": "<base64>"} y devuelve el audio del agente como {"Kind":"AudioData","AudioData":{"Data":"<base64>"},"StopAudio":null}. El primer frame que envía ACS es AudioMetadata (el formato negociado): regístralo e ignóralo. El lado de ElevenLabs utiliza el protocolo WebSocket de agentes estándar.
ACS usa distintos formatos de mayúsculas y minúsculas en el JSON según la dirección: los frames entrantes que envía usan camelCase (kind,
audioData.data), mientras que los frames salientes que espera usan PascalCase (Kind, AudioData.Data,
StopAudio). Mantén ambos formatos diferenciados: la retransmisión de abajo los refleja.
Esta retransmisión es intencionadamente mínima. Para producción, añade registros, reconexión y una desconexión ordenada. Consulta la referencia completa de mensajes en la documentación de WebSocket.
EL_WS se conecta a un agente público. Para un agente privado, haz que el puente solicite una URL firmada de corta duración
en el servidor: GET /v1/convai/conversation/get-signed-url?agent_id=... con tu clave de API,
y conéctate en su lugar a la URL devuelta. Para residencia de
datos, configura ELEVENLABS_ORIGIN con tu host de
residencia (wss://api.eu.residency.elevenlabs.io, .in. o .sg.): las solicitudes de URL firmada
usan el host https:// correspondiente.
Despliega en Azure Container Apps y captura el FQDN público:
Después, configura BRIDGE_PUBLIC_HOST=$FQDN y la cadena de conexión de ACS (como secreto) en la aplicación.
Con el rol Colaborador (no Propietario), az containerapp up no puede crear el rol de extracción de ACR
de identidad administrada. Activa el usuario administrador del registro (az acr update --admin-enabled true) y asígnalo
con az containerapp registry set; después ejecuta az containerapp update --image ....
Paso 3: dirige IncomingCall al puente
Crea una suscripción de Event Grid en el recurso ACS que publique IncomingCall en el puente. El protocolo de validación del puente (anterior) completa la suscripción automáticamente.
La suscripción aparece en el panel Events del recurso ACS:

Marca el número: el agente responderá.
Conexión con Teams
- Marcación directa: un usuario de Teams con Teams Phone y un plan de llamadas puede marcar el número de ACS como cualquier número externo.
- Cuenta de recursos de Teams (TPE): vincula una cuenta de recursos de Teams al recurso ACS con Teams Phone Extensibility para que las llamadas a la cuenta de recursos activen el mismo flujo
IncomingCall→ puente.
Fin de la llamada
Cuando el agente termina la conversación (por ejemplo, mediante su herramienta Finalizar llamada), ElevenLabs cierra el WebSocket. Cuelga el extremo de ACS para que quien llama no quede en una línea muerta:
Transferencia asistida a una persona
Las herramientas de transferencia nativas de ElevenLabs solo se aplican cuando ElevenLabs gestiona la telefonía, así que aquí el agente activa una herramienta de cliente personalizada (por ejemplo, transfer_to_human) que tu puente gestiona añadiendo a la persona a la llamada activa con add_participant (asistida), en lugar de realizar una transferencia ciega:
ACS envía devoluciones de llamada AddParticipantSucceeded / AddParticipantFailed a /api/callbacks. Devuelve un client_tool_result al agente para que pueda decir su frase de transferencia. Consulta las herramientas del sistema para configurar el lado del agente.
Configura la protección de transferencia en el momento en que se active la herramienta (antes de llamar a add_participant), o un cierre rápido del
WebSocket de EL podría competir con el cuelgue y finalizar la llamada antes de que se una la persona.
Solución de problemas
No llega ningún IncomingCall al puente
Confirma que la suscripción de Event Grid se aprovisionó (provisioningState: Succeeded) y que
/api/incomingCall del puente devolvió el eco de validación. Confirma que el número tiene llamadas
entrantes y está en el mismo recurso ACS en el que se encuentra la suscripción. En la pestaña
Filters de la suscripción, los tipos de evento deben incluir Incoming Call:

CreateCallFailed / AddParticipantFailed para un número internacional
CreateCallFailed / AddParticipantFailed para un número internacional
Las llamadas salientes de ACS a algunos destinos (por ejemplo, India) tienen restricciones o son intermitentes. Utiliza un destino compatible o conecta el extremo de la persona mediante un número SIP/de operador. La lógica del puente no se ve afectada: es un fallo a nivel de operador en el extremo saliente.
El audio está distorsionado o a una velocidad incorrecta
Ambos lados deben ser PCM mono de 16 kHz. Configura el formato de entrada/salida del agente en pcm_16000; el
puente registra el formato negociado desde conversation_initiation_metadata.
No puedo comprar un número / el número no está disponible en mi país
La compra de números requiere un tipo de suscripción de pago (MCA/EA/PAYG). Si ACS no ofrece números en tu país, utiliza un proveedor SIP.