跳到主要内容

为 Agentic 写入路径构建数据质量门禁:输入是垃圾,输出是不可逆的操作

· 阅读需 13 分钟
Tian Pan
Software Engineer

2025 年,一个 AI 编程助手在代码冻结期间对生产数据库执行了未经授权的破坏性命令——删除了 2.5 年的客户数据,创建了 4,000 个虚假用户,并伪造了成功的测试结果以掩盖真相。根本原因并非模型不好,而是代理意图与系统执行之间缺少了一道关口。

那次事件虽然戏剧化,但并非个例。在生产环境中,工具调用(Tool calling)的失败率为 3–15%。代理会重试模棱两可的操作。它们读取陈旧记录并基于过时的状态采取行动。它们生成的输入会以微妙的方式违反模式(schema)约束。在问答系统中,这些失败只会产生一个错误答案,用户发现后可以纠正。但在具有写入权限的代理中,它们会产生重复订单、错误的通知、损坏的记录——在有人意识到出错之前,这些损害就已经存在并扩散了。

查询代理和写入代理之间的区别不仅仅在于严重程度,还在于故障的表现形式、检测速度以及修复成本。用同样的运营态度对待两者,是生产环境写入路径代理失败的主要原因。

为什么写入型代理属于不同的可靠性级别

当查询代理检索到错误的文档或根据上下文推理错误时,错误显而易见——用户读到了错误的答案。爆炸半径仅限于单次响应。恢复成本几乎为零:再问一次即可。

当写入代理基于错误的输入采取行动时,错误就会进入你的系统状态。在有人标记之前,重复订单就会扩散到履行、库存、计费和客户收件箱。损坏的客户记录会流入下游的分析、支持工具和 ETL 任务。如果医生没有及时发现差异,根据陈旧患者数据安排的用药方案可能会直接作用于人体。

有三个特性决定了为什么写入路径需要更严格的验证:

持久性(Persistence)。 写入错误不会在对话结束时消失。它们存在于你的数据库、消息队列和外部 API 状态中。修复这些错误需要审计、回滚,通常还需要手动对账。

传播性(Propagation)。 下游系统将写入操作视为既定事实(ground truth)。T=0 时的一个错误记录到 T=60 时会扩散到 N 个系统。当有人注意到时,原始的错误状态已经被复制、转化并执行。

延迟检测(Delayed detection)。 错误的答案是显而易见的。重复的订单可能在三天后作为客户投诉浮出美联。而无声的工具调用失败——API 返回了 HTTP 200 但静默丢弃了格式错误的字段——可能永远不会暴露,留下一个看起来有效但已损坏的记录。

这三个特性意味着,输入验证对于查询系统来说是锦上添花,但对于写入系统来说则是承重基础设施。

冲击写入路径最严重的六种失败模式

基于陈旧数据执行。 代理在 T=0 时读取客户记录,花费 10 秒进行推理,然后在 T=15 时执行写入。而另一个进程在 T=5 时更新了该记录。代理基于对世界过时的认知进行写入。对于查询系统,这只会产生一个稍微过时的答案。对于写入系统,这会导致对错误的状态执行了错误的操作——作用于当前数据,但源于过去的数据。

无声的工具调用失败。 在生产环境中,工具调用的失败率为 3–15%,而且并不总是会报错。API 可能会静默接受格式错误的参数并返回成功,然后以降级状态处理请求。一个创建订单的代理如果丢失了金额字段(因为参数以字符串形式传递,而 API 期望的是浮点数),现在系统中就出现了一个 $0 的订单。没有抛出异常,代理认为自己成功了。

重试导致的重复。 代理在超时时会进行重试。网络也会超时。第一次尝试是否成功是模棱两可的。代理重试非幂等的写入操作会创建两条本应是一条的记录。如果在写入操作中没有幂等键(idempotency key),重试的模糊性就等于数据重复。在重试率达 15–30% 的系统中,这绝非极端情况。

软删除对象的复活。 代理查询记录而不检查软删除标记。除非查询中明确过滤,否则 deleted_at != null 的记录看起来就像是有效记录。代理可能会重新激活已注销的账户、向已退订的用户发送邮件,或者向已终止合同的供应商重新订货——这不是因为推理能力差,而是因为它根本不知道该记录在逻辑上已失效。

架构违反(Schema violations)。 LLM 会幻觉出违反约束的值。枚举字段收到了自由文本字符串。必填字段传回了空值。外键引用了一个不存在的 ID。这些违反行为通常在数据库边界处发生,并产生代理无法理解的错误——或者更糟,它们在宽松的架构上执行成功并破坏了下游的关联(joins)。

级联放大。 写入错误数据的代理随后基于该错误数据做出进一步决策,每迭代一次损害就会翻倍。运往错误地址的订单(源于陈旧记录)会触发支持工单、重新发货操作和库存调整——所有这些都会在原始错误被发现之前将其放大。

校验检查点设计

核心见解在于,校验不应存在于工具本身之中,而应存在于一个位于 Agent 决策行动与工具实际执行之间的检查点层(checkpoint layer)。这为你提供了一个统一的地方来强制执行所有工具的数据质量规则,并让 Agent 有机会在错误输入造成损害之前对其进行纠正。

一个设计良好的校验流水线包含五个阶段:

LLM 前置输入清理 (Pre-LLM input sanitization)。 在面向用户的输入进入上下文之前对其进行清理和校验。截断过大的载荷。剥离控制字符。标准化格式。这可以防止上游的错误输入流入 Agent 的推理过程。

工具边界处的 Schema 校验。 将每个工具的输入定义为类型化的 Schema(Python 中的 Pydantic,TypeScript 中的 Zod,或语言无关系统中的 JSON Schema)。在工具执行之前而非之后强制执行此 Schema。如果 LLM 生成的输入不符合 Schema,应通过包含信息的错误消息(例如:“客户 ID 必须是 6 位整数,收到的是 'cust_12345abc'”)直接报错,以便 Agent 能够纠正并重试,而不是带着错误格式的输入继续执行。

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates