写作

AGENTS.md 与轻量 Spec-driven 协作

与 Coding Agent 长期协作,需要持久的规则与明确的决策,但不意味着每个改动都要写一份 Spec。

第一次和 Coding Agent 协作通常很简单:解释目标,检查结果,指出问题,然后继续。

第十次协作会困难得多。

有些决定留在聊天记录里,有些已经进入代码,还有一些只存在于人的记忆中。新的 Agent 可以读懂仓库,却不知道为什么一个看起来合理的方案在三周前被否决。同一场讨论会重新发生,术语逐渐漂移,测试全部通过,结果却已经偏离产品方向。

这不是 Prompt 问题,而是一次协作如何长期保存决策的问题。

我逐渐发现两个很小、但很有用的机制:一份持续更新的 AGENTS.md,以及只为真正需要的改动准备的轻量 Spec。

三类知识,三个位置

如果把所有上下文都塞进一份巨大的指令文件,协作很快会变得混乱。

我更倾向于区分三类知识:

  • AGENTS.md 保存当前协作规则。 它说明现在应该怎样在这个仓库里工作。
  • Spec 保存某项改动的决策。 它记录问题、预期行为、边界与验收标准。
  • 代码保存实现。 它不应该依赖大段注释重新讲述整场设计讨论。

聊天依然适合探索、争论与快速反馈,却不是可靠的长期 Source of Truth。一项决定一旦能够复用于未来任务,就应该离开对话,进入正确的持久载体。

AGENTS.md 不是项目编年史

有用的 AGENTS.md 更像当前的行动指南,而不是一部宪法。

它应该回答 Agent 会反复遇到的问题:

  • 这个产品正在变成什么?
  • 哪些架构与设计边界是有意保留的?
  • 哪些命令可以提供真正有意义的验证?
  • 什么事情没有明确授权就绝对不能发生?
  • 不同类型的代码与内容应该放在哪里?
  • 哪些已经被否决的方案不应该被随手重新引入?

它不应该把每次修正都追加成一条带日期的新规定。当新共识取代旧共识时,文件也应该直接替换旧规则;重复内容应该合并,已经失效的内容应该删除。

目标不是保留完整的协作故事,而是让下一次正确行动更容易发生。

不是每个需求都需要 Spec

Spec-driven 很容易退化成一种仪式:先写文档,等待批准,实现一个很小的改动,最后维护文档花费的时间比修改产品更多。

这不是严谨,而是把同一套流程施加在风险完全不同的任务上。

一处文案修正、间距调整或局部 Bug,影响范围通常很窄,结果也足够明确。对话本身已经能够完成对齐。

当一项决定会影响多个 Surface,或者回滚成本较高时,Spec 才真正有价值。例如:

  • 重做页面或核心用户路径;
  • 改变导航与信息架构;
  • 引入国际化或新的内容模型;
  • 新增带状态的交互或外部服务;
  • 改变技术栈、部署方式或公开 Contract。

真正的判断问题不是“这项任务重要吗”,而是:

如果双方对它的理解不同,会产生多少歧义、耦合与回滚成本?

Spec 的深度应该与这种风险一起增长。

一份很小的 Spec 通常就足够

大多数产品改动并不需要长篇需求文档。一份有用的轻量 Spec 可以只有几个部分:

  1. 问题与目标——什么应该变得更好,对谁更好?
  2. Non-goals——哪些相邻工作明确不在本次范围?
  3. 行为或内容——用户最终会观察到什么?
  4. 影响范围——哪些页面、Contract、数据或系统会变化?
  5. Acceptance Criteria——什么证据可以证明结果正确?
  6. 验证与发布边界——哪些可以在本地确认,哪些仍需要人的判断或生产验证?

Non-goals 对 Coding Agent 尤其重要。它可以防止一个合理的实现步骤继续扩张成未被请求的重设计、依赖变更、Migration 或清理工作。

Spec 应该减少实现过程中仍需临时做出的决定。如果它只是用更多文字复述需求,就没有产生价值。

Approval 属于决策,而不是文档

写 Spec 的目的不是制造许可。

Approval 表示人和 Agent 已经对真正会产生后果的决定达成一致:方向、范围、取舍,以及需要怎样的证据。如果这些决定在实现过程中发生实质变化,就应该先更新 Spec,再让代码继续走向另一条路径。

小型发现不需要重新发起一轮审批。缺失的类型、更合适的内部命名,或者等价的实现细节,属于工程判断。新增数据来源、改变公开行为或扩大 Release Boundary,则不是。

这样的分工让 Agent 可以在已确认的 Solution 内保持自主,同时把产品 authority 留给人。

Local Acceptance 与 Release 是不同状态

长期 Agent 协作中,最有价值的边界之一,是区分实现、验证、验收与发布。

一条清晰的顺序是:

  1. 对齐高影响决策;
  2. 在确认的范围内实现;
  3. 执行相关技术验证;
  4. 需要主观判断时,由人检查真实结果;
  5. 只有获得明确授权后才 Release。

测试可以证明路由存在、类型有效、Build 成功,却不能证明文案读起来正确、信息层级表达了预期身份,或者一版重设计拥有恰当的克制度。

同样,人说“本地版本看起来不错”,也不应该自动授权部署、域名切换、数据 Migration 或外部通知。这些动作拥有完全不同的后果,应该保持独立。

这种区分不是官僚流程,而是防止技术完成悄悄扩张成外部副作用。

协作本身也需要可维护

我们对代码要求的工程质量,同样适用于 Agent 指令。

它们应该:

  • 内聚:一条规则只有一个明确位置;
  • 最小:真正重要的约束始终可见;
  • 保持当前:失效决策不会继续与新决定竞争;
  • 可以验证:验证命令和验收标准能够产生证据;
  • 范围明确:仓库规则不会变成全局个人偏好;
  • 安全:工具改变外部状态之前,authority 边界已经清楚。

一份只增加、不删除的指令文件,最终会变成另一个 Legacy System。Agent 会选择最支持自己当前行动的那句话,人也会逐渐放弃阅读它。

因此,可维护性比完整性更重要。

意图与代码之间的持久接口

Coding Agent 显著加快了实现速度,但速度也会放大方向模糊的代价。在任何人发现决策错误之前,更多代码已经被生产出来。

AGENTS.md 与轻量 Spec 分别处理这个问题的不同部分:前者保存当前协作规则,后者让一项高影响改动在扩散到整个系统之前变得明确。

它们都不应该试图保存一切。真正的价值,是留下那些未来工作绝不能意外忘记的少数决定。

最终得到的不是一个更听话的 Agent,而是一种不需要反复重新谈判基础、双方依然能够快速前进的协作关系。

文章数据

次阅读条评论

讨论

评论区

关于文章本身,也欢迎留下不同意见或补充。

留下评论

评论会立即公开,并可在当前浏览器中删除。

发布时会进行一次隐私友好的人机验证。