给智能体做预发布环境。
标准直觉——把依赖 mock 掉、让模型随意浮动——对智能体来说恰好是反的;这正是为什么多数智能体预发布环境一片绿,生产却在烧。把工具 mock 掉,等于删掉了延迟、错误形态与 schema 漂移,而那些正是你原本想抓的失败;与此同时,模型才是那个你可以免费钉死的部件。让工具保持真实、把模型钉住,并把边界挪到副作用之前的最后一跳。
服务那套手册搬不过来,因为这个环境不归你所有。
给一个服务做预发布是已解决的问题,因为它的依赖图是可掌控的:你自己的代码、一个你能灌数据的数据库、一条消息总线,外加几个你同样能部署的内部服务。起一套副本、灌上 fixture、跑测试。而智能体的依赖图不是这个形状。老实写出来,里面装着:
- 一个你没法部署副本的模型。它是别人的服务,按别人的节奏更新,而它的行为是一个分布,不是一个函数。
- 你克隆不了的第三方 SaaS。CRM、工单系统、支付处理商。有些提供沙箱;而沙箱的数据量不同、限流不同,还常常 API 版本也差一截。
- 一份文本归别人所有的工具目录。一个 MCP server 的描述是你 prompt 的一部分,而它会在你这边没有任何提交的情况下改变——这正是第三方工具漂移整篇在讲的事。
- 状态本身就是关键。智能体的行为是「它去看时看到了什么」的函数:多少条记录、有多乱、有多自相矛盾。一个灌了十二行的租户,测的是另一个程序,不是你发布的那个。
- 一个人。审批、打断、只说了一半的要求,以及两小时后的追问。
所以并不存在某一个叫作「预发布」的环境。存在的是一架保真度的梯子,每一级都在某个维度上便宜、在另一个维度上不诚实;而运维要回答的问题不是「我们有没有预发布环境」,而是哪一级有资格为哪一步发布把关。
把模型钉住,让工具保持真实。
人们从服务测试里带来的直觉,是把又慢又飘的外部东西换成又快又稳的假货。用在智能体身上,这等于把研究对象本身删掉了:
- mock 掉的工具瞬间返回,而延迟占了一条轨迹的绝大部分。一次二十步、打真实 API 的运行,其挂钟时间的绝大多数都花在工具调用里面。把它们 mock 掉,你的超时策略、并行度、重试预算与上下文增长曲线就全都没被测过——这与给智能体系统做压测所依据的是同一个论证。
- mock 掉的工具只会返回你想到过的错误。真实的那些会返回带着你没解析的
Retry-After的 HTTP 429、一个写了一半记录的 200、一个从整数变成了字符串的字段,以及一个跑到半路过期的 OAuth token。错误处理是智能体代码的大头,而 mock 测的是你本来就已经理解的那一半。 - mock 掉的工具永远不会漂移。预发布环境能为智能体做的最有价值的一件事,就是察觉某个依赖变了。而一个 mock 是你信念的快照,所以它会永远同意你。
模型则是相反的情形。把它钉住几乎不花钱,却买来了真正的可比性:一个具体的模型版本而不是一个浮动别名、一个固定的系统提示词与工具目录哈希并记录在每次运行上、一份检索索引的快照,以及在任务允许时的低温度。别高估这买到了什么——钉住不等于确定性,理由见可复现性与确定性——所以一次绿色的预发布运行是一个样本,不是一份证明。每个把关场景多跑几次,读通过率;一个五次里过四次的场景,是一项不稳定的功能,不是一条不稳定的测试。
把环境的身份打在每一条 trace 上:模型版本、prompt 哈希、工具目录哈希、索引快照 id、保真度等级。没有这五个字段,你回答不了「这次回归来自我们的改动、模型,还是某个厂商」——而这正是预发布与生产不一致时,所有人唯一会问的问题。
四级台阶,以及一条关于「谁能为谁把关」的规矩。
- 第 0 级——录制并回放的流量。真实响应录一次,之后从磁盘回放。跑一次以秒计,在工具侧是确定性的,免费。能抓住提示词回归、解析变更、控制流缺陷。为每一次提交把关。它的失败模式是无声的陈旧化,所以要把录制当易腐品:按周期重录,当某盘磁带超过你的阈值就让构建失败,并且——这一步团队常跳过——用一个每晚跑的任务去哈希线上响应的 schema,好让你从 CI 而不是从客户那里得知录制已经过时。
- 第 1 级——厂商沙箱与测试模式。真实的 API 表面、真实的鉴权、真实的错误分类、灌好的租户。跑一次以分钟计。能抓住被第 0 级冻在外面的集成与 schema 问题。为合并把关。要明确说清沙箱在哪些地方撒谎:它们通常更小,有时落后一个版本,而它们的限流很少和生产对得上。
- 第 2 级——生产依赖,副作用在最后一跳被中和。智能体面对的是真实系统、真实数据量与真实延迟;只有写操作被拦截。能抓住一切「取决于规模与真实世界之乱」的问题。为发布把关。
- 第 3 级——真实副作用,爆炸半径受限。一个内部租户、一批员工用户、一类低价值交易。环境里属于人的那一半,终于在这里登场。它与灰度与版本管理里的分阶段发布一道,为全量可用把关。
让这架梯子真正有用的那条规矩是:一级只能为「它本来抓得住其失败」的那一步发布把关。让第 0 级去为发布把关,就是一支团队怎么把一个从未见过限流的智能体发出去的。把这份映射写下来,因为「第 0 级绿了就放行」的压力,总是在你已经延期的那天到来。
写阻断器才是那件产物。把它建在出网处,不是建在工具封装里。
第 2 级是这架梯子里能回本的那一级,而它存不存在,只取决于一件基础设施:一个让读操作放行到生产、并从智能体自身代码之外拒绝写操作的东西。
- 把它放在网络边界上。一个所有出站调用都要穿过的正向代理,按方法与路由把每个请求分类为读或写,对目的地做白名单,并对任何它不认识的东西失败闭合。放在工具封装里,它就只是一条建议——一个自己写出 HTTP 调用的模型,或者一个添加了你没封装过的工具的框架,绕过去就是了。这与智能体的出网管控所描述的是同一项控制,只是对准了另一种威胁。
- 被拦下的写,必须返回一个智能体会相信的东西。这个细节决定了第 2 级到底测没测出东西。如果代理返回 403,那每一次运行都变成对你错误路径的测试,而你对正常路径一无所知。返回一个逼真的成功——一份录制下来的响应体,配一个合成 id——好让智能体走到第九步,而缺陷就住在那里。
- 厂商自带 dry-run 时优先用厂商的——仅校验标志、测试模式密钥、发件用的黑洞域名——因为厂商的空跑比你对空跑的模仿更诚实。代理留给那些没有空跑的。
- 把每一次被拦截的写记录为一次「被提议的副作用」,并与上一个版本做差分。智能体想要做的那串写操作,是这整套装置产出的最值得评审的一件产物;也正是靠它,你才会注意到某次提示词改动悄悄把被触及的记录数翻了倍。
如果预算只够做一件事,那就做这个代理。它免费地把你的生产依赖变成了一个高保真测试环境;当同一个智能体真跑起来时,它又兼任一项遏制控制;而它吐出的那份「被提议的写」差分,比任何人写的发布说明都好。
按形态灌数据,而且绝不用生产数据的副本。
状态是程序的一部分。一个读着「十二条整洁记录」的租户的智能体,会检索得很好、很早收尾、看起来出色;同一个智能体面对四十万条带重复、三套命名习惯、外加十年遗留自定义字段的记录时,就是另一个系统了。所以种子数据是一件带规格的测试资产,不是某人生成过一次的 fixture。
- 按体量、混乱度与权限来灌——近似重复项、自相矛盾的记录、空字段与超大字段、混合语言与编码,以及智能体的凭证不该看得见的记录。最后这一类,是唯一能测出权限感知检索是否真的成立的办法。
- 把对抗性的那几行也放进去。一份含有指令的文档,在真实语料里是件很正常的事。如果你的种子集里一次注入尝试都没有,那你的预发布环境从未测过你最在意的那项控制。
- 不要把生产数据克隆进沙箱。这是从「我们改进了测试」通往「一起需要上报的事故」的最短路径,因为沙箱的访问控制更弱、凭证活得更久、里面的人更多。要做子集加脱敏,或者干脆生成;并且按数据治理的要求,让种子集适用与其他数据相同的留存规则。
- 把种子集和代码一起做版本管理。一次既归因不到代码、也归因不到模型的质量变化,通常是一次没人记录的数据变更。
哪一级都告诉不了你的事,以及那个用来调这架梯子的数字。
有四样东西在结构上够不着,而假装够得着,正是团队在预发布上过度投入、在生产安全上投入不足的原因:
- 真实的请求分布。你的场景是你想到过的任务;用户带来的是长尾,而智能体正是在长尾上失败。
- 真实的对抗性输入。你可以把已知攻击灌进去。你灌不进下周才被人发明出来的那一个。
- 厂商侧在负载下的行为。别人服务上的容量、排队与退化,不会按你的日程表复现。
- 人。审批延迟、含糊的指令,以及智能体在下午四点五十五分提问时人们会做什么。
所以你信心中固定的一部分,必须在生产里买——灰度、影子运行,以及智能体的在线实验里那些刻意的设计——而这架梯子的职责,是把那一部分压到你负担得起,而不是压到零。
用一个数字来调它:逃逸率,即被追溯到「某个更低台阶本该抓住」的失败的生产事故数量,并归到漏掉它的那一级头上。逃过第 0 级,说明你的录制陈旧了或者场景集有洞;逃过第 1 级,说明沙箱在某个你没写下来的地方与生产分了叉;逃过第 2 级,说明写阻断器有一条路径没盖住。每一次逃逸,都以「在某一具体台阶上补一条具体的东西」收尾。把它和磁带年龄以及预发布对生产的行为差值——同一批场景在第 2 级与在生产中的工具调用次数、步数与拒答率之差——一起跟踪,你就有了一个会随时间变得更诚实、而不是悄悄变得更不诚实的预发布环境。
如果你从这一页只做一件事,那就把出网写阻断器建起来,并让你现有的场景在它背后打真实的生产依赖。每一次值得拥有的智能体预发布失败,都是一次保真度上的失败;而你手边能拿到的、性价比最高的那一大截保真度提升,就是别再 mock 工具、改为拦截写操作。mock 会永远同意你;生产会立刻反对你,而这正是它全部的价值所在。然后把第二天花在「会大声过期」的录制上,第三天花在一份带着脏乱的种子集上。
延伸:以评测驱动的智能体开发讲每一级台阶上该跑什么,修复智能体已经做过的事讲你没拦住的那些写操作要付出的代价,而智能体外壳讲的是「为什么环境就是你真正在发布的东西的一半」。