Azure Communication Services
Pozwól użytkownikom dzwonić na numer telefonu odbierany przez twojego agenta ElevenLabs za pomocą ACS Call Automation.
Przegląd
To podejście daje agentowi numer telefonu. Dzwoniący wybiera ten numer, Azure Communication Services (ACS) odbiera połączenie przez dwukierunkowe przesyłanie strumieniowe mediów, a mały most przekazuje audio PCM między ACS a agentem ElevenLabs przez standardowy protokół WebSocket agenta. To model contact center / IVR — podobny do wdrożenia SIP trunking, gdzie ACS jest operatorem.
Łączy się też z Teams na dwa sposoby: użytkownik Teams z Calling Plan może zadzwonić bezpośrednio na numer ACS albo możesz udostępnić numer przez Teams Phone Extensibility, aby połączenia z kontem zasobu Teams trafiały do ACS.
ACS udostępnia numery PSTN tylko w ograniczonej liczbie krajów. Jeśli numer nie jest dostępny w twoim regionie, użyj dostawcy SIP z SIP trunking albo bota połączeń Graph.
Jak to działa
Audio ma format PCM 16 kHz mono po obu stronach (format wejścia/wyjścia agenta to pcm_16000), więc jest przesyłane jako base64 bez resamplingu.
Most udostępnia te ścieżki:
Wymagania
- Płatna subskrypcja Azure (MCA / EA / Pay-As-You-Go) — bezpłatne, próbne i sponsorskie subskrypcje nie mogą kupować numerów.
- Zasób Azure Communication Services.
- Host HTTPS dla mostu z publicznym WebSocketem (Azure Container Apps, App Service lub VM).
- Agent ElevenLabs ustawiony na PCM 16000 Hz po obu stronach: format wyjścia TTS na karcie Voice, format audio wejścia użytkownika na karcie Advanced.
Uprawnienia i role
Przy roli Contributor (nie Owner) az containerapp up nie może utworzyć przypisania roli ACR pull
dla tożsamości zarządzanej. Włącz użytkownika administratora rejestru i przypnij go zamiast tego — zobacz ostrzeżenie w kroku 2.
Krok 1 — Utwórz zasób ACS i numer
Kup numer w zasobie (Portal → twój zasób ACS → Phone numbers → Get albo SDK phone-numbers). Dla agenta, który odbiera połączenia, wystarczy numer z opcją inbound calling; dodaj funkcję outbound, jeśli chcesz też używać /api/outboundCall.

Aby sprawdzić to z CLI (wymaga az extension add --name communication) i pobrać connection string używany przez most jako ACS_CONNECTION_STRING:
Krok 2 — Wdróż most
Most to mała aplikacja Flask + flask-sock używająca azure-communication-callautomation. Główna część przepływu przychodzącego:
W gnieździe /ws przekazuj PCM16 w obie strony: wysyłaj ramki ACS AudioData do ElevenLabs jako {"user_audio_chunk": "<base64>"}, a audio agenta odsyłaj jako {"Kind":"AudioData","AudioData":{"Data":"<base64>"},"StopAudio":null}. Pierwsza ramka wysyłana przez ACS to AudioMetadata (uzgodniony format) — zapisz ją w logach i zignoruj. Po stronie ElevenLabs używany jest standardowy protokół WebSocket agenta.
ACS używa innej wielkości liter w JSON w zależności od kierunku: ramki przychodzące, które wysyła, są w camelCase (kind,
audioData.data), a ramki wychodzące, których oczekuje, w PascalCase (Kind, AudioData.Data,
StopAudio). Nie mieszaj tych dwóch formatów — poniższy przekaźnik je odwzorowuje.
Ten przekaźnik jest celowo prosty. W środowisku produkcyjnym dodaj logowanie, ponowne łączenie i łagodne zamykanie. Pełna lista komunikatów jest w dokumentacji WebSocket .
EL_WS łączy się z publicznym agentem. W przypadku agenta prywatnego most powinien po stronie serwera pobrać krótkotrwały
podpisany URL — GET /v1/convai/conversation/get-signed-url?agent_id=... z twoim kluczem API
— i połączyć się z otrzymanym URL-em. W przypadku rezydencji
danych ustaw ELEVENLABS_ORIGIN na host rezydencji
(wss://api.eu.residency.elevenlabs.io, .in. lub .sg.) — żądania podpisanego URL używają odpowiadającego hosta https://.
Wdróż w Azure Container Apps i zapisz publiczny FQDN:
Następnie ustaw w aplikacji BRIDGE_PUBLIC_HOST=$FQDN oraz connection string ACS (jako sekret).
Przy roli Contributor (nie Owner) az containerapp up nie może utworzyć roli ACR
pull dla tożsamości zarządzanej. Włącz użytkownika administratora rejestru (az acr update --admin-enabled true) i przypnij go
przez az containerapp registry set, a potem uruchom az containerapp update --image ....
Krok 3 — Przekieruj IncomingCall do mostu
Utwórz subskrypcję Event Grid w zasobie ACS, która wysyła IncomingCall do mostu. Walidacja mostu (powyżej) automatycznie kończy tworzenie subskrypcji.
Subskrypcja pojawi się w widoku Events zasobu ACS:

Zadzwoń na numer — agent odbierze.
Łączenie z Teams
- Wybieranie bezpośrednie: użytkownik Teams z Teams Phone + Calling Plan może zadzwonić na numer ACS jak na każdy numer zewnętrzny.
- Konto zasobu Teams (TPE): połącz konto zasobu Teams z zasobem ACS przez Teams Phone Extensibility, aby połączenia z kontem zasobu uruchamiały ten sam przepływ
IncomingCall→ most.
Koniec połączenia
Gdy agent kończy rozmowę (np. narzędziem End Call), ElevenLabs zamyka WebSocket. Rozłącz połączenie ACS, aby dzwoniący nie został na martwej linii:
Ciepłe przekazanie do człowieka
Natywne narzędzia przekazywania ElevenLabs działają tylko wtedy, gdy ElevenLabs obsługuje telefonię. Tutaj agent uruchamia więc niestandardowe narzędzie klienta (np. transfer_to_human), które most obsługuje przez dodanie człowieka do trwającego połączenia za pomocą add_participant (ciepłe przekazanie), zamiast ślepego transferu:
ACS wysyła wywołania zwrotne AddParticipantSucceeded / AddParticipantFailed do /api/callbacks. Zwróć do agenta client_tool_result, aby mógł wypowiedzieć komunikat o przekazaniu. Konfigurację po stronie agenta znajdziesz w narzędziach systemowych.
Ustaw blokadę transferu natychmiast po uruchomieniu narzędzia (przed wywołaniem add_participant), bo szybkie zamknięcie EL
WebSocket może kolidować z rozłączeniem i zakończyć połączenie, zanim człowiek dołączy.
Rozwiązywanie problemów
IncomingCall nie dociera do mostu
Sprawdź, czy subskrypcja Event Grid została utworzona (provisioningState: Succeeded) oraz czy
/api/incomingCall mostu zwróciło odpowiedź walidacyjną. Sprawdź, czy numer ma połączenia przychodzące
i należy do tego samego zasobu ACS, co subskrypcja. Na karcie Filters subskrypcji typy zdarzeń muszą obejmować Incoming Call:

CreateCallFailed / AddParticipantFailed dla numeru międzynarodowego
CreateCallFailed / AddParticipantFailed dla numeru międzynarodowego
Połączenia wychodzące ACS do niektórych krajów (np. Indii) są ograniczone lub niestabilne. Użyj obsługiwanego miejsca docelowego albo obsłuż połączenie z człowiekiem przez numer SIP/Operator. Logika mostu pozostaje bez zmian — to błąd po stronie operatora dla połączenia wychodzącego.
Dźwięk jest zniekształcony lub ma niewłaściwą prędkość
Obie strony muszą używać PCM 16 kHz mono. Ustaw format wejścia/wyjścia agenta na pcm_16000; most
zapisuje uzgodniony format z conversation_initiation_metadata.
Nie mogę kupić numeru / numer nie jest dostępny w moim kraju
Zakup numeru wymaga płatnego typu subskrypcji (MCA/EA/PAYG). Jeśli ACS nie oferuje numerów w twoim kraju, użyj dostawcy SIP.