仕事で大規模なレガシーシステムのマイグレーションを進めるため、Claude Codeを24時間稼働させています。 レビュー役のエージェントを入れたところ、議論が脱線して開発が止まりました。 レビュー役を外して自己レビュー中心に変えると、開発が円滑に進み、 トークン消費も大きく減りました。 この記事では、その失敗と改善で気づいたことをまとめます。

案件や顧客を特定できる情報は載せません。

この記事で分かること

  • Claude Codeのオーケストレーション構成(私・オーケストレーター・ワーカー・サブエージェント)の組み方
  • レビュー役を増やすと、なぜ開発が止まったのか
  • 24時間止めずに回すために、台帳とテストで指示したこと

開発の体制: 私が最終決定権を持つオーケストレーション構成

仕事で、大規模なレガシーシステムのマイグレーションを担当しています。そのために、Claude Codeを24時間稼働させて、開発を進めています。一般的な開発者でも再現できるように、VS Codeのプラグインを選び、その中で開発してきました。

まず、大まかな仕様を決めて、AGENTS.mdとCLAUDE.mdに書き込みました。そのうえで、サブエージェントも活用したオーケストレーション体制を敷きました。体制は次のとおりです。

flowchart TB H["私(最終決定権)"] O["オーケストレーター<br>(Opus・メイン)"] W["ワーカー<br>(Sonnet・複数)"] C["CTO<br>(Opus・サブ)"] R["Redチーム<br>(Opus・サブ)"] H --> O O --> W O --> C O --> R
  • 私: 最終決定権を持ちます。
  • オーケストレーター(Opus 5.5): 全体を進めるメインのエージェントです。ワーカーに作業を割り当て、レビューの結果を裁定します。指揮能力の高いものを選んでいます。
  • ワーカー(Sonnet): 設計、実装、テストを担当します。複数います。ROIが高いエージェントして選んでいます。
  • CTO(Opus): 技術部門のトップとして振る舞うように固定した、独立したサブエージェントです。
  • Redチーム(Opus): 攻撃的な検証役のQAチームとして振る舞うように固定した、独立したサブエージェントです。

最初に決めた進め方: ウォーターフォール型の三者レビュー

まず、全量のコード(数百万ステップ)を解析させました。そして、設計、実装、テストのPDCAを回すように、オーケストレーターに定義させました。

各工程では、ワーカーの成果物をCTOとRedチームがレビューします。そのレビュー内容を、ワーカーを含む三者の意見として、オーケストレーターが調停し、裁定しながら進めます。本当に判断に迷う場合は、人間のゲート(私)に戻します。

進め方は、ウォーターフォールが一番よいと感じました。明確なゴールを立てて、小さく確認しながら確実に作り、積み上げて、最後に結合テストをする方法です。流れは次のとおりです。

flowchart TD W["ワーカー: 設計書を作成"] --> C["CTO: 抜け漏れをレビュー"] W --> R["Redチーム: 攻撃的に検証"] C --> O["オーケストレーター<br>三者の意見を調停して裁定"] R --> O W -. "ワーカーの意見" .-> O O -->|"合格"| N["次の工程へ"] O -->|"不合格"| B["ワーカーへ差し戻し(合格するまで実装・テストはさせない)"] B --> W O -->|"判断に迷う"| H["人間のゲート(私が判断)"]
  1. ワーカーが設計書を作成する
  2. CTOとRedチームが、抜け漏れがないかをレビューする
  3. オーケストレーターが俯瞰して裁定し、前に進める
  4. 問題があれば、ワーカーに指摘して戻す。合格するまで、実装もテストもさせない

理想的な進め方だと考えました。ただ、これが悪夢の始まりでもありました。

失敗: なかなか前に進まない

最初は、うまくいっていると思っていました。会話の内容は毎回確認していて、オーケストレーターが都度上げてくるレポートも、まともな議論に見えたからです。難しくない箇所は、スムーズに進んでいました。

しかし、丸一日どころか、二日、一週間たっても、合格ラインに届かない箇所が出てきました。何かがおかしいと思い、会話をよく読み直しました。すると、CTOとRedチームを入れると、議論が妙な方向に進むことに気づきました。

詳しくは書けませんが、議論が本線から脱線していたのです。

flowchart LR A["レビューで指摘が出る"] --> B["本線から外れた議論になる"] B --> C["元のシステムでも起きる<br>問題を理由にNG判定"] C --> D["ワーカーへ差し戻し"] D --> A

脱線その1: 日時の境界テスト

例えば、コミットのタイミングが23:59から00:00に変わるときの、境界テストの議論です。日付と時刻が一致しないので、オリジナルと違う、という理由で、ワーカーが作ったものをNGにしていました。しかし、これはオリジナルでも起きる問題でした。

人間なら、トランザクションのポイントをどこに置くかで判断できます。ところが、エージェントは、「抜け漏れがないか」「処理に問題がないか」という視点でしか見ていませんでした。同じ議論をループし続けて、デッドロック状態になっていました。

脱線その2: 言語の仕様差

別のケースでは、移行元と移行先の開発言語が、全く違っていました。オリジナルをA言語、移行先をB言語とします(仮の言語で、実在するB言語ではありません)。

A言語とB言語で、ハッシュの計算アルゴリズムが違う、という議論になりました。時間の扱いも、UTCなのかGMTなのかで議論して、前に進んでいませんでした。

指摘しても、記憶のリセットで忘れてしまう

脱線は、毎回指摘して直させていました。しかし、コンテキストウィンドウ(人間でいう海馬のような、一時的な記憶装置)がオーバーフローして、ある程度時間がたつと、指摘を完全に忘れてしまいます。

コンテキストウィンドウをリセットするために、サブエージェントを使い捨てカメラのように、毎回使い捨てにもしてみました。しかし、これも効果がなく、トークンをいたずらに消費するだけで、前に進みませんでした。

そこで、仮説を立てました。良かれと思って、細かな実装までCTOとRedチームを入れていたことが、間違いだったのではないか、という仮説です。これでは、PoCであっても、議論だけが白熱して、前に進みません。

検証: レビュー役を外して、自己レビューにしてみた

そこで、原因と考えたCTOとRedチームを、あえて外して検証しました。

  • レビューは、ワーカー自身に、最大3回まで見直させる
  • オーケストレーターには、最後に1回だけ見直しを指示できる権利を与える

自分で見直させるだけでも、結構効果があることは、以前から知っていました。だから、ワーカー自身に見直しをさせたのです。

flowchart TD W["ワーカー: 設計・実装"] --> S["自己レビュー(最大3回まで)"] S -->|"問題あり"| W S -->|"完了"| O["オーケストレーター: 最後に1回だけ見直しを指示できる"] O -->|"合格"| N["次の工程へ"] O -->|"指摘あり(1回だけ)"| W

結果は、見て分かるほど効果が出ました。開発が円滑に進み始めたのです。設計の精度も高く、トークン消費量をかなり抑えることにも成功しました。これにより、24時間稼働させられるようになりました。

項目 CTO・Redチームを入れた体制 自己レビュー中心の体制
進み具合 議論が脱線して停滞した 円滑に進んだ
トークン消費 いたずらに消費した かなり抑えられた
24時間稼働 難しかった できるようになった

ただし、これは私の案件での結果です。レビュー役が常に不要という意味ではありません。

エージェントは、増やしすぎない

ついでに、サブエージェントをたくさん立ち上げても、開発の速度は上がらないことにも気づきました。トークンをいたずらに消費するだけで、コンフリクトを繰り返し、毎回訂正したり、壊したりしてしまうからです。

そこで、エージェントは最大6つにしました。うち1つはオーケストレーターなので、ワーカー、CTO、Redチームを合わせて、使えるのは5つです。また、同じファイルを編集するような設計、開発、テストは、事前に避けるように指示しました。

開発のスコープ: 台帳で忘れさせず、テストの範囲を指示する

タスクを小項目まで分解し、台帳で管理する

最初から、大項目と中項目くらいまでは、分解して作業させていました。それを、小項目まで、事前にタスク分解させるようにしました。

合わせて、管理台帳を作らせました。何の作業を実施中で、何が完了したのかを、明確に書かせます。バグの管理台帳も作らせました。何が問題になって、何を修正したのかを、エージェントが忘れないように、必ず確認してから開発させます。

テストの方法まで指示する

テストの方法も指示しておかないと、とんでもないことをしようとします。一つのバグを修正するたびに、毎回、全量テストをしようとするのです。これには参りました。

やたらと時間がかかっているので、何をしているのかと問い詰めると、全量テストをしていると、平然と答えてきました。

そこで、次のように指示しました。

  • 修正は、専用のサンドボックス内で、修正した箇所だけを確認・テストして検証する
  • 全量テストは、最後に実施する。どうしてもすぐに確認しなければならない場合だけ、例外として実施する
  • この方針も、忘れないように、明確に書かせる
flowchart TD T["タスクを大・中・小項目<br>まで分解"] --> L["管理台帳<br>実施中・完了を記録"] L --> B["バグ台帳<br>問題と修正内容を記録"] B --> P["作業の前に<br>台帳を必ず確認"] P --> F["実装・修正"] F --> S["専用サンドボックスで<br>修正箇所だけテスト"] S --> A["全量テストは最後に実施<br>(急ぐ場合だけ例外)"]

これにより、指示プロンプトから、すぐには外れないようになりました。

まとめ: 人間と同じで「明確なゴール」と「達成条件」が要る

エージェントも、人間と同じで、「明確なゴール」と「達成条件」を書かせることで、改善できました。気づいたことは、次の3つです。

  1. レビュー役は、増やせばよいわけではない。 視点が違う役を足すと、議論が本線から脱線して、止まることがある。
  2. エージェントは、増やしすぎない。 数を増やしても速度は上がらず、コンフリクトとトークン消費が増える。
  3. 台帳とテストの方針を、先に書かせる。 忘れさせないための仕組みと、テストの範囲の指示が、24時間稼働を支える。

この作業に役立つ本

この記事は、本や他の記事の受け売りではなく、実際に動かして得た結果だけを書いています。

関連記事