「ターミナルをもう1つ開いて、Claude Codeをもう1台起動すればいいのでは?」
フロントエンドとバックエンドを並行で修正したい。テストを回しながら別のエージェントにドキュメント更新を任せたい。この素朴な発想がマルチエージェントの入口であり、同時に地獄の入口でもあります。
私は10台のエージェントを同時に走らせて、壮大に失敗しました。この記事では、マルチエージェント運用で遭遇する3つの致命的な課題と、そこから学んだ原則を共有します。
課題1: コンパクション問題 -- 記憶が溶ける
LLMにはコンテキストウィンドウという物理的な制約があります。Claude 3.5 Sonnetなら200Kトークン。十分に見えますが、エージェントが長時間作業を続けると上限に達します。
上限に達したとき何が起きるか。コンパクション(圧縮)です。
| 作業フェーズ | コンテキスト使用率 | 指示の保持率 |
|---|---|---|
| 開始直後 | 10% | 100% |
| 中盤 | 60% | 90% |
| コンパクション直前 | 95% | 70% |
| コンパクション後 | 40% | 40-50% |
半分近い文脈が失われた状態で、エージェントは「自分は正しく作業している」と思い込みながら進んでいきます。私が500行超のリファクタリングを1台に任せたとき、作業後半で「元の設計方針と真逆の実装」が出てきました。コンパクションで設計方針が蒸発していたのです(気づいたのはPRレビューのときでした)。
課題2: タスク消失 -- やっていたはずの仕事が消える
コンパクション問題の実害として最も厄介なのがタスク消失です。
5つのタスクを依頼するとします。
## 依頼内容
1. Userモデルにemailバリデーションを追加
2. ログインAPIのレスポンス形式を変更
3. テストを全件修正
4. READMEにAPI仕様を追記
5. CIの設定を更新
エージェントは1→2→3と順調に進みます。しかし、3のテスト修正で大量のコンテキストを消費し、コンパクションが発生。すると4と5が「完了済み」と誤認されるか、存在自体が記憶から消えます。
エージェントがサボっているわけではありません。圧縮後の要約に「5つのうち3つ完了」と残っていても、「残り2つは何か」の詳細が失われているのです。
対策は素朴で、タスクリストを外部ファイルに書き出すことです。
# tasks.yaml
tasks:
- id: 1
title: "Userモデルにemailバリデーションを追加"
status: done
- id: 2
title: "ログインAPIのレスポンス形式を変更"
status: done
- id: 3
title: "テストを全件修正"
status: in_progress
- id: 4
title: "READMEにAPI仕様を追記"
status: todo
- id: 5
title: "CIの設定を更新"
status: todo
エージェントにこのファイルを定期的に読み書きさせれば、コンパクションが発生しても「次に何をすべきか」を外部記憶から復元できます。人間でいう「ToDoリストを紙に書く」と同じです(人間もメモしないと忘れるので、AIだけを責められません)。
課題3: 人格喪失 -- 「誰だっけ?」問題
マルチエージェント特有の問題です。
CLAUDE.mdで丁寧に定義した「TypeScriptを使い、関数型スタイルを好み、テストはVitestで書く」というコンテキスト。エージェント1号には渡されていますが、2号はどうでしょう?
エージェント1号(フロントエンド担当)
├── CLAUDE.md ✅ 読み込み済み
├── プロジェクト規約を理解 ✅
└── TypeScript + Vitest で実装 ✅
エージェント2号(バックエンド担当)
├── CLAUDE.md ❓ 読み込み忘れ
├── プロジェクト規約を理解 ❌
└── JavaScript + Jest で実装してしまう
これは極端な例ですが、実際にはもっと微妙なレベルで発生します。命名規約の揺れ、エラーハンドリングの方針の不一致、コメントスタイルの違い。1つ1つは小さくても、マージしたときにコードベース全体の一貫性が崩壊します。
将軍システムの教訓 -- 10台同時起動の末路
私が実際にやらかした事例です。10個のマイクロサービスを同時にリファクタリングする必要がありました。「1サービス1エージェント、10台同時起動で10倍速」-- そう考えて実行しました。
結果は惨憺たるものでした。
- 共有リソースの競合: 10台が同時にpackage.jsonを編集し、コンフリクト多発
- API契約の不整合: サービスAがレスポンス形式を変更したが、サービスBのエージェントはそれを知らない
- テストの相互破壊: サービスCのテストが、サービスDの変更で壊れたが誰も気づかない
- コンテキストの分断: 各エージェントが「自分の担当範囲」しか見えず、全体の整合性を判断できない
これは分散システムで起きる問題そのものです。各エージェントは自分の判断で行動しますが、エージェント間の通信が不完全なため、全体として矛盾した行動を取ってしまう。
失敗から学んだ3つの原則
原則1: エージェント数は最小限にする
「並列化すれば速くなる」は幻想です。エージェント間の調整コストは、エージェント数の二乗に比例して増加します。2台なら調整は1本、3台なら3本、10台なら45本。私の10台同時起動は45本の調整線を無視していました。3台以上を走らせるなら、明確なオーケストレーション戦略が必要です。
原則2: 共有状態を最小化する
各エージェントが触れるファイルの範囲を明確に分離する。共有リソースへのアクセスは「1台だけがオーナー」とするか、ロック機構を設けます。Git worktreeで作業ディレクトリ自体を分けるのが最も確実です。
原則3: 通信プロトコルを定義する
エージェント間で「何を、どのフォーマットで、いつ伝えるか」を事前に決めておく。これがないと各エージェントは孤立した島になります。
Azureのアーキテクチャガイドでは、マルチエージェントのパターンを5つに分類しています。
| パターン | 概要 | 向いている場面 |
|---|---|---|
| シーケンシャル | 順番に処理 | パイプライン的な処理 |
| 並行 | 独立タスクを同時処理 | ファイル単位の変更 |
| ハンドオフ | 別エージェントに引き継ぎ | 専門分野の切り替え |
Claude Code Agent Teamsが採用しているのは並行+ハンドオフの組み合わせで、メインエージェントがサブエージェントにタスクを割り当て、完了報告を集約する構造です。
まとめ
マルチエージェントは「ターミナルを複数開くだけ」では破綻します。コンパクションで記憶が溶け、タスクが消え、人格が喪失する。これらは「AIが悪い」のではなく、人間がハーネス(制御の仕組み)を設計していないことが原因です。
まずは2台から始めて、共有状態を最小化し、通信プロトコルを決める。10台同時起動は、この基本ができてからの話です(私のように45本の調整線を無視すると、結局やり直しになります)。
あなたのプロジェクトでは、エージェント何台が限界ですか?
📘 この記事の内容をさらに詳しく知りたい方へ
ハーネス・エンジニアリング -- AIを"使う"から"操る"へ -- AIエージェントの制御設計を体系的に解説。6つの構成要素からSelf-Evolving Agentまで
