Claude Code에서 여러 에이전트를 병렬로 구동하면, 사령탑(Dispatcher)의 토큰 소비가 병목 현상이 됩니다.
자작 멀티 에이전트 환경인 squad에서, 태스크 지시서 작성과 대시보드 업데이트를 서브 에이전트(Sub-agent)에게 맡겨 Dispatcher의 토큰 소비를 줄인 이야기입니다.
Fable의 5시간 제한에 매번 전멸하곤 했다
squad는 tmux의 한 세션에 Dispatcher(사령탑)와 Worker 1~3(Claude), Worker 4(Codex)가 공존하는 구성입니다.
인간은 Dispatcher에게만 모호한 지시를 내리고, Dispatcher가 이를 태스크로 분해하여 각 Worker에게 배분합니다.
Dispatcher에 Fable와 같은 상위 모델을 사용하면, 금방 5시간 레이트 제한(Rate limit)에 걸리게 됩니다.
제한은 동일 계정 내에서 공유되므로, Dispatcher가 다 써버리면 Worker를 포함해 전부 멈춥니다.
이런 일이 여러 번 발생했습니다.
Dispatcher를 Haiku와 같은 저렴한 모델로 낮추는 방법도 생각했지만, 그만두었습니다.
모호한 지시를 해석하여 태스크로 변환하는 것이 Dispatcher의 역할이기에, 이 부분의 지능을 깎을 수는 없습니다.
깎아야 할 곳은 다른 곳입니다.
토큰을 잡아먹고 있었던 것은 사무 작업이었다
Dispatcher의 소비를 관찰해보니, 대부분은 지능이 필요 없는 작업이었습니다.
첫 번째는 태스크 지시서(task YAML) 작성입니다.
worktree의 설정 절차나 검증 커맨드까지 작성하면, 실제 사례에서 1건당 100~380행에 달합니다.
발주할 때마다 Dispatcher가 이를 직접 작성하고 있었습니다.
두 번째는 대시보드 업데이트입니다.
Worker의 보고 수령이나 PR 머지(Merge)가 일어날 때마다, Dispatcher가 Markdown 표를 읽고(Read) 수정(Edit)합니다.
표의 한 줄을 바꾸기 위해서 매번 파일 전체를 읽고 있었습니다.
이 두 가지를 서브 에이전트에게 맡기기로 했습니다.
task-yaml-author: 태스크 지시서를 작성하게 하기
Claude Code의 서브 에이전트는 .claude/agents/에 Markdown을 두는 것만으로 정의할 수 있습니다.
첫 번째가 task-yaml-author입니다.
---
name: task-yaml-author
description: Use this agent when the Dispatcher needs to author a detailed
...
어떤 Issue를 어떤 Worker에게 배분할지는 Dispatcher가 판단하고, task-yaml-author는 그 결과를 받아 YAML 본문을 작성합니다.
Dispatcher가 전달하는 것은 Issue 번호, 담당 Worker, worktree 키 등 몇 줄뿐입니다.
돌려받는 것도 YAML 경로와 요약 3~5줄뿐입니다.
worktree 절차 템플릿이나 브랜치 운영 규칙 같은 노하우는 289행에 달하는 에이전트 정의 파일에 전부 적혀 있습니다.
이 정의는 서브 에이전트 측의 컨텍스트(Context)에만 로드되므로, Dispatcher는 한 번도 읽지 않습니다.
dashboard-updater: 표 업데이트는 Haiku로도 충분하다
두 번째가 dashboard-updater입니다.
Markdown 표를 바꾸기만 하면 되므로, 모델은 Haiku를 지정했습니다.
서브 에이전트는 작업마다 모델을 선택할 수 있다는 것이 장점입니다.
---
name: dashboard-updater
tools: Read, Edit, Write, Grep, Glob
...
Dispatcher는 태스크 ID, 상태 변화, PR URL 등 6개 항목만 전달합니다.
dashboard-updater가 표를 업데이트하고, 결과를 2~4줄로 반환합니다.
✓ dashboards/squad.md: TASK-007 을 Active → 완료 태스크 표로 이동, 담당 worker1, PR #9
✓ dashboard.md: Worker1의 상태를 가동 중 → 대기 중 으로 업데이트
정의 파일에는 "dashboard 이외에는 편집하지 않는다", "GitHub에는 게시하지 않는다"라는 제약 사항도 적혀 있습니다.
저렴한 모델에 쓰기 권한을 부여하기 때문에, 건드릴 수 있는 범위는 정의 측에서 좁혀둡니다.
결과: Dispatcher의 토큰 절감이 가능해졌다
도입 전후의 transcript (대화 기록)를 비교하면, Dispatcher 스스로 수행하던 dashboard (대시보드) 직접 Edit (수정)가 44회에서 0회로 줄었습니다.
task (태스크) YAML 전문(100~380행)과 dashboard 전문도 Dispatcher의 컨텍스트 (Context, 문맥)에 포함되지 않게 되었습니다.
한 번 컨텍스트에 포함된 내용은 이후의 모든 턴 (Turn)에서 계속 과금되므로, 포함시키지 않음으로써 얻는 효과는 누적됩니다.
체감상 가장 큰 변화는 컨텍스트의 수명입니다.
이전에는 태스크 5개마다 /compact (컨텍스트 압축)가 필요했지만, 지금은 아침부터 태스크 15개를 처리할 때까지 /compact 없이 완주할 수 있습니다.
위임된 부분의 작성 토큰은 서브 에이전트 (Sub-agent) 측의 Sonnet / Haiku가 사용하지만, 단가가 저렴하며 Dispatcher의 소비와는 분리되어 있습니다.
요약
Dispatcher는 똑똑한 모델인 상태로 유지하고, task YAML 작성과 dashboard 업데이트를 서브 에이전트에게 맡겼습니다.
수행한 작업은 .claude/agents/ 디렉토리에 Markdown 파일을 2장 두었을 뿐이지만, Dispatcher의 토큰을 절감할 수 있었고, /compact 빈도 또한 태스크 5개당 1회에서 15개까지 /compact 없이 수행하는 수준으로 줄었습니다.
구성 파일은 h-wata/squad에서 공개하고 있습니다.
Discussion