跳到主要内容

为自主 AI 智能体设计审批门禁

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数代理 (Agent) 故障并非以“爆炸”这种显式方式发生。它们往往是悄无声息的。代理删除了错误的数据记录,给客户发送了过时的信息,或者重复执行了一个已经成功的支付操作 —— 而你直到两天后收到支持工单 (Support Ticket) 时才会察觉。其根本原因几乎如出一辙:代理拥有对生产系统的写入权限,但在“决定行动”与“执行行动”之间缺乏检查点。

审批门禁 (Approval Gates) 是应对这一问题的工程化方案。这里指的不是那种没人看的合规复选框(即弹窗),而是真正的架构中断点 —— 它们能够暂停代理的执行,序列化状态,等待人工决策,然后干净利落地恢复运行。如果设计得当,它们能让你部署具有真实自主权的代理,而无需在每一次推理调用中都拿生产数据去冒险。

为什么审批门禁在构建之前就失败了

针对审批门禁常见的反对意见是,它们违背了自动化的初衷。如果每一个动作都需要人工审批,那你只是构建了一个昂贵的邮件系统。这是一个真实存在的问题,它会导致团队要么在没有任何监管的情况下发布代理,要么过度干预导致操作人员不再关注反馈。

正确的视角应该是:审批门禁应当是稀缺、精准且起支撑作用的。一个每天处理 500 个支持工单的代理,可能只有 5 个需要人工审批 —— 比如涉及超过特定限额的退款、注销账号或被代理分类为“模糊”的操作。对于其余 495 个工单,门禁根本不会被触发。

陷入需要持续审批的代理是配置错误,而非治理良好。大多数团队实际遇到的故障模式并非过度审批,而是相反:代理在原本不该自信的边缘案例中表现得过于自信。

在构建门禁前对动作进行分类

在构建门禁之前,你需要对代理的行为进行分类。实用的分类通常分为三个层级:

AUTO — 无需审批即可执行。 这些是可逆、低风险、主要为读取或边界清晰的操作。例如获取数据、生成草稿、查询内部 API、发送日志条目或将项目添加到已有人工处理的队列中。此类操作的失败模式是可恢复的,且影响范围 (Blast Radius) 较小。

LOG — 执行并记录,用于异步审计。 这些操作通常没有问题,但值得审计。例如发送标准的客户邮件、更新非关键记录、创建日历事件。代理继续执行,但每次执行都会留下审计追踪,人工可以定期进行抽检。

REQUIRE_APPROVAL — 阻塞直至获批。 不可逆操作、金融交易、大规模外发通信、生产部署、删除记录或提权。在人工(或自动策略检查)明确批准该操作之前,代理无法继续。

实际问题在于如何在运行时进行分类。对于许多系统,分类可以是基于规则的:写入数据库的行数超过一定数值需要审批,任何发送给 N 个以上接收者的邮件需要审批,任何超过金额阈值的金融操作需要审批。这些规则不需要 ML 且易于审计。

对于更复杂的动作空间,你可以使用轻量级分类器 —— 甚至是针对小型模型的简单提示词 —— 在主代理行动之前评估风险。分类器不需要完美;它只需要捕捉到基于规则的系统可能会遗漏的高风险案例。

中断-检查点模式 (The Interrupt-Checkpoint Pattern)

审批门禁的基础设施难题在于 Web 服务器无法自然地暂停。一个遇到审批门禁的 HTTP 请求处理程序不能为了等某人查看 Slack 而阻塞线程 20 分钟。你需要一种不同的执行模型。

这种行之有效的模式是中断-检查点-恢复 (Interrupt-Checkpoint-Resume):

  1. 中断 (Interrupt): 当代理遇到被分类为 REQUIRE_APPROVAL 的操作时,它不执行该操作。相反,它会将完整状态 —— 对话历史、正在执行的计划、想要执行的具体操作 —— 序列化到检查点存储中。
  2. 通知 (Notify): 审批请求会发送到相应的渠道(Slack 消息、邮件、仪表板队列)。请求中包含足够的上下文,让评审人员无需深入挖掘即可做出知情决策。
  3. 等待 (Wait): 原始代理的执行终止。线程被释放。检查点存储在持久化存储中(DynamoDB、PostgreSQL、Redis —— 任何持久化介质均可)。
  4. 恢复 (Resume): 当人工批准(或拒绝)时,新的执行进程读取序列化的状态并从检查点继续。审批/拒绝的决策将成为中断调用的返回值。

LangGraph 通过 interrupt() 原语和持久化检查点直接实现了这一模式。OpenAI Agents SDK 通过 RunToolApprovalIteminterruptions 数组来暴露这一功能。如果你在构建自定义技术栈,核心需求是一个以线程 ID 为键的持久化键值存储,以及一种从任意序列化状态恢复执行的方法。

一个关键的设计决策是:让检查点状态保持自足 (Self-contained)。恢复执行时不应需要重新查询外部系统来重建上下文。代理在中断时已知的所有信息都应嵌入在检查点中,因为到审批通过时,外部状态可能已经发生了变化。

置信度阈值作为自动化闸口

基于规则的分类可以处理显而易见的情况。更难的问题是那些看起来常规但在异常背景下发生的动作——比如对错误的数据库执行正确的 SQL 查询,或者使用错误的接收者数据填充正确的模板。

置信度阈值增加了第二层保障。在执行任何 REQUIRE_APPROVAL 动作之前,Agent 会评估其对该动作正确性的信心。如果高于阈值(例如 85%),它会转而路由到 LOG 层级。如果低于阈值,无论动作类型如何,它仍然需要审批。

这种机制通常是一个额外的 Prompt 步骤:在规划动作后,Agent 会评估“根据当前上下文,我有多少把握确定这是正确的动作?”其响应是一个经过校准的分数,而非二进制结果。你也可以从更客观的信号中获取代理置信度:该动作是否匹配用户的明确指令、输入数据是否通过了 Schema 验证、先前的步骤中是否有工具返回了错误。

置信度阈值并不会消除审批闸口——它们的作用是调节闸口。一个在执行高风险动作时保持 95% 以上置信度的 Agent 可能会在 1% 的时间内触发审批。而一个在执行常规动作时频繁触碰 60% 置信度的 Agent 则是在告诉你,它需要更好的指令或工具,而不是更多的人工监督。

异步审批的实践

审批闸口的 UX 与基础设施同样重要。如果一个 Slack 消息只是说“Agent 想要执行动作。批准?[是] [否]”,它会被忽略或被盲目批准,从而失去意义。

有效的审批请求包含四个要素:

  • Agent 想要做什么(带参数的具体动作,而非类别)
  • 为什么它认为这是正确的动作(简短的推理过程)
  • 批准与拒绝分别会发生什么
  • 动作超时或升级前的时间窗口

Slack 适用于低频、高上下文的审批——例如客户成功 Agent 将退款决策路由给 CS 团队,或者部署 Agent 请求生产环境上线许可。邮件队列适用于需要审计的审批,此时审批本身就是记录。当你拥有足够的业务量来支撑专用界面,并需要分组、过滤和批量操作时,Web 仪表板则是更好的选择。

要避免的失败模式是审批疲劳。如果审查人员每天看到 50 个审批请求,其中 49 个都是常规操作,他们会不加阅读地全部批准。这比没有审批闸口更糟糕——它创造了一种虚假的监督感。闸口校准是一项维护任务。监控你的审批率,并标记任何审批通过率超过 98% 且从未被拒绝的闸口。要么是该闸口配置错误,要么是该动作应该被设为 AUTO

拒绝后会发生什么

大多数实现只处理了理想路径(批准 → 恢复),而没有处理拒绝路径。拒绝不应该只是终止 Agent —— 它应该创建一个反馈循环。

当人类拒绝一个动作时,他们知道一些 Agent 不知道的信息。捕捉这些信息:要求提供简短的拒绝理由,将其与 Agent 的置信度分数和动作推理逻辑一起记录,并利用这些数据不断改进分类模型。在特定背景下出现的持续拒绝模式是一个信号,表明需要收紧分类规则或重新训练 Agent。

Agent 被拒绝后的行为也需要设计。选项包括:

  • 中断 (Abort): 停止当前任务,并报告在没有获得批准动作的情况下无法继续。
  • 重路由 (Reroute): 尝试不需要触发闸口动作的替代方案。
  • 升级 (Escalate): 将被拒绝的任务转交给可以接手的人类操作员。

选择哪种方案取决于任务类型。对于不可逆的多步工作流,中断通常更安全。对于探索性任务,重路由通常是合适的。Agent 绝不应该静默地重试被拒绝的动作——那是对信任的违背,会使审批闸口失去意义。

针对系统性故障的熔断机制

审批闸口处理单个风险动作。熔断机制(Circuit breakers)则处理系统性故障——即当 Agent 开始产生异常高比例的拒绝或被标记动作时。

这种模式镜像了分布式系统中的熔断器:在滚动窗口内跟踪拒绝率。如果超过阈值(例如 1 小时内拒绝率达到 15%),则开启熔断——完全暂停 Agent 并提醒操作员。Agent 在 2% 拒绝率时是可靠的;而在 15% 时,环境、指令或工具行为肯定发生了变化,继续运行已不再安全。

熔断机制还能捕获隐蔽的性能下降。一个技术上仍在运行但产生低质量动作的 Agent 可能永远不会触发单个审批闸口,但其行为模式会随着时间的推移偏离基准。通过监控动作分布——不仅是批准/拒绝计数,还有所采取动作的统计概况——让你在漂移演变成生产事故之前捕获它。

监督与自主权的匹配

目标不是最大化监管。目标是适当的监管——足以捕获关键故障,并根据 Agent 行为的实际风险状况进行校准。

随着团队经验的增加,会出现一种模式:新部署的 Agent 从低审批阈值开始(保守策略,除了常规读取操作外拦截所有动作)。随着 Agent 在生产环境中证明其可靠性,阈值会提高,闸口分类会针对此前拦截的动作向 LOGAUTO 调整。人类的角色从批准单个动作转变为监控总体行为并处理升级。

这是一个正确的方向。每隔几分钟就审查一次 Agent 动作的操作员并没有增加安全性——他们只是昂贵且疲惫的。而审查仪表板、处理升级的边缘情况并负责审批系统校准的操作员,才是在真正提供监管。

基础设施的目标是让自主权的逐步提升变得容易,并且如果高自主权层级开始产生故障,能够有清晰的回滚机制。先建立闸口,然后将其调优至必要的最小干预程度。


审批闸口不是对谨慎的勉强让步。它们是让 Agent 获得更多自主权的工程原语(primitive)。没有它们,每一次 Agent 的部署都是在含蓄地赌模型能正确处理每一个边缘案例。有了它们,你就能明确模型在何处将控制权移交给人类——并且你拥有数据来让这种移交随着时间的推移变得越来越少。

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