🔥 每天3分钟,读懂科技圈。点击上方「蓝字」关注 TechHome

最近中文开发者圈里,Codex 的 /goal 命令突然被重新讨论起来。
原因很直接:有人用它跑了一个复杂重构,把单体 Node.js 项目拆成前后端模块和 monorepo,跑了一个多小时,回来发现任务真的做完了;也有人把 openai/codex 源码拉下来,开始追 /goal 到底怎么实现。
如果只看表面,/goal 很像一句增强版的“继续干”:用户给一个长期目标,Codex 自动一轮轮推进,直到完成、阻塞或预算耗尽。
但读完源码后会发现,这个理解太浅了。
/goal 的核心不是“循环调用模型”,而是把长任务所需的目标存储、自动续跑、预算记账、状态权限和完成审计,做成了 Codex 运行时的一部分。
这也是它和很多外部 bash loop、hook loop 最大的区别。
本文基于两篇中文源码解读文章、OpenAI 官方 Cookbook,以及本地更新后的 openai/codex 最新源码阅读。当前本地 Codex CLI 已更新到 0.144.1,源码为 openai/codex main 分支 commit 1f0566d。
1. 先说结论:/goal 不是 TUI 里的一个小命令
很多 slash command 只是前端入口:解析一下用户输入,然后丢给后端。
/goal 不一样。
它在源码里主要集中在这几个位置:
• codex-rs/ext/goal/:Goal extension 的主体;
• codex-rs/ext/goal/templates/goals/continuation.md:真正注入给模型的续跑提示词;
• codex-rs/state/src/runtime/goals.rs:SQLite 状态读写和预算记账;
• codex-rs/state/src/model/thread_goal.rs:Goal 状态模型;
• codex-rs/tui/src/app/thread_goal_actions.rs:TUI / App Server 侧的 set、pause、resume、clear;
• codex-rs/app-server/src/request_processors/thread_goal_processor.rs:thread/goal/set|get|clear 协议入口。

最关键的是 ext/goal/src/extension.rs。
这里的 GoalExtension 挂进了 Codex 的事件循环,实现了一整组生命周期回调:
也就是说,/goal 不是在 Codex 退出后由外部脚本再拉起一次,而是 Codex 运行时里的观察者和调度器。
线程启动、线程恢复、线程空闲、turn 开始、turn 结束、工具调用完成、token 用量更新,这些关键时刻它都在场。
这就解释了一个问题:为什么它能做得比“while true 调 Codex”更稳?
因为它不是在外面猜 Codex 发生了什么,而是在 Codex 内部直接监听这些状态变化。
2. 状态存在 SQLite:一个线程,一个目标,一行记录
/goal 的持久状态不是藏在 prompt 里,也不是靠模型自己记住。
源码里的 thread_goals 表非常直白:
对应的 Rust 模型在 state/src/model/thread_goal.rs:
这里有两个设计点很重要。
第一,目标内容 objective 是本地持久状态,不是模型随便能改的上下文文本。模型可以读取目标,可以在严格条件下更新状态,但不能直接篡改底层 goal 记录。
第二,状态机不是只有 active / complete。它区分了:
• paused:用户暂停;
• blocked:模型认为真的卡住;
• usage_limited:账号/用量限制;
• budget_limited:该 goal 的 token 预算耗尽;
• complete:完成。
这说明 /goal 并不是简单追求“永远跑下去”。它真正关心的是:什么时候该继续,什么时候该停,停下来的原因是什么。
3. 续跑不是定时器:只有线程真的空闲,才会继续
/goal 的续跑入口在 on_thread_idle:
而 continue_if_idle() 里会再次检查:
• goal tools 是否对当前线程可见;
• 当前线程是否还活着;
• SQLite 里的 goal 是否仍然是 active;
• 线程是否真的可以 try_start_turn_if_idle。

这里的关键字是 try_start_turn_if_idle。
它不是强行开一个新 turn,而是让宿主层判断:现在是否真的适合启动自动工作。如果用户输入队列里还有消息,如果当前处于 Plan 模式,如果线程已经 busy,它就不会继续。
这点很克制。
很多“自动 Agent 循环”的危险,不是不会继续,而是太会继续:用户还没来得及插话,它已经又烧了一轮;刚刚报错,它又撞同一个错误;计划还没确认,它已经动手改文件。
/goal 的续跑触发是事件驱动的,不是盲目循环。
4. continuation.md:真正的系统提示词长什么样
/goal 续跑时注入的不是普通用户消息,而是一个带内部来源标签的上下文片段:
这个 prompt 来自:
开头很短:
注意第二句。
目标是用户提供的数据,不是更高优先级的指令。这是一个很重要的安全边界。因为 objective 会长期保存、反复注入,如果里面藏了 prompt injection,不能让它变成系统级指令。
源码里还专门做了 XML 转义:
真正有意思的是后半段。

continuation.md 主要在防四件事。
第一,防目标缩水。
它要求 Codex 保持完整目标,不要把复杂目标改成“当前轮次能完成的小目标”。原文写得很直:
第二,防走捷径。
这句话非常关键。Agent 很容易为了让测试变绿,改出一个更窄、更安全、但偏离真实需求的解法。/goal 明确把这种行为定义为不对齐。
第三,防靠记忆宣布完成。
当前工作树、命令输出、测试结果、运行时行为,才是权威依据。之前上下文只能辅助定位,不能替代验证。
第四,防过早完成。
最值得引用的是这一句:
没有发现明显问题,不等于证明已经完成。
这句话其实抓住了 Agent 长任务里最常见的失败模式:模型干到一半觉得“差不多了”,然后给一个看似完整的总结。
/goal 把举证责任倒过来了:你不能说“我没看到剩余工作”,你必须证明“每一项要求都已经满足”。
5. 模型能用的工具很少:get、create、update,而且 update 只能 complete 或 blocked
ext/goal/src/spec.rs 里暴露给模型的工具只有三个:
其中 update_goal 的 schema 把状态枚举限制死了:
tool.rs 里还有第二道校验:
也就是说,模型不能把 goal 设置成 pause、resume、budget_limited、usage_limited。
这些状态属于用户或系统。
• 用户侧:/goal pause、/goal resume、/goal clear;
• 系统侧:token 预算撞线变成 budget_limited,账号用量问题变成 usage_limited;
• 模型侧:只能声明“完成”或“真的阻塞”。
这是一种很好的权限分离。
让模型判断进展,但不要让模型拥有完整生命周期权限。
6. 预算不是轮数,而是真 token 记账
很多外部 loop 的预算控制很粗:最多跑 N 轮,或者最多跑多少分钟。
/goal 更细。
accounting.rs 里有一个函数专门算 goal token delta:
也就是说,命中 prompt cache 的输入 token 不算进 goal 预算。
这是长任务场景里很实际的设计。如果每一轮都把缓存命中的历史上下文重新算钱,预算会被重复上下文吃掉,而不是被真实新增工作吃掉。
更关键的是,预算状态翻转在 SQLite 里是一条原子 UPDATE。
state/src/runtime/goals.rs 里,account_thread_goal_usage() 在同一条 SQL 里完成三件事:
1. 增加 time_used_seconds;
2. 增加 tokens_used;
3. 如果 tokens_used + delta >= token_budget,把状态改成 budget_limited。
核心片段是:
这不是洁癖,而是为了防 race condition。
Goal extension 会在 turn stop、tool finish、token usage 等多个生命周期点记账。如果用 read-modify-write,两个回调可能读到同一个旧值,导致重复扣或漏翻状态。把累加和状态翻转合进一条 UPDATE,数据库一次性完成,安全得多。
另外,time_used_seconds 只记录,不作为硬停止条件。真正能卡停的是 token budget。
这也解释了为什么 /goal 更像“成本预算”而不是“时间闹钟”。
7. 出错熔断:防止在同一个错误上无限烧钱
长任务最怕一种情况:报错、自动续跑、继续报错、继续续跑。
/goal 在 on_turn_error 里做了熔断。
源码注释写得很清楚:
如果是 usage limit,就把 goal 标成 usage_limited。
如果是不可重试错误或重试耗尽,就把 goal 标成 blocked。
这条逻辑很重要。因为续跑能力越强,越需要可靠的停机机制。没有熔断的 autonomous loop,本质上就是一个 token 焚化炉。
8. 和 Humanize 1.0:不是谁替代谁,而是护栏位置不同
第二篇文章里把 /goal 和 Humanize 1.0 做了对比,这个角度很有价值。
Humanize 1.0 的 RLCR 更像一套外部审查循环:Claude 做实现,Codex 做独立 review,通过 Stop hook 和文件账本把每轮进展、审查意见、下一轮任务串起来。
/goal 则是 Codex 内部的运行时能力:状态在 SQLite,续跑靠线程 idle,完成靠同一个模型在 continuation prompt 约束下自审,然后调用 update_goal。

这里不能简单说谁更高级。
/goal 的优势是轻、快、上下文连续。它不需要每轮重新拉一个进程,也不需要每次把 plan、summary、review 重新灌回上下文。
但它也有明显边界:完成判定还是同一个模型自审。
Humanize 1.0 的优势是外部审查更硬。实现者想说完成,还得过另一个模型审查;状态也落在文件里,更适合事后复盘、diff 和审计。
所以更合理的架构不是二选一,而是叠加:用 /goal 负责长任务保活和预算控制,用外部 review 负责关键交付的独立验收。
这也是工程上更稳的做法。
9. 对 Agent 产品的启发:长任务不是“多跑几轮”这么简单
/goal 这套实现,给所有 Agent 产品一个很清晰的提示。
长任务能力不能只靠一句 prompt。
如果一个 Agent 要真的跑长任务,至少要有五层东西:
1. 目标持久化:目标不能只存在上下文里,要有独立状态;
2. 事件驱动续跑:不是盲目 while loop,而是在安全生命周期点继续;
3. 预算与熔断:知道烧了多少 token,知道什么时候停;
4. 权限分离:模型能声明完成/阻塞,但 pause、resume、clear 等生命周期操作应归用户或系统;
5. 完成审计:不能让“看起来差不多”变成完成。
这五层里,最容易被低估的是第五层。
多数 Agent demo 展示的是“它能一直干”。但真正难的是:它什么时候该停?凭什么说完成?怎么证明不是把目标偷偷改小了?
continuation.md 最有价值的地方就在这里。它没有把完成交给模型的感觉,而是要求模型逐项找证据。
10. 最后的判断
/goal 值得重视,但不要神化。
它确实让 Codex 更接近一个可长跑的工程 Agent:目标有地方放,线程空闲能自动续,预算能算,错误能熔断,模型不能随便改生命周期状态。
但它不是万能自主工程师。
它仍然依赖目标写得是否清楚,验证面是否可执行,测试/benchmark/运行环境是否真的给足。更重要的是,它的完成判定仍然是同模型自审,不是独立对抗审查。
所以,用 /goal 的正确姿势不是:
你随便写个大目标,然后去睡觉。
而是:
写清楚 outcome、verification surface、constraints 和 boundaries,让它长跑;关键结果再用独立 review 或人工验收兜底。
AI Agent 的下一阶段,不是“让模型更努力”,而是给模型一套能长跑、能记账、能刹车、能被审计的运行时。
/goal 的价值就在这里。
引用与核查说明
1. 第一篇微信文章:《codex-goal命令的源码学习》,链接:https://mp.weixin.qq.com/s/q-C40E5s29I2-knLA78YCA。
2. 第二篇微信文章:《Codex goal 代码解读:原生长任务目标的实现,以及它和 Humanize 1.0区别的一点理解》,链接:https://mp.weixin.qq.com/s/J-NvcYCjG5g7QgPt9_jBcA。
3. OpenAI 官方 Cookbook:Using Goals in Codex,链接:https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex。
4. OpenAI Codex 源码:https://github.com/openai/codex。本文本地核查版本为 main 分支 commit 1f0566d,Codex CLI 版本 0.144.1。
5. 关键源码文件:codex-rs/ext/goal/src/extension.rs、runtime.rs、accounting.rs、spec.rs、tool.rs、steering.rs、templates/goals/continuation.md、state/src/runtime/goals.rs、state/src/model/thread_goal.rs。
6. Humanize 1.0 / RLCR 参考仓库:https://github.com/PolyArch/humanize。
📝 觉得有料?点赞、在看、转发走一波
AI · 开源 · 前沿技术,每日更新不掉队 🚀
夜雨聆风