我的 Codex 最佳实践:把一句需求变成可验收的工程结果

从任务契约、Plan、AGENTS.md、Skills、线程与 Worktree,到 Goal、Review 和 Automation,整理一套适合日常开发的 Codex 协作方法。

本文使用humanizerdocumd-visuals

我最早使用 Codex 时,习惯把它当成一个更能干的聊天框:描述需求,等它生成代码,哪里不对再补一句。简单修改通常没有问题,任务一复杂,结果就开始不稳定。它可能正确地修改了错误的模块,也可能完成主要逻辑,却漏掉构建、移动端和旧数据兼容。

后来我用 Codex 搭建并持续修改这个博客。从项目初始化、页面布局、文章专栏、域名部署,到长文写作和图片制作,同一个项目里既有代码任务,也有内容任务和浏览器操作。这段过程让我意识到,代码生成能力很少成为限制。结果更多取决于工作环境:它这一轮能看到什么,哪些决定已经确定,哪里不能动,以及用什么证据判断完成。

我现在使用 Codex 的基本方法可以压缩成一句话:

先把任务变成一份可执行的契约,再让 Agent 在真实反馈中循环,直到证据说明它已经完成。

这篇文章记录我的具体做法。它不是一套必须照抄的仪式。小改动直接做,复杂任务才增加 Plan、状态文件、Worktree 或 Goal。流程的重量应当跟着不确定性增长。

我的 Codex 协作循环:从任务契约到证据验收

一、先写任务契约,不追求万能 Prompt

我以前会花时间润色 Prompt,希望靠措辞让模型一次答对。现在我更关心五件事:

Outcome      最后要得到什么结果
Context      这次优先看哪些事实
Boundaries   哪些地方不能动
Evidence     用什么证明已经完成
Escalation   遇到什么情况必须停下来问我

例如,“把文章页优化一下”几乎把所有决定都留给了 Codex。更可执行的版本会像这样:

目标:调整文章页的桌面布局,让正文保持主视觉中心。

上下文:
- 页面模板在 src/layouts/PostLayout.astro;
- 左侧是专栏目录,右侧是文章目录;
- 参考当前 RAG 文章的实际页面。

边界:
- 不改移动端结构;
- 不改变文章 Markdown 格式;
- 不引入新的 UI 依赖;
- 保留目录滚动高亮。

完成条件:
- 1440px 和 1920px 下两侧留白更均衡;
- 目录与正文不重叠;
- npm run build 通过;
- 打开一篇长文,检查顶部、正文中段和文章末尾。

如果需要重写整个布局组件,先说明原因和影响,不要直接实现。

这类任务描述没有什么神奇句式。它只是把隐含信息搬到了 Codex 能读到的地方。目标控制方向,上下文减少无效搜索,边界避免顺手重构,完成条件给出停止标准,升级条件保留需要人判断的决策。

我不再要求每条 Prompt 都覆盖整个项目。当前模型已经能主动浏览仓库,重复塞入大量背景会挤占有用的上下文。只提供本次任务最可能需要的入口,其余部分让 Codex 按证据继续查找。

二、复杂任务先 Plan,但不要为了 Plan 而 Plan

以下任务适合先规划:

  • 需求有多种合理解释;
  • 会修改多个模块或公共接口;
  • 需要兼顾兼容、迁移或回滚;
  • 我还不确定根因,只知道现象;
  • 执行时间会跨越多个检查点。

Plan 阶段我希望 Codex 回答四个问题:

  1. 当前系统实际上怎样工作?
  2. 哪些事实已经确认,哪些仍是推测?
  3. 有哪些实现选择,需要我决定什么?
  4. 每一步如何验证,失败后如何退回?

我常用的起手式是:

先不要改代码。

读取相关实现,梳理当前链路,并列出仍然影响方案的不确定项。
给出一个推荐方案和必要的备选方案,说明改动范围、兼容风险、
验证方式和回滚路径。只有会显著改变行为或范围的问题才问我,
其余问题基于仓库证据给出默认判断。

“先不要改代码”只适合尚未完成方案对齐的阶段。计划已经清楚后,我会明确让它继续实现和验证,避免 Codex 把每个安全的小决定都重新抛回来。

小任务则直接做。改一个错别字、调整一个已确定的 CSS 值、补一条原因明确的测试,不需要生成一份正式计划。OpenAI 在近期 Codex 指南里也反复强调精简上下文:更强的模型并不需要在每次修改前阅读全部架构资料,也不需要为局部改动执行一整套重型流程。

三、AGENTS.md 只放长期有效的协作规则

Prompt 只负责本次任务,AGENTS.md 保存反复出现的仓库约定。例如:

# Repository guide

## Structure
- src/content/posts/:文章正文
- src/config/sections.ts:专栏和二级分类的唯一配置入口
- public/images/posts/:文章配图

## Validation
- 修改代码或内容后运行 npm run build
- 改动文章布局时检查一篇短文和一篇长文

## Boundaries
- 不改写已有文章,除非任务明确要求
- 不覆盖用户未提交的修改
- 不新增依赖,除非现有方案无法完成任务

## Context routes
- 涉及部署时读取 docs/deployment.md
- 涉及文章排版时读取 docs/article-layout.md

它更像仓库里的路由表和协作协议,不是知识百科。适合写进去的内容包括:

  • 目录职责和权威配置入口;
  • 常用构建、测试、Lint 命令;
  • 不能轻易跨越的系统边界;
  • 代码风格之外的工程习惯;
  • 不同任务应该读取哪份专题文档。

不要把一次需求的实现细节永久写入 AGENTS.md,也不要强制所有任务阅读全部文档。OpenAI 近期对 AGENTS.md 的建议很直接:说明文档在什么场景下需要读取,比要求每次都完整读取更节省上下文。

我的维护规则很朴素。如果 Codex 因为缺少同一条仓库事实连续犯错,我才考虑把它写进 AGENTS.md。如果某条规则已经过期,或者模型通过代码就能轻易判断,我会删掉它。规则数量不是成熟度指标。

四、Skills 保存方法,项目文档保存事实

我一开始很容易把 Skill 理解成“更长的 Prompt”。使用一段时间后,两者的边界越来越清楚。

项目文档记录这个仓库的事实,例如模块结构、业务约束和部署方式。Skill 记录一类任务应该怎样完成,例如:

  • 技术文章如何调研、写作和检查引用;
  • UI 修改如何截图、比较断点并做视觉验收;
  • 故障排查如何收集证据、定位根因和验证修复;
  • 数据库迁移如何检查兼容性并准备回滚。

一份实用 Skill 通常不只有 SKILL.md:

article-writing/
├── SKILL.md
├── references/
│   ├── style-guide.md
│   └── source-policy.md
├── scripts/
│   └── check-links.sh
└── assets/
    └── article-template.md

主文件只说明触发条件和流程路由,需要时再读取 reference、运行 script、复用 asset。这种渐进式加载比一个塞满所有细节的 Skill 更稳定。

我判断一个流程是否值得做成 Skill,会看三个条件:它是否重复出现,步骤是否已经跑通,结果能否验证。还在探索的方法先留在普通线程里。没有验证过的流程过早封装,只会让错误变得更容易重复。

五、一个线程只承载一个可以收口的目标

线程不是越长越有上下文。长线程会同时积累有效决定、废弃方案、临时猜测和已经修复的错误。当任务目标变化后,这些历史内容仍可能影响下一次判断。

我现在按“可验收结果”划分线程,而不是按项目划分线程。同一个博客项目可以有这些独立线程:

调整文章页三栏布局
撰写 SDD 文章并加入 AI Coding 专栏
接入自定义域名
审查本轮改动并修复移动端回归

它们共享仓库,却有不同的完成条件。混在一起后,UI 讨论、文章素材和部署状态会互相污染。

以下信号出现时,我倾向于新开线程或从当前线程 fork:

  • 目标从分析变成实现,或者从实现变成独立 Review;
  • 改动文件集合明显变化;
  • 原有边界被推翻,需要重新做方案;
  • 连续几轮都在解释“不是这个意思”;
  • 已经无法用一句话说明当前完成条件。

线程切换前,把仍然有效的信息写进仓库。需要保存的是结论和当前状态,不是完整聊天记录。

六、长任务把状态写到线程之外

普通任务依靠 Git diff、测试和任务列表已经足够。跨越多轮、多个里程碑的任务,需要一份可以重新进入的状态记录。

我会使用轻量的 STATUS.md:

# 当前状态

## 已完成
- 确认文章目录由 IntersectionObserver 驱动高亮
- 修复点击标题后 URL 锚点不随滚动更新的问题

## 验证
- npm run build 通过
- RAG 和 Harness 两篇长文完成滚动检查

## 风险
- Safari 上尚未检查快速连续滚动

## 下一步
- 补充移动端目录折叠测试

状态文件只保留当前有效事实。过程流水账、已经否定的猜测和大段命令输出没有必要长期留在这里。

对于路径不确定、需要持续实验,但完成条件可以量化的任务,我会考虑 Codex 的 Goal。普通 Prompt 描述下一步,Goal 描述最终必须成立的状态。例如:

/goal 将文章页 Lighthouse accessibility 提升到 95 以上,
以桌面端和移动端两次报告为证据,同时保持 npm run build 通过。
只修改文章布局和公共样式。每轮记录分数变化与下一项实验;
如果三轮修改没有改善,停止并列出证据与阻塞点。

Goal 适合性能优化、迁移、偶现测试排查和多轮研究。一次性编辑、简短解释或边界模糊的任务不适合。Goal 会让目标持续存在,却不能替代清楚的验收面。

七、Worktree 解决并行修改的隔离问题

如果两项工作会修改代码,我不会仅因为“它们可以同时做”就把它们放进同一个工作区。Git worktree 给每个任务独立目录和分支,Codex 可以并行读取、修改和测试,而不污染我正在使用的 checkout。

情况 使用本地工作区 使用 Worktree
和我一起快速迭代当前页面 合适 没有必要
独立补一组测试 可以 适合后台执行
大范围重构或依赖升级 风险较高 更容易审查和丢弃
两个任务会修改同一批文件 不宜并行 仍需调整任务边界
纯调研或代码解释 合适 通常没有必要

Worktree 解决文件和 Git 状态隔离,无法解决逻辑冲突。两个 Agent 同时重新设计同一接口,即使分支不同,最后合并仍然困难。并行前要先按模块、文件所有权或交付物切开任务。

我把本地工作区留给需要频繁看页面、即时纠偏的前台任务。边界清楚、可以独立验证的工作交给 Worktree,例如补测试、整理文档、做只读审查或尝试一个可丢弃的方案。

八、实现完成后,让 Codex 换到 Reviewer 视角

“代码写完”只说明生成阶段结束。验收阶段我会把 Codex 当成 Reviewer,要求它重新读取任务目标和 diff:

现在不要继续扩展功能。请以 reviewer 视角检查当前 diff:

1. 是否完整满足原始目标和完成条件;
2. 是否有超出范围的修改;
3. 是否存在兼容、性能、安全或可访问性风险;
4. 测试是否覆盖最可能回归的路径;
5. 哪些部分仍需要人工检查。

发现确定问题可以直接修复并重新验证;
涉及产品取舍或扩大范围时先列出来,不要自行决定。

Reviewer 视角仍然可能继承作者的盲点,所以证据必须来自仓库和运行结果。我至少会检查:

  • git diff 是否只包含预期文件;
  • 相关测试、类型检查、Lint 和构建是否通过;
  • 用户可见行为是否真实打开过;
  • 错误路径、空状态和边界输入是否覆盖;
  • Codex 说的“已修复”能否由测试或页面证明。

界面任务尤其不能只看构建。构建成功证明代码能编译,不证明布局好看。需要打开页面、检查关键断点,有参考图时还要做视觉比较。

九、把权限边界写清楚,让它在边界内持续工作

过度放权会造成越界,过度确认也会把 Agent 退化成需要不断点击“继续”的脚本。我会把决定分成两类。

Codex 可以自行处理:

  • 读取仓库和运行只读检查;
  • 修改任务范围内的文件;
  • 运行已有的本地测试和构建;
  • 修复由本次改动引起的测试失败;
  • 在不改变外部行为时做必要的小调整。

Codex 需要停下来确认:

  • 删除数据或大批文件;
  • 修改公共接口、数据库结构或线上配置;
  • 安装生产依赖;
  • 向外部服务提交信息;
  • 发现原目标无法实现,需要扩大范围。

这份边界可以放在任务 Prompt,也可以把长期部分写进 AGENTS.md。清楚的授权比“凡事都问”更安全,因为 Agent 知道哪些路径可以持续推进,哪些动作必须由人拍板。

十、自动化只放大已经稳定的流程

Codex 的 Automation 很适合周期性工作,例如依赖风险扫描、CI 失败初步归因、每周文档链接检查和固定格式的状态汇总。但我不会把第一次尝试的任务直接设成 Automation。

我的顺序是:

普通线程手动跑通
        ↓
整理成可重复的 Skill
        ↓
连续几次得到稳定结果
        ↓
再交给 Automation 定期运行

进入自动化前,我会检查输入是否稳定、完成条件是否明确、失败是否能被发现,以及结果是否容易 Review。自动化应当输出可审查的报告或 diff,而不是静默地修改大量状态。

十一、按任务规模选择工作流

我不为所有工作套同一个模板。现在大致分成三档。

小任务:直接实现

适合局部且确定的修改:

任务契约
  → 修改
  → 运行相关检查
  → 汇报 diff 与证据

中型任务:Plan 后实现

适合涉及多个文件、存在少量技术选择的功能:

任务契约
  → 读取仓库并做 Plan
  → 确认边界
  → 分步实现与验证
  → Review diff

长任务:外化计划和状态

适合迁移、重构、性能优化或多阶段建设:

Spec / Goal
  → Plan 与里程碑
  → Worktree 隔离
  → 每个里程碑验证
  → 更新 STATUS
  → 收敛 Review

我根据不确定性、持续时间、修改冲突和验收成本,决定是否使用 Skill、Goal 或 Worktree。

十二、一套可以直接复制的 Codex 请求

下面这个模板覆盖了我最常用的信息。小任务可以删掉不需要的部分。

## 目标
<描述最终可观察的结果>

## 上下文
- <优先读取的文件、报错、页面或历史实现>
- <当前已经确认的事实>

## 范围与边界
- 允许修改:<目录或模块>
- 不要修改:<公共接口、数据结构或无关代码>
- 不新增:<依赖、服务或抽象>

## 工作方式
- 先检查现有实现,再决定修改点
- 复杂或高风险时先给计划
- 在范围内持续实现、测试和修复,不必逐步等待确认
- 需要扩大范围或做不可逆操作时停下来说明

## 完成条件
- <具体行为>
- <测试、构建或基准命令>
- <需要人工查看的页面或 diff>

## 交付
- 说明改了什么
- 列出验证结果
- 指出剩余风险和没有验证的部分

模板不必填满,完成条件却必须可以验证。“优化一下”“更合理”“最好看一点”都可以作为讨论起点,却不能作为 Agent 的终点。

十三、我的最终判断标准

我评价一次 Codex 协作,不看它写了多少代码,也不看对话持续了多久。我只看以下结果:

  1. 它是否正确理解了我要改变的行为;
  2. diff 是否保持在约定范围内;
  3. 关键判断是否来自代码、文档和运行结果;
  4. 测试、构建、页面或基准能否证明完成;
  5. 下一位接手的人能否理解改动和剩余风险。

Codex 会随着模型升级变得更能自主判断,旧的繁琐指令也需要持续清理。稳定的方法不会依赖某一句万能 Prompt。给出清楚的终点,提供与任务相关的上下文,保留需要人决定的边界,再让证据决定什么时候结束。这套方法既适用于十分钟的小修复,也能扩展到持续数小时的工程任务。

参考资料