Chapter 8

멀티 에이전트

  • 8.1 에이전트는 몇 개나 필요할까?
  • 8.2 에이전트 추가 원칙
  • 8.3 멀티 에이전트 조율
  • 8.4 에이전틱 시스템의 자동 설계
  • 8.5 에이전트 통신 기법
  • 8.6 메시지 브로커와 이벤트 버스
  • 8.7 액터 프레임워크
  • 8.8 오케스트레이션 및 워크플로 엔진
  • 8.9 상태와 영속성 관리

원제 "From One Agent to Many" — 드디어 에이전트 하나에서 여러 개로 넘어가는 챕터야. 1장에서 "점진적 설계 — 처음부터 멀티 에이전트 만들지 마"라고 했는데, 이제 "그래서 언제, 어떻게 만드냐"를 본격적으로 다루지.

제일 먼저 던지는 질문이 **에이전트 하나로 안 되나?**야. 대부분의 경우 답은 "된다"거든.

단일 에이전트가 충분한 경우:

  • 작업이 하나의 도메인에 집중되어 있을 때
  • 순차적으로 처리해도 괜찮을 때
  • 컨텍스트 윈도 안에 필요한 정보가 다 들어갈 때

멀티 에이전트가 필요한 경우:

  • 전문성이 다른 여러 도메인을 넘나들어야 할 때 (코드 작성 + 코드 리뷰 + 테스트)
  • 병렬 처리가 필요한 대규모 작업
  • 서로 다른 관점에서 검증이 필요할 때 (생성자 + 검증자)
  • 하나의 에이전트에 도구를 너무 많이 붙이면 성능이 떨어질 때

핵심 통찰은 이거야 — 에이전트를 늘리면 능력은 올라가지만 **조율 비용(coordination overhead)**도 같이 올라가. 에이전트 7개 넘어가면 조율 복잡도가 이득을 초과한다는 연구 결과도 있어. 그래서 무작정 늘리는 게 아니라 "이 에이전트가 정말 필요한가?"를 계속 물어봐야 하지.

OpenAI가 실험적으로 공개한 Swarm 프레임워크가 재밌는 접근인데, 핵심 아이디어는 두 가지 추상화뿐이야:

  • 루틴(Routine) — 에이전트의 지시사항과 도구 세트
  • 핸드오프(Handoff) — 한 에이전트가 다른 에이전트에게 대화를 넘기는 것

무거운 오케스트레이션 레이어 없이 에이전트 간 핸드오프만으로 멀티 에이전트를 구현하겠다는 발상이야. 상태를 유지하지 않는 스테이트리스 설계라서 투명하고 디버깅이 쉽다는 장점이 있지. 다만 실험/교육용이었고, 이후 OpenAI Agents SDK로 프로덕션 레디 버전이 나왔어.

스웜의 교훈은 멀티 에이전트가 반드시 복잡할 필요는 없다는 거야. 에이전트 간 핸드오프라는 단순한 패턴만으로도 꽤 많은 시나리오를 커버할 수 있거든.

에이전트를 추가하려면 명확한 이유가 있어야 해. 감으로 "이것도 에이전트 하나 만들까?" 하면 안 되지.

에이전트를 추가하는 타당한 이유:

  • 전문성 분리 — 하나의 에이전트가 너무 많은 역할을 하면 프롬프트가 길어지고 성능이 떨어져. 코드 작성과 코드 리뷰를 같은 에이전트가 하면 자기가 쓴 코드를 자기가 검증하는 꼴이잖아
  • 도구 과부하 방지 — 에이전트에 도구를 20개씩 붙이면 잘못된 도구를 선택할 확률이 올라가. 5~7개가 적정선이야
  • 병렬 처리 — 순차적으로 하면 10분 걸리는 걸 에이전트 3개가 나눠서 3분에 끝내는 거지
  • 견제와 검증 — 생성하는 에이전트와 검증하는 에이전트를 분리하면 품질이 올라가

추가하면 안 되는 경우:

  • 단순히 "있으면 좋겠다" 수준의 기능
  • 기존 에이전트의 도구 하나 추가로 해결되는 것
  • 에이전트 간 통신 비용이 에이전트 추가 이득보다 클 때

결국 소프트웨어 엔지니어링의 **단일 책임 원칙(Single Responsibility Principle)**이랑 같은 맥락이야. 마이크로서비스에서 서비스 쪼개는 판단이랑 비슷하지 — 쪼개면 독립성은 올라가지만 통신 복잡도도 올라가거든.

에이전트가 여러 개일 때 가장 큰 문제는 누가 뭘 하고, 순서는 어떻게 정하냐야. 네 가지 조율 패턴이 있어.

**민주적 조율(Democratic Coordination)**은 에이전트들이 동등한 위치에서 합의를 통해 결정하는 거야. 각 에이전트가 의견을 내고, 투표나 합의 과정을 거쳐서 최종 결정을 내리지.

  • 장점: 다양한 관점 반영, 단일 실패점 없음
  • 단점: 합의 비용이 큼, 에이전트 수가 늘어나면 수렴이 어려움
  • 적합한 경우: 브레인스토밍, 다각도 검토가 필요한 의사결정

**관리자 중심 조율(Manager Coordination)**은 하나의 관리자(Manager) 에이전트가 작업을 분배하고 결과를 수집하는 거야. 나머지는 워커(Worker) 에이전트로 지시받은 일을 수행하지.

  • 장점: 명확한 책임 분리, 작업 분배가 효율적
  • 단점: 관리자가 병목/단일 실패점이 될 수 있음
  • 적합한 경우: 작업이 명확하게 분할 가능한 경우. 고객 지원에서 라우터 에이전트가 문의 유형별로 전문 에이전트에게 배분하는 패턴

이게 실무에서 제일 많이 쓰이는 패턴이야. CrewAI의 매니저 모드가 여기 해당하지.

**계층형 조율(Hierarchical Coordination)**은 관리자 중심을 다층으로 확장한 거야. 상위 에이전트가 중간 관리자 에이전트를 지휘하고, 중간 관리자가 다시 워커 에이전트를 지휘하는 구조지.

  • 장점: 대규모 시스템에서 확장 가능, 에이전트 7개 제한을 우회 — 팀장이 34명 관리, 팀장 밑에 다시 34명
  • 단점: 계층이 깊어지면 지시가 왜곡될 수 있음, 오버헤드 증가
  • 적합한 경우: 복잡한 프로젝트를 여러 팀으로 나눠 실행할 때

군대 지휘 체계랑 비슷하다고 보면 돼. 대장이 소대장한테 지시하고, 소대장이 분대원한테 전달하는 거지.

**액터-크리틱(Actor-Critic)**은 강화학습에서 온 패턴인데, 멀티 에이전트에서도 써. 액터가 행동(코드 작성, 문서 생성 등)을 하고, 크리틱이 그 결과를 평가해서 피드백을 주지. 액터는 피드백 반영해서 다시 시도하고.

  • 장점: 자기 개선 루프가 내장됨, 품질이 반복할수록 올라감
  • 단점: 반복이 많아지면 비용과 시간 증가
  • 적합한 경우: 코드 생성 + 리뷰, 글쓰기 + 편집, 계획 수립 + 검증

실제로 코드 에이전트 시스템에서 많이 쓰는 패턴이야. 코드 짜는 에이전트 따로, 리뷰하는 에이전트 따로. "코드 리뷰어가 통과시킬 때까지 수정하라"는 루프를 돌리는 거지.

기준 민주적 관리자 계층형 액터-크리틱
에이전트 수 소규모 중규모 대규모 2~3개
의사결정 합의 중앙 위임 반복 검증
복잡도 중간 낮음 높음 낮음
적합 시나리오 토론/검토 작업 분배 대형 프로젝트 품질 개선

좀 미래 지향적인 얘기도 나와. 에이전트 시스템을 사람이 설계하는 게 아니라 에이전트가 설계하면 어떨까?

ICLR 2025에서 발표된 ADAS(Automated Design of Agentic Systems) 연구가 대표적이야. 핵심 아이디어:

  • 에이전트를 코드로 정의해
  • **메타 에이전트(Meta Agent)**가 기존 에이전트 아카이브를 참고해서 새로운 에이전트를 프로그래밍하지
  • 반복하면서 점점 더 나은 에이전트 설계를 발견해

Meta Agent Search라는 알고리즘을 통해 코딩, 과학, 수학 등 여러 도메인에서 사람이 수동으로 설계한 에이전트보다 훨씬 좋은 성능의 에이전트를 자동으로 만들어냈다고 해. 심지어 한 도메인에서 발견한 설계가 다른 도메인으로 전이(transfer)도 되고.

프로그래밍 언어가 튜링 완전하니까 이론적으로 모든 가능한 에이전틱 시스템 — 새로운 프롬프트 전략, 도구 사용 패턴, 워크플로 조합 — 을 탐색할 수 있다는 거야. 이게 사람의 설계 노력을 대체할 수 있을 뿐 아니라, 수동 설계보다 더 빠르게 효과적인 해법에 도달할 수 있다고 주장하지.

아직 초기 연구 단계지만 방향은 분명해 — 에이전트가 에이전트를 만드는 시대가 오고 있다는 거야.

멀티 에이전트에서 에이전트끼리 어떻게 소통하냐는 아키텍처를 결정짓는 핵심 선택지야.

같은 프로세스 안에서 에이전트끼리 직접 함수 호출하거나 메모리를 공유하는 로컬 통신 방식이 있어.

  • 직접 호출 — 에이전트 A가 에이전트 B의 메서드를 직접 부름. 단순하지만 결합도 높음
  • 공유 메모리 — 블랙보드 패턴. 공통 데이터 구조에 에이전트들이 읽고 쓰기
  • 메시지 전달 — 인메모리 큐를 통해 메시지를 주고받음

LangGraph나 CrewAI 같은 프레임워크 대부분이 로컬 통신을 사용해. 단일 서버에서 돌리기엔 이게 가장 간단하고 빠르지.

에이전트가 다른 머신, 다른 조직, 다른 클라우드에 있을 때는 분산 통신이 필요해.

  • HTTP/REST — 가장 보편적. 에이전트를 API 서버로 만들고 HTTP로 호출
  • gRPC — 고성능 바이너리 프로토콜. 지연시간 민감한 경우
  • 메시지 큐 — RabbitMQ, Kafka 같은 브로커를 통한 비동기 통신

Google이 2025년 4월에 공개한 Agent2Agent(A2A) 프로토콜이 게임 체인저가 될 수 있는 녀석이야. 50개 이상의 기업(Atlassian, Salesforce, SAP, ServiceNow 등)이 참여했고, 이후 Linux Foundation에 기증되면서 150개 이상 조직이 지원하는 오픈 표준이 됐거든.

A2A의 핵심 개념:

  • 에이전트 카드(Agent Card) — JSON 형식으로 에이전트의 능력, 엔드포인트, 인증 방법을 기술. 에이전트끼리 서로 뭘 할 수 있는지 자동으로 발견
  • 태스크 관리 — 클라이언트 에이전트가 리모트 에이전트에게 태스크를 요청하고, 태스크의 라이프사이클(제출 -> 진행 중 -> 완료)을 추적
  • 컨텍스트 공유 — 에이전트 간에 맥락 정보와 지시사항을 교환
  • UX 협상 — 다양한 UI 환경에 맞춰 결과 형식을 조정

MCP(Model Context Protocol)가 에이전트와 도구 간의 연결이라면, A2A는 에이전트와 에이전트 간의 연결이야. 이 둘이 합쳐지면서 상호운용 가능한 에이전트 생태계의 기반이 만들어지고 있지.

0.3 버전에서는 gRPC 지원과 보안 카드 서명 기능까지 추가됐어. 에이전트가 자기 조직 밖의 에이전트와도 안전하게 협업할 수 있는 토대가 되는 거야.

에이전트끼리 직접 통신하면(point-to-point) 에이전트 수가 늘어날수록 연결이 n(n-1)/2로 폭발하잖아. 그래서 중간에 브로커를 두는 게 확장 가능한 설계야.

에이전트 A가 브로커에 메시지를 보내면, 브로커가 적절한 에이전트 B에게 전달하지. 생산자(publisher)와 소비자(subscriber)가 서로를 몰라도 돼.

대표적인 기술:

  • Apache Kafka — 대용량 이벤트 스트리밍. 메시지를 로그처럼 영속적으로 저장해서 나중에 재생 가능. 에이전트가 죽었다 살아나도 놓친 메시지를 따라잡을 수 있어
  • RabbitMQ — 전통적인 메시지 큐. 라우팅이 유연하고 다양한 전달 보장(at-least-once, exactly-once) 지원
  • Redis Streams — 가벼운 메시지 스트리밍. 빠르고 간단

이벤트 버스는 메시지 브로커의 변형인데, 이벤트 중심 아키텍처에 특화돼 있어. 에이전트가 "이런 일이 일어났다"는 이벤트를 발행하면, 관심 있는 에이전트가 구독해서 받아가는 거야.

Confluent 블로그에서 정리한 이벤트 기반 멀티 에이전트 설계 패턴 네 가지가 있어:

  • 오케스트레이터-워커 — 중앙 오케스트레이터가 이벤트를 발행하고 워커들이 구독
  • 계층형 에이전트 — 이벤트 버스 위에 계층 구조를 얹은 것
  • 블랙보드 — 공유 이벤트 스토어에 모든 에이전트가 읽고 쓰기
  • 마켓 기반 — 에이전트가 경매/입찰 방식으로 태스크를 가져감

이벤트 버스를 쓰면 에이전트 간 **느슨한 결합(loose coupling)**이 실현돼. 새 에이전트를 추가하거나 기존 에이전트를 교체해도 다른 에이전트에 영향이 없지. 마이크로서비스에서 이벤트 드리븐 아키텍처가 대세가 된 것과 같은 이유야.

Solace Agent Mesh 같은 프레임워크는 아예 에이전트 메시징을 위한 전용 이벤트 플랫폼을 제공하기도 해.

**액터 모델(Actor Model)**은 원래 동시성 프로그래밍의 고전적인 패턴인데, 멀티 에이전트에 딱 맞는 모델이야.

핵심은 이래:

  • 각 액터는 독립된 **사적 상태(private state)**를 가짐
  • 액터끼리 직접 상태를 공유하지 않고 메시지만 주고받음
  • 메시지 수신 시 세 가지만 할 수 있음: 새 액터 생성, 다른 액터에게 메시지 전송, 자기 상태 변경

이걸 에이전트에 적용하면 — 각 에이전트가 독립된 액터로 동작하고, 이벤트 버스를 통해 비동기로 메시지를 주고받는 거지. 에이전트 간 직접 연결(스파게티 코드)이 사라지고, 확장성과 디버깅 용이성이 올라가.

Microsoft의 AutoGen v0.4가 대표적으로 액터 모델을 채택한 프레임워크야.

  • 에이전트가 액터로 구현됨 — 독립적이고, 비동기적이고, 이벤트 기반
  • 메시지 전달이 에이전트에서 중앙 컴포넌트로 이동해서 관찰/디버깅이 쉬움
  • 분산 배포 가능 — 에이전트가 서로 다른 서버, 심지어 다른 조직에서 실행 가능
  • 재사용 가능한 컴포넌트 설계

이후 AutoGen은 Microsoft Agent Framework로 통합/발전했는데, 핵심 철학은 유지됐어. 이벤트 기반 통신이 메시지 전달을 에이전트에서 분리해서 관찰 가능성을 높인다는 거지.

액터 모델의 장점은 확장성에 있어. 에이전트 10개든 100개든 패턴이 동일하고, 각 에이전트가 독립적이라 하나가 죽어도 전체가 멈추지 않아. 다만 디버깅 시 비동기 메시지 흐름을 추적하는 게 동기식보다는 어려울 수 있지.

멀티 에이전트 시스템이 프로덕션에 들어가면 **에이전트가 중간에 죽으면 어떡하지?**가 핵심 문제가 돼. 워크플로 엔진은 이 문제를 해결하지.

기본 아키텍처는 이래:

  • 오케스트레이터 — 전체 워크플로의 상태 머신을 관리
  • 플래너 — 다음에 뭘 할지 계획
  • 스케줄러 — 워커에게 작업을 할당
  • 워커 — 실제 작업 수행

작업이 완료되면 오케스트레이터의 상태가 업데이트되고, 다음 단계로 진행해. 이 루프가 워크플로가 끝날 때까지 반복되지.

Temporal이 요즘 에이전트 오케스트레이션에서 가장 주목받는 워크플로 엔진이야. 핵심 개념은 **내구성 있는 실행(Durable Execution)**이지.

  • 워크플로 코드의 모든 진행 상태를 이벤트 히스토리로 자동 기록
  • 프로세스가 죽어도 기록된 상태에서 자동 재개
  • 내장된 재시도, 타이머, 시그널, 태스크 큐 지원
  • 워크플로의 상태가 **내구성 있는 가상 메모리(durable virtual memory)**로 영속화

에이전트 시스템에 이게 왜 중요하냐면 — AI 에이전트의 작업은 몇 분에서 몇 시간까지 걸릴 수 있고, 그 사이에 API 호출 실패, 서버 재시작, 네트워크 문제 같은 일이 생기기 때문이야. Temporal이 이런 장애를 자동으로 처리해주지.

Temporal 공식 OpenAI Agents SDK 통합도 나와서, 기존 OpenAI 에이전트 코드에 최소한의 수정으로 내구성을 추가할 수 있어.

다른 워크플로 엔진들도 있지:

  • LangGraph — 그래프 기반 에이전트 워크플로. 상태 머신을 직접 정의하는 방식. 에이전트 전용이라 학습 곡선이 낮음
  • Azure Durable Functions — 서버리스 환경에서의 내구성 있는 워크플로
  • Dagster — 데이터 파이프라인 중심이지만 에이전트 워크플로에도 활용 가능
  • Prefect/Airflow — 전통적인 워크플로 오케스트레이션. 에이전트에 바로 쓰기엔 좀 무거움

선택 기준은 명확해 — 프로토타입이면 LangGraph로 빠르게, 프로덕션이면 Temporal 같은 내구성 있는 엔진으로 넘어가는 게 안전하지.

멀티 에이전트에서 가장 까다로운 문제 중 하나가 상태를 어디에, 어떻게 저장할 것인가야.

상태의 종류를 보면:

  • 에이전트 내부 상태 — 현재 에이전트가 뭘 하고 있는지, 대화 히스토리, 중간 계산 결과
  • 공유 상태 — 여러 에이전트가 같이 접근해야 하는 데이터. 작업 목록, 중간 산출물
  • 워크플로 상태 — 전체 파이프라인에서 현재 어느 단계인지, 어떤 에이전트가 뭘 완료했는지

에이전트가 스테이트리스하면 단순하지만 맥락을 잃어. 스테이트풀하면 똑똑하지만 장애 시 복구가 어렵고. 트레이드오프야.

  • 인메모리 — 가장 빠르지만 프로세스 죽으면 다 날아가. 프로토타입 단계에서만
  • 데이터베이스 — PostgreSQL, MongoDB 같은 DB에 상태 저장. 안전하지만 읽기/쓰기 지연
  • 이벤트 소싱 — 상태 자체를 저장하는 게 아니라 상태를 바꾼 이벤트들을 순서대로 저장. Kafka 같은 이벤트 스토어 활용. 언제든 이벤트를 재생해서 특정 시점의 상태를 복원 가능
  • 체크포인트 — 주기적으로 현재 상태의 스냅샷을 저장. Temporal이 이 방식이야. LangGraph도 체크포인터를 통해 그래프 실행 중간에 상태를 저장하고 복원할 수 있지

에이전트 A가 공유 상태를 읽는 사이에 에이전트 B가 그 상태를 바꾸면? 분산 시스템의 고전적인 문제 — **동시성 제어(Concurrency Control)**가 여기서도 등장해.

해결 방법:

  • 낙관적 잠금 — 읽을 때 버전을 기록하고, 쓸 때 버전이 바뀌었으면 재시도
  • 메시지 기반 동기화 — 상태를 직접 공유하지 않고 메시지로만 상태 변경을 전달 (액터 모델)
  • 단일 소유자 원칙 — 각 상태 조각에 대해 쓰기 권한은 하나의 에이전트만 가지고, 나머지는 읽기만

핵심은 가능하면 공유 상태를 최소화하라는 거야. 에이전트 간 결합도가 낮을수록 시스템이 견고해지거든. 꼭 공유해야 하는 상태만 공유하고, 나머지는 에이전트가 각자 관리하게 하는 게 맞지.


정리

8장에서 가져갈 거 네 가지:

  1. 멀티 에이전트는 기본값이 아니야. 단일 에이전트로 충분한지 먼저 확인하고, 에이전트를 추가할 때는 명확한 이유가 있어야 해
  2. 조율 패턴은 상황에 맞게 골라야 해. 민주적, 관리자 중심, 계층형, 액터-크리틱 — 은탄환은 없고 시나리오에 맞는 패턴을 선택하는 거야
  3. 통신 인프라가 확장성을 결정하지. 직접 호출에서 시작해도 결국 메시지 브로커나 이벤트 버스, 액터 모델로 가게 돼. A2A 프로토콜은 조직 경계를 넘는 에이전트 협업의 표준이 될 가능성이 높아
  4. 상태 관리를 소홀히 하면 안 돼. 프로토타입에선 인메모리로 충분하지만, 프로덕션에선 내구성 있는 실행(Temporal)과 영속성 전략이 필수야