Claude Codeで11人編成のマルチエージェント開発チームを構築した話

はじめに

普段、個人で複数のWebアプリを開発している。それぞれ別のリポジトリで別の技術スタックで、並行して進めている。

Claude Codeを導入して開発速度は上がった。が、3プロジェクト並行で回し始めたら、1セッションでは回らなくなった。設計しながらレビューして、テストも書いて、仕様確認もして——結果、中途半端に全部進んで、どれも完成しない。人間のマルチタスクと同じ罠にAIもハマった。

「じゃあ、AIにもチームを組ませればいいのでは」と思い、tmuxベースのマルチエージェント開発チームを構築した。

最初に言っておくと、個人開発に11人チームは明らかにやりすぎだ。友人に話したら笑われた。でも「やりすぎた結果見えたもの」が予想以上に面白かったので、試行錯誤の過程も含めて共有したい。

最初は3人チームだった

いきなり11人にしたわけではない。最初はPM・TL・Engineerの3人構成で始めた。

これでも1セッションよりはマシだったが、すぐに問題が見えた。TLがコードレビューをしつつ仕様の妥当性も判断するのは荷が重い。「技術的にはOKだけど、そもそもこの仕様って正しいんだっけ?」という問いにTL1人で答えるのは無理がある。

次にBL(ビジネスリード)を追加して4人にした。仕様面のレビューが分離されて品質は上がったが、今度はUIの問題が出てきた。Engineerが「とりあえず動くUI」を作って、後から「これ使いにくい」となってやり直す。結局、UIの専門家がいないと画面設計の手戻りが止まらない。

そんな感じで「必要に迫られて1人ずつ増やした」結果が11人だ。最初からこの構成を計画していたわけではない。

現在のチーム構成

tmuxの1セッションが1プロジェクトに対応し、Window/Paneで役割を分離している。

tmux session: {project-name}
├── Window: pm (1 pane)
│   └── PM — 全体統括・進捗管理・承認
├── Window: lead (3 panes)
│   ├── TL — 技術統括・アーキテクチャ・コードレビュー
│   ├── BL — 要件定義・仕様検証・ビジネスロジック確認
│   └── UI Lead — UI/UX設計統括・デザインチーム管理
├── Window: ui (2 panes)
│   ├── UI Designer — 画面デザイン・コンポーネント設計
│   └── UX Architect — 情報設計・ユーザーフロー設計
└── Window: dev (5 panes)
    ├── Engineer ×3 — 実装担当
    ├── Tester — テストインフラ・UT/IT作成
    └── QA — E2Eテスト・探索的テスト・品質保証

設計判断のポイント

  • PMは作業しない。計画・承認・進捗管理のみ。最初はPMにも軽い実装をやらせていたが、「自分が書いたコードの設計変更を承認する」というバイアスが生まれたのでやめた
  • TLとBLの分離。ここは3人チーム時代の反省から。技術的正しさと仕様的正しさは別の脳が必要
  • テスターとQAの分離。ユニットテストを書く人と、E2Eで壊しにいく人では、マインドセットが真逆。同じエージェントにやらせると「自分が書いたテストが通るように壊す」という本末転倒が起きた

各エージェントは team.yaml で自分の役割を認識する。

# team.yaml(抜粋)
members:
  - role: tl
    window: lead
    pane: 0
    responsibilities:
      - 技術統括・アーキテクチャ設計
      - コードレビュー
      - 技術的意思決定
    reports_to: pm
    reviews: [bl]  # BLと相互レビュー

通信プロトコル:カオスとの戦い

11人が自由にしゃべり始めたらどうなるか。試しにルーティングルールなしで走らせてみたことがある。

5分後にはカオスだった。EngineerがPMに直接「この仕様おかしくないですか」と送り、PMが「TLに聞いて」と返し、TLが「それBL案件では」と返す。その間にもう1人のEngineerが別の質問をPMに投げていて、PMのコンテキストは仕様相談で埋まり、肝心の進捗管理ができなくなった。ダッシュボードを見たら、11人中8人が「誰かの返答待ち」で止まっていた。

このとき悟った。自由なコミュニケーションは生産的なコミュニケーションとは違う。人間の組織にルーティングルールがある理由を、身をもって理解した瞬間だった。

tmux直接通信(通知のみ)

# TLからEngineer(pane 0)へ通知
tmux send-keys -t {session}:dev.0 \
  "設計書あり: /tmp/shared/{session}/mailbox/eng0-design.md" C-m

「ファイル置いたから読んで」程度の短い通知だけに使う。

ファイルベースMailbox(本文)

/tmp/shared/{project}/mailbox/{recipient}-{topic}.md

設計書、レビュー結果、詳細な指示——実質的なコミュニケーションはすべてMarkdownファイル経由。

最初はtmux send-keysで全部送っていた。が、長いメッセージを送ると受信側のコンテキストウィンドウを一気に食う。あるとき、TLに設計書を丸ごと送り込んだら、それだけでコンテキストの1/4を消費してしまい、その後のレビューがスカスカになった。それ以降、本文はファイル経由に統一した。

副次的に、全てのやりとりがMarkdownファイルとして残るので監査証跡にもなる。「なぜこの設計判断をしたか」を後から追えるのは、実際にデバッグで何度か助けられた。

ルーティングルール

用件送信元宛先
開発作業指示TLdev
仕様不明点devBL
技術質問devTL
レビュー依頼devTL
デザインハンドオフUI DesignerEngineer
エスカレーションTL/BLPM

PMはEngineerに直接指示しない。必ずTLを経由する。人間の組織では当たり前だが、AI相手だと「PMから直接言った方が早くない?」と思いがち。実際にやると、TLが把握していない実装が進行して後からコンフリクトするので、遠回りに見えてもルーティングを守った方が結果的に速い。

Gate System:勝手に先に進ませない仕組み

マルチエージェントで一番困ったのは「設計レビューが終わってないのにEngineerが実装を始めている」問題だ。

最初にこれが起きたのはあるプロジェクトの認証機能で、BLが仕様レビュー中なのにEngineer2が「待ち時間がもったいない」とばかりに実装を始めていた。結果、BLが「この認証フローは要件と違う」とNGを出した時点で、すでに3ファイル200行が書かれていた。全部書き直し。正直、あのときは「なんで先に始めてるんだよ」と画面に向かって声が出た。

2回目は設計のレビュー中に別機能の実装が走った。3回目はテスト仕様が確定する前にテストコードが書かれた。3回目でさすがに仕組みで止めないと無理だと悟り、gate.shを書いた。約800行のBashスクリプトで、フェーズ制御を強制する。

2つのモード

Feature Mode(単機能開発):

調査 → 設計 → 実装 → レビュー → テスト

System Mode(システム全体開発):

[システムフェーズ]
  調査 → アーキテクチャ設計 → 計画
[フィーチャーフェーズ] ※依存関係あり、並列実行可能
  各機能: 設計 → 実装 → レビュー
[仕上げフェーズ]
  結合テスト → E2Eテスト

System Modeでは機能間の依存関係も管理する。「ユーザー管理」が「認証」に依存しているなら、認証が完了するまでユーザー管理の設計には入れない。

使い方

# プロジェクト初期化
gate.sh init $SESSION feature
 
# フェーズの流れ
gate.sh check $SESSION "設計"         # 前提条件を検証(NGなら作業禁止)
gate.sh start $SESSION "設計"         # フェーズ開始を記録
gate.sh review $SESSION "設計" bl ok  # BLレビューOK
gate.sh review $SESSION "設計" tl ok  # TLレビューOK
gate.sh approve $SESSION "設計"       # PM承認
gate.sh complete $SESSION "設計"      # フェーズ完了 → 次へ

状態は /tmp/shared/{project}/workflow-state.json で管理される。複数エージェントが同時にフェーズを更新しようとする競合を避けるため、jqで一時ファイルに書き出してから mv でアトミックに置き換える。直接編集は禁止。

痛い目を見て追加したルール

レビュアー ≠ 実施者。 最初はこの制約を入れていなかった。TLが自分で書いたアーキテクチャ設計を自分でレビューOKにして、結果、大きな見落としがそのまま実装まで行ったことがある。

NG 2回でPM介入。 TLとBLがレビューで延々と往復する現象が発生した。「技術的にはこうすべき」「仕様的にはこうあるべき」が噛み合わず5往復。以降、2回NGが出たらPMが最終判断を下すルールにした。

git pre-commit hookとの連携。 gate.shの状態をpre-commit hookで参照し、フェーズが「実装」で開始済みでない場合はcommitをブロックする。これで「設計フェーズなのにこっそりコード書いてた」が物理的に不可能になった。

リアルタイム監視ダッシュボード

Gate Systemで「勝手に進む」問題は解決した。次の問題は「今何が起きているか分からない」だった。

tmuxのウィンドウを順番に覗いていくのは11人×3プロジェクトだと現実的ではない。ある日、あるプロジェクトのEngineerが許可待ちで30分止まっていたことに気づかず、その間TLもBLも「Engineer待ち」でIDLEだった。人間がボトルネックになっていたのに、それに気づく手段がなかった。

この経験からagent-status.sh(173行)でターミナルTUIを作った。

Agent Status Dashboard

━━━ project-a (19m) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ● pm           Screen and document output tests
 ○ tl           —
 ○ bl           —
 ● engineer3    engineer3

━━━ project-b (10h 40m) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ◆ pm           [許可待ち] Project retrospective
 ● tl           Set up Biome linting with Husky pre-c...
 ● bl           Review demo HTML specifications
 ○ ui_lead      —

2 sessions | 22 agents | 1 perm | 1 working | 6 done | 14 idle

Claude Codeの状態をどう外部判定するか

公式APIがないので、かなり泥臭いハックになった。

Claude Codeはtmuxのpane_titleにスピナー文字を表示する。処理中はブレイユ文字(U+2800-28FF)が回り、完了すると✳に変わる。これをxxd -pでバイト列に変換し、e2 a0e2 a3の範囲かどうかで処理中/完了を判定している。

# pane_titleの先頭バイトをhexで取得
hex=$(echo -n "$title_char" | xxd -p | head -c6)
# ブレイユ文字範囲なら処理中

正直、Claude Codeのバージョンアップでスピナー表示が変わったら壊れる。脆い実装だとは分かっているが、他に方法がなかった。実用上は今のところ安定している。

一番役に立っているのはPERM(許可待ち)の検出で、tmux capture-paneで最終10行を取得し、"Allow", "Deny", "Permission" 等のキーワードを探す。--dangerously-skip-permissionsを使わない運用だと、人間の承認待ちでエージェントが止まるので、これがないと「気づいたら30分間6人が止まっていた」ということが起きる(実際に起きた)。

Manager層:プロジェクト横断の統括

ここまでが1プロジェクト内の話。3プロジェクト並行となると、さらに上位の調整が必要になる。

最初はManagerなしで3つのtmuxセッションを手動で切り替えていた。「プロジェクトAの設計レビューして」「次はプロジェクトBのPMに指示出して」とセッション間を行き来する。15分ごとにコンテキストが切り替わり、各プロジェクトの状態を自分の頭で管理していた。正直、これが一番つらかった。

そこでManager層を追加した。

~/workspace/manager/          # Manager(全プロジェクト統括)
~/workspace/develop/          # 各プロジェクトの開発チーム

Managerは各プロジェクトのPMにのみ通信する。開発メンバーへの直接通信は禁止。ここでもルーティングの原則は同じだ。

# ManagerからPMへ指示
tmux send-keys -t project-a:pm.0 \
  "指示あり: /tmp/shared/manager/mailbox/project-a-sprint-plan.md" C-m

Managerの仕事は、各プロジェクトのPMから上がってくる進捗報告を集約し、リソース配分を調整すること。「プロジェクトCの認証機能が遅れているから、プロジェクトAは今日のところはIDLEで」みたいな判断をする。人間がやっていたプロジェクト間の切り替えコストをManagerが吸収してくれるので、だいぶ楽になった。

現在、以下の3プロジェクトをこの体制で並行運用している。

  • プロジェクトA: 業務管理システム(Feature Mode)
  • プロジェクトB: コンテンツ共有アプリ(Feature Mode)
  • プロジェクトC: 審査システム(System Mode、8フィーチャー並行開発)

コストの話:正直に書く

一番聞かれるので先に答えておく。11エージェント並列はレートリミットとの戦いだ。

Claude Code Maxプラン(月額$200)を使っている。Proプラン($20)の5倍のレートリミットがあるが、11人が一斉に動くとそれでも上限に当たることがある。特にOpusモデルでTL/BLが大きなファイルを読み込むレビューフェーズは消費が激しい。体感として、3プロジェクト全員稼働だと数時間でレートリミットに達する日もあった。

実用的には、全員を同時に動かす必要はない。Feature Modeなら同時稼働は3〜5人程度で、残りはIDLE。System Modeの並列フィーチャー開発時に最大稼働になるが、それも一時的。常に11人がフル回転しているわけではない。

節約のために地味だが効果のある工夫をしている。

  • Readツールでoffset/limitを必ず指定。800行のファイルを全部読ませるのと、変更対象の30行だけ読ませるのではトークン消費が全然違う
  • サブエージェントには行範囲つきで指示。「src/router.ts見て」ではなく「src/router.ts:30-50を見て」
  • レビューはgit diffのみ。変更されてないファイルの再読み込みは禁止
  • コミットは1論理変更ずつ。巨大なdiffをレビューさせるとそれだけでコンテキストが埋まる

月額$200が高いか安いかは人それぞれだが、個人開発でこの体制を維持するなら必要経費だと割り切っている。3プロジェクトを人間のフリーランスに頼んだら桁が3つ違う。

実際に運用して得られたもの

品質:別視点のレビューは本当に効く

あるプロジェクトの登録機能で、TLが「実装OK、LGTM」とレビューしたものをBLが差し戻したことがあった。理由は「ステータス遷移が要件定義と違う」。TLは技術面(バリデーション、型安全性、エラーハンドリング)を見ていて、ビジネスロジックの妥当性は視野に入っていなかった。

別の機能では、UIデザイナーがFigmaで作ったデザインをEngineerが実装した後、UI Leadが「この画面遷移だとユーザーが迷う」とUX観点で差し戻した。技術的にもデザイン的にも正しいが、ユーザー体験としてNGというケース。1人では絶対に気づけない。

こういう「別視点からの差し戻し」が月に数回発生する。毎回「分離しておいてよかった」と思う。

想定外だったのは、BLとTLの設計レビューのやりとり自体が設計ドキュメントとして機能し始めたこと。mailboxに残ったレビューの往復を後から読むと、「なぜこの設計にしたか」「どの案を棄却したか」が全部残っている。意図して作った仕組みではないが、結果的に一番役に立っている副産物かもしれない。

プロセス:もどかしいけど手戻りよりマシ

Gate Systemで手戻りが体感で7割減った。「設計が固まってないのに実装を始めて全部やり直し」がなくなった。

代わりに「設計レビュー待ちでEngineerが暇」という時間が発生する。もどかしい。でも、200行書き直すよりレビュー待ちの30分の方がずっとマシ。これは人間のチーム開発でも同じで、「プロセスが遅く感じる」のは正しく機能している証拠でもある。

運用:ダッシュボードは生命線

22エージェントを1画面で見られるようにしたことで、運用の質が変わった。特にPERM待ちの検出。以前は「なんか進捗ないな」と思って各ペインを巡回して「あ、3人許可待ちだった」と気づくまでに15分かかっていた。今はダッシュボードの赤◆を見れば1秒で分かる。

残っている課題

ターミナルの視認性はまだ課題で、個別ペインの中身を見たいときはダッシュボードでは不十分。通信レイテンシもファイルベース通信の宿命で、数秒〜数十秒のラグがある。リアルタイムな議論には向かない。

コンテキストウィンドウの消費も悩みどころで、長時間稼働するとTL/BLのコンテキストが埋まる。定期的にセッションをリフレッシュする運用でカバーしているが、もう少しスマートな方法がないか模索中。

--dangerously-skip-permissions は実用上ほぼ必須になっている。11人が毎回許可を求めてきたら、人間がボタンを押す作業だけで午前中が終わる。名前の通りdangerousではあるが、代替手段がない現状ではトレードオフとして受け入れている。

始めるならどこから

「面白そうだけど、いきなり11人は無理」という人向けに、段階的な導入パスを書いておく。

Step 1: 3人チーム(PM + TL + Engineer) 最小構成。PMが計画と承認、TLがレビュー、Engineerが実装。これだけでも「セルフレビューの限界」は突破できる。自分が最初にやったのもこの構成で、初日から「別人にレビューしてもらう」効果を実感した。tmuxのセットアップは以下の通り。

# 最小3人チームの起動例
tmux new-session -d -s myproject -n pm
tmux new-window -t myproject -n lead
tmux new-window -t myproject -n dev
mkdir -p /tmp/shared/myproject/mailbox
 
# 各paneでClaude Codeを起動し、CLAUDE.mdで役割を認識させる

Step 2: +BL(4人) 仕様の妥当性チェックが必要になったら追加。自分の場合、TLが「技術OK」と言ったものをBLが「仕様NG」で差し戻すケースが出始めて「これは分けないとまずい」と感じた。leadウィンドウにpaneを1つ足すだけ。

Step 3: +Tester(5人) 実装者がテストも書くと、テストが実装に寄り添いすぎる。独立したTesterを入れるとテストの観点が変わる。

Step 4: UI Designer + UI Lead(7人) UIの手戻りが目立ち始めたら。フロントエンドがあるプロジェクトでは特に効果が大きい。

Step 5〜: 必要に応じて QA、UX Architect、Engineer追加は、プロジェクトの複雑さ次第。必要を感じてから増やす。「多分必要」で増やすと遊休エージェントが出るだけ。

gate.shは3人構成でも使える。むしろ少人数のうちにワークフロー制御を入れておくと、人数が増えたときにスムーズ。

まとめ

一番印象に残っているのは、ルーティングルールなしで11人を走らせた日のことだ。5分で8人が待ち状態になり、「ああ、組織のルールって飾りじゃなかったんだ」と本気で思った。

この体制を作って運用してみて分かったのは、AIエージェントのオーケストレーションに必要な知識は、新しい技術ではなくて昔からある組織論だということ。役割の分離、指揮系統の設計、プロセスの強制、状態の可視化。どれも人間の組織で長年かけて磨かれてきたプラクティスで、それがAI相手でもそのまま通用した。

逆に言えば、AIだから特別なことをする必要はなかった。レビュアーと実施者を分ける、PMは手を動かさない、指揮系統を飛ばさない——全部、人間のチームでも言われることだ。違いがあるとすれば、AIはルールを明文化しないと本当に守らない、という点くらい。人間なら「空気を読んで」できることも、AIには team.yamlgate.sh で明示的に書かないといけない。

この体制が正解かは分からない。Claude Codeのアップデートで壊れるかもしれないし、もっとスマートなやり方が出てくるかもしれない。でも、「AIに組織で働いてもらう」という実験を通じて、人間の組織設計の理由が身体感覚として分かったことは、個人的には一番の収穫だった。

関連記事