O'Reilly 来稿:智能体开发,规格说明写多少才合适?

Stack Overflow Blog 2026-08-22T02:58:43.966829

我在关于智能体的讨论里反复看到同一个观点:详细的规格说明已经成了旧时代的额外负担。给模型一个粗略的目标,让它自己去探索,把返回的结果修一修,然后继续往前走。听起来很高效,但也把成本藏了起来。

一句简单的提示词(prompt)看起来又便宜又让人心动,因为它能让实现立刻启动。但紧接着就是一轮又一轮的纠错循环:你检查输出、澄清意图、要求修改、重跑测试、发现下一个缺口,然后再来一遍。总得有个人来判断结果究竟符不符合真实目标——这个人就成了"拍板人"(oracle)。

另一个极端是完整的形式化规格,前期的成本显然很高。写验收标准、契约测试,或者行为驱动开发(BDD)场景,都要花不少功夫。但后续成本就不一样了,因为更多的"拍板"变成了可执行的东西。测试每次都会检查同一个条件,它不会在午饭前五分钟觉得累了、赶时间,或者突然乐观起来。

这才是真正的取舍。问题不在于规格说明是好是坏,而在于总成本的最低点落在哪里。对大多数智能体开发来说,这个点在中间偏中间的位置:既要有足够的结构来约束工作,也要有足够的示例让意图变得具体,还要有足够的可执行检查,让评审不至于变成猜谜。

零规格并不是什么智能又精简的做法,它只是成本很高的"凭感觉写代码"(vibe-coding)。

瓶颈转移了,并没有消失

软件工程从来都不是主要关乎敲键盘,甚至也不只是写代码。它真正决定的是:什么应该存在、什么绝不能发生、哪些取舍值得在意,以及当问题触碰到现实世界时,"做完"究竟是什么意思。

多年来,团队是靠人与人之间的摩擦来发现规格缺失的。评审人注意到一个边界情况,测试人员发现了没人描述过的那条路径,资深工程师脑子里装着半数真实需求,然后在一场接一场的会议里慢慢传递出来。这些方式都不优雅,但确实把模糊之处逼到了明面上。

智能体从根本上改变了这一点。它们让实现变得便宜得多、快得多。但这也意味着:一个需求不清的想法,可能在大家还没真正就"这套系统究竟该是什么意思"达成一致之前,就变成一套有模有样的系统了。

旧世界里,需求模糊只会撞上人的迟缓。在智能体世界里,需求模糊则会撞上机器的高速。

这正是规格突然再次变得重要的原因。其实它一直都很重要,只是我们一直把实现成本当作一种粗略的倒逼机制,管最后的结果叫“流程”。

Line graph showing that as implementation automation increases, implementation effort decreases while specification and verification effort rises to become the primary engineering difficulty.

随着实现越来越便宜,更多难题转移到“定义正确”和“可靠地验证正确”上。

光写规格还不够

这是我最常看到大家跳过的一步。他们说起来好像流程很简单:先写规格,然后让智能体去实现。但被漏掉的那一步,恰恰是成本最高的一步。

规格本身需要评审。

即使一份规格写得很仔细,也会以熟悉的方式失效。它可能自相矛盾;可能只覆盖顺利路径,对重试、速率限制、部分失败只字不提;可能描述了听起来很精确、实际却无法验证的行为。有时候,它精确的方向恰恰是错的:它说的是你写下的东西,而不是你真正想表达的东西。

当智能体忠实执行一份有缺陷的规格时,失败反而更难诊断。实现看起来可能很自洽,甚至能通过你提供的检查。但真正的问题在上游——规格本身。所以修复时,你得把代码和推理过程一起拆开梳理。

因此我建议,把规格验证单独立项。在实现开始之前,需要有人问几个朴素的问题:规格内部自洽吗?对这个任务来说足够完整吗?哪些部分是可测试的?我们还在哪些地方依赖人工判断?哪些失败模式因为大家心里默认“应该有”而被漏掉了?

智能体在这里可以帮忙,但前提是我们让它做的事比“写需求”更有价值。这个提示词通常只会产出包装精美的迷雾。更好的提示词要具体得多:

起草一份最小的规格说明,让另一个智能体能够据此安全地实现这项功能。说明中要包含假设、非目标、验收标准、边界情况、可观察结果和待定问题。并标明哪些结论可以转成自动化测试,哪些仍需要人工审核。

草稿写完后,把它交给另一个智能体,让它专门攻击这份结果:

找出其中的矛盾、含糊的术语、隐藏的依赖、无法测试的断言、缺失的故障模式,以及那些「实现结果符合书面标准、却违背原本意图」的地方。

就这么简单的工作流,也能明显降低产出一份值得人工判断的规格说明的成本。

A line graph comparing relative total cost for human-written versus agent-assisted specifications across increasing completeness, showing agent-assisted specs have a lower minimum cost and slower cost increase.

智能体并不会让规格说明变得多余,它只是让「把规格精确到真正有用的程度」这件事变得更便宜了。

为什么多智能体系统需要更严格的契约

单个智能体处理小而明确的任务时,往往能从含糊的指令中自行恢复。循环短、影响范围限于局部,出现偏差时人通常也能把它拉回正轨——甚至偏差刚冒头,人就能轻易发现。

多智能体系统就完全是另一回事了。一旦一个智能体的输出变成另一个智能体的输入,理解偏差就会层层叠加。智能体 B 并不知道智能体 A 对某个需求理解偏了 10%,它只会把收到的输出当作准确信息,继续往下走。等人最终看到结果时,最初的错误可能早已被埋进好几层看起来相当专业的成果之下。

到了这一步,规格说明就不再只是参考,而更像是一份契约。

这种交互契约不能只是一段意图说明,还需要定义数据结构(schema)、不变量、容许的模糊范围、校验规则,以及明确的失败处理行为。很多场景下,还得配套契约测试、类型化接口和可机器校验的交接格式。交接本身就是产品的一部分——这没大家想象的那么光鲜,但更贴近现实。

行为驱动开发(BDD)和可执行的验收测试,也恰恰属于这个范畴。它们的价值不只是方法论本身,而是把一部分「人工判定基准」变成了可重复运行的东西。当行为稳定到可以精确描述时,一份可执行的规格说明,往往比再来一轮人工评审更划算。

折线图:多智能体流水线的总成本在「类型化契约 + 校验器」处达到最低,更强的交接契约一边降低解释漂移,一边推高编写成本。

一旦智能体开始把工作交给另一个智能体,交接本身就需要像真正的接口一样,被定义清楚、被反复校验。

规格说明应该有保质期

团队在这里还会犯另一个错误:他们沿着规格说明的曲线一路加码,好像文字越多就越安全。其实并非如此,至少对当前的大语言模型来说不是。

Chroma 关于 contextrot(上下文退化)的研究,把问题的前半段说清楚了:输入越长,模型的表现就越不稳定,哪怕任务本身很简单。而在编码类项目里,还有第二个问题叠加在上面:塞进上下文的设计文字、示例、计划、注释、工单和旧的验收标准越多,模型就越难分清,哪些部分是给它的指令,哪些只是历史遗留的产物。

严格来说,这不算安全意义上的提示注入(Prompt Injection)。没人故意攻击模型,更像是一种自己造成的指令漂移。上下文里混杂着旧设计意图、当前实现、半失效的示例、三场会话之前生成的计划,甚至可能还有一份早已过期的软件设计文档,里面描述的类早就被删了。到了这一步,模型根本不是在读一份规格说明,而是在多个互相矛盾的信息源之间取平均值。

规格写到这个精细程度,就不再是帮助,而是开始给模型添乱了。智能体根本分不清某段文字到底是当前需求、历史备注,还是已经被代码实现替换掉的内容。

设计文档在项目早期很有用,因为代码还不存在。但到了后期,它就该瘦身。一旦接口、测试和不变量都真正落地,详细的构建计划就应该逐步消失。文档里只留那些代码自己表达不清楚的东西就够了:业务理由、非目标、安全约束、外部契约,以及少数几条你不想靠试错重新发现的不变量。至于那些只是复述类和方法已有功能的文字,直接删掉。

否则,你最终会同时拥有两份规格。人类在评审时会抱怨,而智能体往往会努力同时遵守这两份规格。

API 设计能让代码自己充当规格

这个故事也有更乐观的一面。有些代码库能比其他代码库更快达到「代码即规格」的状态,而 API 设计是其中很大的因素。

如果内部 API 把行为藏在各种约定背后,参数是弱类型的,初始化靠黑魔法,报错全是笼统的一句话,那么智能体就没法把代码当作规格来用。它只能从零散的文字描述和试错中去重建规则。这对人类来说很慢,对模型来说更糟。

反过来也同样成立。一个命名清晰、方法按任务粒度划分、类型严格、校验可读、示例充分、报错有实际指引导向的 API,能让智能体有实实在在的立足点。智能体可以检查 API 的暴露面,看清某个方法做什么,明白什么样的输入合法,出错后不用瞎猜就能恢复——这样的代码本身就承担了绝大部分规格说明的职责。

AI 友好的 API 设计理念,正是在这里体现出实际价值。显式的可发现性,胜过约定俗成。方法应该对应真实任务,而不是逼着智能体去走十几步一碰就断的流程。类型和校验规则,要能说明什么样的输入才是合法的。错误信息应该指向下一步怎么修复,而不是只宣布一句“失败了”。自省能力和示例,能帮助模型从已有的代码库里学会 API 的整体结构。性能的透明度同样重要——如果 API 不透露任何线索,智能体会很乐意在某个昂贵的调用外面,套上一个正确但糟糕透顶的循环。

这不仅仅关乎公开的 SDK,也适用于内部服务边界、库客户端、仓库抽象层,甚至大型 monorepo 里的辅助类。API 越容易被发现和检视,智能体就越容易把代码本身当作权威的规格说明,而不是往上下文里塞进更多文字描述。这些内容我之前写过更详细的文章,感兴趣的话可以翻来看看。

该把精力投在哪里

我坚信,规格说明没有一个统一的“正确数量”。答案取决于你正在做的工作类型。对于一个小而边界清晰的任务,最佳状态通常是结构化的意图:目标、几个示例、明确“不要做什么”(nongoals),以及清晰的验收标准。这通常就足以让智能体保持高效,又不至于让前期准备比任务本身还重。

对于确定性的工作,比如 CRUD 流程、API 集成和数据转换,最佳点则向右移动。这些领域容易约束,也容易测试。多一些规格说明很快就能回本,因为它能减少反复的评审和返工。这正是行为驱动开发(BDD)、契约测试和可执行验收标准最能发挥作用的地方。

而对于探索性的工作,比如架构选型、研究综合或全新的产品想法,最佳点又向左移动。规格说明过度,反而会扼杀智能体最有价值的那份灵活性。这种情况下,我更愿意限定边界而不是限定结果:必须满足什么条件、绝不能发生什么、需要提供什么证据,以及还有哪些决策需要由人来拍板。

对于多智能体流水线(multi-agent pipeline)来说,最优规格量又一次右移。每两个智能体之间的交互边界都需要一份契约。没有契约,你并不是在协调一个系统,而是在堆叠各自的解读,然后指望它们互相抵消。

Four charts show that the optimal specification completeness (the "sweet spot" for minimum total cost) varies by work type: "Intent + constraints" for exploratory work, "Acceptance criteria" for single bounded tasks, "BDD / contract tests" for deterministic work, and "Typed contracts" for multi-agent pipelines.

不存在一个放之四海而皆准的最优规格量。该写多少,取决于工作是探索性的、有明确边界的、确定性的,还是多智能体协作的。

四类场景有一个共通且简单的原则:在扩大实现规模之前,先验证规格。

敏捷和 XP 留下了什么

我不认为 Agent 会让敏捷(Agile)或极限编程(XP,Extreme Programming)变得过时。它们只是让有用的部分更容易和人们早已在忍受的部分区分开来。

最先被淘汰的,是那些主要为了按小时协调人力而存在的“仪式”。每日站会、过度膨胀的待办事项流程,以及那些自信程度远超信息量的工时估算,并不会因为代码由 Agent 所写就变得更有说服力。真要说什么变化,就是它们越来越显得多余。Agent 改变任务形态的速度太快,过去那些工时估算会比以前更快地沦为虚构。这并不意味着规划会消失,而是说规划不能再假装自己

XP 的生命力比想象中更强,因为它从一开始就主张把学习这件事紧贴在代码旁边。测试先行依然有效:实现变得越便宜,可执行的检查就越值钱。持续集成依然重要,智能体的每次改动都需要一道关卡。重构依然重要,因为智能体可以毫无心理负担地写出能跑、能通过几个测试的代码,但留下的结构可能没人愿意下个月去维护。机器没有自尊,它会十足自信地给你产出一团乱麻。

结对编程的形式变了,但内核还在。我依然希望在生成代码的地方,设计判断也近在咫尺。有时表现为一个人直接和一个编码智能体配合;有时表现为一个模型写代码,另一个模型带着更窄的指令做评审。不管哪种形式,结对有价值的从来不是两个人并排坐着各敲各的键盘、中间放杯咖啡,而是在代码定型前快速拿到设计反馈。

小步发布也活了下来,只是理由可能没那么浪漫。当智能体可以廉价地做出极其庞大的改动时,人也倾向于廉价地接受庞大的 diff——这不是好主意。审查、回滚、定位问题,都是小批量更容易办到。一个短命的功能分支,比一个 4000 行的庞然大物好推理得多。

真正褪色的,是把方法论当作安慰剂的做法;真正留下的,是把它当作错误探测器使用。敏捷和 XP 最出色的地方,在于它们让「团队把问题理解错了」这件事的暴露成本变低。这依然是它们的使命。智能体时代只是少了几条借口,多了一些高速犯错的新方式。

真正的杠杆

智能体开发的承诺是真实的。智能体可以把实现成本大幅降低,但代码一旦便宜了,决定项目成与败的地方就转移到了规格和验证上。

杠杆最大的团队,不会是规格写得最少的团队,而是清楚三行要点什么时候够用、什么时候需要一份正式契约、以及契约什么时候必须变成可执行代码的团队。

查看原文