22장. 오케스트레이션
에이전트를 도구로 — 위임은 도구 호출이다
한 줄 요약
Supervisor를 만드는 데 새 기술은 필요 없습니다. Supervisor도 에이전트 하나이고, 다만 그의 도구가 데이터 조회 함수가 아니라 전문 에이전트를 부르는 함수일 뿐입니다. 그래서 위임은 곧 도구 호출입니다.
1. 구조 한 장

고객의 문의는 Supervisor 한 곳으로 들어옵니다. Supervisor는 필요한 전문 에이전트를 부르고, 돌아온 보고를 모아 답합니다. 이 구조를 Supervisor 패턴이라고 부릅니다.
"지난주에 산 운동화가 불량이에요. 검정 270으로 교환 접수해 주세요."라는 문의라면 Supervisor는 이렇게 움직입니다.
| 순서 | Supervisor가 하는 일 | 돌아오는 것 |
|---|---|---|
| 1 | 주문조회 에이전트에게 "지난주 운동화 주문"을 확인시킨다 | 주문번호, 상품, 옵션, 배송 상태 |
| 2 | 정책안내 에이전트에게 불량 교환의 배송비 규정을 묻는다 | 규정과 근거 조항 |
| 3 | 1번에서 받은 주문번호를 요청문에 적어 요청처리 에이전트에게 교환 접수를 맡긴다 | 처리 결과와 처리번호 |
| 4 | 세 보고를 한 답으로 묶어 고객에게 보낸다 |
한 문의 안에서 세 에이전트가 차례로 움직입니다. 3번에서 요청처리 에이전트가 받는 주문번호는 고객이 말한 것이 아니라 Supervisor가 1번의 보고에서 옮겨 적은 것입니다.
2. 에이전트를 함수 하나로 감싼다
21장에서 전문 에이전트의 입출력을 "글로 된 요청을 받아 글로 된 보고를 돌려준다" 로 통일해 두었습니다. 이것은 문자열을 받아 문자열을 돌려주는 함수의 모양과 같습니다. 그래서 함수 하나로 감싸면 도구가 됩니다.
@tool
def ask_order_agent(request: str) -> str:
"""주문·배송·상품·재고·고객 멤버십 등급/포인트에 대한 사실 확인을
주문조회 에이전트에게 요청한다.
Args:
request: 확인할 내용. 예: '고객의 최근 주문과 배송 상태', '고객의 멤버십 등급'
"""
if verbose:
print(f" [위임 → 주문조회] {request}")
return run_agent(agents["order"], request, verbose=False)
| 줄 | 하는 일 |
|---|---|
@tool |
이 함수를 모델이 부를 수 있는 도구로 등록한다 (11장) |
| 설명글(독스트링) | 모델이 언제 이 도구를 부를지 판단하는 근거 (7장) |
request: str |
Supervisor가 전문 에이전트에게 건네는 요청문. 모델이 직접 쓴다 |
run_agent(...) |
함수의 몸통. 전문 에이전트를 실행해 마지막 보고를 돌려준다 |
같은 방식으로 ask_policy_agent, ask_action_agent를 만들어 셋을 Supervisor에게 줍니다. ask_action_agent는 몸통에 장치가 몇 가지 더 들어 있습니다. 그 부분은 뒤의 절에서 따로 봅니다.
supervisor = create_agent(
model=ChatGoogleGenerativeAI(model=MODEL, ...),
tools=[ask_order_agent, ask_policy_agent, ask_action_agent],
system_prompt=SUPERVISOR_SYSTEM,
)
11장에서 쓴 create_agent와 똑같은 호출입니다. 달라진 것은 tools에 들어간 것이 에이전트를 감싼 함수라는 점뿐입니다.
3. 이미 배운 것이 그대로 적용된다
위임이 도구 호출이므로, 도구 호출에서 배운 것이 전부 성립합니다.
| 배운 곳 | 내용 | Supervisor에서는 |
|---|---|---|
| 5장 | 모델은 도구를 고를 뿐, 실행은 우리 코드가 한다 | 누구에게 맡길지는 모델, 전문 에이전트 실행은 코드 |
| 7장 | 도구 선택은 설명글로 정해진다 | 위임 대상이 틀리면 먼저 설명글을 고친다 |
| 9장 | 도구 결과를 보고 다음 행동을 다시 정한다 | 보고를 읽고 다른 에이전트를 더 부를지 정한다 |
| 10장 | 도구 호출 한 번이 곧 비용 | 위임 한 번 안에 LLM 호출이 여러 번 들어 있다 |
마지막 줄을 조금 더 봅니다. Supervisor가 주문조회 에이전트에게 한 번 위임하면, 그 안에서 주문조회 에이전트가 "어떤 도구를 쓸지 정하고 → 결과를 읽고 → 보고를 쓰는" 호출을 따로 합니다. 위임은 겉으로는 한 번이지만 속에서는 LLM을 여러 번 부릅니다. 그래서 "필요한 에이전트만 부른다"가 운영 원칙의 첫 줄이 됩니다.
4. 전문 에이전트는 앞 대화를 모른다
감싼 함수의 몸통을 다시 보면, 전문 에이전트에게 가는 것은 request 한 문장뿐입니다. 고객과 나눈 앞 대화는 넘어가지 않습니다.
| 누가 | 무엇을 기억하나 |
|---|---|
| Supervisor | 고객과의 대화 이력 전체 |
| 전문 에이전트 | 이번에 받은 요청문 하나. 부를 때마다 새로 시작한다 |
그래서 고객이 "그 운동화 검정 270으로 교환해 주세요"라고 하면, Supervisor가 "그 운동화"를 이력에서 풀어 "주문 HR20260721001 쿠션 운동화"처럼 구체적으로 써서 넘겨야 합니다. 이 일을 시키는 문장이 Supervisor 프롬프트의 원칙 4번입니다.
전문 에이전트끼리도 서로의 보고를 모릅니다. 주문조회 에이전트가 찾은 주문번호를 요청처리 에이전트가 쓰려면, Supervisor가 그 번호를 요청문에 옮겨 적어야 합니다. 21장의 실습문제에서 우리가 손으로 한 일을 이제 Supervisor가 합니다.
이렇게 나누면 좋은 점도 있습니다. 전문 에이전트는 매번 깨끗한 상태에서 요청 하나만 보므로, 긴 대화에 섞여 헷갈릴 일이 없습니다.
5. 다른 방식도 있다 — 핸드오프
중앙에서 지휘하는 방식만 있는 것은 아닙니다. 핸드오프(handoff) 는 Supervisor 없이, 에이전트가 자기 일이 아닌 문의를 받으면 대화를 동료 에이전트에게 통째로 넘기는 방식입니다. 전화 상담의 "담당 부서로 연결해 드리겠습니다"와 같습니다.
| Supervisor 패턴 (중앙 지휘) | 핸드오프 | |
|---|---|---|
| 고객과 말하는 쪽 | 항상 Supervisor | 그때그때 넘겨받은 에이전트 |
| 흐름 추적 | 모든 결정이 한 곳을 지나 쉽다 | 주도권이 옮겨 다녀 어렵다 |
| 답을 묶는 책임 | Supervisor로 분명하다 | 마지막에 받은 에이전트 |
| 순환 위험 | 구조로 막기 쉽다 | 서로 넘기기를 반복할 수 있다 |
| 약점 | Supervisor를 거치느라 호출이 한 겹 더 든다 | 전체를 보는 눈이 없다 |
우리는 중앙 지휘를 고릅니다. 근거는 따라하기에서 볼 수 있습니다. 터미널에 찍히는 [위임 →] 한 줄씩만 읽으면 문의가 어떤 경로로 처리됐는지 전부 보입니다.
핵심 정리
- Supervisor는 에이전트 하나이고, 도구가 전문 에이전트를 부르는 함수입니다.
- 전문 에이전트의 입출력이 문자열 → 문자열이라 함수 하나로 감싸면 도구가 됩니다.
- 누구에게 맡길지는 모델이 정하고, 전문 에이전트를 실행하는 것은 우리 코드입니다.
- 위임 한 번 안에는 LLM 호출이 여러 번 들어 있습니다. 위임은 비용입니다.
- 전문 에이전트는 앞 대화도, 다른 에이전트의 보고도 모릅니다. 기억은 Supervisor가 갖고, 요청문에 풀어서 넘깁니다.
- 그래서 한 문의에 세 에이전트가 차례로 움직일 수 있습니다. 앞의 보고가 뒤의 요청문에 담깁니다.
- 중앙 지휘를 고른 이유는 추적이 쉽고, 답의 책임자가 분명하고, 순환을 막기 쉽기 때문입니다.