この記事の前提
Claude Code と Codex の 2 つの AI エージェントを分業させて、7 日間で 30 PR をマージし 70 Issue を起票・処理する半自動開発ワークフローを構築しました。
経緯と結果のサマリは、別記事『Claude CodeとCodexで個人アプリ開発を半自動化した話』にまとめています。
この記事では、そのワークフローを支えた個々の設計判断を「再現用リファレンス」として整理します。サイクルの発火順、ラベル設計、コメント追記方式、PR 集約、新規 Issue 起票禁止と特例、プロンプト管理。それぞれが「なぜそうしたか」を、後から自分が見直したときに掘り起こせる形で書き残します。
メイン記事を読んでいない方のために、最小限の前提だけ先に共有します。
Claude Code を機能開発担当、Codex をレビュー担当に分け、半自動的に開発が進むワークフローを組みました。両者は GitHub のラベルだけを共有して直接通信せず、4 時間サイクル × 1 日 6 回(実装バッチのみ 5 回)で発火する構造です。
実装と詳細化・レビューを別エージェントに分けた理由
両エージェントともベースのモデル能力は十分に高く、原理的にはどちらかに全工程を任せることもできます。それでもあえて分けたのは、 自分が書いたコードを自分でレビューしても、まともなレビューにならない という人間のチーム開発でお馴染みの制約が、AI エージェントにも同じように効くと考えたからです。
実装は「決められた仕様を最短距離でコードに落とす」プロセス、詳細化・レビューは「決められたつもりの仕様を疑い、抜け漏れを探す」プロセスで、思考の方向が逆を向いています。
この方針を成立させているのは、エージェント本体ではなく、 両者に対する正反対のプロンプト です。プロンプトは docs/claude-code-scheduled/ と docs/codex-automations/ にコミット済みで、相互に補完するように書き分けてあります。
-
Claude Code 側プロンプト: Codex の最新コメント(後述の
## [Codex 詳細化 ...]マーカー)を信頼して実装する旨を明記し、 「マージ判断は絶対に行わない」「自分の PR を承認しない」 を太字で禁止事項として列挙 -
Codex 側プロンプト: Issue 詳細化バッチでは「Claude Code が実装に着手できる粒度まで、要件・受入条件・依存関係を落とし込む」ことを必須化。PR レビューバッチでは「実装の正しさだけでなく、Issue の意図と乖離していないかを必ず確認する」「CI green を
gh pr checks <pr> --watchで目視確認したうえでマージする」を明記
特に効いたのは、 Claude Code 側のプロンプトに「自分の PR をマージしない」を強い言葉で書いた点 でした。同一の GitHub アカウントで両エージェントを動かしているため、GitHub 側で self-approval を機械的に防ぐ手段がありません(詳細は別記事『Claude Code と Codex の半自動開発で踏んだ 6 つのワナ』をご参照ください)。それでも 7 日間で Claude Code 側がマージに手を出したケースはゼロでした。
利用プランは Claude Code が Max 5 プラン、Codex が Plus プランです。トークン消費量と処理時間を見る限り、両プランとも今回の負荷では十分に余裕があり、Claude Code の実装バッチは一度に 10 件程度まで Issue を捌けそうな感触でした(試行のため 3 件 / PR に固定して運用しています)。
役割を明示的に分けることで、観点が分離されるだけでなく、プロンプトの責務も小さくなって書き分けやすくなる。半自動開発における品質確保の根幹は、モデル性能ではなくこの「2 役分割」に置きました。
6 ラベルを共有メモリとして使う
エージェント同士は直接通信させず、GitHub のラベルだけで状態を同期する構造にしました。
| 種別 | ラベル | 付与 / 剥がしの責任主体 |
|---|---|---|
| Issue | needs-user-review |
Claude Code が起票時付与、私がトリアージで剥がす |
| Issue | needs-codex-refinement |
Claude Code が起票時付与、Codex が詳細化完了時に剥がす |
| Issue | ready-for-cc-implementation |
Codex が詳細化完了時付与、Claude Code がピック時に剥がす |
| Issue | cc-implementing |
Claude Code がピック時付与、マージ時の自動クローズで消滅 |
| PR | needs-codex-review |
Claude Code が PR 作成・修正完了時付与、Codex がレビュー時に剥がす |
| PR | ready-for-cc-revision |
Codex がレビュー NG 時付与、Claude Code が修正完了時に剥がす |
各バッチは「自分が担当するラベルが付いた Issue / PR が存在するか」だけを見て仕事を判断します。ラベルが付いていなければ、何もせずに終了する単純な構造です。
エージェント同士が直接 API を叩き合って状態を伝えるのではなく、GitHub のラベルを介して非同期に状態を読み書きする形です。この構造により、バッチ間の時間的・実装的な依存関係が消え、各バッチが独立して安全に動ける ようになりました。1 つのバッチが落ちても他に影響しない、いわば疎結合な設計です。
4 時間サイクルを 1 時間ずらしてパイプライン化する
サイクルの発火時刻は、4 つのバッチを 1 時間ずつずらしました。
- 00:00 / 04:00 / 08:00 / 12:00 / 16:00 / 20:00: Codex Issue 詳細化バッチ
- 01:00 / 05:00 / 09:00 / 13:00 / 17:00 / 21:00: Codex PR レビューバッチ
- 02:00 / 06:00 / 10:00 / 14:00 / 18:00 / 22:00: Claude Code PR 修正バッチ
- 03:00 / 07:00 / 11:00 / 15:00 / 19:00: Claude Code Issue 実装バッチ
- 23:00: Claude Code E2E スモーク実行バッチ(1 日 1 回)
各バッチの「入力ラベル → 処理 → 出力ラベル」の対応は次の通りです。
| バッチ | 入力 (探すラベル) | 処理 | 出力 (付け替えるラベル) |
|---|---|---|---|
| Codex Issue 詳細化 | Issue: needs-codex-refinement
|
要件・受入条件・依存関係をコメント追記 | Issue: ready-for-cc-implementation
|
| Claude Code Issue 実装 | Issue: ready-for-cc-implementation
|
最大 3 件をピックして 1 PR にまとめて実装 | Issue: cc-implementing / PR: needs-codex-review
|
| Codex PR レビュー | PR: needs-codex-review
|
レビュー結果をコメント追記。OK かつ CI green なら gh pr merge でマージ |
OK 時: PR クローズ + Issue 自動クローズ / NG 時: PR ready-for-cc-revision
|
| Claude Code PR 修正 | PR: ready-for-cc-revision
|
同ブランチに追加コミット | PR: needs-codex-review
|
| Claude Code E2E スモーク実行 | (ラベル参照なし、pnpm e2e 実行) |
スモークテスト実行 + 失敗時に Issue 自動起票 | Issue: needs-codex-refinement (失敗時のみ) |
発火順を 1 時間ずつずらしたのは、詳細化 → レビュー → 修正 → 実装のパイプラインを同一サイクル内で完結させる ためです。たとえば 00:00 の詳細化で ready-for-cc-implementation に切り替わった Issue は、03:00 の実装バッチで拾えます。次のサイクル(04:00)を待つ必要がない構造になっています。
同じ時刻に複数のバッチを並列発火させなかったのは、競合や予期せぬ干渉が起きる可能性を排除したかったからです。Claude Code と Codex は同一ローカルマシン(私の Mac)上で動いているため、並列発火は実行環境の取り合いを生むリスクもありました。
Issue / PR 本文を不変にするコメント追記方式
Codex の詳細化結果やレビュー結果は、Issue / PR の本文には書き込みません。すべてコメントとして追記し、冒頭に以下のマーカー行を必ず置きます。
## [Codex 詳細化 (2026-05-22)]
## [Codex レビュー OK (2026-05-23)]
## [Codex レビュー 要修正 (2026-05-23)]
Claude Code はこのマーカーを検索して、最新の Codex コメントを機械的に取り出し、詳細化結果やレビュー指摘を読み込みます。
本文を不変に保つ理由は 2 つあります。1 つは、最初に書いた要求仕様や Issue 概要が、エージェント側のやり取りで上書きされて消えるのを防ぐため です。
もう 1 つは、エージェント間の対話履歴をコメント時系列として残すため です。後から再読したときに「どの議論を経て実装に至ったか」を追えるようにしておきたいからです。
再詳細化・再レビューが発生した場合も、既存コメントは編集せず、新規コメントとして追記します。古い詳細化結果も時系列として残るため、Claude Code はマーカー行の日付で最新のものを識別する仕組みです。
1 PR = 3 Issue 集約と merge commit の意図
Claude Code の実装バッチは、ready-for-cc-implementation の Issue から最大 3 件をピックして、1 つの PR にまとめて実装します。ピック条件は、仕様詳細化時に Codex がコメントに残す 「依存先(blocked-by / 親 Issue)がすべて Closed であること」 を必須にしました。依存関係が解けていない Issue を先取りすると、別 Issue の実装で前提が崩れて手戻りが発生するためです。
3 件を「別ブランチ・別 PR」ではなく「同じブランチ・同じ PR」にまとめたのは、並列実装で起きるマージコンフリクトを構造的に排除する ためです。別ブランチで進めると、同じファイルを触ったときに衝突解決の追加コストが発生します。同じブランチに 3 件分のコミットを積めば、PR 間衝突はそもそも生まれません。
マージ方式は merge commit 固定で、squash / rebase は無効化しています。これは、PR 単位の OK / NG 判定と、Issue 単位のコミット履歴の保持を両立させる ための判断です。
squash すると 1 Issue = 1 コミットの粒度が失われ、後から git log で Issue 由来の変更を追えなくなります。コミットメッセージは [#<issue>] <summary> 形式で統一しているため、merge commit にしておけば Issue ごとの履歴がそのまま履歴ツリーに残ります。
新規 Issue 起票を原則禁止し、特例を 2 つに限定する
エージェント側からの新規 Issue 起票は、原則として禁止しました。実装中に発見した課題や追加要件は、すべて当該 PR の description または PR コメントに残し、Issue 化の要否は私が手動で判断します。
理由は単純で、自動エージェントが新規 Issue を無条件に起票し続けると、完了判定(Issue / PR の残件 0 件)が破綻し、ループが収束しなくなる ためです。
ただし、ここに 2 つの特例を設けました。
特例 1: E2E スモーク実行バッチによる自動起票
1 つ目は、E2E スモーク実行バッチ(23:00 JST / 1 日 1 回)による E2E 失敗 Issue の自動起票です。日々の自動デグレ検知と修正のサイクルを成立させるための仕組みで、テンプレ e2e-failure.yml 経由でのみ起票を許可しています。
濫用を避けるため、同症状の既存 open Issue があれば新規起票はせず、既存 Issue にコメント追記で再現報を残す制約も併せて課しました。
特例 2: ユーザーヒアリング駆動の起票(手動トリガー)
2 つ目は、ユーザーヒアリング駆動の Issue 起票です。私が手動で触ったアプリの操作感を Codex がヒアリングシートに記録します。Claude Code は私の明示指示で、そのシートからインサイトを抽出して起票します。
起票時のラベルは needs-user-review のみで、Codex 詳細化ループには勝手に流れません。私のトリアージを必ず挟む構造としました。
プロンプトは git で版管理する
Claude Code Scheduled Task と Codex Automations のプロンプトは、docs/claude-code-scheduled/ と docs/codex-automations/ に Markdown として保管し、リポジトリにコミットしています。バッチの挙動を変えたいときは、プロンプトを書き換えて git に乗せ、次回のスケジュール起動時に新しいプロンプトが読み込まれます。
これは、プロンプト自体をワークフローの構成要素として版管理する ための判断です。試行錯誤の履歴は git log で追え、設計変更の意思決定もコミットメッセージとして残ります。
プロンプトを管理画面の UI に直接書き込む運用と比べて、書き換えのレビュー、履歴の透明性、ロールバックのしやすさが大きく違います。半自動開発のワークフロー自体が一種のシステムであり、その挙動を決めるプロンプトはコードと同等に管理されるべきだ、というのが運用を通じて確かめられた感覚でした。
ループの収束は完了判定で担保する
オープンな Issue と PR がともに 0 件になった時点で、本プロジェクトを完了とみなします。
無限ループや滞留の自動検知ガードレールは設けず、私の毎日の目視確認で対応する運用としました。これは、ガードレールを増やすほど運用ルールが複雑化し、別の破綻リスクが立ち上がる という判断によるものです。
1 日 6 サイクル × 4 バッチ + E2E バッチ + ヒアリング駆動という構成は、ラベル 6 種とマーカー行と特例 2 つで十分に閉じていました。設計が閉じていれば、人間が見るべきは「想定外の挙動が起きていないか」だけで済みます。
半自動開発を実用域に押し上げるための最後のピースは、人間の介入ポイントを仕様策定・例外対応・ユーザーヒアリング / トリアージの 3 つに絞り切ること でした。これは、メイン記事で書いた「7 日間の運用から見えたこと」と同じ結論に、設計の側から到達した形でもあります。
ここまでに書いた設計は、最初からこの形に落ち着いていたわけではありません。GitHub Free プランの制約、gh CLI への統一、worktree モードのブランチ命名 など、設計時には見えていなかった壁を何度も踏みながら現在の形になりました。
それらの経緯は別記事『Claude Code と Codex の半自動開発で踏んだ 6 つのワナ』で書いています。仕組みを再現したい方は、こちらと併せて参照してください。