Azure Communication Services
Laat gebruikers een telefoonnummer bellen dat je ElevenLabs-agent beantwoordt, via ACS Call Automation.
Overzicht
Met deze aanpak krijgt je agent een telefoonnummer. Een beller belt dit nummer, Azure Communication Services (ACS) neemt op met bidirectionele mediastreaming, en een kleine bridge stuurt PCM-audio door tussen ACS en de ElevenLabs-agent via het standaard agent WebSocket-protocol. Dit is het contactcenter-/IVR-patroon — dezelfde opzet als een implementatie met SIP-trunking, met ACS als provider.
Het verbindt ook op twee manieren met Teams: een Teams-gebruiker met een Calling Plan kan het ACS-nummer rechtstreeks bellen, of je kunt het nummer koppelen aan Teams Phone Extensibility, zodat oproepen naar een Teams-resourceaccount naar ACS worden gerouteerd.
ACS levert PSTN-nummers alleen in een beperkt aantal landen. Als er in je regio geen nummer beschikbaar is, gebruik dan een SIP-provider met SIP- trunking, of de Graph calling- bot.
Zo werkt het
Audio is op beide kanten PCM 16 kHz mono (het invoer-/uitvoerformaat van de agent is pcm_16000), en wordt dus als base64 doorgestuurd zonder resampling.
De bridge biedt deze routes:
Vereisten
- Een betaald Azure-abonnement (MCA / EA / Pay-As-You-Go) — gratis/proef-/sponsorabonnementen kunnen geen nummers kopen.
- Een Azure Communication Services-resource.
- Een HTTPS-host voor de bridge met een openbare WebSocket (Azure Container Apps, App Service of een VM).
- Een ElevenLabs-agent ingesteld op PCM 16000 Hz aan beide kanten: TTS-uitvoerformaat op het tabblad Voice, audio-invoerformaat van de gebruiker op het tabblad Advanced.
Machtigingen en rollen
Met Contributor (niet Owner) kan az containerapp up de ACR-pullroltoewijzing voor de managed identity niet maken.
Schakel in plaats daarvan de registry admin-gebruiker in en koppel die — zie de waarschuwing in stap 2.
Stap 1 — De ACS-resource en het nummer inrichten
Koop een nummer in de resource (Portal → je ACS-resource → Phone numbers → Get, of via de phone-numbers SDK). Voor een agent die oproepen beantwoordt, volstaat een nummer met inbound calling; voeg de mogelijkheid outbound toe als je ook /api/outboundCall wilt gebruiken.

Om dit via de CLI te verifiëren (vereist az extension add --name communication) en de connection string op te halen die de bridge als ACS_CONNECTION_STRING gebruikt:
Stap 2 — De bridge implementeren
De bridge is een kleine Flask- + flask-sock-app die azure-communication-callautomation gebruikt. De kern van de inkomende flow:
Stuur op de /ws-socket PCM16 in beide richtingen door: stuur ACS-frames van AudioData door naar ElevenLabs als {"user_audio_chunk": "<base64>"}, en stuur de audio van de agent terug als {"Kind":"AudioData","AudioData":{"Data":"<base64>"},"StopAudio":null}. Het eerste frame dat ACS verstuurt is AudioMetadata (het overeengekomen formaat) — log dit en negeer het. De ElevenLabs-kant gebruikt het standaard agent WebSocket-protocol.
ACS gebruikt per richting verschillende JSON-hoofdlettergebruik: inkomende frames die het verstuurt gebruiken camelCase (kind,
audioData.data), terwijl uitgaande frames die het verwacht PascalCase gebruiken (Kind, AudioData.Data,
StopAudio). Houd de twee vormen gescheiden — de onderstaande relay volgt dit.
Deze relay is bewust minimaal. Voeg voor productie logging, herverbinding en gecontroleerd afsluiten toe. De volledige berichtreferentie staat in de WebSocket- documentatie.
EL_WS maakt verbinding met een openbare agent. Laat de bridge voor een privéagent server-side een kortdurende
ondertekende URL aanvragen — GET /v1/convai/conversation/get-signed-url?agent_id=... met je API-
sleutel — en maak in plaats daarvan verbinding met de geretourneerde URL. Stel bij data-
residency ELEVENLABS_ORIGIN in op je
residency-host (wss://api.eu.residency.elevenlabs.io, .in. of .sg.) — aanvragen voor ondertekende URL’s
gebruiken de bijbehorende https://-host.
Implementeer in Azure Container Apps en leg de openbare FQDN vast:
Stel vervolgens BRIDGE_PUBLIC_HOST=$FQDN en de ACS-connection string (als secret) in voor de app.
Met Contributor (niet Owner) kan az containerapp up de ACR-pullrol voor de managed identity niet maken.
Schakel de registry admin-gebruiker in (az acr update --admin-enabled true) en koppel deze
met az containerapp registry set. Gebruik daarna az containerapp update --image ....
Stap 3 — IncomingCall naar de bridge routeren
Maak een Event Grid-abonnement voor de ACS-resource dat IncomingCall naar de bridge stuurt. De validatiehandshake van de bridge (hierboven) voltooit het abonnement automatisch.
Het abonnement verschijnt onder de blade Events van de ACS-resource:

Bel het nummer — de agent neemt op.
Verbinden met Teams
- Rechtstreeks bellen: een Teams-gebruiker met Teams Phone + een Calling Plan kan het ACS-nummer bellen zoals elk extern nummer.
- Teams-resourceaccount (TPE): koppel een Teams-resourceaccount aan de ACS-resource met Teams Phone Extensibility, zodat oproepen naar het resourceaccount dezelfde flow
IncomingCall→ bridge starten.
Einde van het gesprek
Wanneer de agent het gesprek beëindigt (bijvoorbeeld met de tool End Call), sluit ElevenLabs de WebSocket. Hang de ACS-kant op zodat de beller niet op een dode lijn achterblijft:
Warme overdracht naar een persoon
De ingebouwde overdrachtstools van ElevenLabs werken alleen wanneer ElevenLabs de telefonie beheert. Hier activeert de agent dus een aangepaste clienttool (bijvoorbeeld transfer_to_human) die je bridge afhandelt door de persoon met add_participant toe te voegen aan het actieve gesprek (warm), in plaats van een blinde overdracht:
ACS stuurt callbacks voor AddParticipantSucceeded / AddParticipantFailed naar /api/callbacks. Stuur een client_tool_result terug naar de agent zodat deze de overdrachtszin kan uitspreken. Zie systeemtools voor de configuratie aan de agentzijde.
Stel de overdrachtsbeveiliging in zodra de tool wordt geactiveerd (vóór je add_participant aanroept), anders kan een snelle sluiting van de EL-
WebSocket concurreren met het ophangen en de oproep verbreken voordat de persoon deelneemt.
Problemen oplossen
Geen IncomingCall bereikt de bridge
Controleer of het Event Grid-abonnement is ingericht (provisioningState: Succeeded) en of de
/api/incomingCall van de bridge de validatie-echo heeft teruggegeven. Controleer of het nummer inbound
calling ondersteunt en zich in dezelfde ACS-resource bevindt als waarop het abonnement is ingesteld. Op het tabblad
Filters van het abonnement moeten de eventtypen Incoming Call bevatten:

CreateCallFailed / AddParticipantFailed voor een internationaal nummer
CreateCallFailed / AddParticipantFailed voor een internationaal nummer
Uitgaande ACS-oproepen naar bepaalde bestemmingen (zoals India) zijn beperkt of onregelmatig. Gebruik een ondersteunde bestemming, of laat de menselijke kant via een SIP-/Operator-nummer lopen. De logica van de bridge blijft ongewijzigd — het gaat om een fout op providerniveau aan de uitgaande kant.
Audio is vervormd of heeft de verkeerde snelheid
Beide kanten moeten PCM 16 kHz mono gebruiken. Stel het invoer-/uitvoerformaat van de agent in op pcm_16000; de
bridge logt het overeengekomen formaat uit conversation_initiation_metadata.
Kan geen nummer kopen / nummer niet beschikbaar in mijn land
Voor het kopen van nummers is een betaald abonnementstype nodig (MCA/EA/PAYG). Als ACS geen nummers aanbiedt in je land, gebruik dan een SIP-provider.