다중 에이전트 시스템
다중 에이전트 시스템 (Multi-Agent Systems)
서로 협력하고 작업을 위임하는 특화된 에이전트 팀을 구축해요.
출처: 문서
본문
왜 다중 에이전트인가? (Why Multi-Agent?)
복잡한 작업은 특화(specialization)에서 이점을 얻어요. 모든 걸 하려는 하나의 모놀리식 에이전트 대신, 초점화된 에이전트 팀을 만들 수 있어요:
- 전체 목표를 이해하고 위임하는 조정자(coordinator)
- 파일시스템과 셸 접근으로 코드를 작성하는 개발자(developer)
- 코드 품질을 검사하는 리뷰어(reviewer)
- 정보를 위해 웹을 검색하는 연구자(researcher)
각 에이전트는 특정 역할에 맞게 최적화된 자신만의 모델, 도구, 지침을 가져요.
두 가지 패턴: 위임 vs. 핸드오프 (Two Patterns: Delegation vs. Handoffs)
Docker Agent는 두 가지 다중 에이전트 패턴을 지원해요:
Delegation (sub_agents) |
Handoffs (handoffs) |
|
|---|---|---|
| 토폴로지 | 계층적 (부모 → 자식 → 부모) | 동료 간 그래프 (A → B → C → A) |
| 세션 | 자식이 하위 세션에서 실행 | 대화가 같은 세션에 유지 |
| 컨텍스트 | 자식이 깨끗한 작업 설명을 받음 | 다음 에이전트가 전체 대화 기록을 봄 |
| 제어 흐름 | 부모가 자식이 끝날 때까지 블록 후 계속 | 활성 에이전트 전환 — 이전 에이전트는 루프에서 벗어남 |
| 도구 | transfer_task |
handoff |
| 최적 용도 | 전문가에게 작업 위임 | 파이프라인 워크플로, 대화 라우팅 |
같은 구성에서 두 패턴을 결합할 수 있어요 — 에이전트가 sub_agents 와 handoffs 를 모두 가질 수 있답니다.
Tip 언제 어떤 것을 써야 할까
sub_agents— 조정자가 전문가에게 작업을 보내고 그 결과를 종합해야 할 때 사용.handoffs— 에이전트들이 같은 대화를 번갈아 처리해야 할 때(파이프라인, 라우팅) 사용.background_agents— 여러 독립 작업을 동시에 실행할 수 있을 때 사용.
sub_agents로 위임하기 (Delegation with sub_agents)
에이전트는 내장된 transfer_task 도구로 작업을 위임해요. 이 도구는 sub_agents 가 있는 모든 에이전트에 자동으로 제공돼요. 부모 에이전트가 자식 에이전트에 작업을 보내고, 결과를 기다린 뒤 계속해요.
- 사용자가 루트 에이전트에 메시지를 보냄
- 루트 에이전트가 요청을 분석하고 어떤 하위 에이전트가 처리할지 결정
- 루트 에이전트가 대상 에이전트, 작업 설명, 기대 출력과 함께
transfer_task호출 - 하위 에이전트가 자신의 도구를 사용해 자신의 에이전트 루프에서 작업 처리
- 결과가 루트 에이전트로 흘러가고, 루트 에이전트가 사용자에게 응답
# The transfer_task tool call looks like:
transfer_task(
agent="developer",
task="Create a REST API endpoint for user authentication",
expected_output="Working Go code with tests"
)
Note 자동 승인 (Auto-Approved) 다른 도구와 달리
transfer_task는 항상 자동 승인돼요 — 사용자 확인이 필요 없어요. 이로써 에이전트 간 원활한 위임이 가능해져요.
핸드오프 라우팅 (Handoffs Routing)
핸드오프는 에이전트가 전체 대화를 다른 에이전트에게 넘기는 동료 간 라우팅 패턴이에요. 위임과 달리 하위 세션이 없어요 — 대화가 단일 세션에 유지되고 활성 에이전트만 전환돼요.
이 패턴은 다음에 이상적이에요:
- 파이프라인 워크플로 — 데이터가 특화된 에이전트 체인을 통해 흐름
- 대화형 라우팅 — 조정자가 사용자를 올바른 전문가에게 라우팅하고, 전문가는 끝나면 되돌려보낼 수 있음
- 그래프 토폴로지 — 에이전트가 순환을 형성해(A → B → C → A) 반복 워크플로를 가능하게 함
동작 원리 (How It Works)
- 사용자가 시작 에이전트에 메시지를 보냄
- 에이전트 A가 메시지를 처리한 뒤 에이전트 B로 라우팅하기 위해
handoff호출 - 에이전트 B가 활성 에이전트가 되어 전체 대화 기록을 봄
- 에이전트 B는 응답하거나, 자신의 도구를 사용하거나, 다른 에이전트에게 핸드오프할 수 있음
- 에이전트가 핸드오프 없이 직접 응답할 때까지 계속됨
# The handoff tool call looks like:
handoff(
agent="summarizer"
)
Note 범위 지정된 핸드오프 대상 (Scoped Handoff Targets) 각 에이전트는 자신의
handoffs배열에 나열된 에이전트에게만 핸드오프할 수 있어요.handoff도구는 자동으로 주입되므로 수동으로 추가할 필요가 없어요.
예제 (Example)
조정자가 연구자에게 라우팅하고, 연구자는 요약자에게 핸드오프하고, 요약자는 조정자에게 돌아와요:
Root ──→ Researcher ──→ Summarizer ──→ Root
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Coordinator that routes queries
instruction: |
Route research queries to the researcher.
handoffs:
- researcher
researcher:
model: openai/gpt-5
description: Web researcher
instruction: |
Search the web, then hand off to the summarizer.
toolsets:
- type: mcp
ref: docker:duckduckgo
handoffs:
- summarizer
summarizer:
model: openai/gpt-5
description: Summarizes findings
instruction: |
Summarize the research results, then hand off
back to root.
handoffs:
- root
Tip 전체 파이프라인 예제 분기와 여러 처리 단계가 있는 더 복잡한 핸드오프 그래프는 examples/handoff.yaml 참고.
강제 핸드오프 (Forced Handoffs)
handoffs 를 쓰면 모델이 handoff 도구 호출 여부를 스스로 결정해요 — 즉 잊어버릴 수 있고, 엄격한 순서에 의존하는 파이프라인이 깨질 수 있어요. force_handoff 는 그 불확실성을 없애줘요: 에이전트가 최종 응답을 만들 때마다 런타임 자체가 LLM의 도구 호출을 건너뛰고 대화를 이름 있는 에이전트로 라우팅해요. 전체 대화 컨텍스트는 그대로 이어져요.
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Extracts key facts from the input
instruction: |
Extract the key facts from the user's input as a bullet list.
force_handoff: summarizer
summarizer:
model: anthropic/claude-sonnet-4-5
description: Produces the final summary
instruction: |
Summarize the extracted facts for the user.
구성 로드 시점에 강제되는 규칙:
- 대상은 구성에 정의된 에이전트(또는 외부 참조)여야 함
- 에이전트는 자기 자신에게
force_handoff할 수 없음 force_handoff엣지의 체인은 순환을 형성하면 안 됨 (A → B → A는 거부됨)
실행 가능한 예제는 examples/force_handoff.yaml 참고.
백그라운드 에이전트로 병렬 위임 (Parallel Delegation with Background Agents)
transfer_task 는 순차적이에요 — 조정자가 하위 에이전트가 끝날 때까지 기다렸다가 계속해요. 여러 에이전트에게 동시에 작업을 분산해야 할 때는 대신 background_agents toolset을 사용해요.
조정자의 toolsets에 추가해요:
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Research coordinator
sub_agents: [researcher, analyst, writer]
toolsets:
- type: think
- type: background_agents
그러면 조정자는 다음을 할 수 있어요:
run_background_agent로 한 번에 여러 작업을 발송 — 각각 즉시 작업 ID를 반환list_background_agents또는view_background_agent로 진행 상황 모니터링- 작업이 끝나면 결과 수집
- 더 이상 필요 없는 작업은
stop_background_agent로 취소
# Start two tasks in parallel
run_background_agent(agent="researcher", task="Find recent papers on LLM agents")
run_background_agent(agent="analyst", task="Analyze our current architecture")
# Check on all tasks
list_background_agents()
# Read results when ready
view_background_agent(task_id="agent_task_abc123")
레지스트리의 외부 하위 에이전트 (External Sub-Agents from Registries)
하위 에이전트는 로컬에 정의할 필요가 없어요 — sub_agents 목록에서 어떤 OCI 호환 레지스트리의 에이전트든 직접 참조할 수 있어요. 이렇게 하면 구성을 복제하지 않고 공유 에이전트를 사용해 팀을 구성할 수 있어요.
agents:
root:
model: openai/gpt-5
description: Coordinator that delegates to local and external sub-agents
instruction: |
Delegate tasks to the most appropriate sub-agent.
sub_agents:
- local_helper
- myorg/agent:tag # pulled from registry automatically
local_helper:
model: openai/gpt-5
description: A local helper agent for simple tasks
instruction: You are a helpful assistant.
외부 하위 에이전트는 마지막 경로 세그먼트(태그 제외) 뒤에 자동으로 이름이 붙어요 — 예를 들어 myorg/agent:tag 는 agent 가 돼요. name:reference 구문으로 명시적인 이름을 줄 수도 있어요:
sub_agents:
- my_agent:myorg/agent:tag # available as "my_agent"
- reviewer:docker.io/myorg/review-agent:latest
외부 하위 에이전트를 다이제스트로 고정 (Pin external sub-agents to a digest)
외부 참조는 기본적으로 태그를 사용해요: myorg/agent 는 myorg/agent:latest 의 줄임말이에요. 태그 참조는 매 docker agent run 마다 레지스트리에서 다시 확인돼요: 고정되지 않은 각 외부 하위 에이전트는 시작 시 다이제스트 조회를 유발하며, 그 하위 에이전트가 세션에서 호출되지 않더라도 그래요. 정상 연결에서는 보통 참조당 1~2초를 더해요(네트워크와 레지스트리에 따라 다름), 그리고 레지스트리나 자격 증명 헬퍼가 잘못 동작하면 멈출 수 있는 경로 중 하나예요.
참조를 불변 다이제스트(@sha256:…)로 고정하면 런타임이 네트워크 왕복 없이 로컬 캐시에서 바로 제공하므로 시작이 빠르고 팀이 완전히 재현 가능해요:
sub_agents:
- reviewer:docker.io/myorg/review-agent@sha256:44117e73263afa5c861bdf3730dae7925918ffdd146827eee5bcff20bc55e8fa
레지스트리에서 다이제스트를 복사하거나(Docker Hub는 태그 옆에 표시), docker buildx imagetools inspect <reference> 같은 표준 OCI 도구로 읽어요. Docker Agent는 태그 대신 다이제스트를 여전히 사용하는 외부 OCI 참조에 대해 시작 경고를 기록해요.
handoffs 와 force_handoff 의 외부 참조도 같은 실행당 비용을 가지므로, 그것들도 다이제스트로 고정하세요.
Tip 외부 하위 에이전트는 어떤 OCI 호환 레지스트리에서든 동작해요. 레지스트리 참조에 대한 자세한 내용은 Agent Distribution 참고. 로컬과 외부 하위 에이전트를 섞는 완전한 예제는 examples/sub-agents-from-registry.yaml 참고.
Harness 기반 하위 에이전트 (Harness-Backed Sub-Agents)
하위 에이전트는 모델 API 대신 외부 코딩 CLI — Claude Code, Codex, opencode, 또는 pi — 로 지원될 수 있어요. model: 필드 대신 harness: 블록을 추가하면 harness 하위 에이전트를 만들 수 있어요:
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Orchestrator that plans and delegates
instruction: |
Break down coding tasks and delegate to the coding agents.
sub_agents:
- claude-coder
- codex-coder
claude-coder:
description: Claude Code specialist
harness:
type: claude-code
effort: high
codex-coder:
description: Codex specialist
harness:
type: codex
오케스트레이터는 다른 하위 에이전트처럼 transfer_task 를 사용해 harness 하위 에이전트에 작업을 보내요. Docker Agent가 오케스트레이션과 훅을 처리하고, 외부 CLI가 코딩 루프를 구동해요.
Tip 더 알아보기 전체 필드 참조, 병렬 디스패치 패턴, harness 에이전트 내부에서 동작하지 않는 것들은 Coding Harnesses 참고.
예제: 개발 팀 (Example: Development Team)
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Technical lead coordinating development
instruction: |
You are a technical lead managing a development team.
Analyze requests and delegate to the right specialist.
Ensure quality by reviewing results before responding.
sub_agents: [developer, reviewer, tester]
toolsets:
- type: think
developer:
model: anthropic/claude-sonnet-4-5
description: Expert software developer
instruction: |
You are an expert developer. Write clean, efficient code
and follow best practices.
toolsets:
- type: filesystem
- type: shell
- type: think
reviewer:
model: openai/gpt-5
description: Code review specialist
instruction: |
You review code for quality, security, and maintainability.
Provide actionable feedback.
toolsets:
- type: filesystem
tester:
model: openai/gpt-5
description: Quality assurance engineer
instruction: |
You write tests and ensure software quality. Run tests
and report results.
toolsets:
- type: shell
- type: todo
예제: 연구 팀 (Example: Research Team)
agents:
root:
model: anthropic/claude-sonnet-4-5
description: Research coordinator
instruction: |
Coordinate research tasks. Delegate web searches to
the researcher and writing to the writer.
sub_agents: [researcher, writer]
toolsets:
- type: think
researcher:
model: openai/gpt-5
description: Web researcher
instruction: Search the web and gather information.
toolsets:
- type: mcp
ref: docker:duckduckgo
- type: memory
path: ./research.db
writer:
model: anthropic/claude-sonnet-4-5
description: Content writer
instruction: Write clear, well-structured content.
toolsets:
- type: filesystem
다중 모델 팀 (Multi-Model Teams)
다중 에이전트 시스템의 핵심 장점은 역할마다 다른 모델을 사용해 각 작업에 최적의 모델을 고르는 거예요:
models:
fast:
provider: openai
model: gpt-5-mini
temperature: 0.2 # precise
creative:
provider: openai
model: gpt-5
temperature: 0.8 # creative
local:
provider: dmr
model: ai/qwen3 # runs locally, no API cost
agents:
analyst:
model: fast # cheap and fast for analysis
writer:
model: creative # creative for content
helper:
model: local # free for simple tasks
공유 도구 (Shared Tools)
todo 같은 도구는 협력적 작업 추적을 위해 에이전트 간에 공유할 수 있어요:
toolsets:
- type: todo
shared: true # all agents see the same todo list
모범 사례 (Best Practices)
- 에이전트를 초점화하세요 — 각 에이전트는 명확하고 좁은 역할을 가져야 해요
- 명확한 설명을 작성하세요 — 조정자가 설명을 사용해 누구에게 위임할지 결정해요
- 최소한의 도구를 주세요 — 각 에이전트에게 특정 역할에 필요한 도구만 주세요
- 필요할 때 think 도구를 사용하세요 — 네이티브 추론이 없는 모델의 경우, 조정자에게
think도구를 줘서 위임에 대해 추론하게 하세요. 내장 thinking이 있는 모델(예:thinking_budget사용)은 필요 없어요. - 올바른 모델을 사용하세요 — 복잡한 추론에는 유능한 모델을, 간단한 작업에는 저렴한 모델을
- 올바른 패턴을 고르세요 — 계층적 작업 위임에는
sub_agents, 파이프라인 워크플로와 대화 라우팅에는handoffs를
Note Docker Agent 너머로 다른 에이전트 프레임워크와의 상호운용성을 위해, Docker Agent는 A2A 프로토콜을 지원하고 MCP Mode를 통해 에이전트를 노출할 수 있어요.