はじめに
Codex と Claude Code を同じリポジトリで使っていると、片方の AI からもう片方の AI へ作業を渡したくなる場面があります。
最初は handoff を「次にやってほしいこと」のメモとして書いていました。しかし、依頼文だけだと次のようなズレが起きます。
- どのファイルを触ってよいかが曖昧
- commit や push まで進めてよいかが曖昧
- 失敗したときに止まるのか、代替案で進むのかが曖昧
- 完了条件が「いい感じに直す」になり、レビュー観点が残らない
この記事では、AI 同士の handoff を単なる申し送りではなく、作業契約として書くためのチェックリストをまとめます。
詰まったポイント
handoff に「この記事をレビューして」「この機能を実装して」とだけ書くと、受け取った側の AI は不足している条件を推測します。
たとえば記事レビューなら、本文だけ見ればよいのか、関連リンクの実在確認までやるのか、フロントマターを直してよいのかが分かりません。
実装作業なら、対象ファイルの外側までリファクタしてよいのか、テスト追加まで含むのか、失敗時に別アプローチへ切り替えてよいのかが曖昧になります。
AI は曖昧な依頼でも何かしら進めます。そのため、依頼文が薄いほど「やってほしいこと」ではなく「AI が補完したこと」が増えます。
原因
原因は、handoff に必要な情報を 1 種類の文章として扱っていたことでした。
実際には、AI へ作業を渡すときに必要な情報は複数あります。
| 契約 | 書くこと |
|---|---|
| 目的契約 | 何を達成し、何をしないか |
| 範囲契約 | どのファイルや領域を触ってよいか |
| 権限契約 | 編集、commit、push、publish を誰が判断するか |
| 完成契約 | 何を満たしたら完了か |
| 検証契約 | どのコマンドや観点で確認するか |
| 失敗契約 | どこで止まり、何を報告するか |
この 6 つを分けないと、受け取る側の AI は不足部分を会話の文脈から推測します。セッションが変わると、その文脈は失われます。
解決コードではなくテンプレートを渡す
自分の運用では、handoff に次の形を置くようにしました。
目的契約:
- 達成したいこと:
- 今回やらないこと:
範囲契約:
- 触ってよいファイル:
- 触らないファイル:
- 既存の未コミット変更の扱い:
権限契約:
- 編集:
- git add / commit / push:
- 公開やリリース:
完成契約:
- 通常動作:
- 前提条件:
- エラー処理:
- no-regression:
検証契約:
- 実行するコマンド:
- レビュー観点:
- 未確認なら未確認と書く項目:
失敗契約:
- どこで止まるか:
- 何を handoff に戻すか:
ポイントは、すべてを長文で書かないことです。空欄があるなら、そこが未定義だと分かります。
記入例
記事レビューを別 AI に渡す場合は、次のように書けます。
目的契約:
- 対象記事が公開前チェックに耐えるかをレビューする
- 本文の全面リライトはしない
範囲契約:
- 触ってよいファイル: qiita/public/example.md のみ
- 触らないファイル: README.md、候補表、公開ログ
権限契約:
- 編集: 指摘のみ。本文編集はしない
- git add / commit / push: 不可
- publish: 不可
完成契約:
- 重大指摘、軽微指摘、公開可否を分けて返す
- 守秘、文体、リンク、フロントマターを確認する
検証契約:
- 文体NG語を検索する
- 参考リンクが本文の主張と対応しているか見る
失敗契約:
- 事実確認できないリンクがあれば未確認として止める
- 推測で公開可にしない
実装依頼なら、触ってよいファイル と 検証コマンド を具体化します。
範囲契約:
- 触ってよいファイル: src/renderer/hooks/useSchedule.js
- 触らないファイル: src/main/**、package-lock.json
検証契約:
- npm run test
- npm run build
これだけでも、AI が関係ない隣接ファイルへ広がる確率を下げられます。
簡易チェックをスクリプト化する
内容の正しさは人間か別 AI のレビューが必要です。ただし、必要な見出しがあるかだけなら機械的に見られます。
$path = "CLAUDE_CODE_HANDOFF.md"
$text = Get-Content -Raw -Path $path
$required = @(
"目的契約:",
"範囲契約:",
"権限契約:",
"完成契約:",
"検証契約:",
"失敗契約:"
)
foreach ($section in $required) {
if ($text -notmatch [regex]::Escape($section)) {
throw "Missing handoff contract section: $section"
}
}
Write-Host "handoff contract sections found"
throw にしているのは、CI や pre-commit hook に入れたときに止めるためです。手元で確認するだけなら Write-Warning にしても構いません。
注意点
このテンプレートは、AI の判断ミスをゼロにするものではありません。効果があるのは、作業境界と止まる条件を明示することです。
特に次の作業では、失敗契約を省かない方がよいです。
- 外部 API や料金が絡む作業
- DB migration や永続データを触る作業
- publish、push、release など外部へ反映される作業
- 個人情報や守秘情報を含む可能性がある作業
「できなかったら代替案で進める」のか、「止まって報告する」のかを先に書くと、AI が勝手にリスクの高い回避策へ進むことを抑えられます。
まとめ
AI 同士の handoff は、依頼文だけだと受け取る側の推測が増えます。
自分の運用では、handoff を次の 6 つに分けることで、作業境界をかなり明確にできました。
- 目的契約
- 範囲契約
- 権限契約
- 完成契約
- 検証契約
- 失敗契約
複数 AI を使うときに必要なのは、強い自動化よりも、どこまで進めてどこで止まるかを共有できる作業契約でした。