终止开关、断路器与金丝雀 token

Learn~60 minutesPython (stdlib, three-detector simulator: kill switch, circuit breaker, canary)先修要求: Phase 15 · 13 (Cost governors), Phase 15 · 10 (Permission modes)
终止开关是保存在 Agent 编辑范围之外的一个布尔值——一个 Redis 键、一个功能开关、一份已签名的配置——它能完全禁用 Agent。断路器更细粒度:它在特定模式上跳闸(连续五次相同的 tool call),暂停出问题的路径,并升级给人类。金丝雀 token 继承自经典欺骗术:一个伪造的凭证或蜜罐记录,Agent 没有任何正当理由去碰它,一旦访问就触发告警。基于 eBPF 的数据路径(例如 Cilium)可以在内核层把被隔离 pod 的出站流量改写到取证蜜罐;Cilium 公开的基准测试报告,负载下数据路径的 P99 延迟低于 1 毫秒(你的传播预算取决于策略更新如何到达节点,而不是数据路径本身)。适应移动基线的统计检测器(EWMA、CUSUM)会悄悄接受漂移——请把它们与不会弯曲的硬性宪法限制分层叠加。

问题

成本治理器(第 13 课)约束 Agent 可以花多少钱。它们不约束 Agent 在预算内可以做什么。一个带有 50 美元速度限制的 Agent 仍然可以窃取机密、发布错误的帖子或删除资源——昂贵的操作往往在 token 上很便宜。

本课介绍与成本层并列的三种检测器:

  1. 终止开关:保存在 Agent 触及范围之外的布尔关闭按钮。
  2. 断路器:暂停特定路径的动作模式检测器。
  3. 金丝雀 token:一个诱饵,没有正当理由触碰它的 Agent 会因为触碰它而暴露自己。

三者都是前 LLM 时代的工程实践。经典欺骗术、速率限制断路器和功能开关式终止都早于自主 Agent。新的是攻击面:Agent 读取不可信内容(第 11 课)、编辑自己的记忆,并能把许多看似安全的操作组合成一个不安全的操作。这里提到的检测器之所以有效,是因为它们不信任 Agent 的自我报告。

概念

终止开关

终止开关是 Agent 读取但无法写入的布尔值。实现选项:

  • 托管服务中的功能开关。 LaunchDarkly、Statsig、Unleash。更新在数秒内传播。
  • Agent 轮询的 Redis 键。 简单;要求 Agent 进程在每一轮检查。
  • 对象存储中的已签名配置。 Agent 在启动时验证签名;拒绝未签名的状态。
  • OS 级信号或容器生命周期终止。 Docker kill、Kubernetes kubectl delete pod、systemd stop。

正确的终止开关具备的属性:

  • Agent 无法把它设为 off。(它位于 Agent 凭证无法写入的系统中。)
  • 它在每一个有后果的操作上被检查,而不只是启动时。
  • 当它关闭时,Agent 不产生任何外部可观察的行为,包括写入 Agent 能触及的系统的日志。
  • 重新启用它是明确的人工操作,而不是自动超时。

断路器

断路器暂停特定模式,而不是整个 Agent。经典形态(出自 2007 年 Nygard 的书,至今仍然适用):

  • 闭合(Closed):允许操作。
  • 断开(Open):阻止操作。
  • 半开(Half-open):冷却之后,允许 1–3 次探测尝试(默认 1 次);成功则闭合断路器,任何剩余失败都会重新断开它。

Agent 相关的触发条件:

  • 连续五次相同的 tool call(重复循环)。
  • 同一个工具以不同输入连续失败五次(系统性失败)。
  • Tool call 速率高于阈值(第 13 课的速度限制)。
  • 在读取不可信内容之后调用了特定工具(例如 file.delete)(第 11 课)。

金丝雀 token

金丝雀 token(也叫蜜罐 token,honeytoken)是 Agent 绝不应触碰的输入。访问就是警报。

Agent 的示例:

  • 环境中一个伪造的 AWS_SECRET_ACCESS_KEY,没有任何实际权限。窃取尝试可以被立即归因。
  • 一条带有已知哨兵值标记的伪造数据库记录。对该记录的任何读取或更新都会触发告警。
  • 工作区中的一个伪造文件。读取或编辑该文件都是可疑的。
  • 会话开始时注入的一条伪造记忆条目。如果它出现在后续输出中,说明记忆已被窃取。

金丝雀设计是针对具体工作流的。如果 Agent 有正当理由触碰某个金丝雀,它就是噪声。

为什么要把统计限制和硬性限制分层

统计检测器(EWMA、CUSUM、tool call 速率的 z-score)适应移动基线。对合法漂移这是特性,对对抗性漂移这是缺陷。有耐心的攻击者可以把基线移动得足够慢,让任何警报都不触发。

硬性宪法限制(第 17 课)不会弯曲。作为宪法规则,「绝不向 secrets@ 发邮件」更简单、可审计,且无法被缓慢漂移所操纵。分层模式是:统计检测器捕捉大部分噪声,硬性限制捕捉溜过检测器的攻击。

通过 eBPF 数据路径重定向进行隔离

Cilium 基于 eBPF 的网络策略可以在内核层把被隔离 pod 的出站流量改写到取证蜜罐。Cilium 公开的基准测试报告,TCP_RR 上数据路径的 P99 延迟低于 1 毫秒;在你的集群中触发隔离的挂钟预算,主要取决于策略更新从控制平面传播到节点的方式(在预加载 operator 的 Kubernetes 上,几百毫秒是现实的;尾部延迟取决于集群规模和 reconcile 节奏)。这给你两件事:Agent 不会窃取任何真实数据,而且 Agent 在蜜罐内的行为被完整观察。与金丝雀 token 是同一模式、不同层次:Agent 通过它在被围困时试图做什么来暴露意图。

没有检测器能捕捉的东西

  • 由允许的原语组合而成的语义攻击。 每一个单独操作都通过所有检测器;问题出在组合上。这就是第 10 课中的 Auto Mode 组合失效。
  • 把检测器作为载荷一部分的攻击。 如果 Agent 读到一个页面说「行动前先禁用金丝雀」,而 Agent 又有这个能力,检测器就被破坏了。金丝雀 token 应放在 Agent 无法修改的系统中。
circuit-breaker静态版本未包含此交互图

使用它

code/main.py 模拟一条短 Agent 轨迹依次经过三个检测器。终止开关保存在外部 dict 中;断路器在连续五次相同 tool call 时跳闸;一个金丝雀文件在被读取时触发告警。喂入的合成轨迹包括:合法操作、重复循环、金丝雀探测,以及一个由终止开关触发、Agent 操作被停止的场景。

交付它

outputs/skill-tripwire-design.md 审查拟议 Agent 部署的检测器栈,并标出缺口(缺少终止开关、缺少金丝雀、断路器阈值过松)。

练习

  1. 运行 code/main.py。确认断路器在第 5 轮(第五次相同调用)跳闸,金丝雀在第 9 轮(读取伪造密钥)触发。
  1. 添加一个统计检测器:Tool call 速率的 EWMA z-score。喂入一条缓慢漂移的轨迹,展示检测器从不触发。现在添加一个硬性限制(10 分钟内不超过 50 次 tool call),展示硬性限制在同一条轨迹上触发。
  1. 为浏览器 Agent(第 11 课)设计一组金丝雀 token。至少列出三个金丝雀以及每一个能检测什么。
  1. 阅读 Cilium 网络策略文档。具体描述一个出站重定向隔离流程:哪个策略选择器、哪个 pod、哪条出站改写、哪个告警。从「决定隔离」到「第一个被重定向的数据包」之间的挂钟延迟由什么决定?
  1. 为一个被终止开关停用的 Agent 定义重新启用流程。谁能重新启用?必须记录什么?重新启用前 Agent 必须改变什么?

关键术语

术语人们怎么说实际含义
终止开关「关闭按钮」Agent 编辑范围之外的布尔值;在每个有后果的操作上检查
断路器「模式暂停」按重复、失败率或速率限制对特定动作跳闸
金丝雀 token「蜜罐 token」Agent 没有正当理由触碰的诱饵;访问即触发告警
蜜罐「取证沙箱」被隔离 Agent 被观察的重定向流量 / 工作区
EWMA「移动平均」指数加权;适应漂移(既是特性也是缺陷)
CUSUM「累积和」检测相对基线的持续偏移
硬性限制「宪法规则」不适应;无论历史如何都保持不变
宪法限制「恒真规则」与第 17 课的宪法绑定;Agent 无法编辑

延伸阅读

示意图共 1 张

tripwires diagram
tripwires

“Stay hungry, stay foolish.”

— Steve Jobs

esc
↑↓切换↵打开esc关闭