把回复变成脚本能解析的 JSON:`codex exec --output-schema` 实战

2026-08-09

把 Codex(OpenAI Codex)塞进脚本里,第一个卡住人的从来不是”它会不会干活”,而是”它干完之后我怎么读懂结果”。交互式终端里人眼一扫就明白的一段话,换成 shell 脚本或 CI 步骤去消费,就变成了拿正则抠段落、按换行切分、赌它这次的措辞和上次一样。跑十次能对八次,剩下两次半夜报错。

codex exec 有个选项专门治这个:--output-schema <FILE>。本机在 codex-cli 0.147.0(Windows 11)上执行 codex exec --help,这一项的官方说明是「一个 JSON Schema 文件路径,描述模型最终回复的结构」。也就是说,你先把想要的结构写成一份 JSON Schema 文件,再把文件路径交给它。

先把话说在前面:本文里的命令行选项与说明文字来自本机在 codex-cli 0.147.0(Windows 11)上跑 --help 得到的原文,配置文件键位与默认值来自官方 Configuration Reference 页面,我们没有发起过任何模型对话请求,所以下文不会出现”我跑了一次,它返回了什么什么字段”这种描述。命令怎么拼、验收看哪里,我讲清楚;真实产出长什么样,得你自己跑第一次的时候 dump 出来看。

一、schema 文件先写好

--output-schema 要的是文件路径,不是内联字符串,所以第一步是落一个文件。放哪儿无所谓,我习惯集中放在一个目录里,命令行上写绝对路径:

{
  "type": "object",
  "properties": {
    "summary":    { "type": "string" },
    "risk_level": { "type": "string", "enum": ["low", "medium", "high"] },
    "files":      { "type": "array", "items": { "type": "string" } }
  },
  "required": ["summary", "risk_level", "files"],
  "additionalProperties": false
}

说明两点,免得误会:

第一,summary / risk_level / files 这些是我按自己的业务需要起的字段名,跟 Codex 没有任何关系。你要什么字段就写什么字段,下游脚本按这套字段名读就行。

第二,--help 里对这个文件的描述只有”一个 JSON Schema 文件路径”这一句,没有说明它支持 JSON Schema 的哪些关键字、哪个 draft、对 additionalPropertiesrequired 有没有额外要求。这些约束以官方文档为准,我这里不替它下结论。实践上的建议是:先从最朴素的一层对象 + 字符串/枚举/数组开始,跑通了再往里加嵌套和条件关键字,别一上来就写一份三层嵌套 + oneOf 的复杂 schema,出问题你都不知道是 schema 不被支持还是别的地方错了。

二、完整命令,逐项解释

Git Bash / macOS / Linux 侧:

codex exec \
  --output-schema ~/codex-schemas/review-report.json \
  -o ./codex-out/last-message.json \
  --json \
  -s read-only \
  -a never \
  --skip-git-repo-check \
  --color never \
  "审阅当前目录的构建脚本,按 schema 要求输出结果"

Windows PowerShell 侧,续行符和路径写法都不一样,别照抄上面那段:

codex exec `
  --output-schema "$HOME\codex-schemas\review-report.json" `
  -o ".\codex-out\last-message.json" `
  --json `
  -s read-only `
  -a never `
  --skip-git-repo-check `
  --color never `
  "审阅当前目录的构建脚本,按 schema 要求输出结果"

每个选项为什么在这儿:

  • --output-schema:主角,指向上一节那份文件。路径建议一律写绝对路径。命令行上还有个 -C, --cd <DIR> 能改 agent 的工作根目录,两个东西一起用的时候相对路径最容易让人算不清是相对谁,索性不给自己留这个坑。
  • -o, --output-last-message <FILE>--help 原文是「把 agent 的最后一条消息写到文件」。这是你脚本真正要读的那个文件——最终回复直接落盘,不用从终端输出里切。
  • --json--help 原文是「事件以 JSONL 打到 stdout」。它和 -o 不冲突,管的是两件事:-o 给你结果,--json 给你过程。
  • -s read-only:沙箱模式,三个取值是 read-only / workspace-write / danger-full-access。只让它读和总结,就选最紧的那档。
  • -a never:审批策略,--help 里对 never 的释义是「从不询问,执行失败直接回传给模型」。注意 never 不等于放开权限,它只是不再弹审批问你,能不能干仍然由沙箱决定。非交互场景不设它,一遇到需要审批的动作就没人应答了。
  • --skip-git-repo-check:允许在非 Git 仓库里运行。分析临时目录、日志目录时必备,在正经仓库里可以不加。
  • --color never:取值 always / never / auto,默认 auto。在 CI 日志里关掉颜色,省得 ANSI 转义码混进你抓取的文本。

还有几个按需的:--ephemeral 不把会话文件落盘;--ignore-user-config 不加载 $CODEX_HOME/config.toml(注意 --help 特别说明了 auth 仍然使用 CODEX_HOME,它只隔离配置不隔离登录态);--ignore-rules 不加载用户或项目的 execpolicy .rules 文件——这个别随手加,它绕开的是你自己定的执行策略。

输入从管道来的写法

codex exec 的位置参数 [PROMPT] 有两种进 stdin 的方式,--help 写得很清楚:不给参数或给 - 时从 stdin 读;stdin 是管道且同时给了 prompt,则 stdin 会作为 <stdin> 块追加。后一条特别顺手——指令写在参数里保持稳定,待处理的内容从管道喂:

cat build.log | codex exec \
  --output-schema ~/codex-schemas/log-triage.json \
  -o ./codex-out/triage.json \
  -s read-only -a never --skip-git-repo-check \
  "把 stdin 里的构建日志归类,按 schema 输出"

固定住一批设置:用 profile

命令行选项堆到八九个就该往配置里收了。-p, --profile <CONFIG_PROFILE_V2> 会把 $CODEX_HOME/<name>.config.toml 叠加到基础用户配置之上。建一个 ~/.codex/ci.config.toml

sandbox_mode = "read-only"
approval_policy = "never"
model_reasoning_effort = "low"
hide_agent_reasoning = true

然后命令缩成 codex exec -p ci --output-schema ... -o ... "..."。其中 hide_agent_reasoning 官方说明是「在 TUI 与 codex exec 输出里抑制推理内容」,跑批量任务时日志会干净不少。以上为按官方文档键位组合的示例,未逐项实测,以官方文档为准。

三、产出物落在哪、怎么接下一步

只讲有依据的部分,两个出口:

出口一是 -o 指定的文件,里面是 agent 的最后一条消息。这是你 json.load() 的对象,也是加 --output-schema 的意义所在——让这条消息本身就是结构化的,而不是一段需要人读的话。

出口二是 stdout 上的 JSONL 事件流--json)。JSONL 的意思是一行一个 JSON 对象,脚本按行读、逐行解析即可。至于每种事件有哪些字段、事件类型叫什么名字,--help 没给清单,我们也没跑过真实对话,所以本文不列任何字段名。你第一次接的时候老老实实 codex exec --json ... > events.jsonl,把文件拿到手翻一遍再写解析代码,比照着任何一篇文章里的字段名硬猜都靠谱。

接下一步的分工建议很朴素:结果判定读 -o 的文件,流程监控和排障读 JSONL。别把两者混在一个解析器里。

四、怎么验收:五个必看点

1. schema 文件本身是不是合法 JSON。 一个手写的 JSON 少个逗号是常事,先自己校一遍再交给 Codex:

python -c "import json;json.load(open('review-report.json',encoding='utf-8'));print('ok')"

2. 配置到底加载成功没有。 这是我们本机实测里最有价值的一条:在 codex-cli 0.147.0(Windows 11)上故意传一段语法不合法的 TOML(codex -c 'features=[unclosed' doctor --summary),命令没有崩溃退出,doctor 照常跑完,但输出里出现了这么一行:

✗ config       config could not be loaded - Fix the reported config error, then rerun codex doctor.

也就是说配置坏掉时它不一定会拦你,而是安静地不加载。所以”我明明配了 profile / 配了 sandbox_mode,怎么好像没生效”这类问题,第一步就该跑 codex doctor --summary 看 Configuration 组里 config 这一行是不是 ok。

3. -c 的取值有没有被当成字符串。 --help 原文:-c 的 value 按 TOML 解析,解析失败则按字面字符串处理。这个设计很容易埋雷——你以为传了个布尔值,实际进去的是字符串,而且不报错。所以布尔和数组类的覆盖尽量写进 profile 文件,别在命令行上拼。

4. 别指望 --strict-config 兜住拼写错误。 它的作用是”config.toml 里出现本版本不认识的字段时直接报错退出”,但本机在 codex-cli 0.147.0(Windows 11)上执行 codex -c model_reasoning_effortt=high --strict-config exec --help(注意 effortt 多打了一个 t),结果是正常打印 help,没有报未知字段错误。说明这层校验发生在真正加载配置去跑会话的时候,--help 这类不进入会话的路径不触发。拿 --help 去”验证配置写对了”是白验。

5. 沙箱取值拼错会立刻挡下。 这一条反而让人安心,本机在 codex-cli 0.147.0(Windows 11)上执行 codex -s bogus-mode,报错是:

error: invalid value 'bogus-mode' for '--sandbox <SANDBOX_MODE>'
  [possible values: read-only, workspace-write, danger-full-access]

For more information, try '--help'.

枚举类选项属于”错了当场炸”的一类,跟上面第 3、4 点的静默失败正好相反。心里有这个分界,排查时就知道该先怀疑谁。

最后还有一步纯业务的验收:结构合法不等于内容正确。schema 约束的是形状,risk_level 落在枚举里不代表这个判断是对的。脚本侧该有的业务校验一个都不能少,别把 schema 当成正确性的保证。

五、什么情况别这么干

要它真的改文件的时候。 -s read-only 下它动不了工作区;换成 workspace-write 之后,JSON 只是它自己的一份”工作自述”,改了什么必须回到 git status / git diff 上验,不能拿 JSON 里的字段当已落盘的证据。顺带一提,CLI 有个 apply(别名 a)子命令,--help 说明是「把 Codex agent 产生的最新 diff 以 git apply 应用到本地工作树」——改动的落地和结果的汇报是两条线,别混。

需要人中途拍板的活儿。 -a never 意味着不再问你,失败直接回传给模型自己处理。涉及删除、发布、改配置这类动作,老老实实用交互模式,或者用 untrusted(只有受信任命令免审批)这类更紧的策略。

只想看过程的时候。 --output-schema 管的是最终那一条回复。想知道中间发生了什么,是 --json 事件流的活儿,加 schema 没用。

要复盘的时候别加 --ephemeral 它不把会话文件落盘,那 resume 也就无从谈起。CI 里为了干净加上它可以理解,但排查问题的那几次跑,留着。

任务依赖实时联网信息的时候要额外确认。 官方 Configuration Reference 里,配置项 web_search 默认值是 cached——既不是关闭也不是实时;CLI 的 --search 才是开实时联网搜索,而且 --help 明确写了启用后原生 web_search 工具对模型可用、无逐次调用审批。放进无人值守的流水线之前,这个权衡自己想清楚。

相关阅读


本文依据 Codex 官方文档(learn.chatgpt.com/docs/ 的《Non-interactive mode》《Codex CLI》《Configuration Reference》页面)整理,核对日 2026-08-09;文中标注「本机实测」的部分基于 codex-cli 0.147.0 / Windows 11 环境下的只读命令输出。产品功能、模型与价格以官方最新说明为准。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。