본문 바로가기
AI 오케스트레이션 캠프/일차별 회고

55일차 회고|멀티에이전트 오케스트레이션·Router·Supervisor·Output Contract|AI 오케스트레이션 개발자 국비지원

by 랩보다 AI 더 잘해지기 2026. 9. 29.
728x90

오늘 배운 내용

오늘은 멀티에이전트 시스템에서 에이전트를 여러 개 만드는 것과 실제로 에이전트들을 오케스트레이션하는 것은 다르다는 점을 중심으로 학습했다.

오전에는 에이전트 실행 결과를 Output Contract로 검증하고 다음 에이전트에게 전달하는 흐름, Redis를 활용한 실행 상태 추적, 비동기 실행과 run_id, Snapshot 등을 살펴봤다.

오후에는 Router와 Supervisor의 차이를 배우고, 에이전트를 Python 코드가 아니라 YAML로 정의하는 방식까지 확장했다.

특히 오늘은 단순히 "여러 에이전트를 연결한다"는 수준에서 벗어나서,

누가 다음 에이전트를 선택하는가?
결과가 정상인지 어떻게 판단하는가?
문제가 생기면 어디에서 중단하거나 다시 실행하는가?

까지 생각해야 오케스트레이션을 제대로 설계할 수 있다는 것을 이해한 날이었다.


1. Output Contract가 중요한 이유

오늘 오전 수업에서 가장 반복해서 등장한 개념 중 하나가 Output Contract였다.

Output Contract는 쉽게 말하면 에이전트가 어떤 형태의 결과를 반환해야 하는지를 미리 정해놓은 약속이다.

예를 들어 첫 번째 에이전트가 여행 예산을 계산한다면 단순히 문자열을 반환하는 것이 아니라, 정해진 Pydantic 모델에 맞는 구조로 결과를 만들어야 한다.

문제는 LLM이 항상 우리가 원하는 형식으로 결과를 만들어준다는 보장이 없다는 것이다.

그래서 다음 에이전트로 넘기기 전에

  1. 첫 번째 에이전트 실행
  2. 결과가 존재하는지 확인
  3. Output Contract로 검증
  4. 검증 성공 → 다음 에이전트 실행
  5. 검증 실패 → 중단 또는 재처리

와 같은 검증 단계가 필요하다.

오늘 수업에서는 단순히 결과가 None인지 확인하는 것만으로는 부족하다는 것도 알게 됐다.

값이 들어 있더라도 실제 계약에 맞지 않는 결과라면 다음 에이전트로 넘겨서는 안 된다.


2. 에이전트보다 중요한 것은 오케스트레이션

오늘 이전까지는 여러 에이전트를 만들어 서로 연결하는 것 자체에 집중했다면, 오늘은 오케스트레이션의 역할을 좀 더 명확하게 이해했다.

예를 들어 다음과 같은 흐름이 있다.

사용자 요청
   ↓
Budget Agent
   ↓
Output Contract 검증
   ↓
Itinerary Agent
   ↓
최종 결과

여기서 오케스트레이션은 단순히 에이전트를 순서대로 호출하는 코드가 아니다.

각 단계의 결과를 확인하고,

  • 다음 에이전트를 실행할지
  • 실행을 중단할지
  • 다시 시도할지
  • 어떤 데이터를 다음 에이전트에게 넘길지

를 결정한다.

특히 사용자의 원래 요청과 이전 에이전트의 검증된 결과를 함께 다음 단계에 전달할 수 있다는 점도 배웠다.

에이전트가 많아질수록 이런 조건과 분기가 늘어나기 때문에 오케스트레이션 코드가 복잡해지는 이유도 이해할 수 있었다.


3. Redis와 run_id를 이용한 실행 추적

오늘은 멀티에이전트 실행 과정을 추적하는 방법도 살펴봤다.

오케스트레이션이 시작되면 run_id를 만들고, 각 실행 상태를 Redis에 기록한다.

이를 통해 비동기로 실행되는 작업도 나중에 Snapshot API 등을 이용해 현재 상태를 확인할 수 있다.

예를 들어 구조를 단순화하면 다음과 같다.

사용자 요청
   ↓
Router
   ↓
run_id 생성
   ↓
Orchestration 실행
   ↓
Redis에 실행 상태 기록
   ↓
Snapshot으로 상태 확인

기존에는 프론트엔드에서 일정한 간격으로 Snapshot API를 호출하는 Polling 방식을 사용했다.

Polling은 정해진 주기마다 계속 상태를 확인하는 방식이다.

반면 SSE(Server-Sent Events)는 서버에서 이벤트가 발생했을 때 클라이언트로 전달하는 방식이라, 실시간 상태 업데이트를 구현하는 데 더 적합하다는 것도 다시 확인했다.


4. Router와 Supervisor의 차이

오후 수업에서 가장 인상 깊었던 부분이다.

둘 다 여러 에이전트 중 하나를 선택한다는 점에서는 비슷해 보이지만 선택의 목적과 이후 흐름이 다르다.

Router

Router는 사용자의 요청을 보고 어떤 에이전트에게 맡길지를 결정하는 역할이다.

예를 들어,

"배송 상태를 알려주세요."
        ↓
Delivery Agent

또는

"환불하고 싶습니다."
        ↓
Refund Agent

처럼 사용자의 의도를 분류하고 적절한 에이전트에게 넘겨준다.

Router 역시 LLM을 사용할 수 있다.

사용자 질문과 함께 사용할 수 있는 Agent 목록과 라우팅 규칙을 전달하고, 미리 정의된 Schema에 맞춰 어떤 Agent를 선택할지 구조화된 결과를 받는 방식이다.

다만 여기서 중요한 문제가 있었다.

Router가 잘못 판단하면 잘못된 Agent로 요청이 전달될 수 있다.

그래서 Router 역시 테스트와 검증이 필요하다.

특히 주문번호가 필요한 환불 요청인데 사용자가 주문번호를 입력하지 않았다면, 무조건 Refund Agent로 보내는 것이 아니라 필수 정보가 부족한 상황을 먼저 처리해야 한다.


5. Supervisor는 단순한 Router와 다르다

Supervisor는 Router보다 더 적극적으로 전체 작업의 진행 상황을 관리한다.

예를 들어,

Supervisor
   ↓
Analyst
   ↓
Supervisor
   ↓
Developer
   ↓
Supervisor
   ↓
Reviewer
   ↓
Supervisor
   ↓
완료

와 같은 구조가 가능하다.

Supervisor는 현재 상태와 이전 Agent의 결과를 확인하고 다음에 어떤 Worker를 실행할지 결정한다.

결과가 부족하다면 다음 단계로 넘어가지 않고 이전 Agent를 다시 실행할 수도 있다.

예를 들어 Analyst가 요구사항을 충분히 분석하지 못했다면,

Analyst → Supervisor
             ↓
       결과 부족 판단
             ↓
          Analyst 재실행

이 가능하다.

이 부분에서 Supervisor와 Evaluator-Optimizer의 차이도 연결해서 이해할 수 있었다.

Evaluator-Optimizer가 보통

Writer → Reviewer → Writer → Reviewer

처럼 비교적 정해진 반복 구조를 갖는다면,

Supervisor는 여러 Worker 중에서 현재 상황에 필요한 Agent를 선택할 수 있다는 점이 다르다.


6. Supervisor에는 명확한 평가 기준이 필요하다

Supervisor가 결과를 보고 다음 행동을 결정하려면 무엇이 좋은 결과인지에 대한 기준이 필요하다.

예를 들어 사용자가

10만 원 이하의 호텔 5개를 찾아줘.

라고 요청했는데 결과에 호텔이 3개밖에 없거나 가격 조건을 초과하는 호텔이 포함되어 있다면, Supervisor가 그 결과를 그대로 통과시키면 안 된다.

따라서 Supervisor의 프롬프트에는

  • 어떤 Worker를 사용할 수 있는지
  • 각 Worker의 역할은 무엇인지
  • 현재 상태가 무엇인지
  • 어떤 조건에서 다음 단계로 넘어가는지
  • 어떤 경우에 재실행하는지
  • 언제 작업을 완료하는지

등을 명확하게 정의해야 한다.

또한 Supervisor가 계속 Worker를 호출하면서 무한 루프에 빠질 가능성도 있기 때문에 최대 LLM 호출 횟수 같은 제한이 필요하다는 것도 배웠다.


7. Agent를 YAML로 정의하는 방법

오후에는 Agent를 Python 코드에 직접 작성하는 방식에서 한 단계 더 나아가 YAML 파일로 Agent를 정의하는 방식을 배웠다.

YAML은 설정 정보를 사람이 읽기 쉬운 형태로 작성하는 파일 형식이다.

예를 들어 Agent의 역할이나 지침, 사용할 Provider, Tool, Output Contract 등의 정보를 YAML에 선언하고 실행 프로그램에서 이를 불러오는 방식이다.

개념적으로는 다음과 같다.

worker_definition.yaml
        ↓
YAML Load
        ↓
Agent Definition 생성
        ↓
Supervisor
        ↓
Worker 실행

여기서 중요한 점은 YAML이 오케스트레이션 자체를 대신하는 것은 아니라는 것이다.

YAML은 Agent를 어떻게 정의할지에 대한 선언에 가깝고, 실제 실행과 오케스트레이션은 별도의 실행 엔진이 담당한다.

따라서 Python으로 Agent를 정의하든 YAML로 정의하든,

Agent → Contract → Validation → Orchestration

이라는 핵심 구조는 그대로 유지된다.


8. 오늘 직접 설계한 실습 방향

오후 실습에서는 직접 이사 준비 멀티에이전트 시나리오를 설계했다.

사용자가 이사할 도시와 날짜, 옮길 물품, 현장 제약 등을 입력하면 여러 Agent가 순서대로 결과를 만들어내는 구조다.

구상한 흐름은 다음과 같다.

사용자 입력
   ↓
물품 정리 Agent
   ↓
Output Contract 검증
   ↓
포장 준비 Agent
   ↓
Output Contract 검증
   ↓
이사 당일 계획 Agent
   ↓
최종 결과

각 Agent가 아무 문자열이나 반환하도록 하는 것이 아니라 Pydantic Output Contract를 연결해서 다음 단계로 전달하기 전에 검증하는 구조를 생각해봤다.

오늘 수업에서 배운 Supervisor 구조까지 적용한다면, 단순한 순차 실행뿐 아니라 결과가 부족할 때 이전 Agent를 다시 호출하는 방식으로 확장할 수도 있다는 점까지 연결해서 생각할 수 있었다.


9. 오늘 새롭게 이해한 점

오늘 가장 크게 달라진 부분은 멀티에이전트에서 Agent 자체보다 Agent 사이의 흐름을 설계하는 것이 중요하다는 것이다.

처음에는 여러 Agent를 만들어 순서대로 실행하면 멀티에이전트 시스템이 된다고 생각하기 쉬웠다.

하지만 오늘 수업을 통해

Agent를 실행하는 것

과

Agent의 결과를 검증하고 다음 행동을 결정하는 것

은 별개의 문제라는 것을 이해했다.

특히 Router와 Supervisor를 비교하면서 이 차이가 더 명확해졌다.

  • Router → 어디로 보낼 것인가?
  • Orchestration → 정해진 흐름을 어떻게 실행할 것인가?
  • Supervisor → 현재 결과를 보고 다음에 무엇을 할 것인가?
  • Output Contract → 결과를 다음 단계로 넘겨도 되는가?

이렇게 각각의 역할을 나누어 생각하니 이전보다 오케스트레이션 구조가 훨씬 명확해졌다.


10. 오늘 복습할 부분

오늘 배운 내용 중에서는 특히 다음 부분을 다시 정리해볼 필요가 있다.

  1. Router와 Supervisor의 차이
  2. Output Contract 검증 흐름
  3. Supervisor의 평가 기준 설계
  4. Supervisor의 무한 루프 방지
  5. YAML Agent Definition과 Python Agent Definition의 차이
  6. Redis run_id와 Snapshot을 이용한 실행 추적
  7. Polling과 SSE의 차이

특히 Router와 Supervisor를 실제 시나리오에 적용할 때 어떤 경우에 어느 패턴을 선택해야 하는지를 직접 여러 사례에 적용해보면 이해가 더 확실해질 것 같다.


오늘의 회고

오늘은 단순히 "에이전트를 여러 개 연결한다"는 것에서 한 단계 더 나아가 멀티에이전트 시스템의 제어 구조를 배운 날이었다.

Output Contract를 통해 Agent 결과를 검증하고, Router를 통해 적절한 Agent를 선택하고, Supervisor를 통해 현재 결과에 따라 다음 작업이나 재작업을 결정할 수 있다는 것을 연결해서 이해했다.

특히 앞으로 직접 멀티에이전트 시스템을 설계할 때는 Agent를 먼저 많이 만드는 것보다,

어떤 Agent가 필요한가 → 어떤 결과를 주고받는가 → 결과를 어떻게 검증하는가 → 문제가 생기면 어떻게 처리하는가 → 누가 다음 Agent를 결정하는가

를 먼저 설계해야겠다는 생각이 들었다.

오늘 실습에서 설계한 이사 준비 멀티에이전트도 단순한 순차 실행에서 끝내지 않고, 각 단계의 Output Contract와 검증 조건을 명확하게 만들어보는 것이 다음 과제가 될 것 같다.

댓글