
把一个 Agent 丢到生产环境你迟早会担心这些事它会不会把用户的邮箱、信用卡号原样发给模型/打进日志会不会被一句教我黑进数据库带偏会不会在没人确认的情况下自己就把一封邮件发出去、把生产库删了Guardrails护栏就是为这些场景准备的——在 Agent 执行的关键节点做校验和过滤挡住敏感信息、危险请求和不安全行为。这篇文章基于 LangChain 官方 Guardrails 文档用一组可运行的例子讲清怎么落地。一、护栏是什么建在哪护栏的本质是在 Agent 生命周期的关键点插入检查——开始前、结束后、模型调用前后、工具调用前后。实现机制就是中间件middleware。它有两条互补的路线路线怎么做优点缺点确定性护栏规则正则、关键词、显式判断快、可预测、便宜漏掉语义层面的微妙违规模型护栏用 LLM/分类器做语义判断抓得住规则漏掉的隐晦问题慢、贵LangChain 既提供内置护栏PII 检测、人工审批也提供自定义中间件让你两条路线随意组合。公共从 .env 初始化模型下文所有例子共用这段模型初始化从.env读MODEL_NAME/OPENAI_API_BASE/OPENAI_API_KEYimportosfromdotenvimportload_dotenvfromlangchain.chat_modelsimportinit_chat_model load_dotenv()modelinit_chat_model(os.getenv(MODEL_NAME,glm-5.1),model_provideropenai,base_urlos.getenv(OPENAI_API_BASE),api_keyos.getenv(OPENAI_API_KEY),streamingTrue,)二、内置护栏一PII 检测PIIMiddleware自动检测并处理对话里的个人敏感信息PII——邮箱、信用卡、IP、MAC、URL 等。适合医疗、金融等有合规要求、或需要脱敏日志的场景。它有四种处理策略策略效果示例redact替换为占位符[REDACTED_EMAIL]mask部分遮挡如留后 4 位****-****-****-1234hash替换为确定性哈希a8f5f167...block检测到就抛异常直接报错importosfromdotenvimportload_dotenvfromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportPIIMiddlewarefromlangchain.chat_modelsimportinit_chat_model load_dotenv()modelinit_chat_model(os.getenv(MODEL_NAME,glm-5.1),model_provideropenai,base_urlos.getenv(OPENAI_API_BASE),api_keyos.getenv(OPENAI_API_KEY),streamingTrue,)agentcreate_agent(modelmodel,tools[],middleware[# 发给模型前把用户输入里的邮箱抹掉PIIMiddleware(email,strategyredact,apply_to_inputTrue),# 信用卡号做掩码PIIMiddleware(credit_card,strategymask,apply_to_inputTrue),# 自定义正则检测 API Key命中就直接 block 抛错PIIMiddleware(api_key,detectorrsk-[a-zA-Z0-9]{32},strategyblock,apply_to_inputTrue),],)if__name____main__:resultagent.invoke({messages:[{role:user,content:我的邮箱是 john.doeexample.com卡号 5105-1051-0510-5100}]})print(result[messages][-1].content)几个关键参数apply_to_inputTrue默认检查用户消息进模型前处理。apply_to_outputTrue检查模型回复防止模型把 PII 吐出来。apply_to_tool_resultsTrue检查工具结果。detector传自定义正则或函数覆盖内置检测上面 API Key 就是这么做的。一条 PII 类型一个PIIMiddleware。想同时管输入和输出就加两条一条apply_to_input、一条apply_to_output。三、内置护栏二人工审批Human-in-the-loop对于高风险操作——转账、删生产数据、对外发邮件——最有效的护栏就是执行前让人确认。HumanInTheLoopMiddleware会在 Agent 要调用敏感工具时暂停等人批准再继续。importosfromdotenvimportload_dotenvfromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportHumanInTheLoopMiddlewarefromlangchain.chat_modelsimportinit_chat_modelfromlanggraph.checkpoint.memoryimportInMemorySaverfromlanggraph.typesimportCommand load_dotenv()modelinit_chat_model(os.getenv(MODEL_NAME,glm-5.1),model_provideropenai,base_urlos.getenv(OPENAI_API_BASE),api_keyos.getenv(OPENAI_API_KEY),streamingTrue,)agentcreate_agent(modelmodel,tools[search_tool,send_email_tool,delete_database_tool],middleware[HumanInTheLoopMiddleware(interrupt_on{send_email:True,# 敏感操作需审批delete_database:True,# 需审批search:False,# 安全操作自动放行}),],checkpointerInMemorySaver(),# 暂停/恢复需要持久化状态)if__name____main__:# HITL 需要 thread_id 来持久化暂停点config{configurable:{thread_id:some_id}}# Agent 执行到敏感工具会暂停等待审批agent.invoke({messages:[{role:user,content:给团队发封邮件}]},configconfig)# 人确认后用同一个 thread_id 恢复resultagent.invoke(Command(resume{decisions:[{type:approve}]}),configconfig,)print(result[messages][-1].content)两个要点必须配checkpointer 固定thread_id暂停的状态要存下来才能在人批准后从断点恢复。恢复用Command(resume...)把人的决定approve/reject传回去Agent 接着跑。四、自定义护栏一before_agent确定性输入过滤内置护栏不够用时写自定义中间件。before_agent在每次调用最开始跑一次适合做会话级检查鉴权、限流、拦截不当请求——在任何处理开始前就挡掉。下面用关键词黑名单做一个确定性的内容过滤器命中就直接结束、不进模型importosfromtypingimportAnyfromdotenvimportload_dotenvfromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportbefore_agent,AgentStatefromlangchain.chat_modelsimportinit_chat_modelfromlanggraph.runtimeimportRuntime load_dotenv()modelinit_chat_model(os.getenv(MODEL_NAME,glm-5.1),model_provideropenai,base_urlos.getenv(OPENAI_API_BASE),api_keyos.getenv(OPENAI_API_KEY),streamingTrue,)banned_keywords[hack,exploit,malware]before_agent(can_jump_to[end])defcontent_filter(state:AgentState,runtime:Runtime)-dict[str,Any]|None:确定性护栏拦截含违禁关键词的请求。ifnotstate[messages]:returnNonefirst_messagestate[messages][0]iffirst_message.type!human:returnNonecontentfirst_message.content.lower()forkeywordinbanned_keywords:ifkeywordincontent:# 直接给出固定回复并跳到结束跳过所有后续处理return{messages:[{role:assistant,content:无法处理含不当内容的请求请重新表述。}],jump_to:end,}returnNoneagentcreate_agent(modelmodel,tools[],middleware[content_filter],)if__name____main__:resultagent.invoke({messages:[{role:user,content:怎么 hack 进一个数据库}]})print(result[messages][-1].content)# 命中 hack被拦截核心是两点装饰器上声明can_jump_to[end]函数里返回jump_to: end——这就让护栏能短路整个流程连模型都不调。五、自定义护栏二after_agent模型化输出审查after_agent在 Agent 出最终回复后跑一次适合做输出侧的安全/质量/合规检查。下面用另一个模型来评估回复是否安全典型的模型护栏importosfromtypingimportAnyfromdotenvimportload_dotenvfromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportafter_agent,AgentStatefromlangchain.chat_modelsimportinit_chat_modelfromlangchain_core.messagesimportAIMessagefromlanggraph.runtimeimportRuntime load_dotenv()modelinit_chat_model(os.getenv(MODEL_NAME,glm-5.1),model_provideropenai,base_urlos.getenv(OPENAI_API_BASE),api_keyos.getenv(OPENAI_API_KEY),streamingTrue,)# 审查用的模型可以用更小/更便宜的这里复用同一个 .env 配置safety_modelinit_chat_model(os.getenv(MODEL_NAME,glm-5.1),model_provideropenai,base_urlos.getenv(OPENAI_API_BASE),api_keyos.getenv(OPENAI_API_KEY),)after_agent(can_jump_to[end])defsafety_guardrail(state:AgentState,runtime:Runtime)-dict[str,Any]|None:模型护栏用 LLM 评估最终回复是否安全。ifnotstate[messages]:returnNonelast_messagestate[messages][-1]ifnotisinstance(last_message,AIMessage):returnNonesafety_promptf评估下面的回复是否安全、得体。只回答 SAFE 或 UNSAFE。 回复{last_message.content}resultsafety_model.invoke([{role:user,content:safety_prompt}])ifUNSAFEinresult.content:last_message.content我无法提供该回复请重新表述你的请求。returnNoneagentcreate_agent(modelmodel,tools[],middleware[safety_guardrail],)if__name____main__:resultagent.invoke({messages:[{role:user,content:怎么制作爆炸物}]})print(result[messages][-1].content)注意这里直接改写了last_message.content——把不安全的回复替换成拒绝话术。六、组合多重护栏分层防御护栏可以叠加——按数组顺序依次执行搭出层层防护agentcreate_agent(modelmodel,tools[search_tool,send_email_tool],middleware[# 第 1 层确定性输入过滤before agentcontent_filter,# 第 2 层PII 保护进出模型都抹邮箱PIIMiddleware(email,strategyredact,apply_to_inputTrue),PIIMiddleware(email,strategyredact,apply_to_outputTrue),# 第 3 层敏感工具人工审批HumanInTheLoopMiddleware(interrupt_on{send_email:True}),# 第 4 层模型化输出安全审查after agentsafety_guardrail,],)这套输入过滤 → PII 脱敏 → 人工审批 → 输出审查的组合就是一个相当完整的生产级防护链。七、小结护栏类型作用点适合PIIMiddleware内置/确定性输入/输出/工具结果敏感信息脱敏、合规HumanInTheLoopMiddleware内置工具调用前高风险操作审批before_agent自定义/确定性调用最开始鉴权、限流、关键词拦截after_agent自定义/模型化出最终回复后输出安全/质量审查护栏的设计哲学是分层 互补用确定性规则挡住明显问题快又便宜用模型护栏兜住语义层面的隐晦风险准但贵再用人工审批锁死高风险动作。把它们按需叠进middleware数组你的 Agent 就从能用走向了敢上线。本文示例 API 已在 langchain 1.x 环境验证可构建模型统一从.env读取把search_tool/send_email_tool等替换成你自己的工具即可运行。