일반적인 에이전트 활용 시나리오에서도 최근에는 다양한 멀티 에이전트(multi-agent) 활용 방법들이 있습니다. 예를 들어, 인사나 잡담 같은 간단한 대화와 제품 사양이나 절차처럼 전문 지식이 필요한 질문이 섞여 나옵니다. 이 모든 것을 하나의 에이전트에게 맡기면, 간단한 말 한마디에도 업무에 특화된 에이전트의 처리를 매번 기다려야 합니다. 따라서 간단한 응답은 빠른 모델이 담당하고, 전문적인 질문만 전문 에이전트에게 맡기는 식으로 역할을 분담하는 것을 고려하게 됩니다.
Voice Live API는 음성으로 대화하는 에이전트를 만드는 데 사용되는 API이며, foundry_agent 도구를 사용할 경우, 대화를 받는 모델(model)로부터 Foundry의 에이전트를 도구(tool)로 호출할 수 있습니다. Microsoft는 이 구성을 chat-supervisor 패턴이라고 부릅니다.
본 기사에서는 foundry_agent 도구 사용법과 역할을 분담했을 때의 응답 시간 변화, 그리고 대화를 받는 모델(전단 모델, upstream model) 선택 방법에 대해 소개합니다. Voice Live 기능 해설 시리즈의 제4회입니다.
[시리즈 기사 목록 (SDK 1.2.0 / API 2026-07-15)]
Voice Live SDK 1.2.0 변경점 및 API 2026-07-15 GA
SDK에 타입이 없는 기능 분류 -
Voice Live API에서 대화의 '간격'을 다루기
먼저 말하기/말을 망설이기 기다리기/가로채기/대기 시간에 말하기 -
Voice Live의 음성 입력 품질 향상
노이즈 억제/에코 제거/Live-Reference AEC 선택 방법 -
Voice Live에서 MCP 서버의 도구 사용
function calling과의 차이점 및 병렬 도구 호출 - Voice Live에서 Foundry 에이전트를 도구로 호출하기 (본 기사)
chat-supervisor 패턴 사용법 및 전단 모델 선택 방법 -
30초 음성으로 '자신의 목소리'를 만들어 Microsoft Foundry 에이전트가 말하게 하기
Personal Voice 신청부터 구현까지 -
Voice Live API의 아바타 활용 분배
표준/커스텀 사진/커스텀 비디오 설정 및 구현 -
Voice Live의 아바타 영상을 WebSocket으로 받기
WebRTC와의 차이점 및 영상 형식
특별편: Voice Live의 WebRTC 음성 연결에 .NET의 SIPSorcery로 연결하기
SDP를 한 줄씩 대조한 기록
foundry_agent 도구는 API 2026-04-10 (GA)부터 정의되었지만, .NET SDK 1.2.0에는 아직 타입이 없습니다. 따라서 본 기사는 시리즈 중 유일하게 API(WebSocket의 JSON)을 직접 다루는 회가 됩니다.
검증에 사용된 코드는 여기입니다.
Voice Live에서 '에이전트를 사용한다'고 할 때, 세 가지 사용법이 있습니다. 혼동하기 쉬우므로 먼저 정리하겠습니다.
| 사용법 | 무엇을 하는가 | 클라이언트 입장에서의 모습 |
|---|
| ① 대화 상대 | Foundry 에이전트 그 자체와 이야기함 | agent-name +project-name으로 연결 (Agent 세션) |
| ② 도구로 호출하기 (본 기사) | 모델의 세션이 다른 에이전트를 도구로 호출함 | tools에 foundry_agent를 선언하고, 진행 이벤트를 받는 것만 함 |
| ③ 자체 제작 에이전트 가져오기 | 직접 작성한 에이전트를 컨테이너로 Foundry에 배포하여 ①처럼 사용함 | 연결 방법은 ①과 동일 |
같은 하나의 에이전트를 ①의 대화 상대이자 ②의 도구로 모두 사용할 수 있습니다.
API 2026-07-15의 What's new에 나오는 hosted agent invocation은 ②가 아닙니다. ③의 호스팅된 에이전트에 response.create의 invoke_input으로 입력을 전달하고, 비음성 이벤트를 response.invocation.delta로 받는 다른 기능입니다. 이름이 비슷하므로 주의해야 합니다.
①의 대화 상대(Conversation partner)로 연결할 경우, 사용자 발화는 모두 에이전트의 처리를 거쳐서 답변하게 됩니다. 에이전트 처리(Agent Service 호출, 스레드 관리, 도구 실행 등)가 매 턴 포함되기 때문에, 잡담 한마디에도 기다려지게 됩니다.
②에서는 대화를 받는 것은 빠른 모델입니다. 잡담이라면 모델이 그 자리에서 답하고, 에이전트가 필요한 질문일 때만 도구로 호출합니다. 역할을 분리하면 간단한 상호작용은 에이전트를 기다리지 않고 응답할 수 있습니다. 전문적인 질문이라도 호출하기 전에 "검색해 보겠습니다"와 같은 한마디를 돌려줄 수 있어 무음 시간을 줄일 수 있습니다.
에이전트 호출은 Voice Live 서버 측에서 실행되므로, 클라이언트가 에이전트를 호출하는 코드를 작성할 필요가 없습니다.
리소스 생성, 에이전트 생성, 역할 할당(Foundry User), Entra ID 연결까지는 에이전트용 공식 퀵스타트에 따라 진행하면 준비할 수 있습니다.
퀵스타트 환경에서 본 기사의 내용을 테스트할 때는 다음 사항에 주의하십시오.
- 에이전트를 호출하므로 Entra ID 연결이 필요합니다 (API 키로는 사용할 수 없습니다).
- 에이전트 이름과 프로젝트 이름을 기록해 두십시오 (
session.update
의 agent_name와 project_name에 작성합니다) - 호출되는 쪽 에이전트의 프로젝트에도 접속하는 사용자에게 권한이 필요합니다.
session.update의 tools에 foundry_agent를 선언합니다. 본 기사에서 테스트한 것은 전문적인 에이전트 1개입니다. 여러 전문 에이전트를 사용하려면, 에이전트별로 tools에 선언하고 description으로 역할을 구분하는 형태가 될 것이라 생각하지만, 그 정도까지는 테스트하지 않았습니다.
{
"type": "session.update",
"session": {
...
| 필드 | 의미 |
|---|
agent_name / project_name | 호출할 Foundry 에이전트와 프로젝트 |
description | 모델이 "언제 호출할지"를 판단하는 재료. 구체적으로 작성 |
agent_version | 생략 가능. 에이전트의 버전을 고정함 |
agent_context_type | agent_context: 에이전트가 자신의 스레드를 유지함 / no_context: 매번 해당 입력만 전달함 |
return_agent_response_directly | true: 에이전트의 답변을 그대로 말함 / false: 상위 모델(upstream model)이 바꿔서 말함 |
return_agent_response_directly는 대화 기능에서 상위 모델(upstream model)을 효과적으로 활용하기 위한 메커니즘입니다. 에이전트와 음성으로 대화한다는 전제 하에, 전문적인 에이전트가 텍스트 기반의 정보를 대량으로 반환하고, 그것을 그대로 읽어주기 어려운 상황도 있을 것입니다.
그러한 상황에서는 return_agent_response_directly: false로 설정하면, 에이전트의 답변이 길더라도 상위 모델(upstream model)이 음성 청취에 적합하도록 짧게 다듬어 줍니다.
침묵 시간을 줄이는 데 효과적인 부분은 instructions의 "도구를 호출하기 전에 짧은 말을 돌려주는" 부분입니다. 이것이 없으면, 상위 모델(upstream model)은 아무 말 없이 도구를 호출합니다.
클라이언트에는 function_call은 오지 않습니다. 대신, 에이전트 호출 진행을 나타내는 이벤트가 도착합니다. MCP의 response.mcp_call.*와 같은 형태입니다.
| 이벤트 | 의미 |
|---|
response.foundry_agent_call_arguments.delta / .done | 모델이 구성한 에이전트 입력값 (스트리밍) |
response.foundry_agent_call.in_progress | 에이전트 실행 중 |
response.foundry_agent_call.completed | 에이전트 실행 완료 |
response.foundry_agent_call.failed | 실패 |
실제 기기에서 음성으로 "XR에 대해 알려주세요"라고 말하자, 모델은 에이전트 입력값을 {"input":"XR이란 무엇인지 알려주세요."}와 같이 정형화하여 호출했습니다. in_progress는 2번 수신되었고, 두 번째에 에이전트 측 응답 ID(agent_response_id)가 붙었습니다. 에이전트의 답변은 도구를 호출했을 때의 응답과는 별개의 새로운 응답으로 음성 출력됩니다.
측정 스크립트를 작성했을 때, 처음에는 이 점을 인지하지 못하고 측정을 잘못했습니다.
도구를 호출한 첫 번째 응답인 response.done은 즉시 도착합니다. 에이전트의 답변은 그 이후에 오는 별도의 응답으로 오기 때문에, 첫 번째 response.done에서 턴을 종료하면 답변을 놓치게 됩니다.
같은 음성(5.3초 분량의 일본어 발화)을 실시간으로 재생하고, 발화가 끝나는 시점(input_audio_buffer.speech_stopped)을 기점으로 측정했습니다. 측정 조건은 리전 japaneast, 전단 모델 gpt-4o, API 2026-04-10, 음성 입력, 각 3회입니다.
| 구성 | 첫 번째 반응 | 최종 답변 |
|---|
| ① 에이전트에 직접 연결 | 3783 ms (무음) | 4413 ms |
② chat-supervisor (foundry_agent ) | 779 ms (“확인해 보겠습니다”) | 6180 ms |
| 참고: 모델만 사용 (도구 없음) | 645 ms | 1091 ms |
- 첫 번째 반응은 3783 → 779 ms로 (약 4.9배 빠름)
- 최종 답변은 4413 → 6180 ms로 (약 1.4배 느림)
chat-supervisor는 첫 번째 반응을 크게 빠르게 하는 대신, 최종 답변이 약간 느려지는 구성입니다. 매 턴이 에이전트에게 질문하는 것이라면 ①의 방식이 최종 답변은 더 빠릅니다. 이 부분은 UX에 따라 최적의 방식을 채택하게 될 것 같습니다.
speech_stopped 역시 이후 응답도 서버에서 오는 이벤트이기 때문에, 이러한 측정 방식으로는 클라이언트와 서버 간의 왕복 지연(Round-trip delay)이 상쇄됩니다. 수치는 서버 측 처리 시간이며, 사용자가 체감하는 시간에는 이 왕복 지연이 추가됩니다. 측정 방식의 차이에 대해서는 다른 글로 자세히 다룰 예정입니다.
chat-supervisor의 효과는 전단에 배치하는 모델에 따라 크게 달라집니다. japaneast에서 텍스트 입력(체감 레이턴시)을 각 4회 측정했습니다.
| 전단 모델 | 도구 호출 가능 횟수 | 잡담 첫 반응 | “확인해 보겠습니다”까지 | 최종 답변까지 |
|---|---|---|---|
| gpt-4o | 4/4 (총 12/12) | 251〜406 ms | 226〜231 ms | 5250 ms |
| ... |
이번에는 검증을 위해 전단 모델이 반드시 도구에 등록된 에이전트를 호출하도록 구현했습니다. 하지만, 전단 모델에 따라 도구를 제대로 호출하지 못하는 경우가 있습니다. 실제로 발생할 수 있는 몇 가지 패턴을 소개하면 다음과 같습니다.
| 실패 유형 | 발생한 모델 | 내용 | 대책 |
|---|
| 출력 위치 오류 | gpt-5-mini | 호출 판단과 인수는 올바른데, 호출 JSON을 텍스트로 말해버림 | 이번에 시도한 범위에서는 프롬프트만으로는 해결되지 않아 모델을 변경함 |
| 위임 판단의 흔들림 | gpt-5.1 | 질문해야 할 상황인데, 스스로 답변해 버림 | 도구 설명이나 지시를 구체적으로 하면 개선할 여지가 있음 |
gpt-5-mini의 실패는 다음과 같은 출력으로 나타납니다.
확인해 보겠습니다
{"input":"〇〇 화면의 제약에 대해 자세히 알려주세요."}
프롬프트를 수정할지 모델을 변경할지는 실패 유형을 보고 결정하는 것이 좋을 것 같습니다.
gpt-4o를 전단으로 사용하기로 했을 때, “2026-10-01에 폐지”라는 정보를 본 적이 있는데, 모델의 폐지일은 버전에 따라 다르게 정해져 있습니다.
| 버전 | 폐지일 |
|---|
gpt-4o 2024-05-13 | 2026-10-01 |
gpt-4o 2024-08-06 | 2027-04-14 |
gpt-4o 2024-11-20 | 2027-04-14 |
실제로 배포된 버전은 session.created의 session.model에서 확인할 수 있습니다 (리전에 따라 버전까지 반환되지 않고 별칭(alias)만 오는 경우도 있음). 모델 이름만으로 폐지일을 검색하면 가장 빠른 날짜를 가져올 수 있으니 주의가 필요합니다.
foundry_agent
도구를 사용하여 빠른 모델이 대화를 받고 에이전트를 도구로 호출하는 구성(chat-supervisor)을 만들 수 있습니다. 에이전트 호출은 서버 측에서 실행되며, 클라이언트는 선언과 이벤트 관찰만 수행합니다.
- 첫 번째 반응 속도는 약 4.9배 빨라졌고, 최종 답변은 약간 느려졌습니다.
- 전단 모델(前段モデル)은 테스트한 모델 중에서는 gpt-4o가 가장 빠르고 도구 호출도 안정적이었습니다.
- 도구 호출 실패에는 출력 목적지 오류와 위임 판단의 흔들림 두 가지 종류가 있으며, 이에 대한 대책이 다릅니다.
- .NET SDK 1.2.0에는 타입이 없으므로, GA(General Availability) API로 사용하기 위해 JSON을 사용합니다.
스피커가 없는 스마트 글래스를 이용해 이 구성을 적용한 실습 예제도 작성했습니다. 무언의 대기 시간이 화면에 아무것도 표시되지 않는 시간이 되면서 효과가 더욱 명확하게 나타났습니다.
다음 회차는 시리즈 제5회 Personal Voice(이미 공개됨)를 거쳐, 제6회에서 아바타의 사용처 분리(사용법 차별화)를 다룰 예정입니다.