第 20 章 AI AgentAgentic Patterns安全

第 20 章 控制流隔离:把"谁做决定"和"谁执行"分开

同一个模型既读又干,边界就没了

第 19 章框定了威胁模型:私有数据 + 不可信内容 + 对外通信,三要素凑齐就危险。那第一层防御怎么立?

核心思路是控制流隔离:把"谁读不可信内容"和"谁下高权限命令"分开。如果同一个模型既读不受信任的数据、又控制高权限工具,那么一条提示注入路径就能把良性上下文变成特权操作。这种耦合把信任边界抹平了,你很难推理"危险行为到底从哪来的"。

这一章讲三个模式,从模型层到工具层到通道层:

  1. Dual LLM Pattern(双 LLM 模式):一个模型读,一个模型干,中间传符号变量。
  2. Tool Capability Compartmentalization(工具能力分区):把"读 / 处理 / 写"拆成不同信任区。
  3. Authenticated Authority Channel(认证权威通道):区分"影响推理的信息"和"授予权限的输入"。

模式一:双 LLM 模式(Dual LLM Pattern)

问题

当同一个模型既读不可信内容、又控制高权限工具时,一条提示注入路径就能把良性上下文变成特权操作。这种耦合把信任边界抹平了,让"危险行为从哪来"变得难以推理。

方案

拆分角色:

  • 特权 LLM(Privileged LLM):负责规划和调用工具,但永远不碰原始不可信数据
  • 隔离 LLM(Quarantined LLM):负责读不可信数据,但零工具权限
  • 数据以符号变量或验证过的原语传递,特权侧只操作引用。

两个模型之间用显式契约:隔离模型只能输出类型化值(或是不透明句柄),特权模型只能操作批准的 schema 和工具。这保留了能力,又防止原始不可信文本进入高权威的推理路径。

var1 = QuarantineLLM("提取邮箱", text)   # 返回 $VAR1,原始文本没暴露
PrivLLM.plan("把 $VAR1 发给老板")         # 特权侧只碰引用
execute(plan, subst={ "$VAR1": var1 })    # 执行时才替换

注意关键点:特权模型做计划时看到的只有 $VAR1 这个占位符,恶意文本没有机会在它的上下文里"说话"。隔离模型读了恶意内容也无所谓,因为它根本没有工具可以用。

证据

  • 证据等级:新兴emerging),来自 Simon Willison(2023),被 Beurer-Kellner 等人(2025)采用为安全设计模式。

怎么用

  • 邮件/日历助手、订票 Agent、API 驱动的聊天机器人,以及任何"处理不可信用户输入 + 有特权动作(数据库写、外部 API 调用、文件系统操作)"的系统。
  • 隔离模型的输出格式要严格(类型化值或句柄),别让它输出自由文本给特权模型。

取舍

  • 好处:信任边界清晰;兼容静态分析(数据流可追踪)。
  • 代价:复杂度增加;跨两个模型调试,出错要两边找。

模式二:工具能力分区(Tool Capability Compartmentalization)

问题

MCP 和各类 Agent 框架经常把三类能力混进一个工具里:私有数据读取器(邮件、文件系统)、网页抓取器(HTTP 客户端)、写入器(API 修改器)。这就造出了"致命三要素":恶意输入可以触发一条链,在一个操作里读敏感数据、外传、改系统。

方案

在工具层做能力分区:

  • 把单体工具拆成 / 处理 / 三个微工具。
  • 跨能力类组合工具时,要求每次调用都显式获得用户同意
  • 每个类在隔离的子进程里跑,配作用域受限的 API key 和文件权限。

把每个能力类当成独立的信任区,有自己的运行时身份和策略检查。跨区组合要求显式策略评估和短期委托 token,让 Agent 无法悄无声息地把"读 + 抓取 + 写"链成一条高风险路径。

# tool-manifest.yml
email_reader:
  capabilities: [private_data, untrusted_input]
  permissions:
    fs: read-only:/mail
    net: none

issue_creator:
  capabilities: [external_comm]
  permissions:
    net: allowlist:github.com

调用时验证工具链,拒绝三能力类齐全的链:

// 跨区验证
function validateToolChain(tools: string[]): boolean {
  const classes = new Set(tools.map(t => getCapabilityClass(t)));
  if (classes.has("PRIVATE_DATA") &&
      classes.has("UNTRUSTED_INPUT") &&
      classes.has("EXTERNAL_COMM")) {
    return false; // 检测到致命三要素
  }
  return true;
}

证据

  • 证据等级:新兴emerging),来自 Simon Willison 对 MCP 的批评:他警告"某个 MCP 把三种模式混进了单一工具"。
  • Clawdbot(生产验证)用基于 profile 的策略做了参考实现;NVIDIA NeMo Guardrails 做基于策略的强制。

怎么用

  • 从 CI 自动生成 manifest,别手写。
  • Agent 运行器构造行动计划前,先查 manifest。
  • 标记任何会重新造出致命三要素的工具链组合。
  • 按能力类分组工具(fs、web、runtime、memory),分配 profile(minimal、coding、messaging),防止混用。
  • 调用时验证工具链:三类能力齐全就拒绝。

取舍

  • 好处:细粒度;和模块化架构配合好。
  • 代价:工具开销更多;权限随时间蔓延的风险(permission creep)。

模式三:认证权威通道(Authenticated Authority Channel)

问题

用工具的 Agent 经常把操作者指令、常设策略、检索到的文档、网页、消息、工具输出、摘要、委派报告全放进同一个模型上下文。不可信内容里于是可以出现看起来像合法命令的祈使语言。如果运行时没有保留"每条指令样语句来自哪",来源内容就可能被当成授权、被持久化成策略、或被用来重定向一个有后果的动作。

这个问题比"判断一段内容是否恶意"更广。一段良性文档可以描述一个真实流程,却不授权 Agent 执行它。 缺失的区别是:哪些是"可以影响推理的信息",哪些是"可以授予权限的输入"。

方案

在整个工作流里维护一条可区分的"权威通道":

  • **控制状态(control state)**包含:认证过的当前操作者意图、显式采纳的常设策略、运行时强制的权限。
  • **归因内容(attributed content)**包含:外部来源、检索文件、分析中的消息、工具输出、模型生成的摘要、委派报告。
  • 归因内容可以提供事实和候选参数,但不能扩大范围、授予权限、修改持久策略、或授权执行。
  • 一个特权执行点在执行前,独立地把提议的操作、目标、目的地、权限、参数对照控制状态验证。
  • 摘要、压缩、委派、持久化必须保留这个区分。来源丢了,就降级为只读工作,或者在有后果的执行前重新请求新鲜的认证批准。
control = load_authenticated_intent_and_policy()   # 认证过的意图和策略
content = retrieve_with_provenance()               # 带来源的检索内容
proposal = reason_over(control.task, content)      # 基于任务+内容推理

if proposal.exceeds(control.authority):
    request_authenticated_approval(proposal)       # 超出权限就请求认证批准
else:
    executor.validate_and_run(proposal, control, content.provenance)  # 独立验证再执行

标签和提示词分隔符能帮模型理解上下文,但它们不是安全边界。要拿作用域受限的凭据、能力控制、出口限制、确定性验证或与后果相称的隔离来支撑这个模式。

和目录里其它更窄的控制互补:Action Selector 把不可信反馈从有限控制循环里拿掉;策略门控代理和沙箱授权在工具边界强制权限;上下文最小化在不再需要时移除污染材料;致命三要素减少危险能力组合。认证权威通道做的则是在不可信材料必须通过检索、摘要、压缩、委派、持久化、执行一直可用时,端到端保住"权威 vs 内容"的区分

证据

  • 证据等级:混合mixed)。
  • 有价值发现:OWASP 记录了通过外部内容的间接提示注入,建议隔离并明确标识不可信内容;CaMeL 为一个更强、更窄的架构(把可信控制流和不可信数据分离,在工具调用时强制能力策略)提供了有效性证据。
  • 未验证:被引用的研究没有直接验证这个横跨检索、摘要、压缩、委派、持久化的更宽端到端模式;单靠提示词标签从未被证明能可靠防护,所以除非运行时也强制边界,否则不能把行为版本描述成"抗提示注入"。

怎么用

  1. 定义哪个认证通道能提供当前操作者意图。别仅仅因为能访问文件、收件箱、仓库或工具结果,就推断出权威。
  2. 外部材料进模型上下文前,附加来源类型和溯源。在摘要和交接里保留这些标签。
  3. 检索到的祈使句保持归因。别自动把它们提升进记忆、循环任务、配置、策略或身份。
  4. 候选动作从认证任务里推导,把来源内容当证据和提议参数。
  5. 执行时,独立验证操作、接收者/目标、目的地、参数、范围、有效权限,别依赖自由形式的源文本。
  6. 压缩或委派后如果运行时重建不了权威边界,停止有后果的执行,继续只读分析,或获取新批准。
  7. 用配对用例测试:良性内容、合法任务相关流程、以及一个声称批准或重定向有后果参数的对抗变体。

取舍

  • 好处:减少意外"权威洗白"(authority laundering);支持在不可信内容上灵活推理;创造清晰的强制和审计点;适用于严格有限动作选择器不切实际的场景。
  • 代价:需要认证意图、感知溯源的上下文构造、独立的执行检查;标签占上下文,可能被不支持的运行时丢掉;批准回退会增加摩擦。
  • 局限溯源建立的是归因,不是真实性或授权。 控制状态可能过期、被攻破、或绑定到错误主体。这个模式减少权威洗白,但不让 LLM 变得可信、不净化恶意数据、不证明来源真实性、也不替代技术隔离。

三个模式怎么选

场景 推荐模式
读不可信数据 + 有特权动作(邮件助手等) 双 LLM 模式
单体工具把读/抓取/写混在一起 工具能力分区
检索内容必须一路可用,又要分清楚权威 认证权威通道

三个模式是控制流隔离的三个层面双 LLM 在模型层分开"读"和"干",工具分区在工具层拆开"读 / 处理 / 写",权威通道在数据流层区分"信息"和"授权"。可以组合:双 LLM 管模型角色,工具分区管工具信任区,权威通道管数据流动。

实践清单

  • 读不可信数据的模型,别给它工具权限;有高权限工具的模型,别让它看原始不可信文本
  • 模型间传符号变量 / 类型化值,特权侧只操作引用,别传原始文本
  • 单体工具拆成读/处理/写微工具,跨能力类组合要显式同意
  • 工具 manifest 从 CI 自动生成,运行时按能力类验证工具链
  • 三类能力(私有数据 / 不可信输入 / 对外通信)齐全的工具链,调用时拒绝
  • 区分"控制状态"和"归因内容":内容能供事实,不能扩权、不能授权执行
  • 执行前用独立执行点验证操作/目标/权限/参数,别信自由文本
  • 摘要、压缩、委派、持久化都保留来源标签,丢了就降级只读
  • 溯源不等于真实性:控制状态可能过期或被攻破,不能替代技术隔离

本章小结

  • 双 LLM:隔离模型读、特权模型干,中间传符号变量,信任边界清晰。
  • 工具能力分区:读/处理/写拆成独立信任区,三类齐全的工具链直接拒绝。
  • 认证权威通道:控制状态给权威,归因内容给事实,执行前独立验证。
  • 控制流隔离的核心:让"读的人"和"干的人"不是同一个,提示注入就少一条路。

下一章讲权限与审批:隔离做好了,剩下的是"能干什么、谁点头"。人在回路审批、精确动作授权绑定、策略门控工具代理、沙箱授权。

📑 Agent 模式实战:生产级 AI Agent 的工程模式

1 第 1 章 什么是 Agent 模式 2 第 2 章 规划-执行-观察:先想清楚,再动手 3 第 3 章 反思闭环:让 Agent 学会检查自己的作业 4 第 4 章 委派:让主 Agent 学会把活分出去 5 第 5 章 上下文预算治理:把 token 当成钱来管 6 第 6 章 上下文压缩与精选:装不下怎么办 7 第 7 章 上下文最小化:别让脏东西留在脑子里 8 第 8 章 记忆体系:让 Agent 记得住过去 9 第 9 章 学习沉淀:让 Agent 和团队一起变聪明 10 第 10 章 工具接口哲学:让 Agent 能用、好用、用得起 11 第 11 章 工具发现:让 Agent 在几百个工具里找到对的 12 第 12 章 执行环境:Agent 在哪动手、怎么动手 13 第 13 章 代码执行与沙箱:先写码,再跑码 14 第 14 章 结构化输出与契约:让 Agent 的输出能接住 15 第 15 章 验证循环:Agent 怎么检查自己的作业 16 第 16 章 评测基建:怎么系统地检验 Agent 17 第 17 章 可观测性:看见 Agent 在想什么、在干嘛 18 第 18 章 韧性工程:扛得住部分失效 19 第 19 章 威胁模型:先看风险长什么样,再谈防御 20 第 20 章 控制流隔离:把"谁做决定"和"谁执行"分开 21 第 21 章 权限与审批:谁有权干什么、谁点头 22 第 22 章 凭据与出口:Agent 手里的钥匙和门 23 第 23 章 多智能体信任:多个 Agent 之间怎么互信、怎么审计 24 第 24 章 反馈信号设计:给 Agent 的是信号,不是更大的提示词 25 第 25 章 评测驱动的改进:让 Agent 在真实使用和对抗测试里变强 26 第 26 章 强化学习:把反馈变成训练信号 27 第 27 章 复合式进化:让 Agent 系统越用越值钱 28 第 28 章 多智能体协调:让一群 Agent 一起干活不掉链子 29 第 29 章 模型路由:谁用哪个模型,怎么用得起 30 第 30 章 推理搜索结构:让 Agent 多想想,而不是一条道走到黑 31 第 31 章 控制谱系:从自动补全到完全自主的滑动条 32 第 32 章 团队与产品:把 Agent 变成团队资产,而不是个人玩具
← 返回本书大纲