Yoda
参考Agent 设计指南工程流

Headless / CI 集成

CC 用 -p/--bare + stream-json 把交互会话降维成管道命令;Codex 用 exec 子命令 + JSONL 事件流原生面向自动化。两家都有官方 GitHub Action,CI 确定性策略截然不同。

Headless / CI 集成

结论

CC 的 headless 是「交互模式加 -p 开关」:默认仍加载本机 hooks/MCP/CLAUDE.md,要确定性必须显式 --bare;输出三档(text/json/stream-json),结构化输出走 --json-schema,权限靠 --allowedTools/--permission-mode 白名单。Codex 的 headless 是独立子命令 codex exec:默认不带 TUI 包袱,--json 输出 thread.*/turn.*/item.* JSONL 事件,--output-schema 约束最终响应,-o 直接落最终消息文件,turn 失败时显式 exit(1)「automation-friendly signaling」。CI 认证:CC 走 ANTHROPIC_API_KEY(或 Bedrock/Vertex 凭据),Codex 支持 CODEX_API_KEY / OPENAI_API_KEY / CODEX_ACCESS_TOKEN 三个环境变量。两家都有官方 Action:anthropics/claude-code-action@v1@claude 提及驱动 + claude_args 透传)与 openai/codex-action(codex 仓库自己的 CI 在用,output-schema + final-message 输出)。

研究问题

  • CC -p 模式的输出协议、退出码与确定性边界在哪?
  • codex exec --json 的事件 schema 与错误信号语义?
  • CI 内的认证、权限收敛与产物回传各自怎么做?

各 Agent 设计与实现

Claude Code

print 模式claude -p "<prompt>" 非交互执行,所有 CLI 选项可叠加 [一手文档](claude-code-docs/docs/headless.md:15-35)。关键开关:

  • --bare:跳过 hooks/skills/plugins/MCP/auto memory/CLAUDE.md 的自动发现,「useful for CI and scripts where you need the same result on every machine」;官方明示 --bare 将来会成为 -p 的默认(headless.md:37-63)[一手文档]。bare 模式跳过 OAuth/keychain,认证只认 ANTHROPIC_API_KEY--settings 里的 apiKeyHelperheadless.md:59)。
  • --output-format text|json|stream-jsonjsontotal_cost_usdsession_idstream-json + --verbose + --include-partial-messages 逐 token 流(headless.md:105-155)。
  • --json-schema '<schema>' → 响应的 structured_output 字段(headless.md:117-125)。
  • --max-turns N:限制 agentic 轮数,「Exits with an error when the limit is reached」(cli-reference.md:86)[一手文档]。
  • 退出码语义:stdin 超 10MB 上限「exits with a clear error and a non-zero status」(headless.md:86);重试期间发 system/api_retry 事件(attempt/max_retries/error 分类,headless.md:157-169);system/init 事件带 plugins/plugin_errors 字段,官方建议「Use the plugin fields to fail CI when a plugin did not load」(headless.md:171-177)[一手文档]。
  • 后台任务:-p 返回结果后约 5 秒强杀 background Bash(v2.1.163 前会被永不退出的后台进程挂死,headless.md:67)。

权限策略(CI 确定性)--allowedTools "Bash(git diff *),Read" 用权限规则语法做前缀白名单;--permission-mode dontAsk 拒绝一切白名单外动作(locked-down CI),acceptEdits 自动放行文件写和 mkdir/mv/cp 类命令,其余仍需规则,否则 run 中止(headless.md:194-216)[一手文档]。注意:/code-review 等用户侧 skill -p 模式不可用,要用自然语言描述任务(headless.md:218-220)。

会话续传--continue 接最近会话,--resume <session_id> 指定会话;session_id 从 --output-format json 的输出里 jq -r '.session_id' 捕获(headless.md:234-252)。

GitHub Actionsanthropics/claude-code-action@claude 在 issue/PR 评论里触发,模式自动检测(v1 移除了 beta 的 mode: tag/agent);beta 的 max_turns/model/allowed_tools 全部折叠进 claude_args(即透传 CLI flag),prompt 直接给任务(github-actions.md:88-110 的 Breaking Changes 对照表)[一手文档]。安装走 /install-github-app 或手动装 GitHub App(Contents/Issues/PR 读写权限)+ ANTHROPIC_API_KEY secret(github-actions.md:43-72);官方强调「Your code stays on Github's runners」——这是与托管 Code Review(跑在 Anthropic 侧)的关键边界。GitLab CI/CD 有对应文档(gitlab-ci-cd.md),Bedrock/Vertex 走各自凭据。

plugin 安装可观测:设 CLAUDE_CODE_SYNC_PLUGIN_INSTALL 后,首 turn 前会流式发出 system/plugin_install 事件(status: started/installed/failed/completed,headless.md:178-188)——CI 里装 marketplace 插件的进度与失败可以被脚本捕获,而不是黑盒等待 [一手文档]。

Codex CLI

exec 子命令codex exec [OPTIONS] [PROMPT],prompt 缺省或 - 时读 stdin;stdin 与 prompt 同时给时 stdin 以 <stdin> 块附加(codex-rs/exec/src/cli.rs:81-86)[一手源码]。关键 flag(均出自 exec/src/cli.rs):

  • --json(alias --experimental-json):JSONL 事件流到 stdout(:63-70
  • --output-schema FILE:JSON Schema 约束最终响应(:52-54
  • -o/--output-last-message FILE:最终消息落文件——CI 产物回传最省事的通道(:72-79
  • --ephemeral:不落盘 session 文件(:30-32);--ignore-user-config:不读 $CODEX_HOME/config.toml(auth 仍用 CODEX_HOME,:34-36);--ignore-rules:跳过 execpolicy .rules:38-40)——这三个加 --strict-config 就是 Codex 版「bare mode」
  • --skip-git-repo-check:允许在非 git 目录跑(:26-28
  • 子命令:codex exec resume <id>|--last 续跑、codex exec review 评审(:165-172,见 code-review 章)
  • --full-auto 已废弃,提示改用 --sandbox workspace-write:102-111

JSONL 事件 schema [一手源码](exec/src/exec_events.rs:9-38,serde tag type):thread.started / turn.started / turn.completed(带 usage)/ turn.failed / item.started / item.updated / item.completed / error。item 细类含 AgentMessageItem/ReasoningItem/CommandExecutionItem/FileChangeItem/McpToolCallItem/WebSearchItem/TodoListItem 等(exec_events.rs:104-315)。

退出码:事件循环里跟踪 error_seen——server 报不可重试错误、或 turn 终态为 Failed/Interrupted 时置位,收尾 std::process::exit(1),注释明言「exit with a non-zero status for automation-friendly signaling」(exec/src/lib.rs:925-1030)[一手源码]。

CI 认证:环境变量常量定义在 login/src/auth/manager.rs:516-518OPENAI_API_KEYCODEX_API_KEYCODEX_ACCESS_TOKEN,均做非空 trim 读取(:520-533)[一手源码]。docs/authentication.md 是指向 developers.openai.com 的存根,细节以源码为准。

GitHub Actionopenai/codex-action@...# v1.7 在 codex 仓库自己的 issue 去重工作流中实战使用:输入 openai-api-key(secret)、sandbox: read-onlysafety-strategy: drop-sudooutput-schema(内联 JSON Schema),输出 final-message 供下游 job 消费(.github/workflows/issue-deduplicator.yml:59-99,114)[一手源码]——这是「exec + 结构化输出 + 产物回传」的官方范本。

差异矩阵

维度Claude CodeCodex CLI
非交互入口claude -p(交互模式的降维开关)codex exec(独立子命令)
确定性模式--bare(显式跳过本机配置,未来默认)--ignore-user-config + --ignore-rules + --ephemeral
流式输出--output-format stream-json(type: system/assistant/result…)--json(type: thread./turn./item.*)
结构化输出--json-schemastructured_output--output-schema FILE → 最终响应本体
产物回传json 输出 jq 提取(.result/.session_id-o FILE 落最终消息 / Action 的 final-message
轮数限制--max-turns(超限报错退出)无对应 flag(未检索到)[一手源码-缺失]
失败信号非零退出 + system/api_retry/plugin_errors 事件error_seenexit(1)turn.failed 事件
权限收敛--allowedTools 规则 + --permission-mode dontAsk/acceptEdits--sandbox read-only/workspace-write + execpolicy rules
CI 认证ANTHROPIC_API_KEY / Bedrock / VertexCODEX_API_KEY / OPENAI_API_KEY / CODEX_ACCESS_TOKEN
官方 Actionanthropics/claude-code-action@v1(@claude 提及 + claude_args)openai/codex-action(v1.7,官方仓库自用)

最小复现

# CC:确定性 CI 调用 + 结构化输出
claude --bare -p "Extract function names from auth.py" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
  | jq '.structured_output'

# CC:捕获 session 再续跑
sid=$(claude --bare -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$sid"

# Codex:JSONL 事件流 + 最终消息落盘 + 失败即非零退出
codex exec --json --ephemeral --skip-git-repo-check \
  -o /tmp/last.md "总结这个目录" ; echo "exit=$?"
# {"type":"thread.started",...}
# {"type":"item.completed","item":{"type":"agent_message",...}}
# {"type":"turn.completed","usage":{...}}

# Codex:续跑最近一次 headless 会话
codex exec resume --last "继续,把结论写成表格"

# Codex:管道输入——stdin 与 prompt 并存时 stdin 以 <stdin> 块附加(cli.rs:81-86)
git diff origin/main | codex exec --json "评审这个 diff"

Harness 接入建议(Yoda 实践)

  • Yoda 的任务模型若要加「无人值守 run」(定时任务/批处理),CC 侧统一用 --bare -p --output-format stream-json 模板:bare 隔离用户机器上的 hooks/MCP 差异,正是 Yoda 多机一致性需要的;同时监听 system/initplugin_errors 在 run 开始即 fail-fast。
  • Codex 侧用 codex exec --json + -o,并把 CODEX_SANDBOX_MODE / CODEX_APPROVAL_POLICY(Yoda 已有这两个 optional env,yoda/AGENTS.md)映射到 --sandbox 与 config override,避免 headless run 卡在审批上。
  • 退出码契约不同:CC 在 max-turns/stdin 超限等多种情况非零退出,Codex 只有 turn 失败/中断一种 exit(1)——Yoda 的 run 状态机不要只看退出码,应同时消费 turn.failed/system/api_retry 事件。
  • 产物回传统一抽象成「最终消息 + 结构化 JSON」两个槽位:CC 填 .result/.structured_output,Codex 填 -o 文件 / --output-schema 响应,与 openai/codex-actionfinal-message 同构。

失效条件

  • --bare 成为 -p 默认后(官方已预告),「-p 默认加载本机配置」的描述过期
  • 2026-06-15 起 claude -p 计入独立 Agent SDK 额度(headless.md:10),CI 成本结论需按新计费复核
  • --experimental-json 转正 / ThreadEvent 增删字段(exec_events.rs)需回归解析器
  • openai/codex-action 输入面(safety-strategy 等)随版本变化;本章引用的是 v1.7 pinned commit
  • Codex 若新增 max-turns 类限制 flag,差异矩阵需更新

参考资料

  • CC:claude-code-docs/docs/headless.mdcli-reference.mdgithub-actions.mdgitlab-ci-cd.md
  • Codex 源码:codex-rs/exec/src/cli.rsexec/src/exec_events.rsexec/src/lib.rs:925-1030login/src/auth/manager.rs:516-533.github/workflows/issue-deduplicator.yml(均 @ b89ce9a)
  • Codex 文档存根:codex/docs/exec.mdhttps://developers.openai.com/codex/noninteractive
  • 交叉章节:chapters/workflow/sdk.md(SDK 即这些 flag 的程序化包装)、chapters/workflow/code-review.md(CI 内评审)

On this page