本文译自 openai/openai-cookbook 仓库 articles/codex_exec_plans.md(commit f581907),原文:articles/codex_exec_plans.md @ f581907;许可:MIT License;版权声明:Copyright (c) 2025 OpenAI;修改说明:翻译为中文并调整排版。MIT 许可全文见来源与许可。

用 PLANS.md 解决需要数小时的问题

Codex 与 gpt-5.2-codex 模型(推荐)可以用于实现复杂任务,这类任务往往需要大量时间进行研究、设计和实现。本文描述的方法,是一种提示模型完成这些任务、并引导它走向成功交付的方式。

这些计划是详尽的设计文档,也是“活文档”。作为 Codex 的用户,你可以在漫长的实现过程开始前,用这些文档核对 Codex 准备采用的方法。下面给出的这份 PLANS.md,与一份曾让 Codex 仅凭单条提示连续工作七个多小时的文档非常接近。

要让 Codex 使用这些文档,我们先更新 AGENTS.md,说明何时使用 PLANS.md,然后把 PLANS.md 文件加入仓库。

AGENTS.md

AGENTS.md 是一种简单格式,用于指导 Codex 这类编程智能体。我们定义一个术语,作为用户可以使用的简写,并给出一条简单规则,说明何时使用计划文档。这里把它称为“ExecPlan”。注意,这是一个任意选定的词,Codex 并没有专门训练过它。这个简写随后可以用于提示 Codex,把它指向某份具体的计划定义。

下面是一段 AGENTS.md 示例,指示智能体何时使用计划:

# ExecPlans

When writing complex features or significant refactors, use an ExecPlan (as described in .agent/PLANS.md) from design to implementation.

PLANS.md

下面是完整文档。文档中的提示经过仔细设计,目的是向用户提供大量反馈,并引导模型精确实现计划所规定的内容。你可能会发现,根据自己的需要定制这份文件、增加或删除必需章节,会更有帮助。

# Codex 执行计划(ExecPlan)

本文档描述执行计划(“ExecPlan”)的要求。ExecPlan 是一份设计文档,编程智能体可以按照它交付可工作的功能或系统变更。请把读者当作对该仓库完全陌生的人:他只有当前工作树和你提供的这一份 ExecPlan 文件,没有先前计划的记忆,也没有外部上下文。

## 如何使用 ExecPlan 与 PLANS.md

编写可执行规格(ExecPlan)时,请**逐字**遵循 PLANS.md。如果它不在你的上下文中,请完整阅读 PLANS.md 以刷新记忆。阅读(并反复阅读)源材料时要彻底,以产出准确的规格。创建规格时,从骨架开始,并在研究过程中逐步填充。

实现可执行规格(ExecPlan)时,不要向用户询问“下一步”;直接推进到下一个里程碑。始终保持所有章节最新;在每个停止点新增或拆分清单条目,明确说明已完成的进度和下一步。自主解决歧义,并频繁提交。

讨论可执行规格(ExecPlan)时,把决策记录到规格内的日志中,供后来者查阅;任何对规格的修改都应清楚地说明原因。ExecPlan 是活文档,任何时候都应能够仅凭 ExecPlan 本身(不依赖其他工作)重新开始。

研究需求棘手或存在重大未知的设计时,用里程碑实现概念验证、“玩具实现”等,以验证用户的方案是否可行。通过查找或获取库的源代码来阅读它们,深入研究,并把原型纳入计划,以指导更完整的实现。

## 要求

不可协商的要求:

* 每份 ExecPlan 必须完全自包含。自包含意味着:以当前形式,它包含新手成功所需的全部知识与指令。
* 每份 ExecPlan 都是活文档。贡献者必须随着进展、发现和设计决策的最终确定而修订它。每次修订都必须保持完全自包含。
* 每份 ExecPlan 必须让完全新手在没有本仓库先验知识的情况下,端到端实现该功能。
* 每份 ExecPlan 必须产生可证明可工作的行为,而不仅仅是“满足定义”的代码改动。
* 每份 ExecPlan 必须用平实语言定义每一个术语,否则就不要使用该术语。

目的与意图优先。开头先用几句话说明:从用户角度看,这项工作为什么重要;完成这次改动后,人们能做到哪些此前做不到的事;以及如何看到它工作。然后引导读者走完达成结果的确切步骤,包括改什么、运行什么、应当观察到什么。

执行计划的智能体可以列文件、读文件、搜索、运行项目和跑测试。它不知道任何先前的上下文,也无法从更早的里程碑推断你的意思。任何你依赖的假设都要重复说明。不要指向外部博客或文档;如果某项知识是必需的,就用你自己的话把它写进计划。如果一份 ExecPlan 建立在另一份已提交的 ExecPlan 之上,可以引用它;如果没有提交,就必须把那份计划中的相关上下文全部包含进来。

## 格式

格式与封装简单而严格。每份 ExecPlan 必须是单个标记为 `md` 的围栏代码块,以三个反引号开始和结束。不要在其中嵌套额外的三反引号代码块;需要展示命令、终端记录、diff 或代码时,请在这一个围栏内用缩进块表示。用缩进而不是内部代码围栏来保持清晰,避免提前关闭 ExecPlan 的围栏。每个标题后空两行,正确使用 `#`、`##` 等层级,以及有序、无序列表的语法。

当把 ExecPlan 写入 Markdown(`.md`)文件,且文件内容**只有**这一份 ExecPlan 时,应省略三反引号。

用平实散文写作。优先使用句子而不是列表。避免清单、表格和长枚举,除非简短表达会掩盖含义。清单只允许出现在 `Progress` 章节,并且在那里是必需的。叙述性章节必须保持以散文为主。

## 指南

自包含与平实语言至关重要。如果你引入一个并非日常英语的词(“daemon”“middleware”“RPC gateway”“filter graph”),要立即定义它,并提醒读者它在本仓库中如何体现(例如指出它出现的文件或命令)。不要说“如前文所定义”或“根据架构文档”。把需要的解释写在这里,即使重复自己。

避免常见的失败模式。不要依赖未定义的术语。不要把“功能的字面要求”描述得过于狭窄,以至于代码虽然能编译却没有任何有意义的行为。不要把关键决策推给读者。存在歧义时,在计划本身中解决,并解释为什么选择这条路径。宁可多解释用户可见的效果,少规定无关紧要的实现细节。

用可观察的结果锚定计划。说明实现后用户可以做什么、要运行哪些命令、应当看到什么输出。验收标准应写成人类可以验证的行为(例如“启动服务后,访问 [http://localhost:8080/health](http://localhost:8080/health) 返回 HTTP 200,响应体为 OK”),而不是内部属性(例如“新增了 HealthCheck 结构体”)。如果改动是内部的,也要说明如何证明它的影响(例如运行改动前失败、改动后通过的测试,并展示一个使用新行为的场景)。

明确写出仓库上下文。用完整的仓库相对路径命名文件,精确命名函数与模块,说明新文件应创建在哪里。如果涉及多个区域,加一段简短的导览,解释这些部分如何拼在一起,让新手能够自信地浏览。运行命令时,给出工作目录和完整命令行。结果依赖环境时,说明假设,并在合理时给出替代方案。

保持幂等与安全。把步骤写成可以多次运行而不造成损坏或漂移。如果某一步可能中途失败,说明如何重试或调整。如果必须执行迁移或破坏性操作,写清备份或安全回退方案。优先选择可增量、可测试、可随做随验的改动。

验证不是可选项。写明如何运行测试、如何启动系统(如适用),以及如何观察它做出有用的行为。对任何新功能或新能力,描述完整的测试方式。给出预期输出和错误信息,让新手能区分成功与失败。尽可能证明改动在编译之外确实有效(例如一个小型端到端场景、一次 CLI 调用,或一段 HTTP 请求/响应记录)。给出适合项目工具链的确切测试命令,并说明如何解读结果。

保留证据。步骤产生终端输出、简短 diff 或日志时,把它们作为缩进示例放进同一个围栏块。保持简洁,聚焦于能证明成功的内容。如果需要包含补丁,优先给出按文件划分的 diff 或小段摘录,让读者能按照你的说明重建,而不是粘贴大块内容。

## 里程碑

里程碑是叙述,不是官僚流程。如果把工作拆成多个里程碑,先用一段简短文字介绍每个里程碑的范围、结束时会出现哪些此前不存在的东西、要运行哪些命令,以及预期观察到什么验收结果。让它读起来像一个故事:目标、工作、结果、证明。进度与里程碑不同:里程碑讲述故事,进度跟踪细粒度工作。两者都必须存在。不要为了简短而省略里程碑,也不要漏掉对未来实现可能至关重要的细节。

每个里程碑都必须可以独立验证,并逐步实现执行计划的总体目标。

## 活计划与设计决策

* ExecPlan 是活文档。做出关键设计决策时,更新计划,记录决策本身以及背后的思考。把所有决策记录在 `Decision Log` 章节。
* ExecPlan 必须包含并维护 `Progress`、`Surprises & Discoveries`、`Decision Log` 和 `Outcomes & Retrospective` 章节。这些不是可选项。
* 当你发现影响实现方式的优化器行为、性能取舍、意外缺陷,或反向/撤销语义时,把观察记录到 `Surprises & Discoveries`,并附上简短证据(测试输出最理想)。
* 如果实现中途改变方向,在 `Decision Log` 中记录原因,并在 `Progress` 中反映其影响。计划既是你自己的清单,也是下一位贡献者的指南。
* 完成重大任务或整个计划时,写一条 `Outcomes & Retrospective`,总结取得了什么、还剩什么、学到什么。

# 原型里程碑与并行实现

当原型能够降低较大改动的风险时,加入明确的原型里程碑是可以接受的,而且通常值得鼓励。例子包括:给依赖项增加一个底层算子以验证可行性,或探索两种组合顺序并测量优化器效果。保持原型可增量、可测试。清楚标注其范围为“原型”,说明如何运行和观察结果,并给出提升为正式实现或丢弃原型的标准。

优先做增量式代码改动,随后再做减法,并保持测试通过。并行实现(例如迁移期间在旧路径旁保留一个适配器)在能够降低风险或让测试在大规模迁移期间继续通过时是可以的。说明如何验证两条路径,以及如何借助测试安全地淘汰其中一条。面对多个新库或新功能区域时,可以考虑分别建立 spike,**独立**评估各项功能的可行性,证明外部库按预期工作,并在隔离环境中实现所需能力。

## 一份好 ExecPlan 的骨架

    # <简短、面向行动的描述>

    本 ExecPlan 是活文档。随着工作推进,`Progress`、`Surprises & Discoveries`、`Decision Log` 和 `Outcomes & Retrospective` 章节必须保持最新。

    如果 PLANS.md 已提交到仓库,请在此处引用从仓库根目录到该文件的路径,并注明本文档必须按照 PLANS.md 维护。

    ## 目的 / 全景

    用几句话说明:这次改动之后,人们能获得什么,如何看到它工作。写清你将启用的用户可见行为。

    ## 进度

    用带复选框的列表总结细粒度步骤。每个停止点都必须记录在这里,即使这意味着把一个部分完成的任务拆成两项(“已完成”与“剩余”)。本章节必须始终反映工作的实际当前状态。

    - [x](2025-10-01 13:00Z)示例:已完成的步骤。
    - [ ] 示例:未完成的步骤。
    - [ ] 示例:部分完成的步骤(已完成:X;剩余:Y)。

    用时间戳衡量进展速度。

    ## 意外与发现

    记录实现过程中发现的意外行为、缺陷、优化或洞见。提供简洁证据。

    - 观察:……
      证据:……

    ## 决策日志

    按以下格式记录制定计划期间做出的每一个决策:

    - 决策:……
      理由:……
      日期/作者:……

    ## 结果与回顾

    在重大里程碑或完成时,总结结果、差距与经验教训。把结果与最初的目的进行对比。

    ## 上下文与导览

    假设读者一无所知,描述与当前任务相关的现状。用完整路径命名关键文件与模块。定义你将使用的任何非显然术语。不要引用先前的计划。

    ## 工作计划

    用散文描述编辑与新增的顺序。对每一处编辑,写明文件与位置(函数、模块),以及要插入或修改什么。保持具体、最小。

    ## 具体步骤

    写明要运行的确切命令,以及在哪里运行(工作目录)。命令产生输出时,给出简短的预期终端记录,供读者对照。本章节必须随着工作推进而更新。

    ## 验证与验收

    说明如何启动或操作该系统,以及应当观察什么。用行为描述验收,给出具体输入与输出。如果涉及测试,写明“运行 <项目的测试命令>,预期 <N> 项通过;新增测试 <名称> 在改动前失败,改动后通过”。

    ## 幂等与恢复

    如果步骤可以安全重复,请说明。如果某一步有风险,提供安全的重试或回滚路径。完成后保持环境干净。

    ## 产物与备注

    把最重要的终端记录、diff 或片段作为缩进示例放在这里。保持简洁,聚焦于能证明成功的内容。

    ## 接口与依赖

    要给出明确规定。命名要使用的库、模块与服务,并说明原因。指定里程碑结束时必须存在的类型、trait/接口与函数签名。优先使用稳定名称与路径,例如 `crate::module::function` 或 `package.submodule.Interface`。例如:

    在 crates/foo/planner.rs 中定义:

        pub trait Planner {
            fn plan(&self, observed: &Observed) -> Vec<Action>;
        }

如果你遵循上面的指导,一个无状态的智能体——或者一个完全陌生的人类——就可以从上到下读完你的 ExecPlan,并产出可工作的、可观察的结果。这就是标准:自包含、自给自足、能引导新手、以结果为中心。

修订计划时,必须确保改动全面反映在所有章节中,包括活文档章节,并在计划末尾写一条说明,描述改了什么以及为什么。ExecPlan 不仅要描述做什么,还要几乎对每件事说明为什么。

译者附注(原创,不属于译文)

这份文章的重点不是某个具体配置项,而是“先写计划、再让智能体执行”的协作方式。实际使用时,建议把 PLANS.md 放在仓库中固定位置,并在 AGENTS.md 里用一条短规则指向它;计划本身保持可独立阅读,不要把关键背景只留在聊天记录里。

本站另有一篇 AGENTS.md 写法要点,可与本文配合阅读。