페이지 목차
이 페이지에서 검색
멀티 에이전트
이 페이지에 묻기
멀티 에이전트 · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.
생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.
MULTI · AGENT
멀티 에이전트
생성 수정
도구 실행·검색·기억·그래프 흐름·전문 에이전트의 협업을 구성하고 권한·평가·사람의 확인으로 통제합니다.
26개 문서 · 3일차 · 23 / 26
22차시 · 오케스트레이션
지도 위치 : 3일차 · README 4장의 ⑤ 협업 층(마무리) | 이전: 21차시 전문 에이전트 구현 | 다음: 23차시 Human-in-the-Loop 키워드 : Supervisor 패턴, 위임, 응답 종합
이 차시를 다 읽으면
- 오케스트레이션과 Supervisor 패턴을 유와 종차로 정의하고 그림으로 그릴 수 있다.
- 위임의 두 방식(다음 담당 고르기 ↔ 전문 에이전트를 도구처럼 호출)을 구별할 수 있다.
- Planner-Worker(20차시)와 Supervisor를 "미리 계획 ↔ 매번 판단" 으로 가를 수 있다.
- StateGraph로 Supervisor를 만드는 원리(관리 노드 + 조건부 엣지 + 돌아오는 엣지)를 코드에서 짚을 수 있다.
- 응답을 종합할 때 출처를 유지하고 모순을 처리 하며, 총 반복 · 총 비용 상한을 코드로 걸 수 있다.
- 실행 추적으로 누가 무엇을 했는지 검수할 수 있다.
0. 이 차시의 판별 축
| # | 축 | 왼쪽 (0) | 오른쪽 (1) | 이 축으로 갈리는 것 | 큰 축 (README 5장) |
|---|---|---|---|---|---|
| 1 | 누가 흐름을 정하는가 ⭐ | 코드 — 엣지가 다음 노드를 정함 | 모델 — 관리 에이전트가 다음 담당을 고름 | 협업의 순서를 누가 쥐나 | 5.2 중심 축 |
| 2 | 미리 계획 ↔ 매번 판단 | 실행 전에 작업 목록 확정 (Planner-Worker) | 결과를 볼 때마다 다음을 정함 (Supervisor) | 계획의 시점 | 이 차시의 축 |
| 3 | 하나 ↔ 여럿 | 에이전트 하나 | 관리 + 전문 에이전트 여럿 | 협업 구조인가 | ⑤ 하나 ↔ 여럿 |
| 4 | 부탁 ↔ 강제 | "적당히 끝내"라고 관리 에이전트에 부탁 | 총 반복 · 총 비용을 State에 세고 코드로 끊음 | 폭주가 실제로 막히는가 | ②의 파생 |
| 5 | 증거 ↔ 주장 | 출처 · 실행 추적이 붙은 답 | 누가 어떻게 냈는지 모르는 답 | 종합된 답을 믿을 수 있나 | ⑧의 파생 |
이 차시가 답하는 질문은 "전문 에이전트 여럿에게 누가, 어떤 순서로 일을 맡기고, 결과를 어떻게 하나의 답으로 묶나?" 입니다. 앞 차시(21차시)에서 인사 · IT · 규정 에이전트를 계약(AgentRequest → AgentResult)으로 만들었습니다. 이번에는 그들을 지휘하는 자리를 만듭니다. README 5.2 중심 축에서 이 과정이 가장 오른쪽 까지 가는 차시입니다.
1. 오케스트레이션과 Supervisor 패턴
1.1 정의
오케스트레이션 — [멀티에이전트의 운영 방식]인데, [ 여러 에이전트의 실행 순서 · 일 배분 · 결과 모음을 한 곳에서 조율한다 ]는 점에서 에이전트끼리 직접 말을 주고받는 분산 협업과 구별된다.
Supervisor 패턴 — [오케스트레이션 패턴]인데, [ 관리 에이전트(LLM)가 매 단계 결과를 보고 다음에 일할 전문 에이전트를 고르며, 끝낼 때를 스스로 정한다 ]는 점에서 실행 전에 작업 목록을 확정하는 Planner-Worker와 구별된다.
사용자 요청
↓
┌──[supervisor]──┐ ← 매번 "다음은 누구?" 또는 "끝"
│ ↑ ↑ ↑ │
┌────┘ │ │ │ └──── FINISH → [종합] → 답
↓ │ │ │
[hr] ──────┘ │ │ ← 일이 끝나면 늘 supervisor로 돌아옴
[it] ───────────┘ │
[policy] ──────────────┘
1.2 반례 — 이건 Supervisor가 아닙니다
| 대상 | 왜 아닌가 |
|---|---|
| 19차시의 라우터 | 길을 한 번 고르고 끝. 결과를 보고 다시 고르지 않음 |
| 20차시의 Planner | 실행 전에 한 번 계획. 중간 결과로 계획을 바꾸지 않음 (재계획은 실패 시에만) |
| 에이전트끼리 서로 직접 호출 | 조율하는 한 곳이 없음. 누가 흐름을 쥐는지 추적하기 어려움 |
💡 비유 (기억 보조용) — 오케스트라의 지휘자 . 지휘자는 악기를 연주하지 않고, 지금 어느 파트가 들어갈지 매 순간 정합니다. 악보(계획)를 미리 나눠 주는 편곡자(Planner)와는 일하는 시점이 다릅니다.
2. 위임 — 두 가지 방식
위임 — [제어 넘기기]인데, [ 관리 에이전트가 하위 에이전트에게 일과 필요한 맥락을 넘기고 결과를 받는다 ]는 점에서 관리 에이전트가 직접 도구를 쓰는 것과 구별된다.
| (가) 다음 담당 고르기 | (나) 전문 에이전트를 도구처럼 호출 | |
|---|---|---|
| 모양 | supervisor 노드가 next="hr"을 내고, 그래프 엣지가 hr 노드로 보냄 | 관리 에이전트의 도구 목록에 ask_hr(task) 같은 도구가 있음 |
| 앞에서 배운 것 | 19차시 조건부 엣지 | 5 · 9차시 도구 호출과 루프 |
| 흐름이 보이는 곳 | 그래프 그림 과 State | 관리 에이전트의 루프 안 (추적으로 봄) |
| 병렬 | 그래프 설계에 따라 | 한 응답에 도구 여러 개 요청 → 병렬 호출 가능 |
| 맞는 경우 | 흐름을 그림으로 검수 · 멈춤 · 재개해야 할 때 | 간단히 시작할 때, 에이전트 수가 적을 때 |
두 방식 모두 누가 흐름을 정하는가의 오른쪽 입니다. 다음 담당을 모델이 고르기 때문입니다. 다만 (가)는 갈 수 있는 길을 그래프가, (나)는 쓸 수 있는 도구 목록을 코드가 정해 두었다는 점에서 완전한 자유는 아닙니다. 이 노트는 23차시의 멈춤 · 재개와 이어지도록 (가)로 설명합니다.
3. 미리 계획 ↔ 매번 판단 — Planner-Worker와의 경계
| Planner-Worker (20차시) | Supervisor (이 차시) | |
|---|---|---|
| 계획 시점 | 실행 전에 한 번 | 결과를 볼 때마다 |
| 중간 결과로 방향 바꾸기 | 어려움 (실패 시 재계획) | 자연스러움 ("잔여가 0일이네 → 규정 대신 IT 안 물어도 됨") |
| 사람이 미리 검수 | 계획표를 실행 전에 읽을 수 있음 | 어려움 — 추적으로 사후에 봄 |
| 병렬 | 의존성으로 독립 작업을 동시에 | 기본은 한 번에 한 담당 |
| LLM 호출 | 계획 1 + 워커 N + 취합 1 | (supervisor 판단 + 담당) × 단계 수 + 종합 |
| 폭주 위험 | 작업 수가 정해져 있어 낮음 | supervisor가 끝을 안 정하면 계속 돎 |
| 맞는 경우 | 작업이 미리 보이는 복합 요청 | 앞 결과에 따라 다음 일이 달라지는 요청 |
⭐ 둘 중 하나만 고를 필요는 없습니다. 오피스봇은 복합 요청이 미리 보이면 Planner, 결과에 따라 흐름이 갈리면 Supervisor 로 보내도 됩니다. 판단 기준은 이번에도 문장 1 — 더 예측 가능한 쪽(왼쪽)으로 충분하면 오른쪽으로 가지 않습니다.
4. StateGraph로 구현하는 원리
세 부품만 있으면 됩니다. supervisor 노드 (다음 담당을 고름) + 조건부 엣지 (고른 담당에게 보냄, 19차시) + 돌아오는 엣지 (담당이 끝나면 supervisor로).
import operator
from typing import Annotated, Literal, TypedDict
from pydantic import BaseModel
class Decision(BaseModel):
next: Literal["hr", "it", "policy", "FINISH"]
task: str # 다음 담당에게 줄 한 줄 지시
reason: str
class State(TypedDict):
question: str
results: Annotated[list[dict], operator.add] # AgentResult가 차례로 쌓임
next: str
task: str
steps: int
tokens: int
def supervisor(state: State) -> dict:
if state["steps"] >= MAX_STEPS or state["tokens"] >= MAX_TOKENS: # 코드가 먼저 끊음
return {"next": "FINISH"}
r = client.messages.parse(model="claude-opus-5-5", max_tokens=1024,
system=SUPERVISOR_PROMPT,
messages=[{"role": "user", "content": render(state)}],
output_format=Decision)
d = r.parsed_output
used = r.usage.input_tokens + r.usage.output_tokens
return {"next": d.next, "task": d.task, "steps": state["steps"] + 1,
"tokens": state["tokens"] + used}
g.add_conditional_edges("supervisor", lambda s: s["next"],
{"hr": "hr", "it": "it", "policy": "policy", "FINISH": "synthesize"})
for agent in ["hr", "it", "policy"]:
g.add_edge(agent, "supervisor") # 일이 끝나면 늘 돌아옴
g.add_edge("synthesize", END)
🔍 읽는 포인트
Decision.next: Literal[...]— 관리 에이전트가 고를 수 있는 담당은 이 넷뿐 입니다. 없는 에이전트를 지어낼 수 없습니다.if state["steps"] >= MAX_STEPS ...— 모델에게 묻기 전에 코드가 상한을 확인합니다. 6절의 가드레일입니다.g.add_edge(agent, "supervisor")— 돌아오는 엣지 . 담당은 끝나면 답을 사용자에게 바로 주지 않고 관리 에이전트에게 돌아갑니다. 이 선이 Supervisor 그림(1.1)의 화살표입니다.results: Annotated[..., operator.add]— 담당들의AgentResult가 덮어써지지 않고 쌓입니다 (18차시 리듀서). 종합 단계가 이 목록을 읽습니다.- 💡 Supervisor 구성을 도와주는 별도 패키지(예: langgraph-supervisor)도 있지만 버전에 따라 이름과 사용법이 다릅니다. 원리를 먼저 이 구조로 이해하고, 패키지를 쓸 때는 공식 문서를 확인하세요.
5. 응답 종합 — 출처 유지와 모순 처리
응답 종합 — [결과 처리 단계]인데, [ 여러 에이전트의 결과를 하나의 답으로 묶되 각 내용의 출처를 유지하고 결과끼리의 모순을 드러낸다 ]는 점에서 마지막 에이전트의 답을 그대로 내보내는 것과 구별된다.
| 다룰 것 | 예 | 처리 |
|---|---|---|
| 출처 유지 | policy가 낸 "취업규칙 제23조" | 종합된 문장에도 그대로 붙임. 종합 단계가 출처를 새로 만들지 않음 |
| 모순 | hr: "잔여 2일" / policy 답에 "잔여 3일이면" | 조회 결과를 우선하고, 다르다는 사실을 답에 적음 |
| 못 한 일 | it이 status="error" | "확인하지 못했습니다"를 밝힘 |
| 승인 필요 | hr이 needs_approval | 답에서 "신청 완료"라고 말하지 않음 → 23차시 승인 흐름 |
⚠️ 종합 단계는 가장 그럴듯한 하나의 이야기 를 만들려는 경향이 있습니다. 그 과정에서 출처가 사라지고 모순이 매끄럽게 덮입니다. 앞에서 배운 근거 기반 답변(14차시)의 원칙 — 근거에 없으면 답하지 않는다 — 을 종합 단계에도 그대로 적용합니다. AgentResult.sources가 계약에 있던 이유입니다(21차시).
6. 가드레일 재적용 — 총 반복 · 총 비용
앞에서 배운 루프 가드레일(10차시)은 에이전트 하나 의 루프에 상한을 걸었습니다. 멀티에이전트에서는 상한이 두 층 이 됩니다.
| 층 | 무엇을 세나 | 어디에 거나 |
|---|---|---|
| 에이전트 안 | 그 에이전트의 도구 반복 횟수 · 토큰 | 각 전문 에이전트의 루프 (10차시 그대로) |
| 전체 | supervisor 판단 횟수 · 모든 에이전트 토큰 합 | State의 steps · tokens, 그래프의 recursion_limit (19차시) |
| 같은 위임 반복 | 같은 담당에게 같은 지시를 연달아 | supervisor 노드에서 직전 결정과 비교해 끊음 |
⚠️ 에이전트마다 상한이 있어도 전체 상한이 없으면 폭주합니다. supervisor가 hr → policy → hr → policy를 오가면 각자는 상한 안에 있지만 전체 비용은 계속 늘어납니다. 그래서 4절 코드에서 모델에게 묻기 전에 전체 상한을 먼저 확인했습니다. 상한에 닿으면 그때까지의 결과로 종합하고 "일부만 처리했습니다"를 밝힙니다.
7. 실행 추적으로 검수 — 누가 무엇을 했나
앞에서 배운 트레이싱(11차시)은 각 단계의 입력 · 출력 · 토큰 · 시간을 기록했습니다. 멀티에이전트에서는 이것이 유일한 검수 수단 에 가깝습니다. Planner와 달리 미리 읽을 계획표가 없기 때문입니다(3절).
| 추적에서 볼 것 | 이상 신호 |
|---|---|
supervisor의 결정 순서와 reason | 같은 담당을 반복 호출, 필요 없는 담당 호출 |
각 담당이 받은 task | 원래 요청의 조건(날짜 등)이 빠짐 — 넘겨주는 정보 손실 (21차시) |
각 담당의 status와 sources | 범위 밖인데 done, 출처 없는 done |
| 단계별 토큰 | 한 단계가 유독 큼 — 대화 전체를 넘기고 있지 않은가 |
| 최종 답의 문장별 출처 | 종합이 출처를 지어냈는가 |
⚠️ 추적 기록은 외부 서비스로 전송될 수 있습니다(축 ④). 앞에서 배운 마스킹(8차시)과 장기 기억의 외부 전송 점검(17차시)을 추적에도 적용하세요.
앞으로 다시 만납니다 — 23차시에서
needs_approval을 받은 흐름을 멈추고 , 사람이 승인하면 재개 합니다. 24차시에서는 이 추적의 진행 상황을 화면에 스트리밍으로 보여 줍니다("인사 담당이 휴가 잔여를 확인하는 중...").
8. 실습 — 맡기고 검수하기
지시
21차시의 인사 · IT · 규정 에이전트 위에 Supervisor를 만들어줘.
참고 공식 문서: LangGraph StateGraph · 조건부 엣지 · recursion_limit, Claude API 구조화 출력, LangSmith 트레이싱.
설치된 langgraph 버전을 출력하고 그 버전 문서 기준으로 작성할 것. 별도 supervisor 패키지는 쓰지 말 것.
구조: supervisor(Decision 스키마) → 조건부 엣지 → hr/it/policy → supervisor로 복귀 → FINISH면 synthesize → END.
제약:
- MAX_STEPS=6, MAX_TOKENS 상한(값은 보고)을 supervisor 노드에서 모델 호출 전에 검사.
- 같은 담당 · 같은 task 연속 2회면 FINISH.
- synthesize는 AgentResult.sources만 출처로 사용. needs_approval은 "승인 대기"로 답할 것.
- 트레이싱을 켜되 사번 · 전화번호는 마스킹 후 전송.
테스트: ① "다음 주 월요일 휴가 쓰려는데 잔여 확인하고, 노트북 반납 절차도 알려줘" ② 단일 의도 질문 2개
③ 담당끼리 답이 모순되게 만든 테스트 데이터 ④ supervisor가 계속 위임하도록 유도하는 질문 ⑤ 모니터 신청 요청
보고 형식: 시나리오마다 [단계 | supervisor 결정 | reason | 담당 | status | sources | 누적 토큰] 표 + 최종 답 원문.
20차시 Planner-Worker 방식과 ①의 호출 수 · 토큰을 비교.
추측하지 말고 실행 출력 원문과 추적 화면 캡처(또는 추적 기록 원문)를 붙여.
받을 증거
- 시나리오별 단계 표 와 최종 답 원문
- ④에서 상한에 닿아 FINISH로 끊긴 단계 기록
- 추적 기록에서 사번 · 전화번호가 가려진 화면
- ①에 대한 Planner-Worker 대비 호출 수 · 토큰 비교
내가 직접 확인할 것
| 볼 것 | 이걸로 아는 것 |
|---|---|
| ②에서 supervisor가 한 담당만 부르고 끝냈는가 | 단순한 질문에 과하게 돌지 않는가 (3) |
| ③의 답에 모순이 드러나 있는가 | 종합이 모순을 덮지 않는가 (5) |
| ④에서 단계 수가 6을 넘지 않았는가 | 전체 상한이 코드로 걸렸는가 (6) |
| ⑤의 답이 "신청 완료"가 아닌가 | 승인 필요가 종합에서 지켜지는가 (5) |
| 최종 답의 출처가 담당의 sources에 있는 것뿐인가 | 출처를 지어내지 않는가 (5) |
| Planner-Worker 대비 토큰 차이 | 매번 판단의 대가 (3) |
부록 A. 스스로 확인하기
| # | 질문 | 답이 있는 곳 |
|---|---|---|
| 1 | 오케스트레이션과 Supervisor 패턴을 유와 종차로 정의하면? | 1.1 |
| 2 | 19차시 라우터와 Supervisor의 차이는? | 1.2 |
| 3 | 위임의 두 방식은 무엇이고 각각 언제 맞나? | 2 |
| 4 | 미리 계획 ↔ 매번 판단을 표로 비교하면? | 3 |
| 5 | Supervisor를 StateGraph로 만드는 세 부품은? | 4 |
| 6 | 상한 검사를 모델 호출 전에 하는 이유는? | 4, 6 |
| 7 | 응답 종합에서 다룰 네 가지는? | 5 |
| 8 | 에이전트별 상한만으로 부족한 이유는? | 6 |
| 9 | 추적에서 "넘겨주는 정보 손실"을 찾는 법은? | 7 |
부록 B. 자주 하는 실수
| 실수 | 바로잡기 |
|---|---|
| "Supervisor가 Planner보다 발전된 것" | ❌ 계획 시점이 다를 뿐입니다. 미리 보이는 요청은 Planner가 예측 가능합니다 |
| 담당이 끝나면 사용자에게 바로 답함 | ⚠️ 돌아오는 엣지가 없으면 다른 담당의 결과와 종합되지 않습니다 |
| 전체 상한 없이 에이전트별 상한만 둠 | ❌ 담당 사이를 오가며 폭주합니다. State에 전체 횟수 · 토큰을 |
| 상한 검사를 모델에게 맡김 ("6번 넘으면 끝내") | ❌ 부탁입니다. 노드 코드에서 먼저 검사 |
| 종합 단계가 출처를 새로 만듦 | ❌ 담당의 sources만 쓰게 하세요 |
| 모순을 매끄럽게 하나로 정리 | ⚠️ 모순은 드러내고, 조회 결과를 우선합니다 |
| 추적을 원문 그대로 외부로 보냄 | ⚠️ 개인정보가 나갑니다. 마스킹 후 전송 |
부록 C. NotebookLM 복습 프롬프트
이 22차시 노트만 근거로 비전공자용 5문제를 내줘.
"Supervisor와 Planner-Worker의 경계(미리 계획 ↔ 매번 판단)", "돌아오는 엣지", "응답 종합의 출처와 모순", "전체 상한을 코드로"는 반드시 포함해줘.
내가 답한 뒤에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.
LangTailor