【ITニュース解説】Running multiple Claude Code agents in parallel: what worktrees cannot see
2026年10月19日に「Dev.to」が公開したITニュース「Running multiple Claude Code agents in parallel: what worktrees cannot see」について初心者にもわかりやすく解説しています。
ITニュース概要
複数のAI開発ツールで並行作業すると、ファイル衝突や意味的な計画矛盾が起きる。Git Worktreeはファイル衝突を防ぐが、Gitは意味的な矛盾を見抜けない。そこで「Foremerge」は、AIが変更意図を事前に宣言し、計画の衝突を検知することで、並行開発の効率を高める。
ITニュース解説
システムエンジニアを目指す初心者の皆さん、最近のソフトウェア開発ではAIを活用した「コーディングエージェント」が注目されている。これは人間が指示を出すと、AIがコードを生成したり修正したりしてくれる便利なツールだ。もしあなたが一人で一つのAIエージェントを使って開発を進めているなら、ほとんど問題は起きないかもしれない。しかし、より効率的に開発を進めたいと考え、複数のAIエージェントを同時に動かした場合、思わぬ落とし穴にはまることがある。この記事は、そんな複数のAIエージェントを並行して使う際に発生する問題と、その解決策について詳しく解説する。
まず、複数のAIエージェントを同じプロジェクトで動かすと何が起きるか。最も分かりやすいのは「ファイルの衝突」だ。例えば、二つのエージェントが同時に同じファイルの内容を書き換えようとしたり、一方がファイルをインストールしている最中にもう一方がそのファイルを壊したりする状況だ。これではコードがめちゃくちゃになり、開発は全く進まない。この問題に対する標準的な解決策が「Gitワークツリー」の活用だ。
Gitワークツリーは、一つのGitリポジトリ(プロジェクトのコード全体が保存されている場所)から、複数の独立した作業環境を同時に作り出す機能である。各ワークツリーは、リポジトリの異なるブランチを、それぞれ別のディレクトリにチェックアウトする。これにより、各AIエージェントは自分専用の作業スペースとブランチを持ち、他のエージェントのファイルに影響を与えることなく作業を進められる。例えば、Claude Codeというエージェントを使う場合なら「claude --worktree feature-auth」のようにコマンドを実行するだけで、新しいワークツリーとブランチを作成できる。通常のGitコマンドでも「git worktree add ../myapp-paypal -b agent/paypal」のようにしてワークツリーを追加できる。この仕組みによって、AIエージェント同士がファイルを上書きし合う問題は基本的に解決される。
しかし、Gitワークツリーを使っても解決できない問題がいくつかある。例えば、Gitの管理下にない依存関係ファイル(node_modulesや仮想環境など)は各ワークツリーで個別にインストールする必要がある。また、複数のエージェントが同じポートで開発サーバーを立ち上げたり、同じローカルデータベースを操作したりすると、ファイルは異なっても共有リソースで衝突が発生する。さらに、Gitの仕様上、一つのブランチは一つのワークツリーでしかチェックアウトできないため、各エージェントは必ず異なるブランチで作業する必要がある。最終的には、これらのブランチを一つに統合する「マージ」作業が発生するが、そのマージを誰がどう行うか、複数のエージェントに任せると収拾がつかなくなる可能性があるため、統合役は人間か、特定のエージェントに限定すべきだ。
さて、ここまでの対策でファイルレベルの衝突は解決したが、より根深い問題が残る。それが「意味的衝突(Semantic Conflict)」である。Gitはファイルの「テキスト」の変更を比較してマージを行う。もし二つのエージェントが同じファイルの同じ行を変更した場合は、Gitがこれを衝突として検知し、マージを停止させるため、人間が手動で解決できる。これはGitが得意とする領域だ。しかし、もし二つのエージェントが異なるファイルや同じファイルの異なる行を変更した場合、Gitは何も衝突がないと判断し、きれいにマージを実行してしまう。この「きれいにマージされるが、実際にはプログラムの動作がおかしくなる」状況こそが意味的衝突なのだ。
具体的な例を挙げてみよう。「エージェントA」には「支払いサービス(PaymentService)をStripePaymentServiceに置き換える」という指示を与え、「エージェントB」には「既存の支払いサービスにPayPalのサポートを追加する」という指示を与えたとする。エージェントAはPaymentServiceを利用しているすべてのコードを新しいStripePaymentServiceを使うように変更し、エージェントBはPaymentServiceクラスにPayPal関連のコードを追加する。この二つのエージェントはそれぞれ異なるファイルを変更する可能性がある。Gitはこれらの変更を「異なるファイルや異なる行への変更」とみなし、何の問題もなくマージを完了させる。しかし、マージされたコードでは、エージェントAがPaymentServiceの呼び出しをすべてStripePaymentServiceに切り替えてしまったため、エージェントBが追加したPayPal機能は、もはやどこからも呼び出されず、全く機能しない状態になってしまう。それぞれのブランチ上ではテストがパスしていても、マージされた結果は期待通りに動かないのだ。これはGitが「コードの意図(プラン)」ではなく「テキストの変更」しか見ていないために起こる。このような意味的衝突は、コンパイラや一般的な自動テスト(CI)でも検知しにくい場合が多く、プログラムが実際に動作するまで発覚しないこともある。
この意味的衝突の問題を解決するために開発されたのが「Foremerge」というツールだ。ForemergeはGitの上に位置する「コーディネーションプロトコル」であり、AIエージェントの「プラン」を比較することで衝突を検出する。具体的には、AIエージェントがコードの変更に着手する前に、何を変更するつもりか(意図)を「宣言」としてForemergeに伝える。この宣言には、「セマンティックスコープ」と呼ばれる、シンボル、API、スキーマ、設定、ファイルなど、変更の対象となる概念的な範囲と、その変更が「置き換え」「拡張」「追加」など、どのような操作であるかが含まれる。
Foremergeは、リポジトリ内のすべてのAIエージェントが宣言したプランをリアルタイムで比較する。先ほどの支払いサービスの例で言えば、エージェントAが「symbol:PaymentService=replace」(PaymentServiceシンボルを置き換える)と宣言し、エージェントBが「symbol:PaymentService=extend」(PaymentServiceシンボルを拡張する)と宣言した場合、Foremergeは「破壊的な変更と追加的な変更が衝突している」と検知し、高い優先度で警告を発する。そして、エージェント同士で「まずは安定したPaymentProviderインターフェースを定義してから、StripeとPayPalの実装をそれぞれ進めるべきだ」といった調整の提案を行う。この情報はGitワークツリーをまたいで共有され、異なるベンダーのAIエージェント(Claude Code、Codex、Cursorなど)間でも連携できるのが特徴だ。AIエージェントはコードをコミットする前に、計画段階で衝突がないかを確認できるため、問題が大きくなる前に早期発見、早期解決が可能となる。
Foremergeは、ファイルやブランチをロックしたり、エージェントの作業を強制的に停止させたりはしない。代わりに、検出された衝突と、他のエージェントの意図に関するコンテキストをエージェントに提供し、人間が判断を下すための情報を提供する。最終的な「変更の受け入れ」は、登録された自動テストが全てパスし、かつ高優先度の衝突が解決されているか、正当な理由とともに上書きされている場合にのみ許可される。これは、エージェントが「テストはパスした」と報告するだけでは不十分で、実際の動作で検証される必要があるという考え方に基づいている。
Foremergeのようなツールを使わずとも、意味的衝突を減らすための作業分割のヒントはいくつかある。まず、タスクを分割する際は、タスク名ではなく「実際に何を変更するか」に基づいて考えることだ。たとえば、「決済機能のリファクタリング」と「PayPalサポートの追加」は異なるタスクに見えるが、同じクラスを変更する可能性がある。どのクラス、エンドポイント、データベーステーブル、設定キーを変更するのかを事前に洗い出し、重複がないタスクを並行で進めるべきだ。次に、変更の種類を明確にすること。単に追加したり、既存のものを拡張したりする作業は、他の変更との衝突が少ない。しかし、何かを「置き換え」「削除」「名前変更」「移行」するような破壊的な変更は、他の作業がそれに依存している可能性が高いため、単独で、あるいは他の作業より先に実施すべきだ。もし二つのタスクがある境界(インターフェースやAPIなど)で交わるなら、その境界を最初に定義し、それをマージしてから並行作業を開始するのが賢明だ。また、ルートファイル、環境変数テンプレート、依存関係のリスト、移行ファイルのナンバリング、機能フラグのリストなど、多くのタスクが触れる共通の「レジストリ」を常に意識し、これらの変更を計画に含めること。そして何よりも重要なのは、各エージェントの「プラン」を、実際にコードを書き始める前に、全員が読める共有の場所に明記しておくことだ。これにより、重複した作業や、置き換えと拡張のような根本的な衝突を、コードになる前に人間が発見できる可能性が高まる。最後に、各AIエージェントのブランチが個別にテストをパスしたとしても、必ず「マージされた結果」をビルドし、型チェックし、テストを実行することだ。個別のブランチが正常でも、マージされた全体が動くとは限らない。
Foremergeにはまだいくつかの限界もある。例えば、エージェントが宣言した内容と異なる変更を行った場合は検出できない。また、クラス全体に対するスコープと、そのクラスの特定メソッドに対するスコープといった「スコープの階層性」は、現在のバージョンでは完全に一致するものとして扱われない。エージェントが宣言しなかったファイルへの変更や、異なる用語で同じ概念を指す「同義語」の問題も、検出が難しい場合がある。リアルタイムのプッシュ通知機能はなく、異なるマシン間での連携もサポート範囲外だ。
しかし、これらの限界があっても、Gitワークツリーがファイルレベルの衝突を防ぎ、Foremergeがプランレベルの意味的衝突を早期に検出するという役割分担は、複数のAIエージェントを用いた効率的な並行開発において非常に有効なアプローチだ。もしあなたが複数のAIエージェントを動かして開発を進めたいなら、Gitワークツリーで作業環境を隔離し、Foremergeのようなツールでエージェントの意図を調整することで、テキストの衝突だけでなく、意味の衝突も回避し、よりスムーズな開発体験を得られるだろう。