Azure Communication Services
ACS Call Automation을 통해 사용자가 ElevenLabs 에이전트가 응답하는 전화번호로 전화를 걸 수 있게 합니다.
개요
이 방식은 에이전트에 전화번호를 부여합니다. 발신자가 해당 번호로 전화를 걸면 Azure Communication Services(ACS)가 양방향 미디어 스트리밍으로 응답하고, 작은 브리지가 표준 에이전트 WebSocket 프로토콜을 사용해 ACS와 ElevenLabs 에이전트 간 PCM 오디오를 중계합니다. 이는 컨택 센터/IVR 패턴으로, ACS를 통신사로 사용하는 SIP 트렁킹 배포와 같은 구조입니다.
Teams에도 두 가지 방식으로 연결됩니다. Calling Plan이 있는 Teams 사용자는 ACS 번호로 직접 전화를 걸 수 있고, Teams Phone Extensibility를 번호 앞단에 구성하여 Teams 리소스 계정으로 걸려오는 통화를 ACS로 라우팅할 수도 있습니다.
ACS는 제한된 국가 목록에서만 PSTN 번호를 제공합니다. 지역에서 번호를 사용할 수 없다면 SIP 트렁킹을 지원하는 SIP 제공업체나 Graph 통화 봇을 대신 사용하세요.
작동 방식
양쪽 모두 오디오는 PCM 16kHz 모노(에이전트 입력/출력 형식은 pcm_16000)이므로 리샘플링 없이 base64로 전달됩니다.
브리지는 다음 경로를 노출합니다:
요구 사항
- 유료 Azure 구독(MCA / EA / 종량제) — 무료/평가판/스폰서십 구독으로는 번호를 구매할 수 없습니다.
- Azure Communication Services 리소스.
- 공개 WebSocket이 있는 브리지용 HTTPS 호스트(Azure Container Apps, App Service 또는 VM).
- 양쪽 모두 PCM 16000Hz로 설정된 ElevenLabs 에이전트: Voice 탭의 TTS 출력 형식 및 Advanced 탭의 사용자 입력 오디오 형식.
권한 및 역할
Contributor 권한(Owner 아님)에서는 az containerapp up이 관리형 ID의 ACR pull 역할 할당을 생성할 수 없습니다. 레지스트리 관리자 사용자를 활성화하고 대신 연결하세요. Step 2의 경고를 참조하세요.
Step 1 — ACS 리소스 및 번호 프로비저닝
리소스에서 번호를 구매합니다(포털 → ACS 리소스 → Phone numbers → Get 또는 phone-numbers SDK). 전화를 응답하는 에이전트에는 수신 통화 기능이 있는 번호면 충분합니다. /api/outboundCall도 사용하려면 발신 기능을 추가하세요.

CLI에서 확인하려면(az extension add --name communication 필요), 그리고 브리지가 ACS_CONNECTION_STRING으로 사용하는 연결 문자열을 가져오려면 다음을 실행하세요:
Step 2 — 브리지 배포
브리지는 azure-communication-callautomation을 사용하는 소규모 Flask + flask-sock 앱입니다. 수신 흐름의 핵심은 다음과 같습니다:
/ws 소켓에서 PCM16을 양방향으로 중계합니다. ACS AudioData 프레임은 {"user_audio_chunk": "<base64>"}로 ElevenLabs에 전달하고, 에이전트 오디오는 {"Kind":"AudioData","AudioData":{"Data":"<base64>"},"StopAudio":null}로 다시 전송합니다. ACS가 처음 보내는 프레임은 AudioMetadata(협상된 형식)이므로 로그에 기록하고 무시합니다. ElevenLabs 측은 표준 에이전트 WebSocket 프로토콜입니다.
ACS는 방향에 따라 서로 다른 JSON 대소문자 표기를 사용합니다. 전송하는 수신 프레임은 camelCase(kind, audioData.data)이고, 기대하는 발신 프레임은 PascalCase(Kind, AudioData.Data, StopAudio)입니다. 두 표기를 구분하세요. 아래 릴레이는 이를 그대로 반영합니다.
이 릴레이는 의도적으로 최소한으로 구현되었습니다. 프로덕션 환경에서는 로깅, 재연결, 정상 종료를 추가하세요. 전체 메시지 레퍼런스는 WebSocket 문서에 있습니다.
EL_WS는 공개 에이전트에 연결합니다. 비공개 에이전트의 경우 브리지가 서버 측에서 단기 서명 URL을 요청하세요. API 키로 GET /v1/convai/conversation/get-signed-url?agent_id=...를 호출한 후 반환된 URL에 연결합니다. 데이터 레지던시를 사용하는 경우 ELEVENLABS_ORIGIN을 레지던시 호스트(wss://api.eu.residency.elevenlabs.io, .in., 또는 .sg.)로 설정하세요. 서명 URL 요청은 일치하는 https:// 호스트를 사용합니다.
Azure Container Apps에 배포하고 공개 FQDN을 가져옵니다:
그런 다음 앱에 BRIDGE_PUBLIC_HOST=$FQDN과 ACS 연결 문자열(시크릿으로)을 설정하세요.
Contributor 권한(Owner 아님)에서는 az containerapp up이 관리형 ID의 ACR pull 역할을 생성할 수 없습니다. 레지스트리 관리자 사용자(az acr update --admin-enabled true)를 활성화하고 az containerapp registry set으로 연결한 다음 az containerapp update --image ...를 실행하세요.
Step 3 — IncomingCall을 브리지로 라우팅
ACS 리소스에서 IncomingCall을 브리지에 게시하는 Event Grid 구독을 만듭니다. 브리지의 검증 핸드셰이크(위)가 자동으로 구독을 완료합니다.
구독은 ACS 리소스의 Events 블레이드에 표시됩니다:

번호로 전화를 걸면 에이전트가 응답합니다.
Teams에 연결하기
- 직접 전화: Teams Phone + Calling Plan이 있는 Teams 사용자는 다른 외부 번호처럼 ACS 번호로 전화를 걸 수 있습니다.
- Teams 리소스 계정(TPE): Teams Phone Extensibility를 사용하여 Teams 리소스 계정을 ACS 리소스에 바인딩하면, 리소스 계정으로 걸려오는 통화가 동일한
IncomingCall→ 브리지 흐름을 실행합니다.
통화 종료
에이전트가 대화를 종료하면(예: End Call 도구) ElevenLabs가 WebSocket을 닫습니다. 발신자가 끊긴 회선에 남지 않도록 ACS 연결을 종료하세요:
상담원에게 웜 트랜스퍼
ElevenLabs의 기본 전환 도구는 ElevenLabs가 전화 통신을 소유할 때만 적용됩니다. 따라서 여기서는 에이전트가 사용자 지정 클라이언트 도구(예: transfer_to_human)를 실행하고, 브리지는 블라인드 전환 대신 add_participant로 라이브 통화에 상담원을 추가하여 웜 트랜스퍼를 처리합니다:
ACS는 /api/callbacks에 AddParticipantSucceeded / AddParticipantFailed 콜백을 전송합니다. 에이전트가 인계 멘트를 말할 수 있도록 client_tool_result를 반환하세요. 에이전트 측 구성은 시스템 도구를 참조하세요.
도구가 실행되는 즉시( add_participant 호출 전) 전환 가드를 설정하세요. 그렇지 않으면 빠른 EL WebSocket 종료가 통화 종료와 경합하여 상담원이 참여하기 전에 통화가 끊길 수 있습니다.
문제 해결
IncomingCall이 브리지에 도달하지 않음
Event Grid 구독이 프로비저닝되었는지(provisioningState: Succeeded)와 브리지의 /api/incomingCall이 검증 에코를 반환했는지 확인하세요. 번호에 수신 통화 기능이 있고 구독이 있는 ACS 리소스와 동일한 리소스에 있는지도 확인하세요. 구독의 Filters 탭에서 이벤트 유형에 Incoming Call이 포함되어야 합니다:

국제 번호에서 CreateCallFailed / AddParticipantFailed 발생
국제 번호에서 CreateCallFailed / AddParticipantFailed 발생
일부 대상 국가(예: 인도)에 대한 ACS 발신은 제한되거나 간헐적으로 실패할 수 있습니다. 지원되는 대상 국가를 사용하거나 SIP/Operator 번호를 상담원 연결 앞단에 사용하세요. 브리지 로직에는 영향이 없으며, 발신 연결에서 발생하는 통신사 수준의 실패입니다.
오디오가 왜곡되거나 속도가 잘못됨
양쪽 모두 PCM 16kHz 모노여야 합니다. 에이전트 입력/출력 형식을 pcm_16000으로 설정하세요. 브리지는 conversation_initiation_metadata에서 협상된 형식을 로그에 기록합니다.
번호를 구매할 수 없거나 국가에서 번호를 사용할 수 없음
번호 구매에는 유료 구독 유형(MCA/EA/PAYG)이 필요합니다. ACS가 해당 국가에서 번호를 제공하지 않는 경우 SIP 제공업체를 대신 사용하세요.