---
title: 'Cookbook解读｜Codex Goal 如何把“继续”变成完成协议'
description: '从 OpenAI Cookbook 的 Codex Goals 出发，拆解持久目标、证据审计与自动续跑怎样组成完成协议，并对比 Claude Code 的独立判定循环。'
pubDate: 2026-08-03
slug: codex-goals-completion-contract
tags: [agent, Codex, workflow, Cookbook解读]
lang: zh-CN
draft: false
---

用 Coding Agent 做一个稍长的任务，很容易出现这种对话：

```text
Agent：主体功能已经完成。
你：测试跑了吗？
Agent：还有两个失败。
你：继续。
Agent：修好了一个。
你：继续。
```

问题不一定是 Agent 不会修，而是谁都没有事先说清楚：**什么时候才算真的做完？**

OpenAI Cookbook 的 [Using Goals in Codex](https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex) 正在解决这件事。它给 Codex 增加的不是一句自动重复的“继续”，而是一份持续存在的完成协议：目标是什么，用什么证据验收，哪些东西不能破坏，没达标时怎样继续，什么时候应该承认阻塞。

先说结论：

> Goal 不是更长的 Prompt，也不是放开权限让 Agent 一直跑。它把“完成条件”保存为任务状态，让 Codex 在每轮结束后检查真实证据，再决定继续、完成或停在明确的边界上。

把 Claude Code 的 `/goal` 放到旁边会更容易看清这个设计。两者都想消灭人工催促，却把“谁来判定完成”放在了不同位置：Codex 由工作的 Agent 审计文件、测试和产物；Claude 则让另一个小模型根据对话记录做 Yes/No 判定。前者能接触更完整的现场，后者把执行者和裁判分开，但裁判看不到工作区。

> **数据快照**
>
> - 最后核验：2026-08-03
> - 主要对象：OpenAI Cookbook 的 Using Goals in Codex，以及 Anthropic 的 Claude Code `/goal` 文档
> - Codex Cookbook 标注的最低版本：Codex `0.128.0`
> - 本文比较公开的控制机制，不提供两种 Goal 的成功率、成本或质量排名

## Goal 解决的不是“做什么”，而是“何时停止”

普通 Prompt 描述下一步动作：修复测试、解释报错、修改一个组件。Agent 完成本轮后就把控制权还给用户。Goal 描述的则是一个需要持续成立的终态：

```text
/goal 将 checkout benchmark 的 p95 延迟降到 120 ms 以下，
同时保持 correctness suite 全部通过
```

只把延迟从 180 ms 降到 135 ms，不算完成；延迟达到 110 ms 但正确性测试失败，也不算完成。下一步到底是继续分析热点、撤销错误优化，还是重新跑基准，要由刚得到的证据决定。

Cookbook 因此把两种交互概括成两条不同的路径：Prompt 是“提问、工作、返回结果、等待”，Goal 则是“工作、检查、继续或完成”。

这里多出来的不是一个步骤，而是一条控制回边。目标仍然有效，Agent 就不该因为一轮回复写完了而默认任务结束。

**图 1：Codex Goal 把持久目标、证据审计和续跑条件组成闭环；权限与预算仍然限制每一轮能够做什么**

```mermaid
flowchart LR
  A["用户定义 Goal<br/>终态、证据、约束"] --> B["Codex 工作一轮"]
  B --> C["检查文件、测试<br/>日志、Benchmark、产物"]
  C --> D{"完成条件成立？"}
  D -->|"是"| E["标记完成"]
  D -->|"否，仍有可行路径"| F["选择下一步"]
  F --> B
  D -->|"预算耗尽或需要输入"| G["停止并报告边界"]
```

这张图有两个容易忽略的地方。第一，Goal 不替 Codex 选择固定步骤，它只固定完成标准；第二，循环不是无条件自转。[Cookbook 明确说明](https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex#what-changes-when-a-goal-is-active)，续跑只会发生在当前轮结束、任务空闲、没有排队的用户输入，而且 Goal 仍处于活动状态并在预算内的时候。没有工具调用的续跑还会被抑制，避免 Agent 只用语言反复说“我会继续”。

所以，Goal 更像恒温器，而不是定时电风扇。它关心的是温度有没有到 24℃，不是每隔五分钟机械地转一圈。

## 一份可执行的 Goal 至少要回答六个问题

“把项目做好”当然是目标，可惜不是一个能验收的 Goal。[Cookbook 把强 Goal 拆成六部分](https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex#how-to-write-a-goal)：结果、验证面、约束、边界、迭代策略和阻塞出口。

**表 1：根据 OpenAI Cookbook 整理的 Goal 完成协议；示例是说明性写法，不代表命令已经在本文运行**

| 要素     | 要回答的问题         | 认证模块迁移示例                                       |
| -------- | -------------------- | ------------------------------------------------------ |
| 结果     | 最终必须有什么变化   | 所有旧 API 调用完成迁移                                |
| 验证面   | 什么证据能够证明它   | `python scripts/verify_auth.py` 输出 `AUTH_GOAL: PASS` |
| 约束     | 达标时不能牺牲什么   | 测试通过，公共 API 行为不变                            |
| 边界     | 可以改哪里、使用什么 | 只修改 `src/auth/` 与对应文档                          |
| 迭代策略 | 每轮怎样选择下一步   | 记录失败原因，只处理当前最高影响问题                   |
| 阻塞出口 | 何时不该继续消耗资源 | 验证器不可运行或没有合法路径时报告 blocker             |

按这六项组合，一个更完整的 Goal 可以写成：

```text
/goal 完成 auth 模块的新 API 迁移，由
`python scripts/verify_auth.py` 退出码为 0 且输出
`AUTH_GOAL: PASS` 验证，同时保持现有测试和公共 API 行为不变。

只修改 `src/auth/` 与对应文档。每轮记录验证结果、失败原因和
下一项最小修改。如果验证器无法运行，或在上述边界内没有可行路径，
停止并报告已尝试方案、剩余问题和解除阻塞所需的输入。
```

这个写法没有规定 Agent 先改哪个函数，却把“怎样才算完成”锁住了。它既给探索留空间，也避免 Agent 用“主要功能已经完成”绕过失败的验收项。

多个条件最好继续收敛到一个不可随意修改的验证器。与其让模型从测试、覆盖率、Git Diff 和旧调用搜索的长输出里自行拼结论，不如让脚本统一给出：

```text
tests:             PASS
old_api_calls:     PASS
public_api:        PASS
protected_files:   PASS

AUTH_GOAL: PASS
```

Goal 负责读取结果并控制是否续跑，验证器负责把真实状态压成清晰信号。两者放在一起，才更接近工程上的验收，而不是一次措辞更坚定的自我评价。

## Codex 把 Goal 保存在哪里，决定了它能做什么

[Cookbook 将 Codex Goal 定义为持久化的 thread-scoped state](https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex#how-goals-are-designed-in-codex)，也就是属于当前任务的状态。它不是全局记忆，不会自动变成整个项目的长期规则，也不等同于 `AGENTS.md`。

这份状态记录目标、生命周期、预算和进度信息。目标活动时，Codex 可以继续读取文件、运行命令、检查 Diff、查看测试与生成产物，再用这些证据审计是否完成。用户仍然可以用 `/goal pause`、`/goal resume` 和 `/goal clear` 控制生命周期；到达预算上限只表示应该停止实质工作并汇报进度，不表示目标已经完成。

这个边界很实用：

- `AGENTS.md` 负责“这个仓库长期应该怎样工作”；
- Skill 或工作流负责“这一类任务通常怎样做”；
- Goal 负责“当前任务满足什么证据才可以停”；
- 权限与沙箱负责“哪些动作允许执行”。

它们不是四种写法不同的 Prompt。操作手册不能代替验收标准，验收标准也不会自动授予删除文件、访问网络或部署生产环境的权限。

## Claude Code 也有 `/goal`，但裁判坐在另一间房里

Anthropic 的 [Claude Code `/goal` 文档](https://code.claude.com/docs/en/goal) 描述了另一种闭环。每轮 Claude 工作结束后，一个默认使用小型快速模型的独立 evaluator 会读取 Goal 条件和当前对话，回答 Yes 或 No。回答 No 时，理由进入下一轮；回答 Yes 时，Goal 清除并记录为已达成。

这相当于把修车师傅和质检员分开。好处是执行模型不能只凭自己一句“已经完成”直接放行。限制是质检员隔着玻璃，只能看维修记录，不能自己打开引擎盖。

Claude 的 evaluator 不会运行命令，也不会读取文件。它只能看到工作 Agent 已经展示到 transcript 里的证据。因此，同一个验收条件在两边有不同的可靠写法：

```text
不够稳：
/goal 所有认证测试通过

更容易判定：
/goal `pytest tests/auth -q` 退出码为 0，
并且完整汇总行与 `AUTH_GOAL: PASS` 已出现在当前对话中
```

**表 2：截至 2026-08-03 的公开机制对比；比较的是证据与控制位置，不是质量排名**

| 维度               | Codex Goal                             | Claude Code `/goal`                         |
| ------------------ | -------------------------------------- | ------------------------------------------- |
| 目标范围           | 当前任务的持久状态                     | 当前会话的 Goal                             |
| 完成判定           | 工作 Agent 根据证据进行完成审计        | 独立小模型回答 Yes/No                       |
| 判定时能否使用工具 | 工作 Agent 可以检查文件、测试与产物    | Evaluator 不能调用工具                      |
| 主要证据           | 当前工作区与任务中的实际证据           | 已经出现在对话中的证据                      |
| 生命周期控制       | 查看、暂停、恢复、清除，并记录预算状态 | 设置、查看、清除；恢复会话时可恢复活动 Goal |
| 主要风险           | 做事者同时参与自我验收                 | 裁判可能被不完整 transcript 误导            |

这不是“能用工具一定更好”或“独立裁判一定更客观”的单选题。Codex 的证据面更宽，却仍需防止自我确认；Claude 分离了执行与判定，却可能因为关键测试结果没有进入对话而缺证。两种机制分别减少了一类错误，也分别留下了另一类错误。

更稳健的组合仍然是：执行 Agent 访问真实环境，不可随意修改的验证器给出硬信号，独立 Judge 处理文档质量、需求覆盖等语义问题，隐藏或组合测试防止只对公开指标投机。

## Goal 最危险的失败不是停不下来，而是错误地停下来

Goal 让 Agent 多跑几轮，并不会自动让结果更真实。只要完成条件是一个有漏洞的代理指标，Agent 就可能非常努力地满足指标，同时偏离原始意图。

例如：

```text
/goal 让所有公开测试通过
```

这句话没有保护测试文件，没有要求实现真实规格，也没有检查未公开输入。最短路径可能是修改测试、为固定样本写特殊分支，或者绕开真正应该实现的模块。循环越勤奋，错误方向反而可能走得越远。

因此，完成协议还需要保护自己的尺子：

- 验证器、测试和阈值不能由工作 Agent 随意降低；
- 除了显式测试，还要检查组合行为与隐藏样本；
- 主观质量交给独立 Review，而不是伪装成布尔条件；
- 长任务设置预算与阻塞出口，避免无意义重试；
- 研究任务把“确认、近似、代理证据、阻塞、未知”分开记录。

[Cookbook 的 Deep Hedging 案例](https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex#using-goals-for-complex-research-reproducing-a-quant-paper)正好说明最后一点。Codex 能重建定价和对冲机制、训练替代策略并生成多个结果，但原始随机种子、训练路径、Optimizer State 和 Checkpoint 并不完整。因此，最诚实的终态是“部分、近似复现”，而不是把一张相似图表写成“精确复现”。Goal 的价值不只是推动 Agent 继续做，也包括规定它何时必须承认证据到此为止。

## 什么时候该用 Goal，什么时候只要一句 Prompt

Goal 适合终点明确、路径不确定的中长任务：性能调优、间歇性测试排查、依赖迁移、多步重构、Benchmark 驱动优化，以及需要交付证据清单的研究。

下面这些任务通常不需要 Goal：

- 改一处文案或一行配置；
- 解释一个错误信息；
- 做一次短 Code Review；
- 只需要一个答案，然后希望 Agent 停下来；
- “让架构更优雅”这类还没有验收面的模糊目标。

判断方法其实很简单：如果你已经能预见自己接下来会反复输入“继续、再检查一下、还没满足这个条件”，就值得先把这些话写成 Goal；如果一轮完成后本来就需要你做产品判断，自动续跑反而会抢走必要的决策点。

## 总结

Using Goals in Codex 最值得带走的不是 `/goal` 这条命令，而是一个很朴素的工程判断：**长任务缺的通常不是更大的 Prompt，而是持久、可验证的停止条件。**

Codex 把 Goal 放进当前任务的持久状态，让工作的 Agent 可以围绕真实文件、测试、日志、Benchmark 和产物持续审计；Claude Code 把 `/goal` 做成带独立 evaluator 的 Stop Hook，让另一个模型根据对话证据决定是否继续。前者强调证据能力，后者强调判定分离。

无论使用哪一种，都不要只写“做到最好”。先回答四个问题：最终状态是什么，哪个验证器能够证明，哪些约束不能被破坏，失败到什么程度应该停下来报告。然后再决定是否需要独立 Judge、隐藏测试和预算熔断。

Goal 真正改变的不是 Agent 能工作多久，而是谁有资格说“已经完成”，以及这句话后面到底有没有证据。

## 参考资料

- [OpenAI Cookbook：Using Goals in Codex](https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex)
- [Anthropic：Keep Claude working toward a goal](https://code.claude.com/docs/en/goal)
