スクリーンショットは見たことがあるはずだ。5体、10体、15体のClaude Codeエージェントがtmuxで動いていて、それぞれが同じコードベースの異なる部分を担当している。生産的に見える。ワクワクする。そして実際に再現しようとしたなら、見た目ほど簡単ではないことを知っているはずだ。
Claude Codeエージェントを1体動かすのは簡単だ。タスクを渡して、コードを書いてもらい、レビューする。2体は管理可能だが新しい問題が生まれる:互いの変更を踏み合う可能性がある。5体にはシステムが必要だ。システムなしで10体は、月額請求付きのカオスだ。
このガイドはそのシステムについて書いている。マルチエージェントアーキテクチャの理論ではない。実際のコードベースで複数のClaude Codeエージェントを破綻なく動かすための、実践的なワークフローだ。
なぜ1体では足りないのか
単一のClaude Codeエージェントは驚くほど多くの作業をこなせる。しかし逐次処理だ。バックエンドのエンドポイントを実装している間、フロントエンドは止まっている。テストを書いている間、ドキュメントは遅れる。ビルドエラーをデバッグしている間、3つの新機能がキューで待っている。
ソフトウェア作業の大部分が並列化可能だと気づいたとき、計算が変わる。フロントエンドコンポーネントとバックエンドAPIエンドポイントはファイルを共有しない。テストスイートとドキュメント更新は異なるディレクトリを触る。アーキテクチャレビューとバグ修正は全く異なるタイムスケールで動く。
単一エージェント開発のボトルネックはエージェントの速度ではない。パイプラインの深さだ。1体のエージェントは一度に1つの作業しか進められない。複数エージェントなら複数の作業が同時に進み、1人の開発者が1日に出荷できるものが変わる。
作業分割の戦略
2つ目のtmuxペインを開く前に、作業の分割方法を決める必要がある。実践で機能する3つのパターンがある。
コンポーネント別分割
最もシンプルなアプローチ。エージェントAがcomponents/を所有、エージェントBがserver/を所有、エージェントCがlib/を所有。各エージェントは自分のテリトリーで作業し、外のファイルには決して触れない。
コードベースに明確なアーキテクチャ境界がある場合にうまく機能する。フロントエンドコンポーネント、バックエンドアクション、共有ライブラリが分かれたNext.jsアプリは、自然にこれらのラインで分割できる。
制限:横断的な作業。UI、API、データ層すべてに変更が必要な機能は、単一エージェントのテリトリーにきれいに収まらない。機能をコンポーネント単位のサブタスクに分解し、順序付けすることで対処する。
ロール別分割
コードの場所ではなく、機能で分割する。1体のエージェントがコードを書く。別の1体がテストを書く。3体目がドキュメントを担当。4体目がコードレビューを行う。
これは人間のチームの働き方を反映しており、より高品質な出力を生む。テストエージェントはコードが書きやすかったかどうかを知らない(し、気にもしない)。仕様に対してテストし、作者の仮定に対してではない。
トレードオフは調整オーバーヘッドの増加だ。テストエージェントは実装エージェントの完了を待つ必要がある。ドキュメントエージェントは両方を待つ。並列ワーカーではなく、パイプラインを管理していることになる。
ライフサイクルフェーズ別分割
ロール分割のより洗練されたバージョン。1体のエージェントがブレインストームと計画を行う。別の1体が実装する。3体目が検証する。作業はフェーズを通じて流れ、各エージェントはそのフェーズに特化している。
これはBeadboxで使っているパターンだ。アーキテクトエージェントが設計し、エンジニアリングエージェントが実装し、QAエージェントが独立して検証する。同じタスクが複数のスペシャリストを通過し、それぞれがジェネラリストエージェントでは到達できない品質レイヤーを追加する。フルセットアップについては13体のAIエージェントでソフトウェアを出荷しているに書いた。
正しい戦略はプロジェクトによる。ファイル境界が明確な小さなプロジェクトはコンポーネント分割でうまくいく。品質が重要な大きなプロジェクトはロール分割やライフサイクル分割の恩恵を受ける。ほとんどのチームはハイブリッドに落ち着く。
CLAUDE.mdアイデンティティパターン
ここで理論が実装と出会う。各Claude Codeエージェントは独自のCLAUDE.mdファイルを持ち、このファイルがマルチエージェントシステム全体で最も重要な要素だ。
CLAUDE.mdは4つのことを定義する:
- エージェントが何であるか。 役割、専門性、ドメイン。
- 何を所有するか。 制御するファイル、ディレクトリ、責任範囲。
- 何に触れてはならないか。 コンフリクトを防ぐ明示的な境界。
- どう通信するか。 作業報告と他エージェントとの調整のプロトコル。
実例を示す。補完的なスコープを持つ2体のClaude Codeエージェント:
# CLAUDE.md for Agent: frontend-eng
## Identity
Frontend engineer. You implement UI components, pages, and client-side
logic. You own everything under components/, app/, and hooks/.
## File Ownership
- components/** (you own these)
- app/** (you own these)
- hooks/** (you own these)
- lib/utils.ts (shared, read-only for you)
- server/** (DO NOT MODIFY — owned by backend-eng)
## Communication
When you need a backend change, create a task describing what API
you need. Do not implement it yourself.
When done with a task, comment: "DONE: <summary>. Commit: <hash>"
# CLAUDE.md for Agent: backend-eng
## Identity
Backend engineer. You implement server actions, API routes, and
data layer logic. You own everything under server/, actions/, and lib/.
## File Ownership
- server/** (you own these)
- actions/** (you own these)
- lib/** (you own these, except utils.ts is shared)
- components/** (DO NOT MODIFY — owned by frontend-eng)
- app/** (DO NOT MODIFY — owned by frontend-eng)
## Communication
When you change a data type in lib/types.ts, notify frontend-eng
by commenting on the relevant task.
When done with a task, comment: "DONE: <summary>. Commit: <hash>"
明示的な「DO NOT MODIFY」行に注目してほしい。これがないとエージェントはドリフトする。所有していないファイルのタイポを修正して「助けよう」とする機会を見つけ、突然マージコンフリクトが発生する。もっと悪い場合、別のエージェントが依存していたコードを黙ってリファクタリングする。
アイデンティティセクションは飾りではない。Claude Codeはセッション開始時にCLAUDE.mdを読み、行動のスコープを決めるために使う。「フロントエンドエンジニア」と伝えられたエージェントは自然にバックエンド変更を避ける。特定のディレクトリを所有すると伝えられたエージェントは、それ以外のファイルを変更する前に確認する。
マージコンフリクトの回避
上記のCLAUDE.md例で示したファイルレベルの所有権は第一の防御線だ。しかし唯一ではない。
頻繁にコミットしてプッシュする。 45分間コミットなしで作業するエージェントは、マージコンフリクトの時限爆弾を作っている。エージェントに(CLAUDE.mdで)論理的な作業単位を完了するごとにコミットするよう指示する。
新しい作業の前にプルする。 各エージェントは新しいタスクを開始する前にgit pull --rebaseを実行すべきだ。CLAUDE.mdのスタートアッププロトコルに追加するだけで簡単に強制できる。
横断的作業にはフィーチャーフラグを使う。 2体のエージェントが同じファイルを変更する必要がある場合、より安全なアプローチは1体がインターフェースやフラグを作成してコミット・プッシュし、2体目がプルしてその上に構築することだ。代替がマージの悪夢なら、逐次が並列に勝る。
リスクのある作業には別ブランチ。 エージェントが実験的なことをしている場合、専用ブランチを与える。アーキテクチャスパイクやランディングしない可能性のあるリファクタリング作業に特に有用だ。
実践では、ファイル所有権ルールと頻繁なコミットの組み合わせがマージコンフリクトの90%を排除する。残りの10%はtypes.tsやpackage.jsonのような共有ファイルで発生し、大抵は解決が簡単だ。
エージェント間通信
Claude Codeエージェントは直接会話できない。共有メモリもメッセージバスもリアルタイムチャネルもない。これは実は良いことだ。エージェント間の直接通信は結合、レースコンディション、デバッグの悪夢を生む。
代わりに、通信はアーティファクトを通じて行われる。3つのパターンが機能する:
タスクコメント
最も信頼性の高いパターン。エージェントAが作業を完了し、共有タスクにコメントする:「DONE: /api/usersエンドポイントを実装。JSONを返す。スキーマはlib/types.tsにある。」エージェントBはタスクコメントを読み、何が利用可能か正確に把握する。
ステータス更新
各タスクにはステータスがある:open、in_progress、done、blocked。エージェントAが前提条件タスクをdoneとマークすると、エージェントB(または自分、またはコーディネーター)は依存する作業を開始できることを知る。
ファイル変更
最もシンプルな形式。エージェントAがTypeScriptインターフェースをlib/types.tsに書いてコミットする。エージェントBがプルして新しい型を見る。コード自体がメッセージなので、明示的な通信は不要だ。
機能しないもの:エージェント間のリアルタイムメッセージパッシングシステムを構築しようとすること。エージェントAがエージェントBの出力を待つ必要がある場合、同期呼び出しではなくタスク間の依存関係としてモデル化する。
ディスパッチループ
誰かが指揮を執る必要がある。マルチエージェントClaude Codeセットアップには2つのオプションがある:手動で行うか、コーディネーターエージェントを指定するかだ。
手動ディスパッチ
タスクリストを管理する。エージェントにタスクを割り当てる。進捗を確認する。ブロッカーを処理する。これは約5体のエージェントまで機能し、それを超えると調整オーバーヘッドが生産性向上分を食い始める。
典型的な手動ディスパッチサイクル:
- 朝: 進行中、ブロック中、作業準備完了の状態を確認
- 割り当て: 各エージェントにコンテキスト付きで次のタスクを送る
- 監視: 10-15分ごとにエージェント出力を確認し、スタックの兆候を探す
- アンブロック: エージェントが問題に遭遇したら、介入または再割り当て
- 終了: 1日の終わりに出荷された内容を確認し、翌日の計画を立てる
tmuxでは、ペインを切り替え、最近の出力を読み、各エージェントが次に何を必要としているか判断する形になる。gp(エージェントの最近の出力を中断せずに覗く)のようなツールは助けになるが、自分がボトルネックであることに変わりはない。
コーディネーターエージェント
1体のClaude Codeエージェントを他のエージェントへの作業ディスパッチ専任にする。このエージェントはコードを書かない。タスクバックログを読み、利用可能なエージェントに作業を割り当て、進捗を確認し、ディスパッチループをプログラム的に処理する。
これが我々が使っているパターンだ。「super」エージェントがパトロールループを実行する:数分ごとに各アクティブエージェントを確認し、タスクステータスをチェックし、ブロッカーを特定し、エージェントがアイドルになったら新しい作業をディスパッチする。人間(自分)が優先度の判断を下し、曖昧な状況を解決する。Superがロジスティクスを処理する。
コーディネーターエージェントには独自のCLAUDE.mdが必要だ:
# CLAUDE.md for Agent: super
## Identity
Dispatch coordinator. You assign work to agents, monitor progress,
and ensure the pipeline keeps moving. You do NOT write code.
## Responsibilities
- Maintain awareness of all active tasks and their statuses
- Assign ready tasks to idle agents
- Monitor agent progress every 5-10 minutes
- Escalate blockers to the human when agents can't self-resolve
- Verify agents follow the protocol: plan before code, test before done
## Communication
- To assign work: message the agent with task ID and priority
- To check progress: peek at agent's recent output
- To escalate: message the human with context and options
コーディネーターパターンは手動ディスパッチよりはるかにスケールする。10体以上のエージェントでは、手動調整はフルタイムの仕事だ。コーディネーターエージェントがルーティンのロジスティクスを処理し、人間の判断が必要な決定のみをエスカレートする。
マルチエージェント作業のtmuxレイアウト
物理的なレイアウトは思っている以上に重要だ。複数のClaude Codeエージェントを実行するためのtmux設定:
# Create a new tmux session
tmux new-session -s agents -n super
# Split into panes for each agent
tmux split-window -h -t agents:super
tmux split-window -v -t agents:super.1
# Or create named windows (easier to manage at scale)
tmux new-window -t agents -n eng1
tmux new-window -t agents -n eng2
tmux new-window -t agents -n qa1
tmux new-window -t agents -n frontend
tmux new-window -t agents -n backend
名前付きウィンドウは4体を超えるとスプリットペインに勝る。1画面で5つのペインは読めないが、名前付きウィンドウ間の切り替えは素早い。命名規則も重要だ。eng1、eng2、qa1は即座にスキャンできる。agent-1、agent-2、agent-3は何も伝えない。
各エージェントを独自の作業ディレクトリと独自のCLAUDE.mdで起動する:
# In the eng1 window
cd ~/project
claude --claude-md ./agents/eng1/CLAUDE.md
# In the qa1 window
cd ~/project
claude --claude-md ./agents/qa1/CLAUDE.md
実用的なヒント:単なるシェルの「ダッシュボード」ウィンドウを保持する。git log --oneline -10の実行、タスクステータスの確認、エージェントの作業を中断せずに観察するために使う。これがコマンドセンターになる。
うまくいかないとき
マルチエージェントワークフローは予測可能な方法で失敗する。失敗モードを知ることで、苦い経験をせずに済む。
2体のエージェントが同じファイルを編集する。 大抵はCLAUDE.mdのファイル所有権が十分に具体的でなかったため。lib/utils.tsは典型的なコンフリクトマグネットだ。解決策:共有ユーティリティファイルを特定のエージェントに割り当てるか、全員にとってリードオンリーにして単一のオーナーを通じて変更をルーティングする。
エージェントが沈黙する。 レートリミット、エラーループ、または深い推論チェーンでスタックした。出力を確認する。同じ失敗するコマンドをリトライし続けている場合、セッションを終了してより明確な指示で再起動する。定期的なヘルスチェック(10-15分ごと)で1時間を無駄にする前にこれをキャッチする。
コンテキストウィンドウが埋まる。 長時間実行エージェントはコンテキストを蓄積し、パフォーマンスが低下する。各エージェントのCLAUDE.mdにこのためのプロトコルを含めるべきだ:「90分以上作業している場合、状態を保存して新しいセッションを要求する。」実践では、エージェントが作業をコミットし、中断箇所を記録し、そのコミットから新しいClaude Codeセッションが引き継ぐことを意味する。
作業が仕様から逸脱する。 エージェントが技術的には動くが要求と一致しないものを構築する。解決策はコード前に計画するパターン:コードを書く前に、エージェントが実装計画をコメントする。60秒で計画をレビューし、500行のdiffになる前に誤解をキャッチする。
パイプラインが停滞する。 エージェントBがエージェントAを待っているが、エージェントAは自分の判断を待っている。その間、エージェントCは30分前に作業を終えてアイドル状態だ。これは技術的な問題ではなく調整の失敗だ。コーディネーターエージェント(または自分)がブロッカーを監視しアイドルエージェントを再割り当てしてパイプラインを動かし続ける必要がある。
Beadsでこれをどう解決したか
上記のすべては付箋と善意で機能する。しかし5体あたりで非公式なアプローチにひびが入り始める。エージェントCが何に取り組んでいたか忘れる。どのタスクがブロックされているか見失う。エージェントBが必要とするAPIエンドポイントが完了したのか着手したばかりなのか思い出せない。
これがbeadsが解決する問題だ。Beadsはオープンソースの、ローカルファーストなイシュートラッカーだ。各タスクは一意のID、ステータス、説明、受け入れ基準、依存関係、コメントスレッドを持つ「bead」だ。すべてbdというCLI経由でアクセス可能で、Claude Codeエージェントがターミナルを離れずに読み書きできることを意味する。
beadsを使ったディスパッチループの様子:
# See what's ready for work
bd list --status open
# Assign a task to an agent
bd update bb-a1b2 --claim --actor eng1
# Agent reads its assignment
bd show bb-a1b2
# Agent comments its plan before coding
bd comments add bb-a1b2 --author eng1 "PLAN:
1. Add endpoint at /api/users
2. Define UserResponse type in lib/types.ts
3. Write integration test
Files: server/api/users.ts (new), lib/types.ts (modify)
Test: curl localhost:3000/api/users returns 200 with JSON array"
# Agent finishes and comments what it did
bd comments add bb-a1b2 --author eng1 "DONE: /api/users endpoint live.
Returns paginated JSON. Added UserResponse type.
Verification:
1. curl http://localhost:3000/api/users → 200, JSON array
2. curl http://localhost:3000/api/users?page=2 → 200, second page
3. pnpm test → all passing
Commit: 8f3c2a1"
# Agent marks the task done
bd update bb-a1b2 --status closed
すべてのエージェントがこのプロトコルに従う:クレーム、計画、実装、DONEコメント、ステータス更新。各beadのコメントスレッドが、何が起きたか、なぜか、どう検証するかの完全な監査証跡になる。
依存関係がコンフリクトする作業を防止する:
# Create a task that depends on another
bd create --title "Build user list component" \
--deps bb-a1b2 \
--description "Frontend component that calls /api/users. Blocked until API is live."
依存タスクはbb-a1b2が完了するまでブロックされたままだ。エージェントが早まって取り上げることはない。まだ存在しないAPIのフロントエンドを構築して時間を無駄にする者はいない。
bd listコマンドでパイプライン全体のスナップショットが得られる:
bd list --status in_progress
# Shows what every agent is actively working on
bd blocked
# 未完了の依存関係を待っているタスクを表示
bd list --status open --priority p1
# Shows the highest-priority work that's ready to start
これが頭の中で保持していたメンタルモデルを置き換える。各タスクの状態、各エージェントの現在の作業、すべての依存関係チェーン、すべてコマンドラインからクエリ可能だ。
可視性のスケーリング
CLIは機能する。しかしスケールでは、ターミナルでbd listを実行して吸収できる量には限界がある。8体のエージェントが3つのエピックで17の未完了タスクと12の依存関係に取り組んでいるとき、作業のリストではなく作業の形を見る必要がある。
これがBeadboxで埋めようとしたギャップだ。Beadboxはbeadsの上に位置するリアルタイムダッシュボードで、以下を表示する:
- エピックツリーとプログレスバーで、各機能が全サブタスクにわたってどう進捗しているか確認
- 依存関係グラフで、パイプラインを停滞させる前にブロックされた作業を可視化
- エージェントアクティビティで、どのエージェントが何に取り組んでいるか、計画コメントとdoneコメントがコンテキスト内で表示
- リアルタイム更新:ダッシュボードがbeadsデータベースを監視し、エージェントがタスクステータスを更新すると自動更新
BeadboxはCLIを置き換えない。エージェントは引き続きbd経由でbeadsに読み書きする。Beadboxは全体像を提供し、判断の意思決定を可能にする:どのエピックが遅れているか、どのエージェントが助けを必要としているか、どこにボトルネックが形成されているか。
ベータ期間中は無料だ。このようなワークフローを構築しているなら、GitHubでBeadboxにスターを。
始め方
13体のエージェントがなくても恩恵は受けられる。最小限のセットアップ:
- 2体のClaude Codeエージェントを別々のtmuxウィンドウで、それぞれファイル所有権の境界を定義する独自のCLAUDE.mdを持たせる。
- タスクリスト(このスケールではテキストファイルでも機能する)で両エージェントが何に取り組んでいて次は何かを把握する。
- コミットプロトコル: 両エージェントが頻繁にコミットし、新しい作業の前にプルする。
それが自然に感じられたら、テストやドキュメント用に3体目のエージェントを追加する。次にコーディネーターエージェントを検討する。次にbeadsを導入して構造化されたタスクトラッキングを行う。調整の痛みが増加したときにシステムをスケールさせる。その前ではなく。
難しいのはツーリングではない。考え方の転換だ:「AIアシスタントを使っている」から「チームを運営している」へ。CLAUDE.mdファイル、ディスパッチプロトコル、所有権の境界:これらは設定ファイルではなくマネジメントプラクティスだ。チームメンバーがAPI呼び出しで動いているとしても、組織を構築している。
2体のエージェントと明確な境界から始める。他のすべてはそこから続く。