首页 / 资料库 / OpenAI 实践手册

资料库20 分钟读完MITOpenAICodex计划文档

用 PLANS.md 驱动数小时的复杂任务

译自《Using PLANS.md for multi-hour problem solving》 · 查看英文原文

原文出处Using PLANS.md for multi-hour problem solving 原作者:OpenAI · 许可证:MIT License 中文译本由诸葛AI学院整理,仅供学习参考,版权归原作者与 OpenAI 所有。

用 PLANS.md 驱动数小时的复杂任务

Codex 搭配 gpt-5.2-codex 模型(推荐),可以完成那些需要花大量时间调研、设计和实现的复杂任务。本文介绍的这套做法,讲的是怎么用提示词让模型承接这类任务,并把它引向项目的成功交付。

这些计划文档既是详尽的设计文档,也是"活的文档"。作为 Codex 的用户,你可以在它开始漫长的实现过程之前,用这些文档检查它打算走的路子对不对。下文这份 PLANS.md,与那份让 Codex 凭一条提示词连续工作超过七小时的计划几乎一模一样。

要让 Codex 能用上这类文档,先更新 AGENTS.md,写清楚什么时候该用 PLANS.md,然后把 PLANS.md 文件加进仓库。

AGENTS.md

AGENTS.md 是一种简单的格式,用来给 Codex 这类编码智能体(coding agent)指路。这里我们定义一个用户可以当简称用的词,再配一条什么时候使用计划文档的简单规则。我们把它叫作"ExecPlan"(执行计划)。注意这是个随口的叫法,Codex 并没有针对这个词做过训练。给 Codex 写提示词时用这个简称,就能把它指向计划的某个特定定义。

下面是一段写在 AGENTS.md 里、告诉智能体什么时候该用计划的指令(原文为英文,供直接取用):

```md

ExecPlans

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

中文意思是:编写复杂功能或做重大重构时,从设计到实现都要使用 ExecPlan(定义见 .agent/PLANS.md)。

PLANS.md

下面是这份文档的全文。文中的提示词措辞是经过仔细挑选的,目的是给用户足量的反馈,并引导模型精确地按计划落实。你可以按需定制这个文件,增删必填章节。

~~~md

Codex 执行计划(ExecPlans):

本文档规定执行计划(简称 ExecPlan)的要求。执行计划是一份设计文档,编码智能体照着它做,就能交付一个可用的功能或系统改动。请把读者当成对这个仓库一无所知的人:他手里只有当前的工作目录,加上你提供的这一份 ExecPlan 文件。他没有以前任何计划的记忆,也没有外部上下文。

如何使用 ExecPlans 和 PLANS.md

撰写可执行规格(ExecPlan)时,逐字逐句遵守 PLANS.md。如果它不在你的上下文里,把整份 PLANS.md 重读一遍来唤起记忆。写规格时要 thoroughly(彻底)地阅读原始材料,反复读也无妨。创建规格时,先搭骨架,随着调研的深入再往里填肉。

实施可执行规格(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 200,响应体为 OK"),而不是内部属性("新增了一个 HealthCheck 结构体")。如果改动纯粹是内部的事,说明它的影响还能怎么演示出来,比如跑一个改动前失败、改动后通过的测试,再比如演示一个用上新行为的场景。

明确交代仓库上下文。文件用仓库相对路径的完整路径点名,函数和模块要指名道姓,新文件建在哪里也要说清。要动好几个区域时,加一小段导览,说明这些部分怎么衔接,让新手能自信地找到路。写命令时,标出工作目录和完整的命令行。结果依赖环境时,写清楚假设,合理的话给出替代方案。

步骤要幂等、安全。写出来的步骤要能在不造成破坏或漂移的前提下反复执行。某一步可能半途失败,就附上重试或变通的办法。非做不可迁移或破坏性操作时,把备份或安全回退写明白。优先做可测试的增量改动,边做边验证。

验证不是可选项。要包含跑测试的说明、(如果适用)启动系统的方法,以及观察系统做出有用之事的步骤。任何新功能或新能力,都要写全测试方案。给出预期输出和预期报错,让新手分得清成败。尽可能展示怎么证明改动有效,而不只是"能编译":一个小的端到端场景、一次命令行调用、一份 HTTP 请求/响应记录都行。写清楚与本项目工具链匹配的确切测试命令,以及怎么解读结果。

留下证据。步骤产生了终端输出、简短 diff 或日志时,把它们作为缩进示例放进那个唯一的代码块里。要精简,只留能证明成功的内容。需要放补丁时,优先用限定到单个文件的 diff 或小片段;读者照你的说明能自己复现的,就不要粘贴大块内容。

里程碑

里程碑是叙事,不是官僚流程。把工程拆成里程碑时,每个里程碑先用一小段开场:范围是什么,这一段做完会多出什么此前没有的东西,跑什么命令,你预期达到什么验收。让它像故事一样可读:目标、干活、结果、证明。Progress(进展)和里程碑是两回事:里程碑讲故事,进展记细账,两者都得有。绝不为了简短而砍掉里程碑内容,对未来实现可能关键的细节不许省略。

每个里程碑必须能独立验证,并且整体目标的推进要靠它一点点完成。

活文档与设计决策

  • ExecPlan 是活的文档。做出关键设计决策时,更新计划,把决策和背后的思考一起记下来。所有决策都记入 Decision Log(决策日志)一节。
  • ExecPlan 必须包含并持续维护四个章节:Progress(进展)、Surprises & Discoveries(意外与发现)、Decision Log(决策日志)、Outcomes & Retrospective(成果与复盘)。这四节不是可选的。
  • 实现过程中发现了优化器行为、性能取舍、意外 bug,或影响你方案的反向/撤销语义,把这些观察记进 Surprises & Discoveries 一节,配上简短证据(测试输出最好)。
  • 如果在实现中途改变方向,把原因写进 Decision Log,并把由此产生的影响一并写进 Progress。计划既是给你自己用的清单,也是给下一位贡献者用的指南。
  • 完成一个大任务或整份计划时,写一篇 Outcomes & Retrospective:做成了什么、还欠着什么、学到什么。把结果对照最初的目的。

原型里程碑与并行实现

在计划里安排明确的原型里程碑是可以的,常常还值得鼓励:它们能给大改动降风险。例子:给某个依赖库加一个底层算子来验证可行性,或者在测量优化器影响的同时探索两种组合顺序。原型保持增量、可测试。把范围标明是"原型"(prototyping),写清怎么运行、怎么看结果,并说明把它转正或丢弃的判据。

优先做加法式的代码改动,之后再做减法,全程保持测试通过。并行实现(比如迁移期间让一个适配器与旧路径并存)在能降低风险、或能让测试在大迁移期间持续通过时完全可行。写清楚两条路径各自怎么验证,以及怎么安全地用测试护送旧路径退役。涉及多个新库或新功能区域时,可以考虑做若干独立的技术探针(spike),让它们彼此独立地评估可行性:单独验证外部库表现符合预期、单独验证它实现了我们需要的功能。

一份好 ExecPlan 的骨架

# <简短、以动作导向的标题>

这份 ExecPlan 是活的文档。`Progress`、`Surprises & Discoveries`、`Decision Log`、`Outcomes & Retrospective` 四个章节必须随工作推进保持更新。

如果 PLANS.md 文件已签入仓库,在这里写上它从仓库根算起的路径,并注明本文档须按照 PLANS.md 的要求维护。

## 目的 / 全景(Purpose / Big Picture)

用几句话说明这次改动之后能收获什么、怎么看它在工作。写出你要解锁的用户可见行为。

## 进展(Progress)

用带勾选框的列表归纳细粒度步骤。每个停手点都必须记在这里,哪怕要把一个没做完的任务拆成两条("已完成"与"未完成")。这一节必须始终是工作的真实现状。

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

用时间戳来度量推进速度。

## 意外与发现(Surprises & Discoveries)

记录实现过程中发现的意外行为、bug、优化点或洞见。附上简短证据。

- 观察:…
  证据:…

## 决策日志(Decision Log)

按计划工作时做出的每个决策都按下面的格式记录:

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

## 成果与复盘(Outcomes & Retrospective)

在重大里程碑或完工时,总结成果、差距与教训。把结果对照最初的目的。

## 背景与导览(Context and Orientation)

假设读者一无所知,描述与本任务相关的现状。用完整路径点名关键文件和模块,定义你会用到的每个不言自明的术语。不要引用先前的计划。

## 工作方案(Plan of Work)

用散文描述编辑与新增的先后顺序。每次改动,点明文件、位置(函数、模块)以及要插入或修改什么。具体、精简。

## 具体步骤(Concrete Steps)

写出要跑的确切命令和运行位置(工作目录)。命令会产生输出的,附一段简短的预期记录供读者比对。这一节必须随工作推进更新。

## 验证与验收(Validation and Acceptance)

说明怎么启动或操练系统、观察什么。验收写成行为,带上具体的输入和输出。涉及测试的话,写"运行 <项目的测试命令>,预期 <N> 条通过;新测试 <名称> 在改动前失败、改动后通过"。

## 幂等与恢复(Idempotence and Recovery)

步骤能安全重复的,直说。哪一步有风险,给出安全的重试或回滚路径。完工后让环境保持干净。

## 工件与备注(Artifacts and Notes)

把最重要的终端记录、diff 或片段作为缩进示例附在这里。精简,只留能证明成功的内容。

## 接口与依赖(Interfaces and Dependencies)

要给出明确规定。点名用哪些库、模块、服务,以及为什么。指定里程碑结束时必须存在的类型、trait/接口和函数签名。优先使用稳定、可寻址的名字和路径,如 `crate::module::function` 或 `package.submodule.Interface`。例如:

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

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

照着上面的指南写,一个没有记忆的单一智能体,或者一个人类新手,就能从头到尾读完你的 ExecPlan,做出一个能工作、可观察的结果。标准就是这个:自包含、自给自足、新手可照做、以结果为导向。

修订计划时,必须确保改动在所有章节都得到全面的落实,包括那几个活文档章节,并在计划末尾写一条说明,讲清改了什么、为什么改。ExecPlan 几乎对每件事都要写清楚"是什么"之外的"为什么"。 ~~~

这篇在讲什么,跟咱们的课怎么对?

资料库是大厂公开教材的中文译本,偏原理和工程做法。想看面向中小企业的白话版本,去入门课场景课