Stack Overflow Blog

Dispatches from O'Reilly: The right amount of spec for agentic development

8.5内容质量

TL;DR · AI 摘要

代理开发需平衡规格说明的详细程度,过度简化或过度设计均存在成本陷阱,审查规格本身是关键步骤。

核心要点

  • 零规格开发是'成本幻觉',实际需要可执行的检查机制
  • 代理开发使模糊需求通过机器速度加速实现,反而提高规格必要性
  • 规格审查成本常被低估,需纳入开发流程核心环节

结构提纲

按章节快速跳转。

  1. 代码成本降低后,定义'正确'的标准成为新挑战。

  2. 过度简化导致验证成本激增,过度设计增加前期投入。

  3. 传统人力摩擦消失后,模糊需求通过代理加速实现。

  4. 规格本身需要系统性审查,这是常被忽视的关键步骤。

  5. 实施成本下降后,验证标准制定成为主要成本中心。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • 代理开发的规格平衡
    • 成本权衡
      • 过度简化风险
      • 过度设计成本
    • 瓶颈转移
      • 人力摩擦消失
      • 机器速度放大需求模糊性
    • 关键步骤
      • 规格审查必须化
      • 验证标准重构

金句 / Highlights

值得收藏与分享的关键句。

#agentic development#软件工程#规格说明#AI开发
打开原文

O'Reilly动态:代理开发中恰到好处的规格说明

2026年8月21日

O'Reilly动态:代理开发中恰到好处的规格说明

当代码变得廉价时,真正的挑战变成了定义"正确"的含义,并建立可靠的方式来验证它。

[

在关于代理的讨论中,我反复看到同样的观点:详尽的规格说明已成为旧时代的负担。给模型一个粗略的目标,让它自行探索,修正返回结果,继续推进。这听起来高效,却隐藏着成本。

简单的提示看似廉价且诱人,因为它能立即启动实现过程。但随后会进入修正循环:你审查输出、澄清意图、要求修改、重新运行测试、发现下一个漏洞,然后重复这个过程。最终仍需有人判断结果是否符合真实目标,这个人就变成了"神谕"。

在另一个极端,完整的正式规格说明显然前期成本高昂。编写验收标准、契约测试或行为驱动开发(BDD)场景需要大量工作。但后续成本的差异在于,更多"神谕"内容可以被自动化执行。测试每次都会检查相同条件,它不会疲倦、不会仓促,也不会在午餐前五分钟变得乐观。

这才是真正的权衡点。问题不是规格说明本身好坏,而是总成本最低点在哪里。对于大多数代理开发工作,答案往往在中间地带:提供足够的结构约束工作范围,提供足够的示例使意图具体化,提供足够的可执行检查,避免审查变成猜测。

零规格说明既不智能也不精简,只是代价高昂的氛围编码。

瓶颈转移了,而非消失

软件工程从未主要关于打字或编写代码。它关乎决定什么应该存在,什么永远不该发生,哪些权衡至关重要,以及当问题触及现实世界时"完成"意味着什么。

多年来,团队通过人为摩擦发现缺失的规格说明。审阅者注意到边缘情况,QA发现了无人描述的路径,资深工程师在脑海中保存着真实需求的一半,并在每次会议中逐步翻译出来。这些方式并不优雅,但确实将模糊性暴露在阳光下。

代理从根本上改变了这一点。它们使实现过程更廉价更快。这也意味着,一个定义模糊的构想可能在任何人真正达成系统含义共识之前,就变成一个看似合理的系统。

在旧时代,模糊需求会撞上人类的缓慢。在代理时代,模糊需求会撞上机器的高速。

这就是为什么规格说明突然再次变得重要。它一直都很重要。我们过去只是用实现成本作为粗暴的强制函数,并将结果称为流程。

当实现成本降低时,更多困难转移到了定义"正确"含义并可靠验证的环节。

当代理忠实地执行有缺陷的规范时,故障会更难诊断。实现可能看起来是连贯的,甚至可能通过你提供的检查。但真正的问题其实出现在上游的规范中,因此修复它意味着需要回溯代码并共同推理。

这就是为什么我认为规范验证应该单独作为一个项目条目。在开始实现之前,有人需要提出几个简单的问题:这个规范在内部是否一致?它对当前任务来说是否足够完整?哪些部分是可测试的?我们仍然依赖人工判断的部分在哪里?由于所有人都默默认为而缺失的故障模式有哪些?

代理在此处可以提供帮助,但前提是我们将它们用于比“编写需求”更有用的事情。这个提示通常会产生经过润色的模糊描述。一个更好的提示要具体得多:

草拟一个最小的规范,让另一个代理能够安全地实现它。包含假设条件、非目标、验收标准、边界情况、可观测结果和开放问题。标明哪些声明可以转化为自动化测试,哪些仍然需要人工审核。

完成此步骤后,将草稿交给另一个代理,并让它攻击结果:

找出矛盾之处、模糊术语、隐藏依赖、不可测试的声明、缺失的故障模式,以及实现可能通过书面标准但仍违反意图的地方。

即使只是采用这种简单的流程,也能降低获得值得人工判断的规范的成本。

代理不会消除对规范的需求。它们只是让达到真正有用的特定性水平的成本更低。

为什么多代理系统需要更强的契约

单个代理在处理小型、有限的任务时,通常可以从松散的指令中恢复。循环是紧凑的,影响范围是局部的,当它偏离轨道时,人类通常能够将其重新引导回正确方向。人类甚至可以轻松地发现最初的偏离。

多代理系统是一个完全不同的问题。一旦一个代理的输出成为另一个代理的输入,解释性偏差就会开始累积。代理B并不知道代理A误解了10%的需求。它只是将输出视为事实并继续执行。当人类看到结果时,最初的错误可能已经被几层看似专业的工作所掩盖。

到了这个时候,规范不再只是指导,而更像是一种契约。

这个契约需要的不只是意图的段落。它需要模式、不变量、允许的模糊性、验证规则和明确的失败行为。在许多情况下,它还需要契约测试、类型化接口和可由机器检查的交接格式。交接是产品的一部分,虽然不如人们希望的那样有魅力,但更接近现实。

这也是BDD(行为驱动开发)和可执行的验收测试的归属之处。它们的价值不仅在于方法论,还在于将部分人工预言转化为可重复的内容。当行为稳定到可以精确指定时,可执行的规范通常比另一轮评审更便宜。

一旦代理开始将工作交给其他代理,交接本身就需要像真正的接口一样被指定和验证。

规范应有到期日

团队在此处还可能犯另一种错误:当他们不断推动规范曲线,仿佛更多文字总是更安全时,这种错误就会显现。事实并非如此。至少对于当前模型来说,事实并非如此。

Chroma 对上下文腐烂的研究使问题的第一部分变得清晰:随着输入规模的增加,即使在简单任务上,模型性能也会变得越来越不可靠。在编码项目中,还存在另一个问题。你将越来越多的设计说明、示例、计划、注释、工单和旧的验收标准塞入上下文中,就会越来越难以分辨哪些部分是指示,哪些部分是产物。

我不会从安全角度称其为提示注入。没有人试图攻击模型。这更接近于自我造成的指令漂移。上下文中包含着旧的设计意图、当前的实现、半有效的示例、三小时前生成的计划,甚至可能还有一份过时的软件设计文档,仍然描述着已经不存在的类。此时,模型读取的不再是单一的规范,而是在多个真实来源之间进行平均。

当过度指定停止帮助并开始混淆模型时,问题就出现了。代理无法判断段落是当前需求、历史说明,还是已经被代码替代的内容。

设计文档在早期很有用,因为代码尚未存在。但之后,它需要缩减。一旦接口、测试和不变式成为现实,详细的构建计划就应该开始消失。“保留部分”代码在表达业务理由、非目标、安全约束、外部契约以及不希望被试错重新发现的少数不变式时表现不佳。删除那些只是重复类和方法已有功能的描述性文字。

否则,你最终会得到两个规范。人类在代码审查时会抱怨这一点,代理则常常试图同时遵守两者。

API 可使代码表现得像规范

这个故事还有一个更乐观的版本。有些代码库比其他代码库更快达到“代码即规范”的状态,而 API 设计是其中的重要原因。

如果一个内部 API 将行为隐藏在惯例、弱类型参数、设置魔法和通用错误之后,代理就无法将代码视为规范。它必须从分散的文本和试错中重建规则。这对人类来说效率低下,对模型来说更糟糕。

相反的情况同样成立。一个具有显式名称、任务级方法、强类型、可读验证、有用示例和可操作错误的 API,为代理提供了具体的立足点。如果代理能够检查接口,看到方法的作用,理解合法输入,并在不猜测的情况下从错误中恢复,那么代码本身就能承担更多规范的负担。

这正是 AI 友好的 API 设计理念在实践中发挥作用的地方。显式可发现性优于惯例。方法应与真实任务对齐,而不是迫使代理经历十几个脆弱的步骤。类型和验证应展示合法输入的形态。错误信息应指向下一个修复步骤,而不仅仅是宣布失败。内省和示例帮助模型从已有代码库中学习 API 的形状。性能透明度同样重要,因为如果 API 没有提供任何线索,代理会很乐意围绕昂贵的调用编写一个正确但糟糕的循环。

这不仅适用于公开的SDK。它同样适用于内部服务边界、库客户端、仓库抽象,甚至大型单体仓库中的辅助类。API越容易被发现和检查,代理就越容易将代码视为权威规范,而不是将更多文字引入上下文。如果你感兴趣,我之前曾更深入地探讨过所有这些内容。

投资方向

我坚信不存在一个统一的规范量度标准。答案取决于你正在从事的工作类型。对于小型且边界明确的任务,最佳平衡点通常是结构化的意图:目标、几个示例、非目标以及清晰的验收标准。这通常足以保持代理的生产力,而不会使设置过程比任务本身更繁重。

对于确定性工作(如CRUD流程、API集成和数据转换),最佳点会向右移动。这些领域易于约束且易于测试。更多的规范会迅速带来回报,因为它能减少重复的审查和返工。在这些场景中,行为驱动开发(BDD)、契约测试和可执行的验收条件能发挥最大作用。

对于探索性工作(如架构选项、研究整合或新产品创意),最佳点再次向左移动。过度规范可能会扼杀代理的灵活性。在这种情况下,我宁愿指定边界而非结果:必须成立的条件、必须避免的情况、所需的证据,以及仍需人类决策的事项。

对于多代理流水线,最佳点再次向右移动。代理之间的每个边界都需要契约。没有契约,你不是在协调系统,而是在堆叠解释并希望它们相互抵消。

没有普适的最佳点。规范的适当程度取决于工作是探索性、边界明确、确定性还是多代理的。

所有四种情况的共同规则很简单:在扩展实现之前,先验证规范。

敏捷和XP的延续

我认为代理不会使敏捷或极限编程变得无关紧要。它们只是让原本人们已经容忍的部分更容易与有价值的部分区分开来。

第一个牺牲品是那些主要用于逐小时协调人力的仪式。每日状态会议、夸大的待办事项仪式,以及以过度自信而非信息呈现的估算,不会因为代理编写了代码而变得更强大。实际上,它们会变得更弱。代理可以如此快速地改变任务形态,以至于旧的工时估算比以往更快沦为虚构。这并不意味着计划会消失,而是意味着计划必须停止假装能像代码是缓慢部分时那样准确预测实现成本。

从敏捷中留存下来的是反馈逻辑。短周期仍然重要。薄的垂直切片仍然重要。客户或利益相关者的审查仍然重要。可运行的软件仍然优于进度表演,因为代理可以迅速生成大量令人信服的错误。事实上,我认为现在反馈速度比以往更重要。如果一个团队能在早晨从模糊的想法快速过渡到大型实现,它也需要一种方式在午餐前发现这个想法是错误的。

XP 的生存优势更加明显,因为它始终强调将学习与代码紧密联系。测试优先的理念依然重要,因为可执行的检查在实现成本降低时价值更高。持续集成依然重要,因为每个代理的变更都需要通过验证关卡。重构依然重要,因为代理可以生成能运行、通过部分测试的代码,但留下的代码结构可能让下个月的维护者望而生畏。机器在这里并不在意,它会以完美的自信生成一团混乱。

结对编程的形式发生了变化,但核心理念依然存在。我仍然希望设计判断与代码生成保持紧密。有时这表现为人类直接与一个编码代理协作,有时则表现为一个模型生成代码,另一个模型根据更具体的指令进行审查。无论如何,结对编程真正有价值的部分从来不是两个键盘在人类喝咖啡时和谐地并排敲击。而是在代码最终确定前快速获得设计反馈。

小版本发布也依然适用,或许出于更现实的原因。当代理能够低成本地进行大规模修改时,人们很容易被诱惑接受同样低成本的大规模代码差异。这是个糟糕的主意。审查、回滚和诊断在小批量处理时更容易完成。一个生命周期短的功能分支比一个4000行的怪物更容易理解。

逐渐消失的是作为保障的方法论,而真正延续的是作为错误检测的方法论。敏捷和 XP 最出色的时候,是让团队以更低的成本发现他们对问题的理解存在严重偏差。这仍然是核心任务。代理时代只是去除了部分借口,同时增加了新的高速犯错方式。

真正的杠杆

代理开发的承诺是真实的。代理可以大幅降低实现成本,但一旦代码变得廉价,规范与验证就成为项目成败的关键。

获得最大杠杆效应的团队,不会是规定最少的团队。而是那些知道何时三个要点就足够、何时需要真正的合同、何时合同必须可执行的团队。

代理正在变得更好。但决策权仍然掌握在我们手中。