Background Agentを試してみたものの、「なんとなく使ってはいるが、本当に効果的に使えている気がしない」という感覚はありませんか?
私自身、最初の1〜2週間はそうでした。起動して待つ、途中で確認する、思った通りの結果にならない……そのサイクルを繰り返していて、「これ、本当に使えるのか?」と正直疑っていました。
転機になったのは、Background Agentがなぜ普通のエージェントと根本的に違うのかをアーキテクチャレベルで理解したときです。その後、タスク設計を見直し、AGENTS.mdを整備し、git worktreeと組み合わせるようになってから、開発の進み方が大きく変わりました。
個人開発でレビュアーが自分しかいない環境だと、この「近いけれど違う」結果をどう扱うかが、そのまま生産性になります。
ここではBackground Agentを「なんとなく使うツール」から「本番開発に組み込んだ協働者」に変えるために必要だったことを書き出しました。あわせて、以前の版で私が事実を確認しないまま載せていた箇所を、一次情報にあたって全面的に直しています。
Background Agentが「単なる非同期処理」と根本的に違う理由
Antigravityのインラインエージェントとの最大の違いは、Background Agentが完全に隔離されたLinux仮想マシン上で動作する点です。これは「非同期で動く」という話ではなく、アーキテクチャが根本から異なります。
サンドボックスVMの内部構造
Background Agentが起動すると、Antigravityはあなたのリポジトリのスナップショットを取り、独立したVM環境を立ち上げます。このVMは:
- あなたのローカル環境には直接アクセスしない
- ネットワークはインターネットに出られるが、ローカルのlocalhost:3000などは参照できない
- ファイルシステムへの書き込みはVM内で完結し、完了時にプルリクエスト(またはコミット)として返ってくる
- VSCodeのデバッガやdevtoolsは使用不可(CLIツールのみ)
この隔離性がBackground Agentの強さであり、同時に制約でもあります。「ブラウザで確認しながら修正してほしい」「ローカルDBに接続して動作確認してほしい」といった用途には向いていません。一方で、「コードを解析して改善する」「テストを生成する」「ドキュメントを更新する」といったタスクでは、邪魔されずに長時間集中して作業できます。
通常エージェントとの使い分け判断基準
どちらのエージェントを使うべきか、私は次の基準で判断しています:
Background Agentに適しているタスク:
- 完了まで5分以上かかりそうなもの
- 結果を確認するまで自分の判断が不要なもの
- ローカル環境の状態(実行中サーバー、DB接続など)に依存しないもの
- 明確な「完了条件」を事前に言語化できるもの
通常エージェントが適しているタスク:
- 「こんな感じで」という対話が必要なもの
- UIの見た目を確認しながら進めたいもの
- 10分以内に終わりそうなシンプルなもの
- 設計判断が途中で必要になりそうなもの
特に「完了条件を言語化できるか」は重要です。これが曖昧だと、Background Agentはそれなりに仕事をしてくれますが、期待通りの結果にならないことが多くなります。
成果を最大化するタスク仕様書の設計
Background Agentへの指示は、インタラクティブなチャットとは根本的に違います。対話による補正ができないため、最初の指示の質がそのまま結果の質に直結します。
タスク仕様書の構造
私が実際に使っているテンプレートを共有します。このフォーマットを使うようになってから、Background Agentの成功率が体感で7割から9割以上に上がりました:
## 目標
UserProfile コンポーネントのテストカバレッジを80%以上に引き上げてください。
現在のカバレッジ: 約35%(`npx vitest coverage` で確認済み)
## 対象ファイル
- src/components/UserProfile.tsx(主要対象)
- src/components/UserProfile.test.tsx(新規または追記)
- src/types/user.ts(参照のみ)
## 使用するテストフレームワーク
- vitest + @testing-library/react
- モックは vi.mock() を使用
- ユーザーイベントは @testing-library/user-event
## 完了条件(全て満たすこと)
1. `npx vitest coverage` でカバレッジ80%以上
2. 既存のテストが全てパス(変更禁止)
3. TypeScript のビルドエラーがゼロ
4. 各テストケースに日本語のdescribeとitコメント付き
## 禁止事項
- UserProfile.tsx の既存の props インターフェースを変更しない
- 外部APIのモックに実際のエンドポイントURLを使わない
- スナップショットテストは作成しない(メンテコストが高いため)
## 参考情報
- 既存のAuthコンポーネントのテスト(src/components/Auth.test.tsx)が参考になります
- テスト実行: `npx vitest run --reporter=verbose`このテンプレートで重要なのは「禁止事項」セクションです。Background Agentは指示されたことをやろうとするあまり、既存コードを予期しない形で変更することがあります。変えてほしくないものを明示することで、大幅に品質が安定します。
タスクの粒度設計
「大きすぎるタスク」はBackground Agentが得意ではありません。具体的には:
# ❌ 大きすぎるタスク(失敗リスク高)
"プロジェクト全体をリファクタリングして、型安全性を向上させてください"
# ✅ 適切な粒度(1つのセッションで完結)
"src/api/ ディレクトリ内のすべてのAPIクライアント関数に、
zod スキーマを使った入出力バリデーションを追加してください"私の経験では、Background Agentが最も安定して動くのは「1〜3時間の人間の作業に相当するタスク」です。半日以上かかるようなタスクは、サブタスクに分割して順番に実行する方が、最終的に速く・品質高く完了できます。
事前のコンテキスト投入
Background Agentを起動する前に、関連するファイルやドキュメントを「Knowledge Items」として追加しておくと、精度が大きく向上します。特に以下は必ず追加しています:
- プロジェクトのアーキテクチャ設計ドキュメント
- コーディング規約(CONTRIBUTING.md など)
- 関連する型定義ファイル(types/ ディレクトリ)
- エラーが起きやすい部分のコメント
AGENTS.md でプロジェクトコンテキストを自動注入する
Background Agentに毎回同じコンテキストを指示するのは非効率です。AGENTS.md を適切に設計すると、そのファイルに書いたことが全てのエージェントセッションに自動で注入されます。
プロジェクト専用 AGENTS.md の設計
# プロジェクト: MyApp — エージェント向け作業指針
## このプロジェクトについて
Next.js 16 App Router + TypeScript + Cloudflare Workers で構築された
個人向けタスク管理SaaSです。日英2言語対応(next-intl v4)。
## 技術的な制約(必読)
- Node.js は使用不可(Cloudflare Workers 環境)
- `fs` モジュールは使用不可 — ファイルI/Oはすべて ASSETS バインディング経由
- npm run build の前に `node scripts/generate-content.mjs` が必要(prebuildに設定済み)
- テストランナー: vitest(jest ではない)
## コーディング規約
- 型定義は `src/types/` に集中管理
- コンポーネントは Server/Client を明示('use client' ディレクティブ)
- APIルートは `src/app/api/` 配下、命名は `route.ts`
- 日本語コメントを推奨(英語も可)
## よくある間違いと回避方法
### ❌ よくやってしまうこと
- `headers()` を同期で呼ぶ → async/await 必須
- `cookies().set()` をクライアントコンポーネントで使う → サーバーコンポーネントのみ
### ✅ 正しいパターン
- 環境変数: `process.env.NEXT_PUBLIC_*` (クライアント) / `process.env.*` (サーバー)
- DBアクセス: `getCloudflareContext().env.DB` を使用
## テスト実行コマンド
\`\`\`bash
npx vitest run # 全テスト実行
npx vitest coverage # カバレッジ計測
npx tsc --noEmit # 型チェック
\`\`\`
## 変更してはいけないファイル
- src/config/pricing.ts(Stripe price ID が格納されている)
- public/robots.txt(SEO設定)
- wrangler.toml(Cloudflare設定)この AGENTS.md があるだけで、Background Agentへの指示から「このプロジェクトでは fs は使えません」「テストはvitestです」といった説明が不要になります。プロジェクト固有の制約が多いほど、AGENTS.md の効果は大きくなります。
ディレクトリ別 AGENTS.md の活用
プロジェクトルートだけでなく、特定のディレクトリにも AGENTS.md を置けます。私は以下のような構成にしています:
project/
├── AGENTS.md ← プロジェクト全体の共通ルール
├── src/
│ ├── components/
│ │ └── AGENTS.md ← UIコンポーネントの設計ルール
│ └── api/
│ └── AGENTS.md ← APIルートの実装規約
└── scripts/
└── AGENTS.md ← スクリプト変更時の注意点
複数Background Agentの並列実行戦略
単一のBackground Agentでも十分強力ですが、複数を並列で走らせることで開発速度をさらに上げられます。ただし、無計画に並列実行すると git の競合地獄に陥ります。
並列化できるタスクの特定
並列実行が安全なのは、変更するファイルが重複しないタスクの組み合わせです:
# ✅ 安全な並列実行の例
エージェントA: src/components/ 配下のテスト追加
エージェントB: src/api/ 配下のバリデーション強化
エージェントC: docs/ 配下のAPI仕様書更新
# ❌ 危険な並列実行(同じファイルを変更する可能性)
エージェントA: src/types/user.ts の型を改善
エージェントB: UserProfile コンポーネントをリファクタリング
(→ 両者が user.ts を変更する可能性)
git worktree との統合
複数のBackground Agentを安全に並列実行するために、git worktree を使います。各エージェントに独立したworktreeを割り当てることで、ブランチ競合を根本から防げます。
# worktreeの事前準備スクリプト
#!/bin/bash
PROJECT_DIR="$HOME/myapp"
WORKTREES_DIR="$HOME/myapp-worktrees"
# 3つの並列タスク用worktreeを作成
for task in "test-coverage" "api-validation" "docs-update"; do
branch="agent/$task-$(date +%Y%m%d)"
worktree_path="$WORKTREES_DIR/$task"
# worktreeを作成(新規ブランチ)
git -C "$PROJECT_DIR" worktree add \
-b "$branch" \
"$worktree_path" \
main
echo "✅ Created worktree: $worktree_path (branch: $branch)"
done
# 確認
git -C "$PROJECT_DIR" worktree listBackground Agentを起動する際は、各worktreeのパスを指定します。エージェントAは myapp-worktrees/test-coverage 上で作業し、エージェントBは myapp-worktrees/api-validation 上で作業するため、完全に独立して動作します。
全エージェントが完了したら:
# 各worktreeのブランチをmainにマージ
for task in "test-coverage" "api-validation" "docs-update"; do
branch=$(git -C "$WORKTREES_DIR/$task" rev-parse --abbrev-ref HEAD)
echo "Merging $branch..."
git -C "$PROJECT_DIR" merge --no-ff "$branch" \
-m "Merge: agent/$task auto-generated changes"
# 完了したworktreeを削除
git -C "$PROJECT_DIR" worktree remove "$WORKTREES_DIR/$task"
git -C "$PROJECT_DIR" branch -d "$branch"
doneこのマージループは3体目で壊れます
上のループ、素直に見えますが実運用では詰まります。私は3体並列にした日に踏みました。
git merge はコンフリクトすると exit 1 を返してリポジトリを MERGE_HEAD が残った状態にします。しかしループは止まりません。次の周回で git merge を呼ぶと、今度は「前のマージが終わっていない」と言われて失敗します。3体目に至っては何が起きたのか画面から読み取れません。最初のコンフリクトのメッセージは、後続2件のエラーに押し流されて消えています。
git worktree remove も同じ性質です。エージェントが未コミットの変更を残していると削除を拒否しますが、その戻り値を誰も見ていないので、worktree は残ったまま branch -d に進みます。そちらは未マージ扱いで拒否されます。結果として、失敗の痕跡だけが静かに積み上がります。
止まるべきところで止めるように書き直したものが、こちらです。
#!/bin/bash
set -u
FAILED=()
for task in "test-coverage" "api-validation" "docs-update"; do
worktree_path="$WORKTREES_DIR/$task"
if [ ! -d "$worktree_path" ]; then
echo "スキップ: $worktree_path がありません"
continue
fi
# エージェントの取りこぼしを先に検出する
if [ -n "$(git -C "$worktree_path" status --porcelain)" ]; then
echo "未コミットの変更が残っています: $task"
FAILED+=("$task (uncommitted)")
continue
fi
branch=$(git -C "$worktree_path" rev-parse --abbrev-ref HEAD)
echo "Merging $branch ..."
if ! git -C "$PROJECT_DIR" merge --no-ff "$branch" \
-m "Merge: agent/$task auto-generated changes"; then
# 中途半端な状態を次の周回に持ち越さない
git -C "$PROJECT_DIR" merge --abort 2>/dev/null
echo "コンフリクトのため保留: $branch"
FAILED+=("$task (conflict)")
continue
fi
git -C "$PROJECT_DIR" worktree remove "$worktree_path"
git -C "$PROJECT_DIR" branch -d "$branch"
done
if [ ${#FAILED[@]} -gt 0 ]; then
echo "--- 手当てが必要なタスク ---"
printf ' %s\n' "${FAILED[@]}"
exit 1
fi要点は3つです。マージ前に status --porcelain で作業ツリーの汚れを見ること。失敗したら merge --abort で必ず巻き戻してから次へ進むこと。そして、保留になったタスクを配列に貯めて最後にまとめて出すこと。
3つ目が地味に効きます。並列実行の失敗は「どれが失敗したか」が分からなくなることそのものが損害で、ログの末尾に2行あるだけで、朝の確認にかかる時間がまるで違いました。
なお set -e は入れていません。ここでは失敗しても残りのマージを進めたいので、素直に書くと set -e が邪魔をします。止めたい場所を自分で書くほうが、この手のループでは読みやすいと感じています。
worktree より一段踏み込んで、ポート帯や DB スキーマまで含めて1エージェント1環境に切り分ける設計は、並列エージェントに実行環境をリースするにまとめています。
監視・エラーハンドリング・リカバリ
Background Agentは「放置して完了を待つ」のが基本ですが、完全に目を離すのも禁物です。特に長時間のタスクでは、適切な監視が最終品質を左右します。
チェックポイントの活用
Antigravityは実行中のエージェントの進捗を定期的にチェックポイントとして保存します。タスクが途中で失敗した場合も、チェックポイントから再開できます。
進捗確認のタイミングとして、私が推奨するのは:
- タスク開始直後(5〜10分後):指示が正しく理解されているか確認
- 中間点(タスクの折り返し付近):方向性が正しいか確認
- 完了後:全ての完了条件を満たしているか確認
よくある失敗パターンと対処
パターン1: コンテキスト不足による迷走
症状:エージェントが同じ場所を行ったり来たりして、進展しません。
原因:プロジェクトの構造や制約が十分に伝わっていません。
対処:AGENTS.md を更新し、特に「変更してはいけない箇所」と「推奨する実装パターン」を追記します。該当タスクを小さく分割して再実行します。
パターン2: テストが壊れる変更
症状:コードは改善されたが、既存のテストが失敗しています。
原因:「完了条件に既存テストのパス」が明示されていなかった。
対処:タスク仕様書に必ず 既存テストが全てパスすること を完了条件として記載します。Background Agentに「まず npm test を実行して現状を確認してから作業開始」と明示します。
パターン3: TypeScript エラーの放置
症状:実装は動作するが、TypeScript の型エラーが残っています。
原因:型チェックの実行が完了条件に含まれていなかった。
対処:完了条件に npx tsc --noEmit でエラーゼロ を必ず含める。
パターン4: 意図しないファイルの変更
症状:指示していないファイルも変更されていた。
原因:エージェントが関連ファイルの改善を「善意で」行った。
対処:AGENTS.md の「変更してはいけないファイル」リストを充実させる。タスク仕様書の「禁止事項」に明示的に記載します。
CI/CD から Background Agent を呼ぶときの入口を間違えていました
ここは、この記事で私がもっとも大きく書き直した箇所です。
以前の版では、GitHub Actions から https://api.antigravity.google/v1/agents/background に POST するサンプルを載せていました。ホスト名の時点で存在しません。コピーして走らせた方の手元では、名前解決で止まっていたはずです。申し訳ありませんでした。
一次情報にあたり直したところ、Background Agent をパイプラインから起動する経路は Gemini API の Interactions API でした。ここからは、そちらの仕様に沿って書き直します。
起動と待機の最小構成
エージェント識別子は antigravity-preview-05-2026、非同期実行は body の background フラグで指定します。バックグラウンド実行のサンプルにだけ Api-Revision ヘッダが付いている点に注意してください。
# 1. バックグラウンドで起動する
RESPONSE=$(curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Api-Revision: 2026-05-20" \
-d '{
"agent": "antigravity-preview-05-2026",
"input": "Run a complex analysis on the repository.",
"environment": "remote",
"background": true
}')
INTERACTION_ID=$(echo "$RESPONSE" | jq -r '.id')
# 2. status が completed / failed になるまでポーリングする
curl -s -X GET "https://generativelanguage.googleapis.com/v1beta/interactions/$INTERACTION_ID" \
-H "x-goog-api-key: $GEMINI_API_KEY"途中で打ち切りたくなったら POST .../v1beta/interactions/INTERACTION_ID:cancel です。ジョブがタイムアウトしたまま走り続ける事故は、これを入れておくだけで防げます。
「構造化フィールドがある」と思い込んでいた部分
以前の版の実害は、URL が違ったことよりも、リクエスト body の形を想像で書いていたことのほうが大きかったと思っています。branch や constraints といったキーを、さもあるかのように並べていました。
実際にドキュメントで確認できた対応は次の通りです。
| やりたいこと | 指定方法 |
|---|---|
| エージェントの選択 | body の agent(antigravity-preview-05-2026) |
| 非同期で走らせる | body の background: true(store は既定で有効) |
| 実行環境 | body の environment("remote" か EnvironmentConfig) |
| 対象リポジトリ・ブランチ | 専用フィールドは無い。input の文章で伝えるか、environment の sources / ネットワーク許可で渡す |
| PR を作らせる | 専用フィールドは無い。input に手順として書き、api.github.com をネットワーク許可に入れる |
| 使用トークンの上限 | agent_config.max_total_tokens(超過時は status: "incomplete") |
つまり、CI から渡したい文脈は基本的に自然言語の input に載ります。YAML 側で凝ったパラメータを組み立てるより、プロンプトを組み立てるほうが正しい設計でした。
書き直した GitHub Actions ワークフロー
カバレッジの低いファイルを拾って、テスト追加を依頼する例です。変わったのはリクエストの作り方だけですが、動くかどうかという点では別物になりました。
# .github/workflows/auto-test-generation.yml
name: Auto Test Generation
on:
pull_request:
types: [opened]
paths:
- 'src/components/**'
- 'src/api/**'
jobs:
generate-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Check coverage
id: coverage
run: |
npx vitest run --coverage --reporter=json 2>/dev/null || true
LOW=$(node -e "
const r = require('./coverage/coverage-summary.json');
const files = Object.entries(r)
.filter(([f, d]) => f !== 'total' && d.lines.pct < 70)
.map(([f]) => f)
.slice(0, 5);
console.log(files.join(','));
")
echo "files=$LOW" >> "$GITHUB_OUTPUT"
- name: Ask the agent to add tests
if: steps.coverage.outputs.files != ''
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
# 依頼内容は全て input の文章に載せる(branch / constraints というキーは存在しない)
PROMPT=$(cat <<PROMPT_END
Clone ${{ github.server_url }}/${{ github.repository }} and check out ${{ github.head_ref }}.
Raise line coverage above 80% for these files: ${{ steps.coverage.outputs.files }}.
Use vitest. Do not modify existing tests. Keep \`npx tsc --noEmit\` clean.
Open a pull request with the result.
PROMPT_END
)
RESPONSE=$(jq -n \
--arg agent "antigravity-preview-05-2026" \
--arg input "$PROMPT" \
'{agent: $agent, input: $input, environment: "remote", background: true}' \
| curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Api-Revision: 2026-05-20" \
-d @-)
ID=$(echo "$RESPONSE" | jq -r '.id // empty')
if [ -z "$ID" ]; then
echo "起動に失敗しました: $RESPONSE"
exit 1
fi
echo "interaction=$ID" >> "$GITHUB_OUTPUT"jq -n でボディを組み立てているのは、見た目の好みではありません。以前の版のように -d "{ \"task\": \"...$FILES\" }" と文字列連結でJSONを作ると、ファイル名にダブルクォートや改行が混ざった瞬間にボディが壊れます。壊れたJSONは 400 で返ってきますが、CI のログでは「エージェントが動かなかった」ようにしか見えません。原因にたどり着くまでに、私は半日ほど溶かしました。
ID が空のときに exit 1 しているのも同じ理由です。起動に失敗しても後続ステップが緑のまま進むと、「依頼したつもりのタスク」が静かに消えます。
起動しっぱなしにしない
CI から投げる場合、結果を待たずにジョブを終えるのが基本です。ただし、投げっぱなしは投げっぱなしで困ります。私は interaction ID を PR コメントに残すようにしました。
gh pr comment "${{ github.event.pull_request.number }}" \
--body "テスト追加を依頼しました。interaction: \`$ID\`(status は interactions API で確認できます)"一行ですが、これがあるかないかで「誰が何を依頼したのか分からないPR」が生まれる頻度が変わります。
依頼文そのものが長くなってきたら、AgentKit 2.0 でコンテキスト圧縮サブエージェントを設計するで扱っている履歴の畳み方が効いてきます。
コストは「クレジット」ではなくトークンで考える
以前の版で、私はここを「クレジット消費」という言葉で書いていました。感覚としては合っていたのですが、課金の実体はトークンです。言葉がずれていると見積もりもずれます。
Antigravity エージェントは Interactions API 経由の従量課金で、料金は裏側の Gemini モデルのトークンと、エージェントが使ったツールに対して発生します。通常のチャットが1回の入出力で終わるのに対し、1リクエストが推論・ツール実行・コード実行・ファイル操作の自律ループを丸ごと回す、という点が金額の質を変えています。
依頼の種類ごとの目安
ドキュメントに掲載されている見積もりです。自分の肌感より、はじめの基準としてはこちらのほうが役に立ちました。
| 依頼の種類 | 入力トークン | 出力トークン | 目安コスト |
|---|---|---|---|
| 調査・情報の統合 | 100k〜500k | 10k〜40k | $0.30〜$1.00 |
| 文書・コンテンツ生成 | 100k〜500k | 15k〜50k | $0.30〜$1.30 |
| プロセス・システム設計 | 100k〜400k | 10k〜30k | $0.25〜$0.80 |
| データ処理・分析 | 300k〜3M | 30k〜150k | $0.70〜$3.25 |
入力トークンの 50〜70% は通常キャッシュが効きます。一方で、ツール呼び出しが多い複雑なワークフローは1回のインタラクションで 300〜500万トークンに達することがあり、そのときは $5 前後まで伸びます。
サンドボックスの CPU・メモリ・実行環境の費用は、プレビュー期間中は請求されません。ここは期間限定の条件なので、恒久的な前提として設計に組み込まないほうが安全です。
上限は願望ではなくパラメータで置く
以前の版には「レート制限は時間帯によって変わる場合があるので、深夜から早朝に走らせると安定する」と書いていました。これは私の印象で、裏付けがありません。取り下げます。
代わりに、明文化されている手段があります。agent_config に max_total_tokens を渡すと、入力・出力・思考を合わせたトークン量に上限を置けます。キャッシュされたトークンは上限に数えません。
{
"agent": "antigravity-preview-05-2026",
"input": "Refactor src/utils/ for type safety.",
"environment": "remote",
"background": true,
"agent_config": {
"type": "antigravity",
"max_total_tokens": 1500000
}
}上限に達したインタラクションは停止し、status は completed でも failed でもなく "incomplete" で返ります。ここを見落とすと厄介です。ポーリング側で completed と failed の2値だけを見ていると、incomplete が判定から漏れて、CI が待ち続けます。
case "$STATUS" in
completed) echo "done" ;;
failed) echo "失敗"; exit 1 ;;
incomplete) echo "トークン上限で打ち切られました。分割して再依頼します"; exit 1 ;;
*) sleep 15 ;; # in_progress / requires_action
esacこの上限は best-effort です。厳密な会計上のキャップとしては扱えません。私は「暴走を止める安全弁」くらいの位置づけで入れています。
曖昧な依頼が高くつく理由
同じ目的でも、仕様書が明確なときと曖昧なときでは消費が体感で2〜3倍変わります。厳密に計測したものではないので数字は参考程度に受け取っていただきたいのですが、理由ははっきりしています。再試行の回数です。
完了条件が言語化されていないと、エージェントは「たぶんこれで良いはず」の状態から抜け出せず、確認と修正を往復します。その往復が全部トークンになります。AGENTS.md に「よくあるエラーと解決策」を書き足すのが費用対効果の高い投資だと感じているのは、この往復を先に潰せるからです。
10分以内に終わる小さな依頼なら、通常のインラインエージェントのほうが結局は軽く済みます。Background Agent は「長い・放置できる・完了条件が書ける」タスクに寄せる。この線引きが、いちばん効きました。
複数のエージェントを同時に走らせるときの予算の置き方は、並行エージェントのトークンコストを予算で抑えるで別途扱っています。
本番開発でのユースケース実例
理論だけでなく、私が実際にBackground Agentを本番開発で使っているユースケースをそのまま共有します。
ユースケース1: 夜間の技術的負債解消
就寝前にBackground Agentを起動し、翌朝起きると技術的負債が解消されているというワークフローです:
## タスク:src/utils/ の型安全性改善
### 目標
`src/utils/` 配下の全ファイルで以下を達成してください:
- `any` 型の使用をゼロにする
- 明示的な型注釈を全関数に追加
- JSDocコメントを全エクスポート関数に追加
### 完了条件
1. `npx tsc --noEmit` でエラーゼロ
2. `any` 型が `grep -r "any" src/utils/` でゼロ件
3. 既存テストが全てパス
4. 各関数に@param/@returns のJSDocあり
### 対象外
- src/utils/legacy/ 配下(別途対応予定)
- テスト用のモックファイルユースケース2: 新機能のサンドボックス実装
設計段階の新機能を「とりあえずBackground Agentに実装させてみる」という使い方です。完璧なコードを期待するのではなく、実装の叩き台を高速に得ることが目的です:
## タスク:通知設定ページの初期実装
### 目標
/settings/notifications ページの基本実装を作成してください。
デザインはMockup.pngを参考に(添付)。
### 実装範囲
- NotificationSettings コンポーネント
- 設定の保存/読み込み(Zustandストア)
- 4種類の通知タイプのトグルUI
### あえて実装しなくて良いもの
- 実際の通知送信ロジック(バックエンド未実装)
- アニメーション
- モバイル対応(後工程で対応)
### 完了条件
1. ページが表示される(エラーなし)
2. TypeScriptエラーゼロ
3. 各トグルのON/OFFがストアに反映されるこの叩き台をレビューして改善点を指示する、という流れで進めると、ゼロから実装するよりも大幅に速く完成品に近づけます。
振り返りに代えて:Background Agent との協働で効いたこと
Background Agentを使いこなすのは、優秀なエンジニアに仕事を依頼するのと似ています。「何を、どこまで、なぜそうするのか」を明確に伝えれば、期待以上の結果を返してくれます。曖昧な依頼には曖昧な結果が返ってくる、というのも同じです。
まず今日試してほしいのは、自分の開発の中で「完了条件を明確に言語化できるタスク」を1つ見つけて、この記事のテンプレートに当てはめてみることです。最初から大きなタスクを委任しようとしなくて大丈夫です。小さな成功体験を積み上げながら、徐々に委任の範囲を広げていくのが、Background Agentとの協働をうまく機能させる一番の近道です。