멀티 에이전트에서 ‘통제자’의 역할을 분리하며 배운 것들
지난 글에서 State와 Message Bus의 역할을 혼동하며 겪었던 혼란을 정리했다.
그 글 마지막에 이렇게 썼다.
“다음 글에서는 이 State를 누가 관리해야 하는지,
이 역할의 경계를 중심으로 정리해보려 한다.
이번 글은 그 이야기다.

1. “누가 이걸 결정한 거지?”가 반복되는 순간
멀티 에이전트를 만들다 보면 처음에는 역할 분담이 깔끔해 보인다.
Planner가 계획을 세우고, Executor가 실행하고, Reviewer가 검토한다.
문제는 이 셋 사이에서 “다음 단계로 넘어가도 되는지”를 누가 결정하느냐였다.
처음에 나는 이 판단도 Agent 중 하나에게 맡겼다.
Planner가 계획도 세우고 진행 여부도 판단하게 했다.
결과는 예상 가능했다. Planner는 자기가 세운 계획이 충분하다고 거의 항상 판단했다.
자기 계획을 스스로 부정하는 LLM은 드물다.
2. 역할이 필요하다고 느낀 순간
Planner에게 진행 판단을 맡기면서 이상한 패턴이 반복됐다.
- 데이터가 부족한데 분석 단계로 넘어가거나
- 에러가 발생했는데 그냥 다음 스텝을 실행하거나
- 같은 입력인데 어떤 때는 3단계, 어떤 때는 7단계를 거치거나
이건 Planner의 문제가 아니었다.
애초에 흐름 제어를 LLM에게 맡긴 설계의 문제였다.
그때 처음으로 “이 시스템에는 에이전트와는 다른 존재가 필요하다”는 생각이 들었다.
에이전트는 자기 역할 안에서 최선의 판단을 내리는 존재다.
하지만 전체 흐름을 보고, 지금 어디까지 왔는지를 판단하고,
다음 단계로 넘길지 말지를 결정하는 건 다른 차원의 책임이다.
3. 역할의 차이
처음에는 Orchestrator도 그냥 “상위 에이전트”라고 생각했다.
더 똑똑한 LLM을 붙여서 전체를 관장하게 하면 되지 않을까.
이 생각이 틀렸다는 걸 깨닫는 데 오래 걸리지 않았다.
내가 지금 이해하는 차이는 이렇다.
Agent는 판단한다.
- “이 데이터를 어떻게 해석할까”
- “어떤 관점에서 분석할까”
- “결과를 어떻게 설명할까”
Orchestrator는 결정한다.
- “지금 이 단계가 끝났는가”
- “다음 단계로 넘어가도 되는가”
- “이 에러는 재시도할 것인가, 중단할 것인가”
- “이 실행은 전체 예산 내에 있는가”
판단과 결정의 차이. 이게 처음에는 비슷해 보이지만, 실제로는 전혀 다르다.
판단은 틀려도 된다. 다음 단계에서 보정할 수 있다. 결정은 틀리면 시스템 전체가 흔들린다.
그래서 통제자는 LLM이 아니라 코드로 만들어야 한다는 결론에 도달했다.

4. Orchestrator를 코드로 분리하고 나서 달라진 것
Orchestrator를 LLM에서 코드로 옮기는 작업은 생각보다 단순했다.
핵심은 세 가지였다.
첫째, 전환 조건을 명시적으로 정의했다.
“분석이 충분하면 다음으로”가 아니라 “결과 필드 A, B, C가 모두 존재하면 다음으로”로 바꿨다.
프롬프트가 아니라 if문이 판단하게 했다.
둘째, 재시도와 종료를 코드로 제어했다.
에러가 발생하면 LLM에게 “어떻게 할까” 묻는 대신 에러 타입별로 재시도 횟수와 fallback 경로를 코드에 정의했다.
셋째, State 업데이트 권한을 통제자에게만 줬다.
그 결과를 State에 반영할지, 어떻게 반영할지는 Orchestrator가 결정한다.
이렇게 바꾸고 나니 시스템의 행동이 눈에 띄게 예측 가능해졌다.
같은 입력에 같은 흐름. 에러에 같은 대응. 종료 조건에 같은 종료.
당연한 것 같지만 LLM에게 흐름을 맡기면 이 “당연함”이 사라진다.
5. 그렇다면 Orchestrator에 LLM이 전혀 필요 없는가
여기서 한 가지 오해하기 쉬운 부분이 있다.
“Orchestrator를 코드로 만들라”는 말이 “LLM을 절대 쓰지 말라”는 뜻은 아니다.
내가 지금 쓰는 방식은 이렇다.
흐름 제어의 뼈대는 코드다. 하지만 특정 지점에서 LLM의 의견을 참고하기도 한다.
예를 들어, Reviewer가 반환한 결과의 품질이 애매할 때 Orchestrator가 LLM에게
“이 결과가 기준을 충족하는지 평가해줘”라고 물을 수 있다.
하지만 최종 결정은 여전히 코드가 한다.
LLM의 응답이 “불충분”이더라도 재시도 횟수가 이미 최대치면 통제자는 그냥 넘어간다.
이 구조에서 LLM은 자문위원이고 통제자는 의사결정권자다.
자문위원의 의견을 듣되 최종 서명은 항상 같은 사람이 한다.

6. 지금 내가 정리한 Orchestrator 설계 원칙
여러 번 구조를 엎고 다시 짜면서 지금 시점에서 정리한 최소 원칙은 이렇다.
1. 존재는 아니다. 역할이 다르고 책임이 다르다.
2. 전환 조건은 코드로 정의한다. “충분하면”이 아니라 “조건 A, B가 참이면”.
3. State 수정 권한은 통제자만 갖는다. 에이전트는 결과를 반환할 뿐이다.
4. LLM은 자문이지 결정이 아니다. 의견을 들을 수 있지만 최종 판단은 코드가 한다.
5. 종료 조건은 반드시 명시한다. 암묵적 종료는 곧 무한 루프다.
이 다섯 가지를 지키기 시작하면서 멀티 에이전트 시스템이 처음으로 “내가 만든 시스템”처럼 느껴지기 시작했다.
마무리하며
멀티 에이전트에서 가장 어려운 건 에이전트를 똑똑하게 만드는 게 아니다.
에이전트들 사이에서 누가 전체를 보고 있는지를 명확히 하는 것이다.
처음에 나는 그 역할을 가장 똑똑한 에이전트에게 맡기면 된다고 생각했다.
하지만 똑똑함과 통제력은 다른 문제였다.
Orchestrator는 똑똑할 필요가 없다. 일관되기만 하면 된다.
다음 글에서는 이 구조 위에서 실제로 금융 도메인의 데이터를 다루며
Agent에게 어떤 Tool을 어떻게 제한적으로 열어줬는지를 정리해보려 한다.
