Kill Switch、熔断器与金丝雀令牌


文档摘要

Kill Switch、熔断器与金丝雀令牌 本节摘要:成本治理(第 13 节)管住了 Agent 能花多少,但管不住 Agent 在预算内能做什么。一个带 50 美元速度限制的 Agent 依然可以外泄一个密钥、发错一条推文、删掉一个资源——代价最高的动作往往是 token 上最便宜的动作。本节讲紧贴成本层之上的三类探测器(detectors):Kill switch(急停开关)是一个 Agent 只读不写的布尔值,装在它够不到的地方(Redis 键、特性开关、签名配置),关掉它就让整个 Agent 失能;熔断器(circuit breaker)更细粒度,按特定模式(连续五次相同工具调用)跳闸、暂停违规路径、升级到人;金丝雀令牌(canary token /

Kill Switch、熔断器与金丝雀令牌

本节摘要:成本治理(第 13 节)管住了 Agent 能花多少,但管不住 Agent 在预算内能做什么。一个带 50 美元速度限制的 Agent 依然可以外泄一个密钥、发错一条推文、删掉一个资源——代价最高的动作往往是 token 上最便宜的动作。本节讲紧贴成本层之上的三类探测器(detectors):**Kill switch(急停开关)**是一个 Agent 只读不写的布尔值,装在它够不到的地方(Redis 键、特性开关、签名配置),关掉它就让整个 Agent 失能;**熔断器(circuit breaker)**更细粒度,按特定模式(连续五次相同工具调用)跳闸、暂停违规路径、升级到人;**金丝雀令牌(canary token / honeytoken)**继承自经典欺骗战术——一条假凭据或蜜罐记录,Agent 没有合法理由去碰,一旦被访问就触发告警。三者都是 LLM 之前的工程遗产,新的是攻击面:Agent 读不可信内容(第 11 节)、改自己的记忆、能把许多「看起来安全」的动作组合成不安全的一个。它们的共同点是:不信任 Agent 的自报告。统计型探测器(EWMA、CUSUM)会向移动基线妥协,需要与不弯曲的硬性宪法限制(第 17 节)分层叠加。

对应原课程:Phase 15 · Lesson 14 · kill-switches-canaries(原英文 phases/15-autonomous-systems/14-kill-switches-canaries/docs/en.md)。前置:第 13 节(成本治理)、第 10 节(权限模式)。

学习目标

阅读完本节,你应当能够:

  1. 区分 kill switch、熔断器、金丝雀令牌三者各自抓什么:全局失能 vs 路径暂停 vs 访问即告警。
  2. 列出一个正确的 kill switch 必须满足的四条性质(只读、每次后果性动作都查、关闭后无外部可观测行为、重启用须人工)。
  3. 描述熔断器的闭合/断开/半开三态,以及与 Agent 相关的四类触发模式。
  4. 为浏览器 Agent、编码 Agent 设计一套金丝雀令牌,说明每条令牌检测什么。
  5. 解释为什么统计探测器要和硬性限制分层:慢漂移(slow drift)能让 EWMA 沉默,而宪法规则不弯。

一、问题与直觉

成本治理(第 13 节)约束了 Agent 能花多少,但没有约束 Agent 在预算内能做什么。一个有 50 美元速度限制的 Agent 仍然可以外泄密钥、发错推文、删掉资源——昂贵的动作往往是 token 上最便宜的动作。

本节覆盖紧贴成本层之上的三类探测器:

  1. Kill switch:Agent 够不到的布尔「关闭键」。
  2. 熔断器:按动作模式跳闸、暂停某条具体路径。
  3. 金丝雀令牌:一个 Agent 没有合法理由去碰的诱饵,碰了就暴露自己。

三者都是 LLM 之前的工程。经典欺骗战术、限流熔断、特性开关急停,都比自主 Agent 早得多。新的是攻击面:Agent 读不可信内容(第 11 节)、编辑自己的记忆、能把许多安全动作组合成一个不安全动作。这里命名的探测器之所以有效,是因为它们不信任 Agent 的自报告

⚠️ 核心张力:这三个探测器都在 Agent 的自报告之外。一旦 Agent 能改自己的状态、能写承载这些标志的系统,整个防线就瓦解了——所以 kill switch 必须住在「Agent 凭据写不到的地方」。

Kill switch 的四条正确性质

一个正确的 kill switch 必须满足:

  • Agent 不能把它设为 off(它住在一个 Agent 凭据无权写入的系统里)。
  • 在每次后果性动作上都检查,而不是只在启动时检查。
  • 当它关闭时,Agent 不做任何外部可观测的行为,包括向 Agent 能触及的日志系统写日志。
  • 重启用是显式的人工动作,不是自动超时。

实现选择:托管服务里的特性开关(LaunchDarkly、Statsig、Unleash,几秒内传播)、Agent 每轮轮询的 Redis 键、对象存储里的签名配置(启动时验签)、OS 级信号或容器生命周期 kill(Docker kill、Kubernetes kubectl delete pod、systemd stop)。

熔断器的三态

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

  • 闭合(Closed):动作允许。
  • 断开(Open):动作被阻断。
  • 半开(Half-open):冷却后允许 1~3 次探测尝试(默认 1);成功则闭合,任何残余失败则重新断开。

Agent 相关触发:连续五次相同工具调用(重复循环)、同一工具五次连续失败且输入不同(系统性失败)、工具调用速率超过阈值(第 13 节的速度限制)、在不可信内容读取之后调用特定工具(如 file.delete,见第 11 节)。

金丝雀令牌

金丝雀令牌(也叫 honeytoken)是 Agent 绝不该碰的输入。访问即告警。面向 Agent 的例子:

  • 环境里一个没有真实权限的假 AWS_SECRET_ACCESS_KEY——外泄企图瞬间可归因。
  • 数据库里一条用已知哨兵值标记的假记录——任何读或更新都触发告警。
  • 工作区里一个假文件——读或编辑都可疑。
  • 会话开始时注入的一条假记忆条目——若它出现在后续输出里,说明记忆被外泄了。

金丝雀设计针对工作流定制。一个 Agent 有合法理由去碰的金丝雀只是噪声。

💡 金丝雀的本质是「Agent 通过它试图做什么来暴露意图」。后面 eBPF 重定向蜜罐是同一模式的不同层。

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

统计探测器(EWMA、CUSUM、对工具调用速率做 z-score)会适应移动基线。这对合法漂移是特性,对对抗性漂移是 bug——耐心的攻击者可以把基线移得足够慢,以至于没有任何告警触发。

硬性宪法限制(第 17 节)不弯。「永远不往 secrets@ 发邮件」作为宪法规则,更简单、可审计、不会被慢漂移玩弄。分层模式:统计探测器抓住大部分噪声,硬性限制抓住溜过探测器的攻击

用 eBPF 数据面重定向做隔离

Cilium 基于 eBPF 的网络策略可以在内核层把一个被隔离 pod 的出站流量重写到一个取证蜜罐。Cilium 公开基准报告 TCP_RR 上 P99 数据面延迟低于 1 毫秒;在集群里触发隔离的墙上时钟预算,主要由策略更新从控制面传播到节点的方式决定(Kubernetes 上 operator 预加载时几百毫秒是现实的;尾部延迟取决于集群规模与调和节奏)。这给你两样东西:Agent 外泄不到任何真实东西,而 Agent 在蜜罐内的行为被完整观察。这与金丝雀令牌是同模式、不同层:Agent 通过它在被收容时试图做什么来暴露意图。

没有探测器能抓到什么

  • 从允许的原语组合出的语义攻击:每个单独动作都过每个探测器,问题是组合。这正是第 10 节 Auto Mode 的组合失败。
  • 把探测器本身纳入载荷的攻击:如果 Agent 读到一个页面说「行动前先禁用金丝雀」,而 Agent 有这个能力,探测器就被攻陷了。金丝雀令牌必须放在 Agent 无法修改的系统里。

二、从零实现:三探测器模拟器

原课程 code/main.py(仅用 Python 标准库)把一段短合成轨迹喂过三个探测器:一个装在外部字典里的 kill switch、一个连续五次相同调用就跳闸的熔断器、一个读取就告警的金丝雀文件。轨迹里混入合法动作、重复循环、金丝雀探测,以及一个 kill switch 触发后 Agent 动作被中止的场景。下面给出关键骨架。

Kill switch:外部只读布尔

def agent_turn(state, kill_switch): """每次后果性动作前都查 kill switch。""" if kill_switch.is_off(): # Agent 只读,不能写 state.halt("kill switch off: 停止所有外部可观测行为") return False return True # 继续执行动作 # 正确实现的四条性质 # 1. kill_switch 住在一个 state.agent_creds 写不到的进程/服务 # 2. 每次后果性动作都查(不是只在启动) # 3. off 时连 Agent 能触及的日志都不写 # 4. 重启用是显式人工动作,不是自动超时

熔断器:模式跳闸 + 半开探测

class CircuitBreaker: def __init__(self, threshold=5, cooldown_turns=3, probes=1): self.same_call_streak = 0 self.threshold = threshold # 连续相同调用几次跳闸 self.state = "closed" # closed / open / half_open self.cooldown = cooldown_turns self.probes = probes def allow(self, tool_name, args): if self.state == "open": return False, "熔断中, 升级到人" # 检测重复循环: 连续相同工具+相同参数 if (self._last_tool, self._last_args) == (tool_name, args): self.same_call_streak += 1 if self.same_call_streak >= self.threshold: self.state = "open" return False, "第%d次相同调用, 跳闸" % self.same_call_streak else: self.same_call_streak = 1 self._last_tool, self._last_args = tool_name, args return True, "闭合允许"

金丝雀令牌:访问即告警

CANARIES = { "/workspace/.deploy_key", # 假部署私钥, 编码 Agent 无合法理由读 "AWS_SECRET_ACCESS_KEY=FAKE...", # 假 AWS 凭据, 无真实权限 "row:user_id=9999", # 哨兵值标记的假 DB 记录 } def tool_guard(action): if action.reads_any(CANARIES): alert("金丝雀被访问: %s —— 意图暴露, 立即归因" % action) action.block() # 金丝雀必须放在 Agent 改不到的系统里 # 否则 '先禁用金丝雀' 这类提示注入载荷会令探测器失灵

设计要点:三个探测器的共同点是不信任 Agent 的自报告。kill switch 不问 Agent「你停了吗」,熔断器不问「你在循环吗」,金丝雀不问「你要外泄吗」——它们各自从 Agent 够不到的地方观测。

三、框架对比:三层探测器的分工

探测器 作用粒度 触发 触发后行为 实现位置
Kill switch 全局 外部人工或外部策略 Agent 整体失能, 无外部可观测行为 Agent 凭据写不到的系统(Redis/特性开关/签名配置)
熔断器 单条路径 模式(重复/失败率/速率) 暂停该路径, 升级到人, 半开探测 Agent 循环内的拦截器
金丝雀令牌 单次访问 访问诱饵 告警 + 归因, 通常不告诉 Agent Agent 改不到的资源(假凭据/蜜罐记录/假文件)
统计探测器(EWMA/CUSUM) 趋势 偏离移动基线 告警, 可能自动限速 遥测管线
硬性宪法限制(第 17 节) 单条规则 规则被违反 硬阻断, 不弯曲 宪法, Agent 不可编辑

关键分层:统计探测器抓「大部分噪声」,硬性限制抓「溜过探测器的攻击」,kill switch 抓「需要整体停下的失控」,熔断器抓「局部失控但整体还好」,金丝雀抓「意图暴露」。五者各管一段, 互不替代

⚠️ 单层防御必然失守。一个只有成本治理(第 13 节)的部署,Agent 可以在预算内把数据库删了。加上 kill switch 还不够——它只在人按下时生效。完整的防线是成本层 + 三探测器 + 硬性宪法的叠加。

四、可复用产物

原课程 outputs/skill-tripwire-design.md 是一份评审技能文档:审阅一个 Agent 部署的拟议探测器栈,标出缺口——缺 kill switch、缺金丝雀、熔断阈值过松、统计探测器没有硬性限制托底等。它把「列举 Agent 的后果性动作 → 为每类动作配探测器 → 检查分层 → 检查 Agent 是否够不到探测器」串成可重复清单。

code/main.py 是零依赖模拟器,改阈值、金丝雀集合、轨迹即可重跑,适合在部署评审里当对抗演练工具——红队构造轨迹,看哪一层先抓住。

五、练习

  1. code/main.py:确认熔断器在第 5 轮(第五次相同调用)跳闸,金丝雀在第 9 轮(假密钥读取)告警。

  2. 加一个统计探测器:对工具调用速率做 EWMA z-score。喂一段慢漂移轨迹,展示探测器永不告警;再加一个硬性限制(10 分钟内不超过 50 次工具调用),展示硬性限制在同一轨迹上告警。

  3. 为浏览器 Agent(第 11 节)设计金丝雀令牌集:列出至少三条金丝雀,说明每条检测什么(如环境里的假 cookie、书签里的蜜罐 URL、记忆里的假会话条目)。

  4. 读 Cilium 网络策略文档:具体描述一条出站重定向隔离流程——哪个策略选择器、哪个 pod、哪种出站重写、哪种告警。是什么决定了从「决定隔离」到「第一个被重定向的包」的墙上时钟延迟?

  5. 定义 kill switch 的重启用流程:谁可以重启用?必须文档化什么?重启用前 Agent 必须改变什么?

本节要点回顾

  1. 成本治理管「能花多少」, 探测器管「能做什么」——昂贵的动作(外泄/误发/删除)往往是 token 上最便宜的。
  2. Kill switch 是 Agent 只读不写的布尔, 关掉 = 整体失能;四条性质:只读、每次后果性动作都查、关闭后无外部可观测行为、重启用须人工。
  3. 熔断器是模式跳闸:闭合/断开/半开三态,按重复、失败率、速率、不可信读取后的特定工具调用触发。
  4. 金丝雀令牌是诱饵:假凭据/蜜罐记录/假文件/假记忆,访问即告警;必须放在 Agent 改不到的系统。
  5. 统计探测器(EWMA/CUSUM)会向慢漂移妥协, 必须与不弯的硬性宪法限制(第 17 节)分层。
  6. eBPF 出站重定向可在内核层隔离 pod 到取证蜜罐,P99 数据面延迟亚毫秒;触发延迟由策略传播决定。
  7. 三者共同点是不信任 Agent 的自报告——这是它们对提示注入、记忆篡改、组合攻击有效的根因。
  8. 没有探测器能抓到「语义组合攻击」和「把探测器纳入载荷的攻击」——前者是 Auto Mode 组合失败,后者要求金丝雀住处不可被 Agent 修改。

下一节,我们从「自动停掉坏的」转向「让人在好的里点头」——Propose-Then-Commit(先提议再提交),看人在环中如何把不可逆动作隔离到一个人工批准闸门之后。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U