高效商业智能体的架构剖析指南

作者:

Matthew Koen,

Ali Shazal

高效商业智能体的架构剖析指南

过去一年里,我们与商业领域的许多团队合作,包括零售商、交易平台、旅游、娱乐和电信服务商,共同使用 Claude 构建商业智能体。

这些智能体已经投入生产。企业客户在使用它们后,购物车金额有所增加,商家运营效率也得到了提升。它们还采用了一种共同的简单架构:让 Claude 在智能体循环中运行,并为其配备一组技能、工具和一套可靠的评测体系。

本文面向正在构建这类智能体(或其他面向消费者的智能体)的工程师和工程负责人。第一部分介绍只需决定一次的架构;第二部分讨论延迟与成本;第三部分讲生产环境中的记忆、安全、评测,以及如何在组织内扩大这项工作的规模。

本指南内容

01

架构

一个模型运行在标准智能体循环中,用技能覆盖长尾需求,用工具调用你已经在运行的系统。这个架构只需决定一次。

什么是商业智能体?

我们将商业智能体定义为:能够简化在线目录中买卖流程的智能体。

有些智能体面向消费者:它们会搜索、比较、寻找替代品并组装订单。订单可能是一辆零售购物车、一份旅行行程、一次手机套餐变更,或为演出暂时锁定的座位。另一些智能体面向企业:它们回答销售相关问题、执行促销和营销活动,并管理库存与定价。

上面两个面板运行的是同一个智能体,使用相同的工具和提示词,唯一的区别是编排框架(harness)。总耗时大致相同,但用户看到界面开始响应的时间却大不一样。

核心架构是让模型运行在一个标准智能体循环中:围绕目标推理、探索上下文、通过工具采取行动、通过技能学习流程、提出澄清问题,并观察操作结果,直到达成目标。

它前面没有把对话切分开的意图路由器,后面也没有一组按领域划分的智能体。

工程上下文

使用技能,而不是子智能体

商业智能体需要覆盖多个品类和意图下的大量能力,因此很容易让人产生一个想法:为每个领域创建一个子智能体。

实践证明,这种做法并不理想,因为商业对话往往是一次紧密耦合的会话,横跨多个意图和多个轮次,需要共享大量上下文。

在子智能体架构中,购物车或暂存的变更、用户偏好和对话历史都由编排器持有。

每次把任务移交给子智能体,都会损失一部分状态。这往往会影响子智能体的回答质量,进而影响整体回答质量。除此之外,每次移交还可能消耗数倍的 Token,并增加数秒延迟。

各个领域也很少能被干净地拆开。比如,退货流程可能同时需要订单历史、当前购物车和商品目录。这意味着,为每个领域设置子智能体,要么得在各处重复提供这些访问能力,要么只能在任务执行到一半时移交。

随着模型变得更智能,它们也能处理更长的上下文、更多技能和更多工具,因此,支撑今天这些分配规则的限制会随着每一代模型的进步而逐渐放宽。

相比之下,智能体技能既能提供类似的按领域模块化能力和上下文控制,又没有移交成本,因为技能指令会加载到已经掌握全部对话历史的主智能体中。

我们对多个企业部署进行了比较。结果显示,配备技能的单智能体方案在质量上始终优于“一套提示词包打天下”的设计和子智能体设计,而且每项任务的成本与延迟通常也更低。

子智能体真正有用的场景是:编排器能够把它当作工具调用,交给它一项范围狭窄或相对独立、适合使用专用上下文窗口完成的任务。

生产环境中的一个常见例子是深度研究子智能体。它会搜索和阅读文档、编写并运行代码、遍历数据模型,也会走进死胡同。所有具体工作都在一个或多个子智能体内部完成,最后只有一份精简答案返回给编排器。

另一种例外情况是,某个领域已经拥有专门打造的智能体。如果你的药房或金融服务业务运行着一个具有独立合规边界的专用智能体,正确做法可能是移交:由该智能体接管任务,通过自己的循环直接与用户协作,直到任务完成。

关键区别在于谁拥有对话。移交会让领域智能体成为用户的直接沟通对象;委派则仍由编排器掌控对话,在同一轮里反复调入、调出领域智能体,而每次交互都会带来质量损失。

系统提示词还是技能:按使用频率决定

决定一组指令应该放在系统提示词还是技能中,首要因素是智能体使用它的频率。加载一个技能会消耗一次模型调用,因此,智能体在大多数轮次都需要的内容通常应该放进系统提示词。

不过,这也取决于你的流量分布,以及评测反映出的智能体行为。一个不错的起点是:凡是与三分之一或更多流量相关的内容,无论这是上线前的预期,还是生产环境中的实际观察,都放进系统提示词;其余内容则放进技能。

如果你已经拥有某种信号,可以据此预测应加载哪个技能,例如用户是从哪个页面进入的,我们建议由编排层在第一次模型调用前注入该技能,省去额外的技能加载轮次。

安全和法律规则、品牌限制,以及过敏信息等关键用户事实,都属于重要指令,应始终放在系统提示词中。

对商业智能体而言,这意味着商品搜索应该写进提示词,因为几乎每次会话都会用到它;长尾功能则由技能承载。

在我们的参考实现中,购物智能体的提示词包含事实依据约束(grounding)、购物车与结账语义、展示规则和商品搜索,其余能力由以下技能覆盖:搜索发现、购买研究、规划目标、客户服务,以及记忆个性化。

商家智能体采用相同的拆分方式。它的技能包括业绩洞察、目录与商品信息、库存运营、定价与促销,以及营销活动,每个运营领域对应一个技能。

放在提示词中 购物智能体 事实依据约束、购物车与结账语义、展示规则和商品搜索。

购物技能 长尾能力 搜索发现 · 购买研究 · 规划目标 · 客户服务 · 记忆个性化

商家技能 每个运营领域一个技能 业绩洞察 · 目录与商品信息 · 库存运营 · 定价与促销 · 营销活动

智能体工具的工程设计

我们在为智能体编写高效工具一文中介绍了通用的工具设计方法。在商业场景中,有两点尤其重要:

在核心系统和业务逻辑之上构建智能体工具。

商业公司通常已经拥有搜索与排序、购物车、偏好与用户档案存储、库存系统、促销与营销活动引擎、销售分析等系统。每套系统都封装了经过多年调优的逻辑,也能看到模型永远无法直接获得的信号。

智能体工具应该调用这些系统,而不是重新实现它们。工具边界应该正好位于这些系统的逻辑终点,也是模型开始做判断的地方。

例如,智能体调用 search_products 时,返回结果应该已经排好序。智能体的工作是判断哪些结果最符合用户目标、应该展示多少个,以及如何展示。

工具结果就是上下文。

只返回模型推理所需的字段,其余全部丢弃。最常见的反面例子,是在每一行搜索结果中都附上图片 URL。

必要时,可以在工具内部重塑原始响应;如果下一步操作无法从数据中直接看出来,还可以附上一条下一步指引。

这一点对错误场景尤为重要:与错误代码相比,模型更能从操作指令中获益。例如,不要只返回一个笼统的 403,而应该附上错误处理指令:“查询库存时请提供商品 ID。”

UI 组件就是工具

商业智能体的大多数响应都不是散文式文字,而是 UI 组件,比如商品轮播、旅行行程、座位图或图表。这意味着智能体需要输出结构化 Schema,而不是普通文本。

有些团队起初会提示模型输出自定义标签,再由客户端解析。随着产品界面越来越复杂,这种做法会逐渐失效,原因包括:

  • 相较于工具调用,模型对你的自定义标记格式训练不足。嵌套组件一多,可靠性就会下降。只靠提示词无法保证数据格式始终正确。
  • 标签定义存放在系统提示词中,每增加一个组件都会让上下文膨胀;每修改一次,也可能导致提示词的其他部分出现回归。
  • 历史对话最终会以一种只有你自己的解析器才能读取的格式保存。重新加载对话历史时,要么让客户端解析原始消息,要么额外维护一份并非模型 API 原生格式的副本。

经得起实践检验的模式,是把每个 UI 组件都做成一个工具。模型使用类型化参数调用 present_productspresent_itinerarypresent_plan_comparison;服务器验证并补充这次调用,随后发出事件;客户端负责渲染。

因为这些组件本身就是工具调用,它们已经以原生格式存在于消息数组里。重新加载旧对话时,不必再次解析。下面的图片和参考仓库展示了一个展示工具的接口契约示例。

上面两个面板运行的是同一个智能体,使用相同的工具和提示词,唯一的区别是编排框架。总耗时大致相同,但用户看到界面开始响应的时间却大不一样。

代价在于流式传输的粒度。工具调用的每个顶层参数都需要先在服务器端缓冲,以便进行验证。因此,即便开启流式传输,展示工具的子组件也只能分批到达。这会影响用户感知到的延迟。

如果要实现 Token 级流式传输,可在工具定义中设置 eager_input_streaming: true。这样会跳过缓冲,同时也放弃服务器端的 Schema 保证。

在我们的评测中,Claude Sonnet 级别及以上的模型极少违反 Schema,但仍应在调用外包一层重试机制,以应对偶发情况。

展示工具还会给智能体留下一份屏幕状态记录。当客户说“第一家酒店”或“左边往下数第三个”时,页面布局就保存在消息数组里,具体位于最近一次展示调用的参数中。

要让这种机制生效,工具参数必须如实反映渲染后的布局。因此,参数结构应与 UI 结构一致,比如按顺序组织为多行和轮播,而不是给客户端一个可以自行重新排列的扁平列表。

02

让智能体既快又省

从端到端延迟和感知延迟两条战线同时下手,再用缓存承担降本重任。所有这些优化都不应该以牺牲智能水平为代价。

延迟在商业场景中非常重要,面向消费者的界面对延迟最不宽容。不过,我们在智能体产品中一再观察到,真正能够推动留存、互动和购物车金额等指标的,是结果质量。

与缩短一点点延迟相比,回答是否切题、任务是否真正完成,对这些指标更为关键。

因此,要从两条战线解决延迟问题:通过良好的工程实践降低端到端延迟,同时降低感知延迟——因为用户看着智能体工作时,会把这段等待理解为任务正在推进。

每个用户都有自己的延迟预算。下面这些方法可以让智能体留在预算之内,又不必牺牲智能水平。

尽量缩短任务完成延迟

任务完成延迟等于所有模型轮次的末 Token 时间与工具处理时间之和。由此可以得到三个杠杆:减少轮次、加快工具,以及提高 Token 生成速度。这些杠杆有时会彼此冲突,因此需要最小化的是总和,而不是其中任何一项。

减少轮次 提前加载大概率需要的上下文、提高模型智能水平,并让模型并行调用互不依赖的工具。

加快工具 优化工具自身的后端,并在参数生成完成时立即分发工具调用。

提高 Token 速度 通过遍历整套评测,选择合适的模型和配置。

减少轮次

查询越复杂,所需轮次越多,而这通常不受你控制。更强的模型能力与相关上下文,可以帮助智能体用更少轮次完成任务。我们在这方面的几个关键经验包括:

  • 提前加载大概率需要的上下文。 如果用户从某个商品页打开助手,或者商家从营销活动仪表盘打开助手,就把当前页面的数据放进会话上下文。接下来的对话很可能与该页面有关,而直接从上下文回答不会额外消耗轮次。
  • 提高模型智能水平。 更智能的模型能够更高效地规划和发出工具调用,从而减少任务的总轮次。这个收益往往会超过 Token 生成速度更慢的影响。如果你的查询普遍较复杂,或者生产数据显示每项任务平均需要约五轮以上,那么更快完成任务的模型往往恰恰是更智能的模型。具体是哪一个取决于你的流量,应按照下文“选择模型”一节所述,通过遍历评测来决定。
  • 让模型并行调用互不依赖的工具。 商业场景经常需要并行执行多项操作,例如同时搜索多种商品、查询多份政策文档,或者从多个销售数据源读取记录。并行调用工具,可以避免这些互不依赖的查询额外消耗轮次。提示模型在一轮内调用多个工具,并把所有结果作为工具结果数组,在一条用户消息中一并返回(参见并行工具使用文档)。

加快工具

  • 优化工具自身的后端。 有时,工具确实需要扇出调用。比如,商家智能体执行“获取今日概况”查询时,要分别读取销售、库存和营销活动状态。但我们经常看到,工具边界变成了拼接缺失后端逻辑的地方:一次库存可用性检查,先为 SKU 调用商品目录,再逐店调用库存服务、调用履约服务获取截止时间,随后在工具自己的代码里应用替代规则和到店自提资格,最后才给出答案。此时,这个工具承载了过多领域知识;规则变化时很难保证正确,而且它承担了本应位于上游系统的逻辑。发现自己正在工具里编写这类逻辑时,正确的解决办法是构建一个能直接回答该问题的后端接口,再由智能体工具调用它。
  • 尽早分发工具调用。 工具参数和其他 Token 一样,会从模型中流式生成。因此,编排层可以在每个工具调用的参数生成完成后立即执行它,并在模型仍在流式输出其他并行工具或内容块时处理结果。我们曾借此把数秒的空档缩短到几百毫秒,Claude Agent SDK默认就采用这种方式。为了最大化延迟收益,应提示模型优先输出最慢的工具调用。

上面两个面板运行的是同一个智能体,使用相同的工具和提示词,唯一的区别是编排框架。总耗时大致相同,但用户看到界面开始响应的时间却大不一样。

感知延迟

感知延迟,是用户觉得“屏幕终于有反应了”之前经过的时间。在面向消费者的场景中,它尤其关键,因为交易过程中的任何阻力都会影响结账率和收入。下面两种方法无需改变模型,就能缩短感知延迟:

  • 组件一形成就开始流式呈现。 一条渲染后的商业智能体响应通常包含 500~700 个输出 Token。如果不使用流式传输,用户会盯着加载动画等待至少五秒。展示工具的每个参数一旦流式生成,就把它发送到客户端,并逐步渲染页面。
  • 展示工作过程。 智能体收集上下文时,用简单语言为每一步显示一条简短进度,例如“正在寻找海边的酒店”。你可以根据工具已有参数生成这行文字,比如使用商品搜索的查询词;也可以给工具添加一个 user_facing_message 参数,提示模型写出这行文字。

上面两个面板运行的是同一个智能体,使用相同的工具和提示词,唯一的区别是编排框架。总耗时大致相同,但用户看到界面开始响应的时间却大不一样。

提示词缓存

提示词缓存是最值得优先考虑的降本手段,而商业流量非常适合使用它。读取缓存输入 Token 的成本只有读取新 Token 的十分之一;写入缓存虽要支付约 1.25 倍的溢价,但同一前缀第二次被使用时就能回本。面向消费者的应用流量很大,因此只需使用最便宜的默认 5 分钟缓存有效期,就有机会达到很高的缓存命中率。

我们见过的最佳商业智能体部署,缓存命中率都达到 90%~99%。从一开始就应该以这个范围为设计目标。我们的经验还显示,在约 10 万 Token 的规模下,读取缓存 Token 的速度会快大约 1.5~2 倍;Token 越多,性能收益大致呈线性增长。

缓存以请求前缀为基础。系统会从缓存中读取内容,直到遇到与上一次请求不同的第一个字节。因此,重要的不只是上下文里放了什么,还包括内容的排列顺序。可以把一次请求看成三个部分,按照变化频率从低到高排列:

  • 全局段: 包含大部分系统提示词和工具定义,每个会话都完全相同。这是命中最稳定的缓存;在规模化流量下,它很可能永远不会过期。确保它在不同轮次和会话之间逐字节相同,并在末尾设置缓存断点。
  • 会话段: 包含每位用户的上下文与对话历史。不同会话之间内容不同,但在同一个会话内保持稳定。它位于全局段之后。
  • 易变段: 包含会话内会发生变化的所有内容,比如当前时间或当前页面。把它放在请求最末端:可以作为带标签的内容块放进最新一条用户消息;如果模型支持对话中途的系统消息,也可以作为 system 角色消息追加到消息数组中。我们最常见到的错误,是把时间戳或当前页面放在系统提示词开头,导致每次请求都悄悄破坏缓存。

这里还要记住两个实现细节。第一,技能应该作为工具结果加载,而不是追加到系统提示词。这样,技能正文就会进入对话前缀,并随前缀一起缓存。

第二,每一轮都要把缓存断点向前滚动:一次请求允许设置的断点数量有限,因此,应把最新的断点移到每一轮用户消息的末尾。这样,每轮请求都能从缓存中读取累积的对话历史,包括搜索响应等很长的工具结果。

选择模型及其配置

模型大小与推理强度设置面对的是同一种权衡:智能水平与延迟、成本之间的取舍。两者都应该通过实际测量来选择:

  1. 确定指标和底线。 选定业务真正依赖的质量指标,例如任务完成率、答案相关性和有据可查的准确性;确定不可低于的评测分数;再设定 p50、p99 延迟和成本预算。
  2. 遍历测试。 用整套评测测试你可能采用的每一个模型和推理强度级别。商家智能体的任务偏重分析,我们建议从 Opus 开始;消费者智能体更看重延迟,建议从 Sonnet 开始。如果已经有生产流量,就按照真实查询分布为测试结果加权,然后让数据做决定。有时,Opus 5 在促进购物车转化的任务上表现更好,足以证明它相对 Sonnet 的成本差异是合理的;有时则不然。
  3. 仔细解读结果。 有两件事经常让团队感到意外。第一,提示词往往是针对某个模型调优的,因此,直接用同一套提示词遍历测试时,其他模型可能表现欠佳。小模型通常需要明确写出当前模型能够自行推断的指令;大模型则会严格执行那些小模型之前忽略的指令。在淘汰某个候选模型前,针对其失败案例迭代几轮,是一项成本很低的工作。第二,更智能的配置有时反而能在延迟上胜出,最常见于 p90 和 p99。尽管它生成 Token 较慢,但它能更好地规划工具调用,并在最复杂的请求上减少执行轮次。

应该衡量每项已完成任务的成本,而不是每次模型调用的成本。一个更便宜的模型如果需要更多轮次,或者失败得更频繁,实际上并不便宜。当结果接近,且成本符合你的单项任务经济模型和延迟要求时,选择更高的智能水平。质量会推动采用和留存;随着模型不断进步,它也能为未来六个月的产品建设留下空间。

03

在生产环境中运行

记忆、安全、评测,以及如何在组织内扩大工作的规模:这些能力决定智能体能否进入生产环境,并持续稳定运行。

最后,我们来讨论让智能体顺利进入生产环境并持续运行的关键:记忆、安全、评测,以及如何在组织内扩大工作的规模。

跨会话保留的记忆

你与客户建立的关系,以及彼此之间的互动,都非常重要。记忆可以让智能体从上次对话中断的地方继续,而不是每次从零开始。一个购物者三月提过自己对坚果过敏,到了六月就不该再说一遍;一个商家每周一都检查同样的三项营销活动,也不该每次都重新点名。长期记忆,也就是那些应该跨会话保留的事实,是一个需要由你构建的系统。它包含三个部分:如何存储事实、如何写入事实,以及如何读取事实。

存储记忆

记忆应该放在你的系统中,而不是模型里。

当用户档案很小,而且只有智能体读取时,用一份扁平的 Markdown 档案就够了。但大多数生产级商业智能体很快就会超出它的能力范围,实用的替代方案是使用你已经在运行的数据库。一条事实是一条小型类型化记录:包括一个键(例如 shoe_size、default_store、preferred_report_cadence)、一个简短的值、一个类别,以及该事实来自哪个会话。部分键由你预先定义,每个用户都有;其余键则由提取器自行发现。随着存储规模扩大,数据库仍然可以查询;你还能围绕特定属性构建确定性行为,并把这些事实与已有用户数据关联起来。

对面向商家的智能体,应按“人”而不是“账户”来索引记忆。商家登录账户经常由多名操作员共享,因此,每名操作员都需要自己的档案;读取操作还必须遵守该操作员的权限:门店经理的智能体不应该回忆起区域经理说过的事实。

在商业领域,智能体记忆会包含个人数据。最值得记住的事实,往往也是受到最严格监管的事实,而各个司法辖区的规则并不相同。因此,应该把记忆视为一个数据处理设计问题,而不仅仅是存储问题。实践中,这意味着四件事:

  • 决定你愿意保存哪些类型的记忆。 在写入路径上强制执行这项规则,让每次保存都经过验证器,而不能只在提示词中规定。
  • 为用户提供查看、更正和删除已存内容的方法。 把删除操作接入账户删除和数据请求流程。
  • 设定保留期限。 几年前的偏好很可能已经过时,保留期限有助于让记忆事实保持新鲜。
  • 记忆应该是每次部署都可以单独控制的开关。 对于无法承担这些义务的地区,可以在不启用记忆的情况下运行。

写入记忆

异步写入记忆。在每轮对话结束时,或者在长会话中每隔几轮,让另一个线程或进程中的智能体读取对话,并在存储中创建、更新或删除事实;随着会话进行,它会维护自己的工作上下文。

这种方式完全不会增加对话延迟,并且在我们的内部商业记忆评测中,将事实召回率提高了 13%。

最直观的替代方案,是为主智能体提供一个保存事实的工具。但对延迟敏感的商业智能体而言,这是错误的选择。每次保存都会在面向用户的轮次中增加一次工具调用;除非整个存储都已放入上下文,否则保存前还必须先读取,以便更新或去重,这又会单独增加一个轮次。

它还会在每一轮都给智能体增加一项决策。在我们的评测中,这种注意力竞争表现为记忆遗漏。

把提取器独立出来,还能让你对它进行精确提示。它只读取用户和助手的文本,从不读取工具结果,因此,商品描述或评论不可能被误存为关于用户的事实。它的提示词会明确说明什么才算事实,例如用户主动说明的尺寸、饮食限制、履约偏好,以及商家惯用的物化视图;也会说明什么不算,例如商品信息中的内容或只出现过一次的细节。

读取记忆

分三层读取记忆。

始终放在上下文中 把一小组固定事实放进每一轮的上下文。这些是几乎每个请求都依赖的事实,例如购物者的默认门店和履约偏好,或操作员所在的门店及其角色。

每轮预取 从触发技能预加载的同类信号中,预取与当前请求有关的事实。搜索鞋子时读取尺码和品牌偏好;询问营销活动时读取操作员惯用的指标。

放在查询工具之后 其余所有事实都通过查询工具按需获取。

记忆属于每位用户的上下文,因此,所有记忆都放在会话段,位于全局缓存断点之后。

安全:强制执行必须由编排层负责

提示词是安全行为的起点,但在商业场景中,不能由它负责强制执行安全规则。这里的失败会造成经济损失,而且往往不可逆;一次提示词注入或一次糟糕的模型采样,就可能绕过提示词规则。下面的所有规则都同时在消费者智能体和商家智能体的代码中强制执行,而且只定义一次,让所有运行环境共享。

模型只暂存,由人或策略执行

任何模型工具调用都不能直接转移资金或改变业务状态。下单、支付、退款、价格变更和营销活动发布,最终都必须交给编排层控制的操作,而不是交给模型。

在消费者一侧,这种限制由系统结构保证:结账工具会渲染购物车,并提供一个下单按钮;智能体调用的后端接口根本没有扣款方法。

在商家一侧,每个写工具都会生成一项带有服务器签发 ID 的暂存变更。只有当该 ID 已通过真实交互界面批准时,apply_change 才会成功。批准可以来自操作员门户中的按钮、CLI 中的确认,或者智能体运行在 Managed Agents 上时,由平台自带的工具审批提示完成。

真正应用变更时,护栏会根据当前限制重新检查,而不是沿用暂存变更时的限制。无论使用哪种交互界面,模式都一样:模型最危险的动作只能是提出建议,而审批必须经过你的业务已经用于这类变更的“发起人与复核人”流程。

写入和渲染只接受服务器签发的 ID

编排层会为每个会话保存一份记录,列出服务器曾交给模型的每一个 ID。任何写入或渲染操作都只接受这份记录中的 ID。

购物车只接受服务器在本次会话中返回过的商品 ID;商家工具只接受智能体确实读取过的商品信息 ID 和营销活动 ID。通过任何其他途径出现的 ID——无论是模型幻觉出来的、用户粘贴的,还是藏在评论里的——都会在抵达后端之前被拒绝。

同样的规则也适用于 UI。展示工具只接收 ID,再由服务器自行补全商品、订单或变更记录,因此,每张卡片只能渲染服务器亲自填充的记录。

这项规则也覆盖受委派的智能体:商家分析子智能体可以读取数据,但永远不能把新 ID 加入主智能体获准写入的 ID 集合。

对于费用、披露信息和其他受监管内容,模型只负责选择需要披露哪个产品;所有文字都由服务器从已批准文案中提供。商家智能体也会把同一批费用字段列入受保护清单,因此,交易双方都不能修改或改写它们;评测则会逐字节核对渲染结果。

交易上限必须经得住重复请求

大多数商业界面都会限制单个用户可以购买的商品数量,例如门票配额、促销定价或反欺诈限制。智能体会用真人点击按钮时不曾出现的方式重试、改写请求并并行操作。

因此,执行上限时必须检查写入后的行项目状态。这样,用户第二次提出“再加两个”时就不能叠加突破上限;同一会话中的购物车写入也要串行执行,避免单轮内的多个并行工具调用合并后超出限制。

商家变更也采用同样的方式,检查价格变动、折扣幅度、补货数量和营销活动预算的上限,并保护任何变更都不得触碰的字段清单。这个规则可以概括为:根据请求执行后的最终状态强制落实每一项限制,而不是只检查单次请求;同一会话的写入必须串行化。

第三方内容必须经过清理

商业场景中的大多数上下文都由外部人员撰写,例如卖家、评论者和竞争对手。因此,后端读取到的所有内容都必须视为不可信输入,并通过同一个清理器处理。

由第三方编写的每项工具结果,包括商品信息、评论、政策、卖家消息和已存记忆,在交给模型之前都要经过清理,并封装在带有固定标签的边界内。

清理器会移除控制字符和双向文本字符,删掉任何模仿边界标记的内容,解除那些伪装成对话轮次或工具调用的文本,并限制内容长度。这套设计可防止恶意商品信息冒充系统指令,或用垃圾内容填满上下文。

提示词承担契约的另一半:边界内的文本只可作为需要转述的材料,绝不能作为需要执行的指令。

评测:如何发布一个非确定性系统

从一次微小的提示词修改到一个新工具,任何改动都可能以难以预测的方式改变智能体行为,而真正发生回归的地方,往往并不是你正在修改的部分。评测能让你在部署前发现这些问题。我们之前的揭开智能体评测的神秘面纱一文介绍了通用实践,本节则聚焦商业智能体的具体方法。

评测状态快照,而不是整段对话

模型 API 是无状态的,因此,智能体的输出是系统提示词、工具和消息数组共同作用的结果。这意味着,商业对话可能到达的任何状态都可以直接构造出来。所以,创建评测用例的方式是:构造待测试状态,追加测试用户消息,然后让智能体从该状态开始运行。

随后评判结果:包括最终状态、渲染后的响应,以及最后一次写入操作的参数。在大多数情况下,我们不建议评判智能体抵达结果的路径,因为这类测试既脆弱,又会限制实现方式。

用第二个模型扮演用户、再让一个裁判评判整段对话的模拟用户评测,并不适合用来测量性能。两个非确定性系统相互作用,需要更大的样本量,每次试验的成本更高,结果更难评判,也很难判断失败究竟来自哪里。它们适合用来发现覆盖盲区,以及对智能体做整体观感检查。因此,可以先用它们发现案例,再把每个案例写成状态快照。

在困难条件下评测行为

大多数团队都没有充分测试注入的状态。评测用例不仅应该描述任务,还应该编码失败发生的前置条件。如果某种行为只有在第一轮进行了多次工具调用后才会出现,或者只有在对话前文存在矛盾时才会出现,那么从干净状态开始的用例会在所有配置上通过,根本提供不了有意义的数据。

我们观察到,大多数评测套件都塞满了这种干净状态用例。因此,务必让一部分用例从冗长、混乱或相互矛盾的对话历史开始。

覆盖不同类型的商业智能体评测

有效评测既要测试期望行为,也要测试不期望出现的行为。

每写一个正向用例,就写一个与之对应的反向用例:每个“应该服务”都要对应一个“应该拒绝”,每个“直接执行”都要对应一个“应该询问”。缺少反向用例,是我们在评测套件中最常见到的漏洞。

需要评测的内容包括:

  • 核心请求。 它们占据大部分流量,失败会影响多数会话。包括简单查询、多约束请求、商品与套餐问题,以及包含多个意图的消息。对于问答,要检查每个价格、库存状态和属性是否都能追溯到返回数据;缺少数据时,智能体是否如实说明,而不是编造。
  • 依赖上下文的请求。 例如指代屏幕上内容的请求、从前几轮延续下来的约束,以及对现有购物车的写入。记忆评测也属于这一类。需要检查记忆是否被正确提取、检索,并真正改变了答案。
  • 安全与品牌用例。 这类失败会损失金钱或信任。包括提示词注入尝试、读取其他用户数据的尝试,以及需要逐字节核对的受监管措辞。注入应该拆成两种用例:一种是用户自行在消息中写入指令的用户侧注入;另一种是埋在商品名、评论或通过工具结果返回的网页片段中的数据面注入。
  • 界面评测。 确保渲染了正确的组件、商品数量上限得到遵守,而且面向用户的文字中没有内部标识符。超时和空结果也要测试。
  • 同时属于多项能力的请求。 操作员可能会问:“如果我把它降价 15%,库存足够满足需求吗?”这既是定价问题,也是库存问题。正确答案应该暂存降价操作,并附上库存预测;错误答案则只处理其中一半。按单项能力编写的评测发现不了这种问题,因为每项评测只会检查自己那一半。要为同时需要相邻两项能力的请求编写用例,并评判答案的两个部分。
与领域专家一起编写评测,并使用真实事故

与亲眼看到问题的领域专家合作设计测试用例,比如产品、法务、商家运营、客户服务和品类管理团队的成员。真实故障能产生最好的评测用例。每条用户流程先准备 50~100 个用例,是一个不错的起点。

如上所述,确保用例类型足够丰富。生产环境的对话记录源源不断地提供新案例,尤其是那些棘手案例。编程智能体很适合继续生成额外用例和对抗性变体。参考仓库中包含一个 Claude Code 插件,其中的评测编写技能采用了我们推荐的方法。

在大型组织中发布

在大型商业企业中,智能体由许多工程团队共同构建。搜索、结账、定价、营销技术、客户服务和商品目录平台等团队,各自拥有智能体依赖的系统,按照自己的节奏发布,也都会希望添加或修改工具、技能或提示词规则。

智能体不同于普通服务,它没有严格的模块边界来保护其他部分:定价团队所做的改动,会与结账逻辑共享同一个上下文窗口。

一种很诱人的解决方案,是把系统拆成许多子智能体,每个业务单元一个。但正如第一部分所述,出于质量原因,我们不建议这样做。下面是我们用于降低多团队协作风险的流程:

  • 所有权跟随系统。 每个技能和工具只归一个团队负责。例如,定价团队负责促销工具和定价技能;客户服务团队负责订单、退货工具和客户服务技能。共享提示词的通用部分由一个平台级负责人统一管理,其中各领域专属的小节则由对应领域负责人管理。
  • 每项改动都要随附评测用例,CI 运行与之匹配的用例集。 提交技能的团队也要提交对应测试,包括反向用例,以及与相邻技能交界处的边界用例。每个拉取请求都运行整套评测,既太慢又太贵,长期无法维持。因此,应从中构建一套 CI 用例集,其中包括覆盖最高流量请求的核心用例,以及全部安全用例。在此基础上,再运行与本次改动相关的用例:如果改的是技能,就运行该技能自身的用例和相邻技能的边界用例;如果改的是工具,就运行所有调用该工具的用例;如果改的是共享提示词,就运行整套评测,因为所有能力都会读取系统提示词。我们建议对多次试验后的通过率、缓存命中率和每轮成本设置合入门槛。每晚以及每次发布前运行整套评测,也是一项好实践。跨团队回归问题会在这些测试中暴露出来。
  • 智能体也应该纳入发布日历。 它是一个整体部署单元,因此,一项糟糕的改动会同时影响所有用户。先向金丝雀用户群逐步发布提示词和技能变更;保留无需重新部署即可关闭单个技能的开关;在业务高峰前冻结智能体,就像冻结其他系统一样。

关于这种组织方式中的人类协作,请参阅构建高效的人机协作团队

展望未来

本文介绍的大部分内容其实都与模型本身无关。工具调用的是你已经在运行的系统;技能编码的是你一直遵循的流程;评测是被写成测试的产品需求文档;编排层执行的是你原本就会为任何客户端落实的政策。模型会不断进步。等更好的模型发布时,这套架构只需修改配置并运行一轮遍历评测,就能采用新模型,其余部分则继续正常工作。

产品交互界面的路线图也值得认真思考。这套架构会比聊天面板存在得更久。同一个智能体可以通过语音工作,也可以在票价下降时主动采取行动,无需等用户开口。对于已经具备评测和工具的团队而言,这些都只是展示层项目。再往后看,访问你线上商店的一部分流量,将来自替用户购物的智能体。那些让自家智能体保持在安全边界内的来源追踪、暂存和审批规则,也正是你安全地向外部智能体开放工具的基础。

商业竞争一直会奖励那些让购买流程尽可能顺畅的公司,而智能体可以让这件事容易得多。欢迎查看完整参考实现,其中同时包含消费者智能体和商家智能体,并提供可运行的零售、旅游、电信与娱乐示例。

致谢

作者:Matthew Koen、Ali Shazal。特别感谢 Michael Segner、Rodrigo Olivares、Amandeep Khurana、Aiza Usman、John Lopus 及其他贡献者。