メインコンテンツへスキップ

AI開発

同時に動かす。混ぜない。

Claude CodeとCodexを並列運用し、 コンフリクトを避ける開発設計

公開日:2026年8月14日 著者:飯田 友広(Tomohiro Iida)

この記事の結論

  • AIエージェントを増やしても、統合方法が決まっていなければ、未確認のブランチとPull Requestが増えるだけです。

  • 並列化するのは、独立して完了条件を判定できるタスクに限定します。

  • Git worktreeはファイル編集を分離しますが、仕様、DB、ポート、環境変数、マージ順序の競合までは解消しません。

  • 各エージェントへ、変更可能パス、変更禁止パス、停止条件を含むTask Contractを渡します。

  • 実装は並列化しても、mainへの統合は一人の統合責任者が依存関係に沿って順番に行います。

AIエージェントを二体に増やせば、開発速度も二倍になる。

この理解は半分だけ正しいものです。

コードを生成する速度は上がります。しかし、複数の変更を読み、前提を揃え、競合を解消し、テストしてmainへ統合する作業も増えます。実装だけを並列化し、統合方法を決めなければ、完成したブランチと未確認のPull Requestが積み上がります。

Netsujoでは、ChatGPT、Claude Code、Codexを設計・実装・監査へ分ける運用を試してきました。その役割分担と、全変更へ三つのAIを直列接続する限界は、ChatGPT・Claude Code・Codexの分業開発で整理しています。

本記事が扱うのは、その次の問題です。

同じリポジトリで、複数のAIエージェントを同時に動かすとき、どうすれば互いの作業を壊さず、mainへ安全に統合できるのか。

結論は単純です。

実装は並列化する。mainへの統合は直列化する。

そのために必要なのは、エージェントを増やすことではありません。作業場所、変更責任、実行環境、統合権限を分け、依存関係に沿って一つずつ統合する仕組みです。

開発速度を決めるのは、最も遅い工程である

AIエージェントによる開発は、次の三工程に分けられます。

開発速度を決めるのは、最も遅い工程である
工程内容主なボトルネック
実装コード、テスト、文書を作るタスクの曖昧さ、既存コードの理解
統合複数の変更を一つの状態へまとめる依存関係、競合、マージ順序
検証変更が正しいと判定するテスト範囲、レビュー能力、実行環境

AIエージェントを増やすと、実装能力は増えます。一方、統合責任者が一人のままなら、統合能力は自動では増えません。

実効的なスループットは、最も遅い工程に制約されます。

たとえば、三つのエージェントが一日に三本のPull Requestを作っても、人間が一日に一本しかレビュー・統合できなければ、二本は在庫になります。翌日も同じ速度で実装を増やせば、古いbase commitを前提とした変更が増え、競合確率も上がります。

この状態で必要なのは四体目のエージェントではありません。

  • タスクを小さくする
  • 並列化する対象を選ぶ
  • 共有部分の所有者を決める
  • 統合待ちの上限を決める
  • 新しい作業より先に、既存のPull Requestを閉じる

AIエージェント活用の指標を「同時に何体動かしたか」に置くと、未統合の成果物を増やすこと自体が目的になります。見るべきなのは、mainへ安全に入った変更の量と、統合までの時間です。

Gitコンフリクトより危険な「前提のコンフリクト」

複数のエージェントを動かしたとき、最も分かりやすい問題はGitのマージコンフリクトです。

同じファイルの同じ行を二つのブランチが編集すれば、Gitが競合を知らせます。しかし、Gitが検知できるのはテキスト上の衝突です。

実務では、次の四種類を分けて考える必要があります。

1. テキストのコンフリクト

同じファイルの近い行を編集する競合です。

例として、二つのエージェントが同じReactコンポーネントのpropsや同じ設定ファイルを変更した場合があります。これはGitが検知できます。

2. 仕様のコンフリクト

異なるファイルを編集していても、前提としている仕様が食い違う状態です。

たとえば、API担当がレスポンスを次の形へ変更したとします。

{
  goal: {
    id: string;
    label: string;
  }
}

一方、UI担当が古い形を前提に実装している場合があります。

{
  goalId: string;
  goalLabel: string;
}

編集ファイルが異なるため、Git上の競合は発生しません。それでも、統合後のtypecheck、build、実行時には壊れます。

3. 実行環境のコンフリクト

worktreeを分けても、次の資源は共有される可能性があります。

  • ローカルデータベース
  • 開発サーバーのポート
  • Redisやキュー
  • 外部APIのテスト環境
  • オブジェクトストレージ
  • キャッシュ
  • テストデータ
  • 環境変数
  • データベースマイグレーション

二つのエージェントが別々のworktreeで作業していても、両方が同じデータベースへマイグレーションを実行すれば、互いの前提を壊します。

4. 統合順序のコンフリクト

依存関係のあるPull Requestを、完成した順にマージすることで発生します。

UI変更が新しいAPI契約へ依存しているのに、UI側を先にmainへ入れれば、一時的に壊れた状態になります。コード単体で正しくても、順序が間違えばmainは正しくありません。

4. 統合順序のコンフリクト
競合の種類Gitが検知するか主な対策
テキスト競合検知するworktree、担当ファイル分離、rebase/merge
仕様競合原則検知しないAPI契約、共有型、契約テスト
実行環境競合検知しないDB・ポート・データ・環境変数の分離
統合順序競合検知しない依存関係表、統合責任者、マージ順序

マージコンフリクトがないことと、安全に統合できることは同じではありません。

並列化してよいタスクの条件

すべてのタスクを並列化する必要はありません。

並列化するかどうかは、エージェントの能力ではなく、タスク間の依存関係で決めます。

並列化しやすいタスク

  • 独立したページやコンポーネントの実装
  • 既存仕様に対するテスト追加
  • ドキュメント作成
  • ログや計測処理の追加
  • 変更を伴わないコード調査
  • 読み取り専用のセキュリティレビュー
  • 異なるパッケージやサービスの修正

共有契約を固定すれば並列化できるタスク

  • バックエンドAPIとフロントエンドUI
  • 共通コンポーネントと利用側画面
  • データモデルとバリデーション
  • 実装とE2Eテスト
  • デザインシステムと各画面

この場合は、API型、props、スキーマ、イベント名、エラー形式、空値の扱いなどを先に確定します。

直列で進めるべきタスク

  • 同じデータベースマイグレーションの変更
  • 認証・認可の中核ロジック
  • 共通型定義の大規模変更
  • 依存ライブラリの一括更新
  • lockfileを伴う複数のパッケージ変更
  • リポジトリ全体を横断するリネーム
  • 方針が未確定な大規模リファクタリング

並列化の前には、次の三問へ答えます。

  1. それぞれのタスクを独立して完了判定できるか
  2. 変更するファイルやディレクトリを事前に予測できるか
  3. 一方の結果によって、もう一方の前提が変わらないか

一つでも明確に答えられない場合は、分割方法を見直すか、直列で進めます。

並列開発を支える四つの分離

安全な並列開発には、四つの分離が必要です。

1. 作業場所を分ける

エージェントごとにworktreeを分けます。

同じ作業ディレクトリで複数のエージェントを動かすと、未コミット変更、生成ファイル、依存関係の更新が混在します。どのエージェントが何を変えたか分からなくなり、片方の検証中にもう片方がファイルを書き換えることもあります。

2. 変更責任を分ける

各エージェントが変更してよいパスを定義します。

「UI担当」「API担当」という機能名だけでは不十分です。UI実装中に共通型、設定、依存関係まで変更する可能性があるため、許可パスと禁止パスを明示します。

3. 実行環境を分ける

開発サーバー、ポート、データベース、テストデータ、外部サービスの名前空間を分けます。

環境を分けられない場合は、同時実行を禁止し、利用順序を決めます。

4. 統合権限を分ける

実装者とmainへの統合責任者を分けます。

エージェントが自分で実装し、自分で競合を解消し、自分でmainへマージする構成では、判断の独立性がありません。実装エージェントはPull Requestまで、mainへの統合は一人の責任者が行う方が追跡しやすくなります。

Git worktreeで作業場所を分ける

Git公式ドキュメントでは、一つのリポジトリに複数のworking treeを関連付け、複数のブランチを同時にcheckoutできる仕組みとしてworktreeが説明されています。

Claude Codeには、分離されたworktreeでセッションを開始する --worktree オプションがあります。Codexアプリにもworktreeの組み込みサポートがあり、複数のエージェントが同じリポジトリで別々のコピーを扱う構成が案内されています。

手動で作成する場合は、最初にmainを最新化します。

git fetch origin
git switch main
git pull --ff-only

UI実装用のworktreeを作ります。

git worktree add ../project-wt-goal-ui -b feat/goal-ui origin/main

API実装用のworktreeを作ります。

git worktree add ../project-wt-goal-api -b feat/goal-api origin/main

読み取り専用に近いレビュー用途では、detached HEADのworktreeも使えます。

git worktree add --detach ../project-wt-goal-review origin/main

現在のworktreeを確認します。

git worktree list

Gitは通常、同じブランチを複数のworktreeへ同時にcheckoutすることを拒否します。したがって、原則は一つのタスクにつき、一つのブランチと一つのworktreeです。

Claude CodeをCLIから起動する場合は、公式ドキュメントで次の形が案内されています。

claude --worktree feature-auth

ただし、worktreeが分離するのは、主にファイル編集とGitの作業状態です。

次は自動では分かれません。

  • API仕様
  • データベース
  • ポート
  • 外部サービスのテスト環境
  • gitignoredな環境ファイル
  • キャッシュ
  • lockfileの意味
  • マージ順序

worktreeは並列化の開始地点であり、コンフリクト対策の完成形ではありません。

Task Contractで変更範囲を固定する

複数のエージェントへ依頼するとき、詳細な実装方法をすべて指示する必要はありません。

一方で、境界は細かく指定する必要があります。

特に重要なのは、「何を変更するか」よりも何を変更してはいけないかです。

Netsujoでは、エージェントへ渡す実装指示を、検証可能なTask Contractとして整理します。

# Task Contract

## Task ID
goal-ui

## 目的
顧客の目標確認画面を追加する。

## Base Commit
<開始時点のcommit SHA>

## 担当
UI実装エージェント

## 変更してよい範囲
- src/features/customer-goal/**
- src/components/customer-goal/**
- tests/customer-goal-ui/**

## 変更してはいけない範囲
- db/migrations/**
- src/shared/contracts/**
- src/server/**
- package.json
- pnpm-lock.yaml

## 依存する仕様
- GoalResponse v1
- POST /api/customer-goal
- error.codeは既存の列挙値を使用する

## 受け入れ条件
- 目標の確認・修正・保存ができる
- 既存画面の導線を維持する
- エラー時に再試行できる
- typecheckが通る
- 対象テストが通る

## 停止条件
次の場合は実装を停止し、変更せずに報告する。
- shared/contractsの変更が必要
- DBスキーマの変更が必要
- API仕様とTask Contractが矛盾する
- 担当外ファイルを変更する必要がある

## 完了報告
- commit SHA
- 変更ファイル一覧
- 実行した検証
- 残っている懸念
- Task Contractから逸脱した箇所

停止条件を入れる理由は、AIエージェントに無理やり完了させないためです。

担当範囲外の問題を発見したとき、その問題まで自動で修正させると、別エージェントの作業領域へ侵入します。

「必要なら関連箇所も改善してください」という指示は、単独作業では便利でも、並列開発では危険です。改善範囲が無制限になり、担当境界が消えるからです。

関連問題は直さず、次の形式で別タスクへ切り出します。

  • 発見した問題
  • 影響範囲
  • 今回のタスクを止めるか
  • 次に必要な担当者
  • 依存するPull Request
  • 推奨するマージ順

ファイル所有権は「予定」と「実績」の二段階で確認する

Task Contractを渡しても、実装中に変更範囲が広がることがあります。

そこで、編集前と完了時の二回、ファイル境界を確認します。

編集前

エージェントに変更予定を出させます。

変更予定:
- src/features/customer-goal/GoalForm.tsx
- src/features/customer-goal/useGoal.ts
- tests/customer-goal-ui/goal-form.test.tsx

変更しない:
- src/shared/contracts/goal.ts
- db/migrations/**

別エージェントの予定ファイルと重なっていたら、その時点でタスクを分割し直します。

完了時

実際の差分を取得し、Task Contractと比較します。

git diff --name-only origin/main...HEAD

予定外のファイルがあれば、次のどれかを選びます。

  1. 担当範囲を正式に拡張する
  2. 予定外の変更を元に戻す
  3. 別Pull Requestへ分離する
  4. 依存タスクとして直列化する

予定外の変更を「ついでの改善」として黙って残すことが、後の競合を増やします。

実行環境もworktree単位で識別する

ファイルだけ分けても、実行環境が同じなら干渉は残ります。

最低限、次をworktreeごとに決めます。

実行環境もworktree単位で識別する
資源分離例
開発サーバー3001、3002のようにポートを分ける
DBdatabase名、schema名、tenant IDを分ける
Redis/キューprefixやnamespaceを分ける
オブジェクトストレージbucket prefixを分ける
テストユーザーagent-a、agent-bのfixtureを分ける
一時ファイルworktree配下へ出力する
外部APIsandbox projectやidempotency keyを分ける

分離できない共有資源には、ロックが必要です。

たとえば本番相当の共有ステージングDBへマイグレーションできるのは一つのタスクだけ、というルールを置きます。並列化できないものを無理に並列化しないことも、並列運用の一部です。

サブエージェントとworktreeは別の仕組みである

サブエージェントを増やせば、並列編集も安全になると考えやすいのですが、二つは別の問題です。

サブエージェントが主に分離するのは、役割、コンテキスト、プロンプト、利用できるツールです。

worktreeが分離するのは、ファイルを編集する作業場所です。

サブエージェントとworktreeは別の仕組みである
目的主に使う仕組み
調査履歴を親コンテキストから分離するサブエージェント
UI、セキュリティ、データを役割分担するカスタムエージェント
複数の実装を同時に編集するworktree
APIや型の前提を揃えるTask Contract、共有契約
mainへの変更を制御するPull Request、CI、ブランチ保護

同じ作業ディレクトリを共有したままサブエージェントだけ増やしても、ファイル競合は解消されません。

実装は並列、統合は直列

二つのPull Requestが完成しても、同時にmainへ入れる必要はありません。

一つ目をマージした後、二つ目のブランチを最新のmainへ追従させ、検証をやり直します。

推奨する依存関係

PR 0: 共有型・API契約
  ├─ PR 1: バックエンド実装
  └─ PR 2: フロントエンド実装
       └─ PR 3: 統合テスト・監査修正

PR 0をmainへ入れた後、そのcommitを起点としてPR 1とPR 2を並列化します。

統合手順

  1. 共有契約を先に確定する
  2. 全エージェントを同じbase commitから開始する
  3. 変更予定ファイルを申告させる
  4. 各worktreeで対象検査を実行する
  5. Pull Request単位で差分監査する
  6. 依存関係に沿って一つずつマージする
  7. 残っているブランチを最新mainへ追従させる
  8. typecheck、test、buildを再実行する
  9. マージ済みworktreeを削除する

main追従の例です。

git fetch origin
git merge origin/main --no-edit

チームでrebaseを採用している場合は、同じ目的でrebaseしても構いません。重要なのは、統合方法を一つに固定し、追従後に検証をやり直すことです。

Claude CodeとCodexを実装競争させない

同じ目的に対してClaude CodeとCodexの両方へ実装させると、二つの実装案を比較し、片方を破棄し、必要な部分を再統合する作業が発生します。

比較実験が目的でなければ、実装競争は開発速度を下げます。

基本形は次です。

Claude CodeとCodexを実装競争させない
役割主な担当書き込み権限
統合責任者タスク分割、共有契約、マージ判断mainと共有契約
実装エージェントA独立機能の実装専用worktree
実装エージェントB別の独立機能やテスト専用worktree
監査エージェント差分レビュー、リスク指摘原則読み取り専用
CIlint、typecheck、test、build判定のみ

実装担当が出した差分を別のエージェントが監査し、修正は原則として元の実装担当へ戻します。

監査エージェントが別ブランチから直接修正を始めると、変更の所有者が増えます。緊急時を除き、監査と修正の権限を分けた方が履歴を追いやすくなります。

mainブランチを品質ゲートにする

「mainへ直接pushしない」というルールは、注意事項ではなくGitHub側の設定として強制します。

最低限、次を設定します。

  • Pull Request経由の変更を必須にする
  • required status checksを設定する
  • レビューコメントの解決を必須にする
  • mainへの直接pushを制限する
  • 高リスク領域にはCODEOWNERSを設定する

GitHubの保護ブランチでは、required status checksが成功するまでマージを禁止できます。strict設定では、対象ブランチが最新のbase branchへ追従していることも要求できます。

ただし、strict設定ではmainが更新されるたびに、残りのPull RequestでCIを再実行する回数が増えます。

CI利用量を抑えたい場合は、検査を省略するのではなく、実行タイミングを分けます。

mainブランチを品質ゲートにする
タイミング検査
作業中対象lint、対象test、typecheck
Pull Request作成時全体lint、typecheck、test
main追従後影響範囲のtest、build
高リスク変更E2E、権限テスト、マイグレーション検証

安価な検査を早く、高コストな検査を統合前へ置く構成です。

並列タスク管理表

複数のエージェントを起動する前に、次の表を作ります。

並列タスク管理表
ID担当ブランチ変更可能範囲依存先マージ順
T0統合責任者feat/goal-contractshared contractsなし1
T1Claude Code Afeat/goal-apiserver、API testsT02
T2Claude Code Bfeat/goal-uifeature UI、UI testsT03
T3Codexdetached/review読み取り専用T1、T2マージなし

重要なのは担当者名ではありません。

  • 変更可能範囲
  • 依存先
  • マージ順

この三つが空欄のままエージェントを起動すると、並列作業ではなく、無調整の同時作業になります。

統合待ちの上限を決める

AIエージェントは実装が速いため、人間は新しいタスクを起動し続けやすくなります。

しかし、未レビューのPull Requestが増えるほど、各ブランチのbase commitは古くなります。仕様変更、依存更新、他のマージが積み重なり、後から統合する費用が増えます。

運用上は、Work in Progressの上限を置きます。

例として、統合責任者一人なら次のように制限します。

  • 実装中は最大二件
  • レビュー待ちは最大二件
  • Highリスク変更は同時に一件
  • 上限に達したら、新規着手より統合を優先する

AIに仕事をさせ続けることより、mainを前へ進めることを優先します。

よくある失敗パターン

「関連箇所も含めて改善する」と指示する

担当範囲がリポジトリ全体へ広がります。

並列運用中は、発見した関連問題を修正させず、別タスクとして報告させます。

二つのエージェントへ同じブランチを渡す

未コミット変更や生成ファイルが混在し、どちらの変更か判別できなくなります。

一つのタスクにつき、一つのブランチと一つのworktreeを割り当てます。

共通型を各エージェントが独自に変更する

異なるファイルへ類似の型が作られ、統合時に仕様が分岐します。

共有型、API契約、DBスキーマには一人の所有者を置きます。

完成した順にマージする

依存先より利用側が先にmainへ入り、一時的に壊れた状態になります。

完成時刻ではなく、依存関係で順序を決めます。

AIへ意味判断を含むコンフリクト解消を丸投げする

import整理やファイル移動のように意図が明確な競合は任せられます。

一方、次の競合は統合責任者が残す仕様を決めます。

  • API契約
  • 認証・認可
  • データベーススキーマ
  • 料金・契約ロジック
  • 共通型
  • lockfile
  • 環境設定

AIには、判断後の機械的な修正を担当させます。

長期間mainへ追従しない

worktreeを分けたまま長期間作業すると、base branchとの差が広がります。

小さな単位でPull Requestを作り、統合までの時間を短くします。競合リスクはエージェント数だけではなく、共有変更範囲と枝分かれしている時間によって増えます。

最低限の運用ルール

AIエージェントを並列で動かす場合、最低限、次を固定します。

  1. 一つのタスクにつき、一つのブランチと一つのworktreeを使う
  2. 全タスクのbase commitを記録する
  3. 各エージェントへTask Contractを渡す
  4. 変更可能パスと変更禁止パスを明記する
  5. 共有契約、DBスキーマ、認証には一人の所有者を置く
  6. DB、ポート、テストデータを分離する
  7. エージェントからmainへ直接pushさせない
  8. 完了時にcommit SHA、変更ファイル、検証結果、懸念点を報告させる
  9. 実装担当と監査担当を分ける
  10. mainへの統合は一人の責任者が順番に行う
  11. 一つマージするたびに、残りのブランチをmainへ追従させる
  12. マージ後にworktreeと不要ブランチを削除する

作業完了後は整理します。

git worktree remove ../project-wt-goal-ui
git branch -d feat/goal-ui
git worktree prune

終了条件には、コードのマージだけではなく、worktreeの削除まで含めます。

まとめ

AIエージェントを並列で動かすと、コードを書く能力は増えます。

その結果、ボトルネックは実装から統合へ移ります。

必要なのは、より多くのエージェントではありません。

  • worktreeによる作業場所の分離
  • Task Contractによる変更責任の分離
  • ポートやDBを含む実行環境の分離
  • Pull RequestとCIによる統合ゲート
  • 一人の責任者による最終的な統合判断

複数のAIエージェントを同時に動かすことと、複数の変更を同時にmainへ入れることは別です。

実装は並列化し、統合は直列化する。

この原則を守ることで、AIエージェントの速度を、ブランチ混乱や手戻りではなく、実際にmainへ届く開発速度へ変えられます。

よくある質問

worktreeを使えばコンフリクトはなくなりますか

なくなりません。

worktreeは作業ディレクトリとGitの作業状態を分けますが、API仕様、共通型、データベース、ポート、外部サービス、マージ順序の競合は残ります。Task Contractと実行環境の分離、統合順序を併用する必要があります。

フロントエンドとバックエンドは並列開発できますか

API契約を先に固定すれば可能です。

リクエスト、レスポンス、エラー形式、認可条件、空値の扱いまで決めてから分割します。API契約が実装途中で変わる状態では、直列で進めた方が手戻りを減らせます。

同じ機能をClaude CodeとCodexの両方に実装させるべきですか

通常は不要です。

実装案を比較する実験でなければ、一方を実装担当、もう一方を読み取り専用の監査担当に分けた方が統合コストを抑えられます。

何体まで同時に動かせますか

モデルやPCの上限ではなく、統合責任者がレビューとマージを処理できる範囲で決めます。

未レビューのPull Requestが積み上がる場合、エージェントを追加しても処理能力は上がりません。新しいタスクを起動する前に、現在の変更をmainへ統合します。

AIにマージコンフリクトを解消させてもよいですか

意図が明確な機械的競合は任せられます。

API仕様、DBスキーマ、認証、料金、契約など、意味の判断を伴う競合は、人間が残す仕様を決めます。AIには判断後の修正を担当させます。

参考資料

製品仕様と公式ドキュメントの記載は、2026年8月14日時点のものです。

この記事の著者

飯田 友広

飯田 友広

代表取締役

Netsujo株式会社 代表取締役。京都発のWeb3・AI実装スタートアップを2023年6月に創業。Webサイトを営業基盤として捉え、経営・営業・検索・生成AI・コンバージョン・計測を横断して課題と改善優先順位を整理する「Netsujo SIGNAL」を設計・運営。さらに、ChatGPT・Codex・Claude Codeを状態再構築、競合回避、独立QC、Exact-head検証、停止、復旧まで含む制御ループで運用する社内AI開発基盤「Netsujo Agent OS」を設計・実運転。Netsujoとして京都ビッグデータ活用プラットフォームに参画(小規模企業会員(ベンチャー))し、同プラットフォーム発のワーキンググループ「Chain Up KYOTO」にも参画(2026年3月10日〜)。IVS2026サイドイベント「なぜ京都でWeb3.0ビジネスなのか」はNetsujoとして京都府庁旧議場で主催・企画・登壇・運営(2026年7月2日/京都府 総合政策環境部 デジタル政策推進課は共催)。京都美術工芸大学・龍谷大学での講義に加え、京都高度技術研究所(ASTEM)、旅館業界、就労支援施設、Open Source Conference等で登壇実績。ITコミュニティ「みやこでIT」(connpassメンバー637名・イベント174件・2019年2月から運営)運営。NPO法人NEMTUS理事、BAR KRYPTO運営。Netsujoはソーシャル企業認証制度「S認証」の認証企業(2026年2月認証・2026年4月公表)。技術領域はWeb3/ブロックチェーン/DID/NFT/生成AI/コミュニティ運営。

プロフィールを見る

この記事が向いている方

  • Claude Code、Codexなど複数のAIコーディングエージェントを同じリポジトリで動かしている方

  • 並列化した結果、ブランチ競合、レビュー待ち、CI増加に悩んでいる開発責任者

  • 少人数の開発体制で、実装速度とmainの安定性を両立させたい経営者・事業責任者

— 壁打ち相談

読者のよくある相談

記事を読んだ後に「自分の状況だとどう判断すべきか」を整理するための壁打ち相談を受け付けています。下記のような相談例が当てはまる方は、お気軽にご連絡ください。

Q. 複数のAIが同じファイルを触り、どの変更を残すべきか分からない

worktreeだけでなく、変更可能パスと共有ファイルの所有者を先に固定します。

Q. Pull Requestは増えるが、mainへ統合する速度が上がらない

Work in Progressの上限を置き、完成時刻ではなく依存関係でマージ順を決めます。

Q. Git上の競合はないのに、統合後にAPIやDBが壊れる

仕様・実行環境・統合順序のコンフリクトを、Gitとは別のゲートで検査します。

上記いずれかが該当する場合、初回30分の壁打ち相談で論点整理に対応します。記事に書ききれない個別事情を踏まえた判断材料が必要な段階こそ、壁打ちが活きやすいフェーズです。

AI導入・PoC・業務実装のご相談

AIエージェントを増やす前に、統合できる開発体制を作る

役割分担、Task Contract、Git worktree、CI、レビュー、公開判断まで、実装速度が手戻りへ変わらない運用を設計します。

連載補章

AIを並列化したら、merge queueが一度も排出されなくなった

Controller不在が起こすqueue starvation

Workerを増やしても完了する仕事が増えなかった実例から、UNKNOWN、main drift、collision、queue starvation、Task ClaimをControllerがどう制御すべきかを整理します。

Incident Card

AIエージェントを並列化すれば、開発速度は上がる。私はそう考えていました。調査、実装、レビュー、CI確認を複数laneで同時に進めれば、人間一人では順番に処理するしかなかった仕事を同時に前へ進められるはずでした。

実際、Pull Requestが作られる速度は上がりました。調査結果も増え、複数のAgentが止まらず動き続けました。ところが、merge queueから成果物が排出されなくなりました。

Incident Card
項目発生したこと
symptomAgentとPull Requestは増えたがmergeが進まない
direct impactCI再実行、再Review、branch同期が増えた
hidden impactqueue下位の候補が評価されないstarvationが起きた
wrong premise各Agentが局所的に正しく動けば全体も自然に前進する

私はAIを並列化したつもりで、未完了作業を並列に増産するシステムを作っていました。

36件すべてがmergeできないと判定された

あるmerge直後、Controller相当のWorkflowが候補Pull Requestを再評価しました。そのrunでは36件中36件のmergeableがnullでした。一方、CI起動後の別runでは38件中nullは0件でした。

つまり最初の36件がすべてmerge不能だったわけではありません。GitHub側のmergeability計算が完了していなかっただけです。しかし当時の判定では、trueをMERGEABLE、falseをNOT_MERGEABLE、nullもNOT_MERGEABLEへ落としていました。

必要だったのは少なくとも三状態です。

  • MERGEABLE: 統合可能であることが確定した
  • NOT_MERGEABLE: 統合不能であることが確定した
  • UNKNOWN: 観測または外部計算が未完了で、まだ判断できない

UNKNOWNはFailureではありません。外部システムのeventual consistencyを内部の終端エラーへ変換すると、正常に回復する候補までqueueから落ちます。

mainが進むたびに自分でEvidenceを壊していた

もう一つの問題がmain driftへの反応でした。mainが進むたびに作業branchを同期する。一見すると安全ですが、branchを同期するとHEADが変わります。HEADが変われば、直前まで有効だったCI、Review、exact-head確認は現在Artifactを証明しません。

典型的なループは次の通りです。

  1. HEAD AでCIがPASSする
  2. HEAD AでReviewがPASSする
  3. mainが進む
  4. branchを同期する
  5. HEAD Bになる
  6. HEAD AのCIとReviewがSTALEになる
  7. 再検証中にmainが再び進む
  8. また同期する

私たちのシステムはmain driftを解消しているつもりで、完了条件を自分で繰り返し無効化していました。

必要なのはbehind commit数ではなくTaskへの影響判定です。

  • 影響なし: 現在PlanとEvidenceを維持する
  • 影響の可能性あり: targeted verificationだけ行う
  • confirmed impact: branch syncとaffected subgraphのReplanを行う

1commitでも同じschemaを変更していれば重大です。20commit進んでいても無関係な文書変更だけなら、現在Taskへの影響はありません。

collisionを検知したのに誰も進めなかった

複数のPull Requestが同じResourceへ影響する場合、collision判定を入れました。しかし初期設計は対称的でした。PR AはPR Bと衝突しているので待つ。PR BもPR Aと衝突しているので待つ。両方とも合理的で、両方とも永遠に進みません。

collision検知だけでは足りません。Controllerには、どちらを先に通すかを決めるAuthorityが必要です。

優先規則の例は次の通りです。

  1. production incidentやsecurity fix
  2. すでに有効なEvidenceが多いFinal Candidate
  3. downstream blockerを解除する変更
  4. 変更範囲が小さく収束しやすい候補
  5. 同順位ならage、risk、残作業量による決定論的順序

Agent同士へ譲り合いを任せると、対称deadlockが生まれます。優先順位は当事者間の相談ではなくControllerが決めます。

queueの先頭だけを見るとstarvationが起きる

Controllerは優先度の高い候補から評価します。しかし先頭候補がUNKNOWN、CI待ち、collision中などで進めない場合、次回も同じ候補が先頭になります。

PR AがUNKNOWNだからといって、独立して進められるPR BやPR Cまで止める理由はありません。必要なのはpriorityとfairnessの両立です。

  • UNKNOWN候補にはbackoff付き再観測時刻を設定する
  • 再観測までqueueから一時退避する
  • lower priorityでも独立して進められる候補を評価する
  • 最大連続defer回数を持つ
  • 長時間待機候補にはage boostを与える

先頭候補を最優先することと、先頭候補一つに全体を拘束することは違います。

同じ問題を別laneが別々に直していた

さらに深刻だったのが、同一root causeに対する重複Pull Requestです。たとえばProduction Goal Smokeの前提未整備という一つの問題に対して、readiness専用Workflow、既存Workflow内preflight、secret参照境界の修正が別laneから並走しました。

各案は合理的です。しかし三案すべてを実装まで進めると、最後に必要になるのは人間による正本選定と統合です。

Controllerが管理すべき対象はPull Requestだけではありません。何の問題を解決しているかというTask Claimも管理する必要があります。

Task Claimには次を持たせます。

  • claim key
  • canonical owner
  • canonical Pull Request
  • branch / worktree / write scope
  • lease / heartbeat / expiry
  • competing proposal

同じclaim keyへ別Agentが着手しようとした場合、新しいPRを作るのではなく、JOIN_EXISTING、PROPOSE_TO_CANONICAL_OWNER、SPLIT_AS_INDEPENDENT_SUBTASK、REJECT_DUPLICATEのいずれかへRoutingします。

ControllerはAgentのDispatcherではない

この事故から、Controllerを単にAgentへ仕事を配るDispatcherとして捉えるのをやめました。Controllerが正本として管理するのは次の5点です。

ControllerはAgentのDispatcherではない
管理対象Controllerの責任
StateTaskが現在どの状態か
Authority誰が変更し、誰が最終判断してよいか
Resourcebranch、worktree、file、PRの所有者
Evidence現在有効な証拠は何か
Transitionどの条件で次のStateへ進むか

Agentが終わったと言ってもDONEにはしない。GitHubがnullを返してもFAILにはしない。collisionを見つけても全員を止めない。mainが進んでも影響を確認せず同期しない。

Controllerは、局所的に正しいAgentの判断を、システム全体の前進へ変換する制御層です。

Rule

並列化ではWorker数より先にControllerを設計する。Controllerは優先順位、所有権、UNKNOWN、競合、Evidence失効を一元管理する。

Guardrail

  • mergeabilityのnullをUNKNOWNとして扱う
  • UNKNOWNにはbackoff付き再観測を適用する
  • UNKNOWN候補がqueue全体を止めないようにする
  • main driftはcommit数ではなく影響範囲で評価する
  • branch同期にはmutation ownerとexpected HEADを要求する
  • collision時はControllerが一方を選ぶ
  • 同一root causeにはcanonical Task Claimを一つだけ持つ
  • 重複案は新規PRではなく正本ownerへのProposalとして扱う
  • queueのfairnessとstarvationを監視する
  • 成果指標をPR作成数ではなくqueue排出数へ置く

Evidence

Controllerが機能しているかは、Agent稼働率ではなく収束性で判断します。

  • queueへ入ったTaskのうちDONEへ到達した割合
  • Pull Request作成からmergeまでの時間
  • UNKNOWNから正常回復した割合
  • main drift後の不要なbranch同期回数
  • 同一Task Claimから作られた重複PR数
  • collisionによる停止時間
  • queue内の最大待機時間
  • stale Evidenceの再取得回数
  • terminal後に残ったassignment数

重要なのは何体のAgentが動いているかではありません。価値のある変更が、どれだけ安全にqueueから排出されたかです。

Remaining Risk

Controllerを置いても、設計を誤れば中央ボトルネックになります。優先順位規則が不適切なら特定Taskが常に後回しになり、Impact Analysisが弱ければ必要な同期を見逃します。Task Claimの粒度が粗すぎれば、独立して進められる仕事まで一つに束ねます。

Controller全体を巨大なLLMへ置き換えるのも危険です。State Transition、Policy、Lease、Evidence Validityなど決定論的に処理できる部分はコードで管理し、LLMは意味的な影響判定や重複性評価へ限定します。

AIエージェントを増やしても完了する仕事が増えるとは限りません。並列化の成否を決めるのはWorker数ではなく、Controllerが未完了作業を安全に終端へ押し出せる能力です。

AI導入について相談する