[LangGraph] A2A 멀티에이전트란? — Agent-to-Agent 프로토콜과 오케스트레이터 패턴
by 우와한개발자

1. 멀티에이전트
1) 개념
- 멀티에이전트는 여러 개의 AI 에이전트가 역할을 나누어 협력하는 아키텍처다.
- 하나의 에이전트가 모든 작업을 처리하는 것이 아니라, 문서 검색·웹 조사·파일 관리·보고서 작성처럼 역할별 에이전트가 각자 맡은 작업을 수행한다.
- 오케스트레이터가 사용자 요청을 분석하고 어떤 에이전트에게 어떤 작업을 맡길지 결정한 뒤, 각 에이전트의 결과를 모아 최종 응답을 만든다.
2) 사용하는 이유
- 복잡한 작업을 역할별로 나누어 처리할 수 있다
- 각 에이전트의 책임이 명확해져 시스템 프롬프트와 로직을 설계하기 쉽다
- 성격이 다른 작업(검색, 작성, 검토)을 각 에이전트에 최적화할 수 있다
- 새 에이전트를 추가해도 기존 에이전트에 영향을 주지 않는다
2. 기존 방식과의 차이
1) 단일 프로세스 멀티에이전트
- 이전 블로그에서 구현한 Supervisor 패턴은 모든 에이전트가 하나의 프로세스 내에서 LangGraph 노드로 연결되는 구조다.
하나의 Python 프로세스
├── planner_node()
├── researcher_node()
├── writer_node()
└── reviewer_node()
- 에이전트 간 데이터는 LangGraph State 객체로 전달된다
- 에이전트를 추가하려면 같은 프로세스 코드를 수정해야 한다
- 하나의 에이전트가 다운되면 전체 시스템이 영향을 받는다
2) A2A 방식 (독립 서버 구조)
- A2A(Agent-to-Agent) 방식은 각 에이전트가 독립된 HTTP 서버로 실행된다.
오케스트레이터 서버 (port 10010)
│ HTTP 요청
├── RAG 에이전트 서버 (port 10012)
├── Web 에이전트 서버 (port 10011)
├── File 에이전트 서버 (port 10013)
└── Report 에이전트 서버 (port 10014)
- 에이전트 간 데이터는 HTTP 요청과 응답으로 전달된다
- 에이전트를 추가할 때 새 서버만 실행하면 된다
- 특정 에이전트가 다운되어도 다른 에이전트는 정상 동작한다
- 에이전트별로 독립적인 배포와 확장이 가능하다
3) 비교
| 구분 | 단일 프로세스 | A2A |
| 실행 방식 | 하나의 프로세스 내 노드 | 독립된 HTTP 서버 |
| 데이터 전달 | LangGraph State | HTTP 요청/응답 |
| 에이전트 추가 | 코드 수정 필요 | 새 서버 실행으로 추가 |
| 장애 영향 | 전체 시스템 영향 | 해당 에이전트만 영향 |
| 적합한 규모 | 소규모 워크플로우 | 확장 가능한 서비스 |
3. A2A 프로토콜
1) 개념
- A2A(Agent-to-Agent)는 에이전트 간 통신을 위한 HTTP 기반 표준 프로토콜이다.
- 각 에이전트는 A2A 스펙에 맞는 HTTP 서버를 구현하고, 오케스트레이터는 A2A SDK를 통해 에이전트를 호출한다. 에이전트 내부 구현이 어떻게 되어 있든 A2A 인터페이스만 맞추면 오케스트레이터와 통신할 수 있다.
2) 통신 방식
- A2A에서 오케스트레이터가 에이전트를 호출하는 방식은 두 가지다.
(1) 일반 HTTP 요청
- 오케스트레이터가 에이전트에게 작업을 요청하고 완료된 결과를 한 번에 받는다
- 처리 시간이 짧은 작업에 적합하다
(2) SSE 스트리밍
- 에이전트가 작업 중간 결과를 실시간으로 스트리밍한다
- Server-Sent Events(SSE) 방식으로 응답을 청크 단위로 전송한다
- 처리 시간이 길거나 LLM 답변을 실시간으로 보여줄 때 사용한다
오케스트레이터 RAG 에이전트
│ │
│── POST /run (작업 요청) ──────>│
│ │ (검색 중...)
│<── data: 검색 완료 ────────────│ SSE 스트림
│<── data: 답변 생성 중... ──────│
│<── data: 최종 답변 ────────────│
│<── data: [DONE] ──────────────│
3) Agent Card
- A2A 에이전트는 자신의 능력과 엔드포인트를 설명하는 Agent Card를 제공한다.
- 에이전트 이름, 설명, 버전 정보
- 지원하는 작업 목록과 입출력 형식
- 엔드포인트 URL
- 오케스트레이터는 Agent Card를 읽어 어떤 에이전트가 어떤 작업을 처리할 수 있는지 파악한다.
4. 오케스트레이터 패턴
1) 개념
- 오케스트레이터는 사용자 요청을 분석하고 어떤 에이전트를 어떤 순서로 호출할지 계획을 세우는 상위 에이전트다.
- 각 에이전트의 실행 결과를 수집하고, 필요하면 결과를 다음 에이전트에게 전달하며, 최종 결과를 사용자에게 반환한다.
2) 역할
- 사용자 요청 분석 및 인텐트 분류
- 실행할 에이전트와 순서 결정 (Plan 생성)
- 독립적인 단계 병렬 실행, 의존 단계 순차 실행
- 에이전트 결과 수집 및 최종 응답 구성
3) 인텐트 분류
- 오케스트레이터는 사용자 질문을 분석하여 적합한 에이전트를 선택한다.
사용자 요청
│
▼
오케스트레이터 (인텐트 분류)
│
├── 사내 문서 질문 → RAG 에이전트
├── 웹 검색 요청 → Web Research 에이전트
├── 파일 관리 요청 → File Management 에이전트
├── 보고서 작성 요청 → Report Writing 에이전트
└── 복합 작업 → 여러 에이전트 순차/병렬 실행
4) 실행 흐름
(1) 순차 실행
- 의존 관계가 있는 작업은 순서대로 실행한다. 앞 단계의 결과를 다음 단계의 입력으로 사용한다.
웹 조사 후 보고서 작성
→ 1단계: Web Research 에이전트 (조사 수행)
→ 2단계: Report Writing 에이전트 (조사 결과로 보고서 작성)
(2) 병렬 실행
- 의존 관계가 없는 작업은 동시에 실행하여 응답 시간을 줄인다.
여러 정보를 동시에 조회
→ RAG 에이전트 실행 ──┐
→ Web 에이전트 실행 ──┤ (동시 실행)
│
▼
결과 합산 후 반환
5. 에이전트별 역할
1) RAG 에이전트 (Internal RAG Agent)
사내 문서를 벡터 검색하여 근거 있는 답변을 생성한다.
- 업로드된 문서를 청크로 분할하고 임베딩 벡터로 변환하여 저장한다
- 사용자 질문과 유사한 청크를 검색하고 해당 내용을 바탕으로 답변을 생성한다
- 출처 파일명과 페이지 번호를 함께 반환한다
2) Web Research 에이전트
Tavily Search API를 사용하여 실시간 웹 검색을 수행한다.
- 사내 문서에 없는 최신 정보나 외부 정보가 필요할 때 호출된다
- 검색 결과의 관련성 점수를 기준으로 낮은 품질의 결과는 반환하지 않는다
- 출처 URL을 함께 반환한다
3) File Management 에이전트
Google Drive 파일 목록 조회, 검색, 업로드를 처리한다.
- RAG 인덱싱 워크플로우에서 파일 목록을 조회한 후 RAG 에이전트로 연계된다
- Google Drive API v3와 OAuth2 인증을 사용한다
4) Report Writing 에이전트
조사 결과나 내용을 정해진 양식의 마크다운 보고서로 작성한다.
- 임원 요약, 조사 보고서, 기술 보고서, 회의록 등 양식을 자동으로 감지한다
- 웹 조사 결과를 입력받아 구조화된 보고서를 생성한다
6. RAG → 웹 자동 폴백
1) 개념
- 사내 문서에서 답변을 찾지 못했을 때 자동으로 웹 검색으로 전환하는 흐름이다.
- 사용자가 매번 "사내 문서에서 찾아봐, 없으면 웹에서 찾아봐"라고 지시하지 않아도 오케스트레이터가 자동으로 처리한다.
2) 흐름
사실 질문
│
▼
RAG 에이전트 검색
│
├── 결과 있음 → 📄 [사내 문서 기반] 답변 반환
│
└── 결과 없음 → "사내 문서에서 찾지 못했습니다. 웹에서 검색합니다..."
│
▼
Web 에이전트 검색
│
├── 관련성 높음 (score ≥ 0.5) → [웹 검색 기반] 답변 반환
└── 관련성 낮음 (score < 0.5) → "관련 정보를 찾을 수 없습니다."
3) 답변 출처 배지
- 사용자가 답변이 어디서 왔는지 알 수 있도록 경로별로 구분된 출처 배지를 답변 앞에 표시한다.
- [사내 문서 기반]: RAG 에이전트가 문서에서 답변을 찾은 경우
- [웹 검색 기반]: 사내 문서 미발견 후 웹에서 찾은 경우
- [AI 직접 답변]: 인사말 등 문서 검색 없이 직접 응답하는 경우
7. 채팅 이력 설계
1) 이력을 오케스트레이터에 전달하지 않는 이유
일반적인 챗봇은 이전 대화 이력을 LLM에 함께 전달하여 맥락을 유지한다.
멀티에이전트에서 이력을 그대로 오케스트레이터에 전달하면 두 가지 문제가 생긴다.
- 이력 텍스트가 RAG 벡터 검색 쿼리에 섞여 임베딩 품질이 저하된다
- 오케스트레이터 LLM이 이력과 현재 질문을 혼동하여 잘못된 에이전트를 선택한다
2) 해결 방법
- 현재 질문만 오케스트레이터로 전달하고, 이력은 DB에만 저장한다.
- 맥락 의존 질문("그것의 조건은?")은 RAG 에이전트 내부의 contextualize_question 노드가 감지하여 "더 구체적으로 질문해 주세요." 형태로 재질문을 유도한다.
'AI > LangChain' 카테고리의 다른 글
블로그의 정보
우와한개발자 님의 블로그
우와한개발자