실무 Multi-Agent 오케스트레이션 22장 · 오케스트레이션 2 / 8 ← 이전목차다음 → TechLead Cro

22장. 오케스트레이션

에이전트를 도구로 — 위임은 도구 호출이다

한 줄 요약

Supervisor를 만드는 데 새 기술은 필요 없습니다. Supervisor도 에이전트 하나이고, 다만 그의 도구가 데이터 조회 함수가 아니라 전문 에이전트를 부르는 함수일 뿐입니다. 그래서 위임은 곧 도구 호출입니다.


1. 구조 한 장

Supervisor 패턴

고객의 문의는 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가 갖고, 요청문에 풀어서 넘깁니다.
  • 그래서 한 문의에 세 에이전트가 차례로 움직일 수 있습니다. 앞의 보고가 뒤의 요청문에 담깁니다.
  • 중앙 지휘를 고른 이유는 추적이 쉽고, 답의 책임자가 분명하고, 순환을 막기 쉽기 때문입니다.
← 이전 절왜 오케스트레이션이 필요한가 — 전문가는 셋인데 지휘할 자리가 비어 있다다음 절 →무한 위임을 막는 두 겹 — 구조와 상한
오명운 · macro@prag-ai.com