Agent Guardrails 护栏系统设计
Guardrails 护栏系统
概述
Guardrails(护栏)是 Agent 系统中的安全与质量控制层,在模型调用前、后以及工具执行前后执行预定义的验证策略。其核心目标是在不中断正常流程的前提下,对违规内容进行早期检测与阻断。
三级护栏架构
Guardrails 按执行时机分为三个层级:
1. InputGuardrail(输入级)
在 Agent 处理用户输入时执行。关键约束:仅 starting_agent 的首轮 turn 运行输入 guardrails,handoff 后的新 Agent 不运行其输入 guardrails。这是为了避免在多 Agent 链路中重复验证已被上游 guardrails 检查过的输入。
执行模式:
| 模式 | 行为 | 适用场景 |
|---|---|---|
顺序执行(run_in_parallel=False) | Guardrails 在模型调用之前同步执行 | 严格阻断场景:输入必须先验证才能调用模型 |
并行执行(run_in_parallel=True,默认) | Guardrails 与模型调用通过 asyncio.gather 并发执行 | 低延迟场景:减少用户等待时间 |
并行执行的代价:如果 guardrail tripwire 触发,正在进行的模型调用需要被取消(task.cancel()),但模型可能已消耗了 token。
2. OutputGuardrail(输出级)
在 Agent 产生最终输出后执行。适用于:内容安全审查、格式校验、业务规则合规检查。
触发条件:仅当 Agent 输出类型为 NextStepFinalOutput 时才执行。中间 turn 的工具调用输出不触发。
3. ToolGuardrails(工具级)
挂载在单个 FunctionTool 上,细粒度控制每个工具调用的安全性:
- ToolInputGuardrail:在工具调用前验证参数(如:路径是否允许访问、参数范围是否合法)
- ToolOutputGuardrail:在工具调用后验证结果(如:输出是否包含敏感信息、是否符合格式要求)
Tripwire 触发机制
Guardrail 函数的返回值通过 GuardrailFunctionOutput 封装,其中 tripwire_triggered 字段决定是否中断执行流。
三种行为模式:
| 行为 | 说明 | 使用场景 |
|---|---|---|
| AllowBehavior | 正常执行,继续流程 | 验证通过 |
| RejectContentBehavior | 替换输出为自定义消息 | 需要友好提示而非硬中断 |
| RaiseExceptionBehavior | 抛出 TripwireTriggered 异常 | 需要立即终止当前 run,由调用方处理 |
Tripwire 异常传播
InputGuardrailTripwireTriggered 和 OutputGuardrailTripwireTriggered 是标准异常类型。它们不会被 run loop 自动捕获——异常会传播到 Runner.run() 的调用方,由调用方决定如何处理(记录日志、返回错误、重试等)。
Run Error Handlers
Guardrails 之外,SDK 提供了运行级错误处理器(RunErrorHandlers),处理两类运行时错误:
max_turns:超过配置的 turn 上限时的回退策略model_refusal:模型安全拒绝(如 OpenAI 的安全过滤)时的回退策略
处理器接收 RunErrorHandlerInput(异常对象、上下文、运行数据快照),返回 RunErrorHandlerResult(最终输出值 + 是否计入历史的标志)。这允许在 guardrails 触发异常或模型拒绝时,仍返回一个有意义的响应而非直接报错。
设计权衡
并行 vs 顺序输入 guardrails
并行优势:减少用户感知延迟——guardrails 与模型调用同时进行。
并行代价:tripwire 触发时模型已消耗 token,且取消操作可能不完整(模型请求已发出)。
顺序优势:模型不会被调用,节省成本。
顺序代价:用户等待时间 = guardrails 执行时间 + 模型调用时间。
工具级 vs Agent 级 guardrails
工具级 guardrails 提供更细粒度的控制(每个工具可独立配置),但增加了配置复杂度。Agent 级 guardrails 适用于全局策略(如”禁止暴力内容”),但无法对单个工具施加差异化规则。
Handoff 后不运行输入 guardrails
优势:避免多 Agent 链路中的重复验证,降低延迟。
风险:如果 handoff input filter 修改了输入,新 Agent 的输入可能未经其自身的 guardrails 检查。
缓解:在 handoff input filter 中内嵌验证逻辑,或将安全策略放在起始 Agent 的输入 guardrails 中。
参考来源
人类中断(HITL)与审批模式
在 Guardrails 之外,Agent 系统中还存在一类主动请求人类介入的模式——Human-in-the-Loop(HITL)。与 guardrails 的”自动阻断”不同,HITL 是 Agent 主动暂停执行,等待人类审批后继续。
中断事件机制
当 Agent 执行到需要人类决策的节点时(如执行敏感操作、确认高风险动作),通过**元事件(MetaEvent)**通知前端:
中断事件类型
| 事件类型 | 方向 | 说明 |
|---|---|---|
LangGraphInterruptEvent | Agent → 前端 | Agent 暂停,等待人类决策 |
LangGraphInterruptResumeEvent | 前端 → Agent | 用户审批完成,恢复执行 |
CopilotKitLangGraphInterruptEvent | Agent → 前端 | 增强版中断事件,携带完整消息历史 |
线程锁与 HITL
在 HITL 场景中,Agent 的执行被暂停,但线程锁仍然有效。因此需要:
- 锁续约(Lock Heartbeat):在用户审批期间,定期续约 Redis 线程锁(默认 15s 续约,最大 TTL 1 小时)
- 锁泄漏防护:如果用户永久不响应,锁最终会因 TTL 过期而自动释放
HITL vs Guardrails 对比
| 维度 | Guardrails | HITL |
|---|---|---|
| 触发方式 | 自动(预定义规则) | Agent 主动请求 |
| 决策主体 | 代码逻辑 | 人类用户 |
| 阻塞模式 | tripwire 直接中断 | 等待人类审批后恢复 |
| 适用场景 | 内容安全、格式校验 | 高风险操作审批、模糊决策 |
| 恢复机制 | 返回错误消息或替换输出 | 审批结果注入,Agent 继续执行 |