Skip to content

CH 13 · 서브에이전트와 멀티 Agent 오케스트레이션

분량약 3,800자소요 시간약 22분선행 지식CH 08, CH 11난이도재현 가능

본장 목표

작업이 너무 크거나 너무 엉켜 있을 때, 한 Agent가 끝까지 매달리지 말고 몇 조각으로 나눠 여러 서브에이전트에게 병렬로 시키고, 끝나면 결과를 모읍니다. 이번 장에서는 다음을 명확히 합니다. 왜 멀티 Agent인지, dsh의 서브에이전트는 어떤 모습인지, 그리고 실습으로 "작업 분할 → 병렬 위임 → 결과 병합"을 돌려보고, 마지막으로 전체 도구 패밀리를 목록으로 정리합니다.

왜 멀티 Agent인가: 단일 스레드의 세 가지 난관

한 Agent가 시작부터 끝까지 가는 길에서 세 가지 문제에 부딪힙니다.

난관증상
컨텍스트 오염작업이 절반쯤 진행됐을 때, 초반 단계의 내용, 중간 결과, 오류가 같은 세션에 쌓여 모델이 "지금 가장 중요한 정보가 무엇인지" 점점 구분하지 못함
병렬화 불가정보 조회, 초안 작성, 코드 리뷰 — 세 가지 일을 줄 세울 수밖에 없어, 앞 것이 끝나야 다음 것이 대기
점점 빗나감긴 작업에서 모델이 잘못된 길로 빠지면 같은 실패 경로를 반복하며 토큰을 태움

멀티 Agent 사고방식이 바로 이 해법입니다. 컨텍스트 격리. 각 서브에이전트는 자기 작업에 관련된 컨텍스트만 들고, 메인 Agent는 분할, 파견, 수집을 담당합니다. 토큰 소비는 통제 가능하고, 모든 단계가 트래젝토리에서 검토 가능합니다.

하나의 사실: 서브에이전트 역시 플러그인

먼저 안심하시기 바랍니다. 서브에이전트는 dsh가 따로 숨겨둔 무엇이 아니라, 플러그인입니다 — CH 08의 "모든 것은 플러그인"을 다시 한 번 확인시켜 줍니다. 그리고 서브에이전트는 이미 현재 Agent 도구들의 표준입니다 — Claude Code, Codex 모두 이 능력을 가지고 있고, 유일한 차이는 dsh에서는 여전히 플러그인으로 존재한다는 점입니다. 원하면 쓰고, 아니면 통째로 교체해도 됩니다.

설정 트리에서 위임 계약 ctx.subagents를 볼 수 있으며, 그 유일한 임무는 "누가 서브에이전트가 될 수 있는지"를 등록하는 것입니다. 그리고 서로 다른 제공자 플러그인들이 구체적인 백엔드를 그것에 연결합니다.

플러그인실행 대상
subagent-spawn-in-process완전히 새로운 in-process 서브에이전트 (독립 컨텍스트)
subagent-fork-in-process부모 세션의 완료된 히스토리에서 "파생"된 서브에이전트
subagent-acpAgent Client Protocol 사용, 프로세스 밖 ACP 호환 Agent를 수용
subagent-codex실제 Codex 실행 (공식 app-server 프로토콜)
subagent-claude-code실제 Claude Code 실행 (공식 Agent SDK)
subagent-dsh-sdkTypeScript SDK로 다른 Harness 전체를 띄움

메인 Agent는 무엇을 볼 수 있을까요. 그것은 "모델에 보이는 도구" 몇 가지입니다. web 설정 트리를 열면 기본값은 다음과 같습니다.

도구하는 일기본값
subagent서브에이전트 파견, continuable 모드on
subagent_fork부모 세션의 메모리를 들고 서브에이전트 파견, 일회성on
ralph매 라운드마다 새 서브에이전트로 같은 목표를 전진on
workflow스크립트를 작성해 여러 하위 작업을 병렬 오케스트레이션off (기본 미활성)
send_message특정 서브에이전트에 후속 지시 전달off (기본 미활성)
interrupt_agent서브에이전트의 현재 라운드를 중단off (기본 미활성)
list_agents현재 서브에이전트와 그 상태 나열off (기본 미활성)

즉, 별다른 설정 없이 subagent, subagent_fork, ralph를 바로 부를 수 있습니다. 나머지 도구는 기본이 꺼져 있어 직접 켜야 하거나, "continuable 모드"에서만 의미가 있는데, 다음 절에서 그것들이 어디에 등장하는지 다룹니다.

spawn vs fork: 두 가지 "출발"

가장 흔히 쓰는 두 서브에이전트의 차이는 단 하나입니다. 부모 세션의 히스토리를 가져오느냐 마느냐.

  • subagent (spawn): 완전히 새로운 컨텍스트. 서브에이전트는 메인 Agent가 무슨 대화를 했는지 모르고, 이번에 주어진 지시만 따릅니다. 토큰을 아끼고, 독립적인 작업에 적합합니다.
  • subagent_fork (fork): 부모 세션의 완료된 부분을 상속. 서브에이전트는 "여태까지 무엇을 분석했는지"를 알고, 거기서 이어 갈 수 있습니다. 컨텍스트가 반복되니 비용이 약간 더 들고, 이전 결론 위에 쌓아야 하는 작업에 적합합니다.

한 가지 주목할 디테일이 있습니다. dsh는 "상속 여부"를 도구 설명에 직접 적어 둡니다 — spawn 스타일 도구 설명은 "이 대화를 볼 수 없다"고 하고, fork 스타일은 "진행 중인 turn을 볼 수 없다"고 합니다. 즉, 모델 자신이 지시 안에 컨텍스트를 반복할지 판단합니다.

병렬 서브에이전트: 메인 Agent가 작업을 분할·파견·수집

한 줄 기억법

subagent는 새로운 동료가 낙하산으로 내려오는 것과 같고, 그에게는 당신이 말로 한 작업 브리핑만 있습니다. subagent_fork는 회의록을 그에게 툭 던져주며 "방금 여기까지 했으니 거기서부터 계속"이라고 하는 것과 같습니다.

직접 해보기: 첫 병렬 서브에이전트

병렬로, 서브에이전트 세 개를 띄우되, 각각 다음을 수행합니다.

  1. deepseek-harness 리포지토리의 packages/ 디렉터리 구조를 정리해 각 능력 패밀리가 무엇을 하는지 설명할 것.
  2. 루트 README가 다루는 핵심 개념을 요약할 것.
  3. docs/ 아래에서 서브에이전트 관련 문서를 찾아 목록으로 나열할 것. 세 개가 모두 끝난 다음, 그 결과를 하나의 요약으로 병합할 것.

이 한 문장에는 세 가지 요소가 들어 있고, 어느 하나라도 빠지면 혼란이 옵니다.

요소왜 필요한가
작업 분할 규칙모델에게 "어떤 조각으로 나눌지" 알려주지 않으면 모델이 제멋대로 추측
대기 메커니즘 (모두 끝날 때까지 대기)이것이 없으면 메인 Agent가 한 서브에이전트가 끝나기도 전에 불완전한 결과를 정리하기 시작할 수 있음
출력 요구사항 (요약으로 병합)이것이 없으면 세 서브에이전트가 각자 원시 텍스트 더미를 던지고, 사용자가 직접 이어 붙여야 함

보낸 뒤, 대화에서 모델이 연속으로 subagent를 여러 번 부르는 것을 볼 수 있습니다 — 그것이 파견하는 모습입니다. 기본 continuable 모드에서는, 모델이 "병렬 가능한 것들을 한꺼번에 먼저 보내고, 자기 일을 계속 진행"하며, 첫 서브에이전트가 돌아올 때까지 기다리지 않습니다.

세 서브에이전트가 병렬로 시작, 메인 에이전트가 결과를 기다림

어떤 서브에이전트가 더 일찍 끝나도 괜찮습니다 — 메인 Agent는 남은 것들을 계속 기다리며, 모두 모였을 때 비로소 병합을 시작합니다.

메인 에이전트가 모든 서브에이전트가 끝나기를 기다린 뒤 병합

트래젝토리의 서브에이전트 도구 행: 세 개의 서브에이전트 호출과 상세 패널

포어그라운드 / 백그라운드 / Continuable: 세 가지 실행 모드

서브에이전트는 "파견하고 결과를 기다리는" 것만이 아닙니다. "기다리느냐, 계속 대화하느냐"에 따라 세 가지 모드로 나뉩니다.

모드언제 쓰나보이는 것
포어그라운드 일회성다음 단계가 바로 이 결과에 의존해야 할 때서브에이전트의 최종 텍스트가 돌아올 때까지 대기
백그라운드 잡 (일회성 백그라운드)기다릴 필요 없이 나중에 수집started background subagent job <id>, job_output으로 수집, job_kill로 중단
Continuable 서브에이전트후속 지시를 보내야 할 수 있어 왕복해야 할 때started subagent <childId>, 나중에 메시지 전송 가능

기본 subagent은 continuable 모드입니다. 기본적으로 백그라운드로 파견되어 돌아가고, 메인 Agent는 자기 일을 진행합니다. 서브에이전트가 끝나면 콜백 알림으로 "끝났다, 여기 결과"가 전달됩니다. 모델은 다음 단계가 정말로 그 결과를 필요로 할 때만 포어그라운드 대기로 전환합니다.

continuable 서브에이전트를 더 정교하게 다루고 싶다면, send_message (후속 지시), interrupt_agent (현재 라운드를 중단, 파괴하지 않으며 재개 가능), list_agents (서브에이전트와 상태 나열)를 켜야 합니다. 이들이 기본 꺼져 있는 이유는 대부분의 시나리오에서 필요 없기 때문이며, "필요할 때 켜는 고급 능력"입니다.

workflow와 ralph: 두 가지 "오케스트레이션" 도구

"작업을 나눠서 병렬로 돌리는" 것 외에, dsh에는 더 구조화된 두 가지 오케스트레이션 유형이 있고, 둘 다 플러그인입니다.

도구하는 일적합한 대상
workflow모델이 작은 오케스트레이션 스크립트를 작성하게 하고, agent() / parallel() / pipeline()으로 하위 작업을 펼쳐서, 마지막에 결과를 반환작업이 많고 구조가 고정적이며 실행 순서를 정밀하게 통제해야 할 때 (예: 문서 10건을 한꺼번에 분석)
ralph매 라운드마다 새 서브에이전트로 같은 목표를 전진시키며, 매 라운드 끝에 인계 보고를 써서 다음 라운드에 넘김다라운드 개선, 같은 함정에 빠지기 쉬운 작업, 창의적 또는 디버깅 작업

ralph는 기본 켜져 있습니다 (서브에이전트는 spawn 사용, 최대 64라운드). workflow는 기본 꺼져 있습니다 — 그 스크립트는 별도 스레드에서 실행되며, "오케스트레이션 제약"이지 보안 샌드박스가 아니므로, 명확한 일괄 시나리오에서만 켤 가치가 있습니다.

::: tl;dr 일상 병렬 → subagent; 이전 결론 이어서 → subagent_fork; 구조화된 대량 → workflow (기본 꺼짐); 같은 함정 탈출용 반복 개선 → ralph. :::

흔한 함정

함정회피법
여러 서브에이전트가 같은 파일에 동시에 쓴다병렬 작업은 읽기(검색, 분석, 리뷰)를 우선시하고, 쓰기는 메인 Agent가 모든 결과를 모아 한 번에 쓰게 한다
지시에서 "모두 끝날 때까지 대기"라고 말하는 것을 잊음파견할 때 대기 메커니즘을 포함한다, 그렇지 않으면 메인 Agent가 반쪽짜리 결과로 일을 시작할 수 있음
작업을 너무 잘게 쪼갬각 서브에이전트에는 시작 비용이 든다; 5분짜리 작업을 10개로 쪼개면 오히려 느려진다; "하나의 의미 있는 일을 독립적으로 완수"할 수 있는 단위까지로 쪼갠다
서브에이전트가 무한 중첩됨위임 깊이에 상한이 있다 (기본 3, 0이면 금지); "메인 Agent → 서브에이전트" 스타 토폴로지를 유지하는 것이 가장 안정적

이번 장에서 배운 것

다음 항목들을 스스로 완수할 수 있으면 합격입니다.

  • [ ] 단일 Agent의 긴 작업에서 나타나는 세 가지 난관과 멀티 Agent의 핵심 가치(컨텍스트 격리)를 말할 수 있다
  • [ ] 서브에이전트 역시 플러그인임을 안다: ctx.subagents는 위임 계약이고, spawn / fork가 가장 흔히 쓰는 두 백엔드다
  • [ ] subagent(완전히 새로운 컨텍스트)와 subagent_fork(부모 세션의 완료된 히스토리를 가짐)를 구분한다
  • [ ] 적어도 한 번 "작업 분할 + 모두 끝날 때까지 대기 + 결과 병합" 병렬 서브에이전트를 돌렸고, 트래젝토리에서 서브에이전트 호출을 보았다
  • [ ] 포어그라운드, 백그라운드 잡, continuable 서브에이전트 모드의 차이를 말할 수 있다
  • [ ] workflow, ralph, send_message, interrupt_agent, list_agents가 각각 무엇을 하는지 안다

Open Source · MIT · Community Driven