개발자를 위한 ADK 멀티 에이전트 패턴 가이드
Source: Google Developers Blog
2025년 12월 16일
Introduction
소프트웨어 개발 세계는 이미 이 교훈을 배웠습니다: 모놀리식 애플리케이션은 확장되지 않는다. 대규모 전자상거래 플랫폼을 구축하든 복잡한 AI 애플리케이션을 만들든, 하나의 통합된 엔터티에 의존하면 병목 현상이 발생하고 디버깅 비용이 증가하며 특화된 성능이 제한됩니다.
같은 원리가 AI 에이전트에도 적용됩니다. **너무 많은 책임을 맡은 단일 에이전트는 “모든 것을 조금씩 하는 사람, 아무것도 잘 하지 못하는 사람”**이 됩니다. 명령이 복잡해질수록 특정 규칙을 따르는 정도가 떨어지고 오류율이 누적되어 점점 더 많은 환각이 발생합니다. 에이전트가 실패했을 때 버그를 찾기 위해 전체 프롬프트를 다 뜯어내야 할 필요는 없습니다.
신뢰성은 분산화와 전문화에서 나옵니다. 멀티‑에이전트 시스템(MAS) 은 AI 버전 마이크로서비스 아키텍처를 구축할 수 있게 해줍니다. 개별 에이전트에 파서(Parser), 비평가(Critic), 디스패처(Dispatcher)와 같은 특정 역할을 할당함으로써, 보다 모듈화되고 테스트 가능하며 신뢰할 수 있는 시스템을 만들 수 있습니다.
이 가이드에서는 Google Agent Development Kit (ADK) 를 사용해 연속 파이프라인(Sequential Pipeline) 부터 인간‑인‑루프(Human‑in‑the‑Loop) 패턴까지 여덟 가지 핵심 설계 패턴을 소개합니다. 생산 수준의 에이전트 팀을 구축하는 데 필요한 구체적인 패턴과 의사코드를 제공할 것입니다.
1. Sequential Pipeline Pattern (aka the assembly line)
에이전트 워크플로우의 기본부터 살펴보겠습니다. 이 패턴을 Agent A가 작업을 마치고 바로 Agent B에게 배턴을 넘겨주는 고전적인 조립 라인이라고 생각하면 됩니다. 선형이고 결정론적이며, 데이터가 정확히 어디서 왔는지 항상 알 수 있기 때문에 디버깅이 매우 쉽습니다.
데이터 처리 파이프라인에 가장 많이 쓰이는 아키텍처입니다. 아래 예시에서는 원시 문서를 처리하는 흐름을 보여줍니다:
| 에이전트 | 역할 |
|---|---|
| Parser | 원시 PDF를 텍스트로 변환 |
| Extractor | 구조화된 데이터를 추출 |
| Summarizer | 최종 요약본을 생성 |

ADK에서는 SequentialAgent 프리미티브가 오케스트레이션을 대신 처리합니다. 여기서 핵심은 상태 관리입니다: output_key를 사용해 공유된 session.state에 기록하면 체인의 다음 에이전트가 정확히 어디서 작업을 이어받아야 할지 알 수 있습니다.
# ADK Pseudocode
# Step 1: Parse the PDF
parser = LlmAgent(
name="ParserAgent",
instruction="Parse raw PDF and extract text.",
tools=[PDFParser],
output_key="raw_text"
)
# Step 2: Extract structured data
extractor = LlmAgent(
name="ExtractorAgent",
instruction="Extract structured data from {raw_text}.",
tools=[RegexExtractor],
output_key="structured_data"
)
# Step 3: Summarize
summarizer = LlmAgent(
name="SummarizerAgent",
instruction="Generate summary from {structured_data}.",
tools=[SummaryEngine]
)
# Orchestrate the Assembly Line
pipeline = SequentialAgent(
name="PDFProcessingPipeline",
sub_agents=[parser, extractor, summarizer]
)
2. 코디네이터 / 디스패처 패턴 (일명 컨시어지)
때때로 체인이 필요하지 않을 때가 있습니다; 대신 의사결정자가 필요합니다. 이 패턴에서는 중앙의 지능형 에이전트가 디스패처 역할을 합니다. 사용자의 의도를 분석하고 작업에 가장 적합한 전문 에이전트에게 요청을 라우팅합니다.
청구서 문제에 대해 “Billing”(청구) 전문 에이전트로, 트러블슈팅에 대해 “Tech Support”(기술 지원) 전문 에이전트로 사용자를 보내야 할 수 있는 복잡한 고객 서비스 봇에 이상적입니다.

이는 LLM 기반 위임에 의존합니다. 상위 CoordinatorAgent를 정의하고 전문 sub_agents 목록을 제공합니다. ADK의 AutoFlow 메커니즘이 나머지를 처리하며, 자식 에이전트에 제공한 설명을 기반으로 실행을 전환합니다.
# ADK Pseudocode
billing_specialist = LlmAgent(
name="BillingSpecialist",
description="Handles billing inquiries and invoices.",
tools=[BillingSystemDB]
)
tech_support = LlmAgent(
name="TechSupportSpecialist",
description="Troubleshoots technical issues.",
tools=[DiagnosticTool]
)
# The Coordinator (Dispatcher)
coordinator = LlmAgent(
name="CoordinatorAgent",
instruction=(
"Analyze user intent. Route billing issues to BillingSpecialist "
"and bugs to TechSupportSpecialist."
),
sub_agents=[billing_specialist, tech_support]
)
3. Parallel Fan‑Out / Gather Pattern (aka the octopus)
속도가 중요합니다. 서로 의존하지 않는 작업이 있다면 왜 하나씩 실행하나요? 이 패턴에서는 여러 에이전트가 작업을 동시에 실행하여 지연 시간을 줄이거나 다양한 관점을 얻습니다. 그런 다음 최종 합성 에이전트가 결과를 집계합니다.
자동 코드 리뷰에 이상적: 보안 감사자, 스타일 검증자, 성능 분석가를 동시에 생성해 Pull Request를 검토합니다. 이들이 작업을 마치면 합성 에이전트가 피드백을 하나의 일관된 리뷰 코멘트로 결합합니다.

ADK의 ParallelAgent를 사용하면 sub_agents를 동시에 실행할 수 있습니다. 이러한 에이전트는 별도의 실행 스레드에서 동작하지만 세션 상태를 공유합니다. 경쟁 상태를 방지하려면 각 에이전트가 데이터를 고유 키에 기록하도록 해야 합니다.
# ADK Pseudocode (illustrative)
security_auditor = LlmAgent(
name="SecurityAuditor",
instruction="Identify security vulnerabilities in the code.",
output_key="security_report"
)
style_enforcer = LlmAgent(
name="StyleEnforcer",
instruction="Check code style compliance.",
output_key="style_report"
)
performance_analyst = LlmAgent(
name="PerformanceAnalyst",
instruction="Analyze performance bottlenecks.",
output_key="performance_report"
)
# Synthesizer that gathers the reports
synthesizer = LlmAgent(
name="ReviewSynthesizer",
instruction=(
"Combine {security_report}, {style_report}, and {performance_report} "
"into a single review comment."
),
tools=[CommentFormatter]
)
# Parallel execution
parallel_review = ParallelAgent(
name="ParallelCodeReview",
sub_agents=[security_auditor, style_enforcer, performance_analyst],
gather_agent=synthesizer
)
나머지 다섯 가지 패턴(Human‑in‑the‑Loop, Retry‑with‑Fallback, Knowledge‑Base Augmentation, Adaptive Routing, Self‑Healing)은 동일한 깔끔한 구조를 따르며 전체 가이드에 자세히 설명되어 있습니다.
# Define parallel workers
security_scanner = LlmAgent(
name="SecurityAuditor",
instruction="Check for vulnerabilities like injection attacks.",
output_key="security_report"
)
style_checker = LlmAgent(
name="StyleEnforcer",
instruction="Check for PEP8 compliance and formatting issues.",
output_key="style_report"
)
complexity_analyzer = LlmAgent(
name="PerformanceAnalyst",
instruction="Analyze time complexity and resource usage.",
output_key="performance_report"
)
# Fan‑out (The Swarm)
parallel_reviews = ParallelAgent(
name="CodeReviewSwarm",
sub_agents=[security_scanner, style_checker, complexity_analyzer]
)
# Gather / Synthesize
pr_summarizer = LlmAgent(
name="PRSummarizer",
instruction=(
"Create a consolidated Pull Request review using "
"{security_report}, {style_report}, and {performance_report}."
)
)
# Wrap in a sequence
workflow = SequentialAgent(sub_agents=[parallel_reviews, pr_summarizer])
4. 계층적 분해 (일명 러시아 인형)
때때로 작업이 단일 에이전트의 컨텍스트 창에 비해 너무 클 때가 있습니다. 고수준 에이전트는 복잡한 목표를 하위 작업으로 나누어 위임할 수 있습니다. 라우팅 패턴과 달리, 상위 에이전트는 작업의 일부를 위임하고 결과를 기다린 뒤 자신의 추론을 계속할 수 있습니다.
아래 다이어그램에서 ReportWriter는 직접 연구를 수행하지 않습니다. 대신 ResearchAssistant에게 위임하고, ResearchAssistant는 다시 WebSearch와 Summarizer 도구를 관리합니다.

하위 에이전트를 도구처럼 취급할 수 있습니다. 에이전트를 AgentTool로 감싸면, 상위 에이전트가 이를 명시적으로 호출할 수 있어 하위 에이전트 전체 워크플로를 하나의 함수 호출처럼 사용할 수 있습니다.
# ADK Pseudocode
# Level 3: Tool Agents
web_searcher = LlmAgent(
name="WebSearchAgent",
description="Searches web for facts."
)
summarizer = LlmAgent(
name="SummarizerAgent",
description="Condenses text."
)
# Level 2: Coordinator Agent
research_assistant = LlmAgent(
name="ResearchAssistant",
description="Finds and summarizes info.",
sub_agents=[web_searcher, summarizer]
)
# Level 1: Top‑Level Agent
report_writer = LlmAgent(
name="ReportWriter",
instruction=(
"Write a comprehensive report on AI trends. "
"Use the ResearchAssistant to gather info."
),
tools=[AgentTool(research_assistant)]
)
5. Generator and Critic (aka the editor’s desk)
고품질이고 신뢰할 수 있는 출력을 생성하려면 종종 두 번째 눈이 필요합니다. 이 패턴에서는 생성과 검증을 분리합니다:
- Generator – 초안을 생성합니다.
- Critic – 하드코딩된 기준이나 논리 검사를 통해 초안을 검토합니다.
아키텍처에는 조건부 루프가 포함됩니다: 검토가 통과하면 루프가 종료되고 내용이 최종 확정됩니다; 그렇지 않으면 피드백이 Generator에게 다시 전달되어 수정됩니다. 이는 구문 검사가 필요한 코드 생성이나 준수 기준을 충족해야 하는 콘텐츠 생성에 특히 유용합니다.

ADK 구현에서는 초안‑검토 상호작용을 위해 SequentialAgent를 사용하고, 품질 게이트를 강제하는 상위 LoopAgent를 사용합니다.
# ADK Pseudocode
# The Generator
generator = LlmAgent(
name="Generator",
instruction=(
"Generate a SQL query. If you receive {feedback}, "
"fix the errors and generate again."
),
output_key="draft"
)
# The Critic
critic = LlmAgent(
name="Critic",
instruction=(
"Check if {draft} is valid SQL. If correct, output 'PASS'. "
"If not, output error details."
),
output_key="feedback"
)
# The Loop
validation_loop = LoopAgent(
name="ValidationLoop",
sub_agents=[generator, critic],
condition_key="feedback",
exit_condition="PASS"
)
6. 반복적 정제 (일명 조각가)
훌륭한 작업은 보통 한 번의 초안으로 완성되지 않습니다. 인간 작가가 수정하고 다듬으며 편집하듯이, 에이전트도 원하는 품질에 도달하기 위해 여러 차례 시도가 필요할 수 있습니다. 이 패턴은 단순한 통과/실패 검사가 아니라 정성적 향상에 초점을 맞춰 Generator‑Critic 아이디어를 확장합니다.
- Generator – 초기 초안을 생성합니다.
- Critique Agent – 최적화 메모를 제공합니다.
- Refinement Agent – 그 메모를 바탕으로 출력을 다듬습니다.
품질 임계값에 도달할 때까지 루프가 계속됩니다. ADK의 LoopAgent는 두 가지 종료 메커니즘을 지원합니다:
- 하드 제한 –
max_iterations. - 조기 완료 – 에이전트가 임계값을 만족하면
EventActions에escalate=True를 신호로 보낼 수 있습니다.
# ADK Pseudocode
# Generator
generator = LlmAgent(
name="Generator",
instruction="Generate an initial rough draft.",
output_key="current_draft"
)
# Critique Agent
critic = LlmAgent(
name="Critic",
instruction=(
"Review {current_draft} and provide a list of improvement notes. "
"If the draft already meets quality standards, set "
"`escalate=True` in the response."
),
output_key="critique_notes"
)
# Refinement Agent
refiner = LlmAgent(
name="Refiner",
instruction=(
"Take {current_draft} and {critique_notes}, then produce a refined version."
),
output_key="refined_draft"
)
# Iterative Loop
refinement_loop = LoopAgent(
name="IterativeRefinement",
sub_agents=[generator, critic, refiner],
condition_key="critique_notes",
exit_condition="escalate",
max_iterations=5
)
LLM Agent 예시
critic = LlmAgent(
name="Critic",
instruction="Review {current_draft}. List ways to optimize it for performance.",
output_key="critique_notes"
)
refiner = LlmAgent(
name="Refiner",
instruction="Read {current_draft} and {critique_notes}. Rewrite the draft to be more efficient.",
output_key="current_draft"
)
loop = LoopAgent(
name="RefinementLoop",
max_iterations=3,
sub_agents=[critic, refiner]
)
workflow = SequentialAgent(sub_agents=[generator, loop])
7. 인간‑인‑루프 (인간 안전망)
AI 에이전트는 강력하지만, 최종 출력이 공개되기 전에 인간이 개입하거나 검증하거나 도메인 전문 지식을 제공해야 할 때가 있습니다. 이 패턴은 자동화된 단계 사이에 수동 체크포인트를 삽입하여 안전성, 규정 준수 또는 품질 기준이 충족되도록 합니다. 인간은 에이전트의 출력을 승인, 편집 또는 거부할 수 있으며, 그 후 워크플로우가 그에 따라 진행됩니다.