codex ci や codex exec を CI / scheduled job に入れたいとき、最初に迷うのは「どのコマンドで呼ぶか」ではありません。問題は、人間がその場で承認できない実行環境で、Codex に何を許すかです。
ローカルの対話セッションなら、危ないコマンドやネットワークアクセスで一度止められます。CIではそうはいきません。承認待ちで詰まる、広い権限で勝手に直す、失敗理由がログに残らない、生成コメントをそのままmerge gateにしてしまう。こうした事故は、Codexの性能ではなく実行契約の設計不足から起きます。
この記事では、OpenAI公式docsの codex exec、sandbox / approvals、GitHub Actionを前提に、Codex CI / non-interactive 実行を安全に走らせる設計だけを扱います。approval_policy = "never" の CI lane と approvals_reviewer = "auto_review" の対話 lane は役割が違うため、approval reviewer の判断境界は Codex auto review ガイド、Codexの権限設計全体は Codex sandbox / approvals 設計ガイド、GitHub PR上のレビュー運用は Codex code review 実践ガイド、セキュリティscan laneは Codex Security plugin 実践ガイド、cloud environmentの再現性は Codex cloud environment 設計ガイド に分けています。
今回は、PRレビューそのものでも、Security pluginでも、internet accessでもありません。CIやscheduled jobから codex exec を呼び、結果を機械的に扱うときの運用境界です。
先に結論: CIでは「直すCodex」と「判定するCodex」を分ける
私なら、CodexをCIに入れるときは最初から2つのlaneに分けます。
| lane | Codexに許すこと | 推奨設定 |
|---|---|---|
| Judge | 差分を読み、JSONで判定だけ返す | read-only + approval_policy = "never" |
| Fixer | 限定ファイルを修正し、patchを作る | workspace-write + 明示されたbranch |
| Reporter | release noteや変更要約を作る | read-only + output schema |
最初から「CIが落ちたらCodexが直してpushする」にしない方がよいです。まずはJudge laneで、Codexがレビュー対象、根拠、リスク、失敗条件を安定して返せるかを見ます。Fixer laneは、対象ファイル、失敗ログ、許可する修正範囲、再実行コマンドが十分に狭い場合だけにします。
OpenAIのdocsでは、非対話実行には codex exec を使い、scriptsやCI jobsからTUIなしでCodexを走らせられると説明されています。つまりCIで必要なのは、対話の代替ではなく、最初から承認、sandbox、出力形式を決めた実行単位です。
codex exec \
--sandbox read-only \
-c approval_policy=never \
"Review this diff for release risk. Return JSON only."
この形なら、CodexはCIの中で「考える reviewer」として動きます。まだ「自動修正する agent」ではありません。
approval_policy = "never" は強い権限ではなく、止まらない約束
CIでよくある誤解は、approval_policy = "never" を「何でもやってよいモード」と考えることです。実際には逆です。
never は、承認プロンプトを出さずに進める設定です。だからこそ、sandbox側を狭くする必要があります。read-only と組み合わせれば、Codexは読める範囲で判断し、境界を越える操作はできません。workspace-write と組み合わせる場合も、どのcheckoutで、どのbranchで、どのファイルまで書いてよいかを別途決めるべきです。
私なら初期設定はこうします。
# ~/.codex/ci-readonly.config.toml
approval_policy = "never"
sandbox_mode = "read-only"
allow_login_shell = false
呼び出し側ではprofileを固定します。
codex exec --profile ci-readonly "Summarize risks in the current PR diff."
この設定で足りないなら、いきなりfull accessへ上げるのではなく、なぜ足りないかをCI jobの責務に戻して考えます。
| 足りないこと | 先に疑うべき設計 |
|---|---|
| dependency installが必要 | setup jobで済ませられないか |
| test実行が必要 | sandbox内で読めるfixtureだけで足りないか |
| file writeが必要 | Fixer laneへ分けるべきではないか |
| external APIが必要 | CIに置くべき仕事か |
非対話CIは、承認を省略する場所ではありません。承認がない前提で、最初から狭い仕事にする場所です。
CI promptは「何を見るか」と「何を返すか」を固定する
CodexをCIで使うなら、promptを自由文のままにしない方が安定します。毎回「レビューして」だけだと、コメント量、重要度、失敗条件が揺れます。
私なら、CI用promptには最低限これを入れます。
You are a CI reviewer.
Scope:
- Review only files changed in this PR.
- Do not suggest unrelated refactors.
- Treat missing tests for touched behavior as a risk.
Return:
- verdict: pass | fail | needs_human
- blockers: array of concise findings
- evidence: commands or files used
- skipped: what you could not verify
重要なのは、Codexの返答を「自然文コメント」ではなく、後段のjobが読める形式にすることです。OpenAIのglossaryでも、codex exec には最終応答を制約するoutput schemaという概念があります。CIで扱うなら、最初からschemaを決めます。
{
"verdict": "pass",
"blockers": [],
"evidence": ["git diff --stat", "pnpm test"],
"skipped": ["no browser e2e in this job"]
}
verdict の意味も固定します。
| verdict | CIでの扱い |
|---|---|
pass | gate通過。ただし人間レビューは省略しない |
fail | merge blocker。根拠file / commandが必要 |
needs_human | CIは落とさず、PR commentやcheck summaryで人間へ戻す |
needs_human を用意しておくと、Codexが判断不能なものを無理にfailへ寄せなくなります。AI reviewerをCIに入れるとき、これはかなり効きます。
Fixer laneは「CIを通す」ではなく「失敗原因を1つ直す」
Codexに修正まで任せる場合、promptはさらに狭くします。
悪い依頼:
CIが落ちています。直してください。
これだと、テスト期待値の書き換え、無関係なformatter差分、広いリファクタに流れやすいです。
良い依頼:
Fix only the TypeScript error shown below.
Do not edit tests unless the production code behavior changed.
Do not modify package dependencies.
After editing, run pnpm typecheck.
If the fix requires broader design changes, stop and return needs_human.
CI上のFixer laneでは、次を必ず分けます。
- 失敗ログを入力として渡す
- 対象ファイルを限定する
- 依存追加を禁止する
- テスト削除や期待値変更を禁止する
- 再実行コマンドを1つだけ指定する
- 成功しても自動mergeしない
Codexが作った修正は、CIの成果物として見るより、PR差分として人間がレビューする方が安全です。自動pushする場合でも、同じbranchに直接積むのではなく、codex-fix/<run_id> のような別branchに出して、採用判断を分けます。
Auto-reviewをCIの代替にしない
Auto-reviewは便利ですが、非対話CIの万能解ではありません。OpenAIのdocsでは、Auto-reviewはapprovalがinteractiveな場合に発火し、approval_policy = "never" ではreview対象のapprovalがありません。
つまり、CIで approval_policy = "never" を使うなら、Auto-reviewに期待する設計は成り立ちません。Auto-reviewは、対話的なCodex実行中にsandbox境界を越えるapproval requestを別agentへ見せる仕組みです。CIで必要なのは、approval requestを誰が見るかではなく、approval requestが出ない範囲に仕事を閉じることです。
使い分けはこうです。
| 目的 | 向いている仕組み |
|---|---|
| ローカル作業中の境界越えを自動判定したい | Auto-review |
| CIでPR差分を機械判定したい | codex exec + read-only |
| CI失敗を限定修正したい | codex exec + workspace-write + narrow prompt |
| 脆弱性専用scanを回したい | Security plugin / Codex Security CLI |
ここを混ぜると、「Auto-reviewがあるからCIでも危険操作を任せてよい」という誤解になります。違います。CIは承認を返せないので、承認が必要な設計にしないことが先です。
GitHub Actionsに入れる最小形
最初のGitHub Actionsは、fail fastよりobserve-onlyで始めます。
name: Codex CI review
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
codex-review:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
fetch-depth: 0
persist-credentials: false
- name: Run Codex review
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
sandbox: read-only
prompt: |
Review only changed files in this pull request.
Return JSON with verdict, blockers, evidence, and skipped.
GitHub Actions では、repository-controlled code を checkout した同じjobに OPENAI_API_KEY や CODEX_API_KEY を広く置かない方が安全です。OpenAI docs でも、GitHub Actions ではCLIを手でinstallしてshell stepから直接 codex exec するより、API key proxy と safety strategy を持つ openai/codex-action@v1 を使う形が推奨されています。codex exec を直接呼ぶ例は、GitHub Actions以外の信頼済みautomation環境か、keyを単一invocationにだけ渡せる場面へ分けます。
最初はこのjobの結果を必須checkにしません。2週間ほど、実際のblocker精度、誤検知、見落とし、実行時間、token消費を見ます。
merge gateにするのは、次が揃ってからで十分です。
failの根拠がfile / line / commandに結びついているneeds_humanが過剰に出ていない- 重要PRで見落としが少ない
- 実行時間がCI予算に収まる
- Codexの出力を人間がすぐ読める
AI reviewerをCIに入れる価値は、人間レビューを消すことではありません。曖昧なPRを早めに止め、レビュー前に論点を圧縮することです。
失敗時の扱いを先に決める
非対話CIでは、失敗時の扱いをprompt任せにしない方がよいです。
| 失敗 | 扱い |
|---|---|
| Codex CLIの実行失敗 | CI infra failureとして再実行 |
| schema違反 | job failure。promptかschemaを直す |
needs_human | PR commentかsummaryに出し、merge gateにはしない |
fail with evidence | 必須check候補 |
fail without evidence | Codex出力の品質問題としてobserve-only |
特に、Codexが「危険そう」と言っただけの結果をmerge blockerにしない方がよいです。blockingにするなら、少なくとも対象file、変更内容、検証不能理由、推奨actionが必要です。
CIでのCodex利用は、強いagentを置くというより、弱くても一貫した判定器を置く方が成功しやすいです。
実務テンプレ: CI投入前チェックリスト
私なら、Codexを非対話CIへ入れる前にこれを確認します。
- Judge / Fixer / Reporter のどのlaneか決めた
read-onlyで始められるか確認したapproval_policy = "never"とsandboxの意味を分けた- promptにscope、禁止事項、返却形式を書いた
- output schemaかJSON形式を固定した
needs_humanを失敗とは別に扱う- 最初の2週間はobserve-onlyにする
- 自動修正は別branchか小さいpatchに限定する
- 依存追加、テスト削除、秘密情報、外部送信を禁止した
- Codexの結果だけでmergeしない
Codexの非対話実行は、CIにAIを混ぜるための便利機能です。ただし、便利さの中心は「勝手に直すこと」ではありません。人間がいない場所でも、何を見たか、何を見ていないか、どの根拠で止めたかを同じ形式で返せることです。
まずは read-only のJudge laneから始め、出力が安定したら限定的なFixer laneへ進める。この順番なら、CodexをCIに入れてもレビュー責任を失いにくくなります。