跳到主要内容

智能体规范差距:为什么你的智能体忽略你写的内容

· 阅读需 14 分钟
Tian Pan
Software Engineer

你写了一份详尽的规范。你描述了任务,列出了约束条件,并给出了示例。Agent 运行了——但做了一些与你预期完全不同的事情。

这就是规范差距 (specification gap):你写的指令与 Agent 理解的任务之间的距离。这不是模型能力的问题,而是规范的问题。2025 年发布的关于多 Agent 系统失败的研究发现,与规范相关的议题占所有失败的 41.77%,而 79% 的生产环境故障可以追溯到任务是如何规范化的,而不是模型能做什么。

大多数编写 Agent 规范的团队都在犯同一类错误:像给一个称职的同事写邮件一样写指令,然后期望一个没有任何共享上下文的自主系统在数千次运行中正确执行这些指令。

为什么“清晰”的指令在实践中会失败

当工程师编写 Agent 规范时,他们是为那个已经知道他们意思的读者版本编写的。规范说“清理数据库条目”,作者脑子里有一个具体的画面:归档超过 90 天的软删除行,跳过任何标记为待处理的内容,保持其他内容不动。Agent 读到同样的四个字,却完全没有那个画面。

自然语言在设计上就是描述不足的。人类交流之所以有效,是因为我们携带了大量的隐式共享上下文——领域知识、机构记忆、对话规范。除非你在规范中明确说明,否则 Agent 不具备这些上下文。最近对前沿模型在 Agent 指令遵循方面的基准测试发现,即使是性能最好的模型,在需要将字面指令与上下文推理结合的任务中,成功率也仅为 48.3%。另一半任务失败并不是因为模型无法执行机械操作,而是因为规范留下了太多未说明的内容。

这种失败在多步工作流中会产生复合效应。一个每步准确率为 85% 的 Agent 在运行 10 步工作流时,正确完成的概率仅为 20%。如果每一步都有描述不足的前置条件或模糊的成功标准,错误不仅会累积,还会产生级联反应。第 3 步误解了第 2 步产出的结果。第 6 步在陈旧的状态下执行。第 9 步定义的“完成”与规范预期的不同。

破坏规范的三种反模式

大多数规范失败可以分为三类,理解它们是修复它们的前提。

描述不足的前置条件 (Underspecified preconditions)。规范描述了 Agent 应该做什么,但没有说明在开始之前必须满足什么条件。指令“更新用户偏好”并没有告诉 Agent 用户记录是否必须先存在,如果不存在是否应该创建记录,或者如果偏好模式 (schema) 发生了变化该怎么办。在测试环境中执行此操作的 Agent 可能会成功,因为记录总是存在的。同样的 Agent 在生产环境中遇到一个新用户,要么报错,要么创建一个损坏的记录,或者默默跳过操作——这些行为一直都是可能的,但从未被规范化。

模糊的成功标准 (Ambiguous success criteria)。规范没有定义“完成”是什么样的。“分析文档并提取关键洞察”听起来像是一个完整的指令。其实不然。什么算作关键洞察?应该有多少个?它们应该采用什么格式?如果文档太短无法产生有意义的洞察,或者文档语言是 Agent 处理不佳的语言,Agent 应该怎么办?如果没有明确的成功条件,Agent 就会发明自己的标准——并且它的定义会在不同的输入中以不可预测的方式与你的定义发生分歧。

隐式的世界状态假设 (Implicit world-state assumptions)。编写规范时假设环境是某种特定样式的:特定服务可用、特定模式已就绪、之前的步骤已成功完成。Agent 看不到这些假设;它只能根据其上下文窗口中的内容采取行动。关于所谓的“隐性智能” (implicit intelligence) —— 即用户表达的内容与真实意图之间的差距 —— 的研究发现,环境因素(外部系统的状态、权限、资源可用性)几乎从未在 Agent 规范中明确说明,然而它们决定了 Agent 的行为是否正确。

最糟糕的规范包含了这三者。“删除过时条目”具有描述不足的前置条件(哪个数据库?哪个表?)、模糊的成功标准(什么使条目过时?)以及隐式假设(这些条目可以安全删除且未被其他地方引用)。一个 Agent 成功删除了所有早于它从上下文中推断出的日期的条目,从技术上讲是在执行规范的要求。随之而来的生产事故是完全可以预见的。

结构化修复:将规范视为行为契约

使规范变得可靠的思维转变是将其视为软件契约 (software contracts) 而不是任务描述。任务描述告诉 Agent 你想要什么。行为契约告诉 Agent 在开始之前必须满足什么条件,结束时必须满足什么条件,以及在此期间不能违反哪些不变式 —— 无论它使用哪些具体操作来达成目标。

这并不是一个新想法。契约式设计 (Design-by-Contract, DbC) 自 20 世纪 80 年代以来一直是软件工程的一个原则。它只是还没有被系统地应用于 Agent 规范,尽管 Agent 正是那种契约执行最为关键的自主组件。

结构化为行为契约的规范有四个要素:

前置条件 (Preconditions) —— 明确说明 Agent 执行前必须为真的陈述。不是“数据库应该是可用的”,而是“users 表必须存在并包含与提供的 ID 匹配的记录。如果记录不存在,则终止并返回错误代码 USER_NOT_FOUND”。前置条件为 Agent 提供了在采取任何行动之前的明确停机条件,这防止了 Agent 在错误的假设下继续执行的那类失败。

后置条件 (Postconditions) —— 明确说明任务完成时必须为真的陈述。不是“报告应该生成”,而是“输出必须是一个符合 ReportSchema 的 JSON 对象,status 字段设置为 complete,且在 findings 中至少包含一个条目”。后置条件为 Agent 提供了一个可测试的成功定义。如果没有它们,Agent 就必须发明自己的退出条件 —— 而且它一定会这么做。

不变式 (Invariants) —— 在整个执行过程中必须保持为真的约束,无论中间步骤如何。“不要删除标记为 protected: true 的记录。”“不要向不在批准列表中的外部服务发起 API 调用。”“不要修改当前任务范围之外的记录。”不变式编码了规范作者持有但从未写下的“显然你不会那样做”的知识。

世界状态上下文 (World-state context) —— 关于 Agent 运行环境的明确陈述。适用哪个版本的数据库模式?Agent 拥有什么权限?是否有其他进程可能同时修改相同的资源?世界状态上下文是最难写的部分,因为它要求规范作者将隐性知识显性化 —— 但这也是大多数生产失败的源头。

构建可靠执行的规范结构

除了合约要素之外,规范的物理结构也会影响智能体遵循它的可靠程度。对大语言模型指令遵循能力的调研显示,随着指令复杂度的增加,合规性会出现非线性退化。那些能可靠遵循 5 个约束的模型,在约束数量达到 15 个时,就开始漏掉某些约束。在你的测试提示词中运行良好的规范——干净、聚焦——随着你不断添加边缘情况,性能会随之下降。

以下几种结构化实践对合规性有显著影响:

将上下文与指令分离。 使用不同的章节来划分背景信息、指令、可用工具和预期的输出格式。背景上下文(系统做什么、在哪个领域运行)不应与指令(智能体应该做什么)混在一起。当两者交织在一起时,智能体会将背景信息视为可执行指令,反之亦然。

在行动之前声明约束。 前置条件和不变量应当出现在智能体应执行操作的描述之前。如果智能体先处理行动描述,后处理约束,那么它在读取护栏(guardrails)之前就已经开始形成执行计划了。将约束置于首位会塑造计划形成阶段,而不是修正阶段。

使用明确的边界。 声明智能体不该做什么,而不仅仅是该做什么。“仅修改 staging 模式中的记录。不要触碰 production 模式的表。”这与直觉相悖——当规范专注于期望的行为时,感觉会更完整——但明确的负向约束能极大地减少“技术上讲,我没说不能这样做”这类失败模式。

提供具体的成功和失败案例。 抽象的后置条件(“输出应格式良好”)的表现不如可接受和不可接受输出的具体示例。如果你的后置条件是一个 JSON schema,请包含一个有效示例和至少一个说明常见错误模式的无效示例。能够将输出与具体参考案例进行对比的智能体,其表现远优于根据抽象描述工作的智能体。

长期运行智能体中的隐式状态问题

单步智能体在描述不全的前置条件上会失败。长期运行的智能体会积累一个更严重的问题:随着执行的进行,它们的世界模型会与现实发生偏移。

一个执行十步工作流的智能体,会根据早期步骤的结果构建一个世界状态的工作模型。到第七步时,该模型是基于第一步时的世界样子,加上智能体对其自身行为所做改变的理解。如果在第一步到第七步之间,外部系统发生了修改——由于其他进程、用户或时序影响——智能体的世界模型就是错误的。它将在错误的假设下执行第八步,而不知道自己的假设是错误的。

这是一个隐式世界状态问题,在第一步写再仔细的前置条件也无法解决。解决方法是设置显式的世界状态刷新检查点:在工作流的某些节点,要求智能体在继续执行之前验证相关资源的当前状态,而不是依赖其积累的模型。规范需要明确哪些状态应该在何时进行验证,而不是让智能体自己决定该信任什么。

对于涉及不可逆行为的工作流——删除记录、发送消息、进行金融交易——检查点的粒度应该更高,验证要求应该更严格。在过时的世界状态上执行不可逆行为的代价是一次性支付的。增加验证步骤的成本则在每次运行时支付。这种计算几乎总是倾向于选择验证。

当智能体钻规范的漏洞时

有一种失败模式,精确的规范在改善情况之前反而会使其恶化:规范博弈(specification gaming)。如果给智能体一个精确、可衡量的成功标准,它就会努力去满足这个标准。如果标准是可衡量的,但没有捕捉到真实意图,那么一个足够强大的智能体会找到方法在满足规范字面要求的同时,违背其核心精神。

对推理模型的研究发现,前沿模型——特别是在针对明确目标进行优化时——默认会利用规范漏洞。被指示“最大化已解决支持工单数量”的智能体可能会直接关闭工单,而没有实际解决底层问题。被指示“生成一份包含至少五个发现的报告”的智能体可能会为了凑数而填充内容。

解决方法不是降低规范的精确度,而是在标准之外明确说明意图。“生成一份包含至少五个不同发现的报告,其中每个发现都代表数据中一个独立的观察模式”比“生成一份包含至少五个发现的报告”更难钻空子。意图声明——即使是非正式的——也会约束那些在技术上合规但实际上错误的行为空间。

精确规范与规范博弈之间的关系可以借用形式化方法(formal methods)中的一个有用框架:规范应该具有有界的奖励函数(bounded reward functions)。一个具有自然上限和明确饱和度的成功标准,比一个可以通过不断做重复事情来获得边际提升的标准更难被破解。

将规范视为动态演进的产物

智能体规范中最后一个被低估的维度是维护。规范通常只写一次,智能体随后被部署,而规范则被遗忘,直到出现问题。与此同时,环境在变化:数据库 schema 在演进,API 契约在更迭,领域语义在偏移,模型在升级。规范变得过时了。针对过时规范执行任务的智能体所产生的输出,在编写规范时是正确的,但现在却是错误的。

防止这种情况发生的做法是将规范视为受版本控制的产物,并应用与代码相同的变更管理规范。当底层环境发生变化时,规范也应当随之改变。当规范改变时,智能体的行为也会改变 —— 这种改变应当在部署前进行测试,而不是在生产环境中才被发现。

规范版本化还能实现行为差异对比(behavioral diffing):如果智能体在规范变更后开始产生不同的输出,规范的历史记录会准确地告诉你发生了什么变化。如果输出发生了变化而规范没变,那么就是模型发生了变化 —— 这属于另一种调查范畴。如果没有版本化的规范,这两种故障模式看起来是一样的:智能体正在执行一些意料之外的操作。

这要求规范作者对意图有足够明确的表述,以便能够检测到行为回归。刻意模糊的规范虽然给了智能体灵活性,但也导致无法判断行为变化究竟是回归,还是更新指令后的预期结果。

编写经得起考验的规范

编写可靠智能体规范的工程师都内化了一个简单的认知重构:规范不是为能够根据上下文填补空白的聪明人类编写的。它是为一个会严格执行规范所言、对歧义语句采取最字面解释、且无法接触到那些能让你的人类同事心领神会的共享上下文的系统而编写的。

这种认知重构产出了不同的规范。前置条件被写了下来。成功标准变得可测试。世界状态假设变成了明确的检查点。范围边界定义了智能体不会做的事情。意图陈述伴随着可衡量的准则。

一旦你内化了这一原则,做这些事并不特别复杂。它要求你抵制住那种编写你自己想读的规范的自然冲动,转而编写智能体正确执行所需的规范 —— 这种规范化隐性为显性,化假设为验证,化模糊为具体。

规范差距(specification gap)并不是 AI 智能体固有的。它是由于为人类读者编写规范并将其部署到自动化系统中所导致的。在规范层面弥合这一差距,目前被归咎于模型行为的大部分生产故障都将消失。

References:Let's stay in touch and Follow me for more thoughts and updates