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 可以只有几个部分:
- 问题与目标——什么应该变得更好,对谁更好?
- Non-goals——哪些相邻工作明确不在本次范围?
- 行为或内容——用户最终会观察到什么?
- 影响范围——哪些页面、Contract、数据或系统会变化?
- Acceptance Criteria——什么证据可以证明结果正确?
- 验证与发布边界——哪些可以在本地确认,哪些仍需要人的判断或生产验证?
Non-goals 对 Coding Agent 尤其重要。它可以防止一个合理的实现步骤继续扩张成未被请求的重设计、依赖变更、Migration 或清理工作。
Spec 应该减少实现过程中仍需临时做出的决定。如果它只是用更多文字复述需求,就没有产生价值。
Approval 属于决策,而不是文档
写 Spec 的目的不是制造许可。
Approval 表示人和 Agent 已经对真正会产生后果的决定达成一致:方向、范围、取舍,以及需要怎样的证据。如果这些决定在实现过程中发生实质变化,就应该先更新 Spec,再让代码继续走向另一条路径。
小型发现不需要重新发起一轮审批。缺失的类型、更合适的内部命名,或者等价的实现细节,属于工程判断。新增数据来源、改变公开行为或扩大 Release Boundary,则不是。
这样的分工让 Agent 可以在已确认的 Solution 内保持自主,同时把产品 authority 留给人。
Local Acceptance 与 Release 是不同状态
长期 Agent 协作中,最有价值的边界之一,是区分实现、验证、验收与发布。
一条清晰的顺序是:
- 对齐高影响决策;
- 在确认的范围内实现;
- 执行相关技术验证;
- 需要主观判断时,由人检查真实结果;
- 只有获得明确授权后才 Release。
测试可以证明路由存在、类型有效、Build 成功,却不能证明文案读起来正确、信息层级表达了预期身份,或者一版重设计拥有恰当的克制度。
同样,人说“本地版本看起来不错”,也不应该自动授权部署、域名切换、数据 Migration 或外部通知。这些动作拥有完全不同的后果,应该保持独立。
这种区分不是官僚流程,而是防止技术完成悄悄扩张成外部副作用。
协作本身也需要可维护
我们对代码要求的工程质量,同样适用于 Agent 指令。
它们应该:
- 内聚:一条规则只有一个明确位置;
- 最小:真正重要的约束始终可见;
- 保持当前:失效决策不会继续与新决定竞争;
- 可以验证:验证命令和验收标准能够产生证据;
- 范围明确:仓库规则不会变成全局个人偏好;
- 安全:工具改变外部状态之前,authority 边界已经清楚。
一份只增加、不删除的指令文件,最终会变成另一个 Legacy System。Agent 会选择最支持自己当前行动的那句话,人也会逐渐放弃阅读它。
因此,可维护性比完整性更重要。
意图与代码之间的持久接口
Coding Agent 显著加快了实现速度,但速度也会放大方向模糊的代价。在任何人发现决策错误之前,更多代码已经被生产出来。
AGENTS.md 与轻量 Spec 分别处理这个问题的不同部分:前者保存当前协作规则,后者让一项高影响改动在扩散到整个系统之前变得明确。
它们都不应该试图保存一切。真正的价值,是留下那些未来工作绝不能意外忘记的少数决定。
最终得到的不是一个更听话的 Agent,而是一种不需要反复重新谈判基础、双方依然能够快速前进的协作关系。


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