Guardrail实战:给AI智能体装三道安全门的完整指南
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
一次真实的"翻车":用户输入被 openai-agents-python 的 Guardrail 判为违规,主 agent 却已经把 token 烧了一半、工具也调过了。这正是这套 AI 防护机制里最反直觉、也最值得先弄懂的部分。智能体安全不能只靠一句"请不要越权"的提示词,而要靠会主动拉闸的校验关卡。本文把输入防护与输出校验拆开讲,再完整走一遍金融客服场景的 tripwire 触发与降级处理。
机制全景:三层关卡怎么卡位
把它想成一栋写字楼的三层关卡。入口安检是输入护栏:用户请求进门时就查一遍;出口安检是输出护栏:agent 交出结果之后、离开之前再扫一遍;而每个办事柜台(工具调用)前后还有各自的拦截点。
第一层关卡有个默认设定。输入护栏默认和主 agent 并行跑,图的是延迟最小,代价是拉闸时主 agent 可能已经跑了一段。想要"不合格坚决不放行",就把run_in_parallel关掉,护栏先审完再开工。第三层是工具护栏,它挂在自定义函数工具上,每次调用前后各查一次,覆盖 agent 级护栏够不到的中间环节。
上图标出了输入防护与输出防护在智能体生命周期里的卡位,中间的节点就是主 agent 的工作区。
金融客服智能体的合规校验拆解
拿一个具体场景:客服智能体背后接了查询和转办工具。风险有两类:用户开口就要越权操作,比如"直接帮我划转这笔钱";或者最终回复里夹带卡号、账户明细这类敏感数据。前者在入口拦,后者在出口拦。
配置前:先想清楚查什么、用什么查
先定两件事:检查用小模型干,主 agent 才用大模型,高频检查别用贵的模型;判决结构里带上理由字段,方便事后审计。输入防护的配置就落在主 agent 的参数上:
class ComplianceCheck(BaseModel): is_compliant: bool reason: str check_agent = Agent( name="合规检查", instructions="判断用户请求是否要求执行越权的资金操作", output_type=ComplianceCheck, )这个检查 agent 就是"小模型裁判",它跟主 agent 收到的输入完全一样。完整可运行的模板见 examples/agent_patterns/input_guardrails.py,可以直接照抄改判据。
配置中:判决函数加一个开关
护栏本体是一个被装饰器包起来的函数,裁判 agent 跑完把结论翻译成 tripwire 信号:
@input_guardrail(run_in_parallel=False) async def compliance_check(ctx, agent, input): result = await Runner.run(check_agent, input, context=ctx.context) verdict = result.final_output_as(ComplianceCheck) return GuardrailFunctionOutput( output_info=verdict, tripwire_triggered=not verdict.is_compliant, ) agent = Agent( name="金融客服", instructions="处理账户咨询,涉及资金划转必须走人工", input_guardrails=[compliance_check], )注意run_in_parallel=False这个开关。默认是并行,拉闸时主 agent 可能已经烧过 token;关掉它就是阻塞模式,护栏审完才放行,越权请求一个 token 都花不出去。判断 tripwire 是否触发的字段定义在 src/agents/guardrail.py,是主 agent 停下来的直接依据。
输出侧的泄露检查长得差不多:
@output_guardrail async def leak_check(ctx, agent, output): leaked = any(word in str(output).lower() for word in ["卡号", "ssn", "balance:"]) return GuardrailFunctionOutput( output_info={"leaked": leaked}, tripwire_triggered=leaked, )输出护栏没有并行选项,因为它本来就要等结果出来才能检查。
触发后:tripwire 拉闸的降级写法
tripwire 触发时,runner 抛的是InputGuardrailTripwireTriggered或OutputGuardrailTripwireTriggered,主流程在Runner.run的边界接住就行:
try: result = await Runner.run(agent, user_input) except InputGuardrailTripwireTriggered as e: log_audit(e.guardrail_result.output.output_info.reason) reply = "该操作超出服务范围,已转人工处理。"被拒的输出不会写进会话,用户拿到的只有固定文案。工具调用层的拦截与降级示例见 examples/basic/tool_guardrails.py,演示了拒绝调用、替换输出和拉闸三种不同力度的处理。
误区与代价
误区:加了防护就一定拖慢速度。真相是并行模式下护栏耗时和主 agent 重叠,额外开销是两者时长的差值,不是总和。真正的大头在裁判用哪个模型,换个小模型比优化护栏代码本身有效得多。流式场景下同一套 tripwire 机制也能用,可参考 examples/agent_patterns/streaming_guardrails.py。
误区:tripwire 触发意味着什么都没发生。并行模式下它本质是取消信号,主 agent 可能已经烧过 token、动过工具。要确保零消耗零副作用,就切阻塞执行,让护栏先跑完再放行。
误区:给主 agent 挂了护栏,整条链路就安全了。agent 级护栏只在首尾各跑一次:输入护栏只对链上的第一个 agent 生效,输出护栏只查产出最终结果的那个。多智能体安全里,中间每一次工具调用都得靠工具护栏兜住。
回头看开头那次翻车:入口的 tripwire 现在能先把"帮我破解"拦在门外,出口的泄露检查再兜住最后一关,翻车现场就变成一条审计日志。建议从风险最高的那个工具调用开始,用上面工具护栏的模板先挂一条输出校验,再逐层往入口推进;更多执行模式的细节,去 docs/guardrails.md 里对照着读。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考