公開日: 更新日: 状態: 公開中 / Snapshot

AI Agent並列開発:最小導入例

初回導入では、まず別 worktree で差分作成を並列に進め、起動、test、E2E、PR、cleanup は作業ごとに直列で進める。 このページでは、Level 1〜2 を試すための最小コマンドだけを見る。

このページの役割

ここに置くのは、Level 1〜2 をまず試すための最小例だけ。 状態管理や自動 cleanup の本格設計は扱わない。 同時検証や自動 cleanup へ進む時は、実行リソースと cleanup 対象の管理を読む。

このページの前提

このページのコードは、既存プロジェクトに次の入口がある前提で書く。

  • make dev: 開発サーバーを起動する
  • make test: unit test を実行する
  • make e2e: BASE_URL を見て E2E を実行する
  • make db-reset-test: test 用 DB を既知状態へ戻す

これらの名前は例である。 実プロジェクトでは、既存の npm run devpnpm testbin/rails testnpm run e2e などに読み替える。

ファイル例: Makefile

既存コマンドを包むだけでもよい。 このページの shell 例では、次の 4 つの入口を使う。

.PHONY: dev test e2e db-reset-test

dev:
	npm run dev -- --port $${PORT:-3000}

test:
	npm test

e2e:
	port="$${PORT:-3000}"; base_url="$${BASE_URL:-http://127.0.0.1:$${port}}"; BASE_URL="$$base_url" npm run e2e

db-reset-test:
	npm run db:reset:test

Level 2 へ進む時は、実 URL を人間が確認できる形にする。 Level 3 へ進む時は、E2E が固定 URL ではなく検証対象の URL を必ず読むようにする。

Level 1: 別 worktree で差分作成を並列に進める

呼び出し例: worktree を 2 つ作る

このコマンドは、同じ origin/main から 2 つの branch と worktree を作る。 Agent A は issue-101、Agent B は issue-102 の worktree だけを対象にする。 この例では、通常の作業ディレクトリを $HOME/src/myapp、Agent 用 worktree を $HOME/worktrees/myapp/* に置く。 worktree 作成コマンドは、通常の作業ディレクトリ側で実行する。

cd "$HOME/src/myapp"
git fetch origin main
git worktree add "$HOME/worktrees/myapp/issue-101" -b agent/issue-101 origin/main
git worktree add "$HOME/worktrees/myapp/issue-102" -b agent/issue-102 origin/main

branch 名や worktree path が既に使われている場合は、既存の worktree を確認してから、新しい branch 名にするか、削除してよい worktree だけ git worktree remove する。

git worktree list

Agent session は worktree ごとに分ける。 worktree を作った後、Agent A は $HOME/worktrees/myapp/issue-101、Agent B は $HOME/worktrees/myapp/issue-102 を起点に起動する。 session を分けてもファイル分離にはならないため、同時にコードを書くなら worktree を分ける。

ファイル例: scripts/verify-worktree.sh

指定した worktree に移動し、開発サーバーを起動して、unit test と E2E を実行する最小例。 Level 1 では同じ port を使うため、この script は片方ずつ実行する。 PORTBASE_URL は対応させ、既定では PORT=3000 から http://127.0.0.1:3000 を作る。

この script が行うこと:

  1. 対象 worktree へ移動する
  2. 開発サーバーを起動する
  3. BASE_URL が応答するまで待つ
  4. make testmake e2e を実行する
  5. 起動した開発サーバーを止める
#!/usr/bin/env bash
set -euo pipefail

worktree_path="${1:?worktree path is required}"
port="${PORT:-3000}"
base_url="${BASE_URL:-http://127.0.0.1:${port}}"
READY_TIMEOUT_SECONDS="${READY_TIMEOUT_SECONDS:-60}"

cd "$worktree_path"

PORT="$port" make dev &
dev_pid=$!
trap 'kill "$dev_pid" 2>/dev/null || true' EXIT

ready=0
ready_started_at="$(date +%s)"
while [ "$(($(date +%s) - ready_started_at))" -lt "$READY_TIMEOUT_SECONDS" ]; do
  if curl --fail --silent --show-error "$base_url/" >/dev/null; then
    ready=1
    break
  fi
  sleep 2
done

if [ "$ready" != "1" ]; then
  echo "app is not ready: $base_url" >&2
  exit 1
fi

make test
PORT="$port" BASE_URL="$base_url" make e2e

trap - EXIT
kill "$dev_pid" 2>/dev/null || true
wait "$dev_pid" 2>/dev/null || true

呼び出し例: Agent A と Agent B を片方ずつ検証する

# 共有 DB を使い、既知状態が必要な検証では、1件目の前にも DB を戻す。
make db-reset-test
scripts/verify-worktree.sh "$HOME/worktrees/myapp/issue-101"

# 1件目の確認が状態を書き換える場合は、2件目の前にも DB を戻す。
make db-reset-test
scripts/verify-worktree.sh "$HOME/worktrees/myapp/issue-102"

読み取り専用の確認だけなら、状態を戻す作業は不要。 make db-reset-test のような reset コマンドは、DB、cache、queue など確認が触った状態を既知状態へ戻せる場合だけ有効。 既知状態へ戻す手順がない、戻した後も既知状態にならない、または状態が残るか判断できない場合は、DB または schema を分ける。

検証した URL は、対象 branch / worktree から起動したアプリに対応している必要がある。 URL だけを記録しても、どの branch を見たのか説明できなければ検証結果として使わない。

PR には、レビューアに意味のある変更内容と検証結果を残す。 local URL や worktree path は、レビューに必要な場合を除いて PR 本文には書かない。

cleanup を確認する

Level 1 の cleanup は、まず起動した process、container、一時ファイル、検証成果物を片付けることを指す。 worktree の削除は、PR が merge 済み、再確認不要、または未 commit の差分がないことを確認してから行う。 PR レビュー中は worktree を残してよい。

cd "$HOME/worktrees/myapp/issue-101"
git status --short

cd "$HOME/worktrees/myapp/issue-102"
git status --short

削除してよいと判断した後だけ、worktree を削除する。

cd "$HOME/src/myapp"
git worktree remove "$HOME/worktrees/myapp/issue-101"
git worktree remove "$HOME/worktrees/myapp/issue-102"

cleanup の担当と対象は必ず決める。 自動 cleanup コマンドがなくても Level 1 は成立する。

Level 2: 必要な場合だけ別 URL で起動する

2 つの画面を同時に比較する時は、port と URL を分ける。 ここでは、Agent A の worktree を 49321、Agent B の worktree を 49388 で起動する例を示す。

呼び出し例: 別 terminal で 2 つの dev server を起動する

# Terminal A
cd "$HOME/worktrees/myapp/issue-101"
PORT=49321 make dev
# Terminal B
cd "$HOME/worktrees/myapp/issue-102"
PORT=49388 make dev

呼び出し例: 対象 URL を明示して E2E を実行する

cd "$HOME/worktrees/myapp/issue-101"
PORT=49321 BASE_URL=http://127.0.0.1:49321 make e2e

cd "$HOME/worktrees/myapp/issue-102"
PORT=49388 BASE_URL=http://127.0.0.1:49388 make e2e

同時起動する時は、E2E や手動確認で別作業の URL を見ないようにする。 terminal、dashboard、ブラウザのタブ名など、自分の運用で取り違えにくい方法を使う。 DB、cache、queue は、読み取り専用、または同時書き込みがなく相互影響もしない場合だけ共有してよい。 更新を伴う手動確認、seed、migration、更新系 E2E は直列化するか、DB / schema / cache / queue を分ける。

関連ページ

このページは発表資料の補足です。