126.Agent-LangChain核心组件-进入Agent之前 摘要本文讲解 LangChain Agent 核心组件中的before_agent装饰器进入 Agent 之前。通过can_jump_to参数声明可跳转节点tools、model、end配合函数返回jump_to字段实现流程控制可用于敏感词检测、VIP 用户权限分流等场景。文中结合完整 Python 代码演示了敏感词拦截与提前结束 Agent 的用法并强调jump_to必须在can_jump_to中预先声明否则跳转失效。内容参考于图灵AI大模型全栈进入Agent之前是通过 before_agent 注解来实现它也叫做装饰器如下图红框它有一个 can_jump_to 参数来告诉LangChain当前函数可以跳转到什么位置如下图红框可以给他传递一个list列表它可以传递的值 “tools”, “model”, “end”Agent会把问题搞成一个执行步骤也就是一个一个的节点这个 can_jump_to 就决定了当前函数可以跳转到那些节点这个可以实现 检测敏感词、vip用户等这样的功能tools表示当前可以跳转到工具节点model表示可以跳转到 调用模型的节点 或 第一个 进入模型之前 的钩子end表示可以跳转到Agent末尾 或 第一个 进入Agent之后 的钩子也就是提前结束Agent的流程它们的触发是通过让函数返回 jump_to 的字段如下图红框它返回的 jump_to 值是 end 这就会提前结束Agent值是model就会进入模型节点返回tools就会跳转到工具节点注意 jump_to 跳转的地方必须在can_jump_to提前设置好如果can_jump_to没有写end然后 jump_to 的值还是end那么jump_to 会失效会不进行跳转如下图红框都写的end如下图红框before_agent中不设置can_jump_to也就是不设置end如下图蓝框可以看出它调用了大模型这说明jump_to跳转失效了并不是每个 装饰器 都可以是以 “tools”, “model”, “end” 这三个值的如下图装饰器支持的值如果给can_jump_to写的不支持的值它会报错manage_human_message_before_agent函数中的逻辑是检测问题中是否出现了下图红框的内容如果出现了就跳转end代码fromdataclassesimportdataclassfromlangchain.agentsimportcreate_agent,AgentStatefromlangchain_core.messagesimportHumanMessage,AIMessage,SystemMessageimportreimportjsonfromlanggraph.runtimeimportRuntimefromtypingimportCallablefromlangchain_qwqimportChatQwenfromdotenvimportload_dotenvimportos# 加载模型# 加载环境变量load_dotenv()# 初始化模型llmChatQwen(modelqwen3.7-flash,api_keyos.getenv(DASHSCOPE_API_KEY),base_urlos.getenv(DASHSCOPE_BASE_URL))# dataclass会自动创建init、repr、eq方法frozen能够保证对象初始化之后不能修改dataclass(frozenTrue)classContext:user_id:intuser_permissions:str# 引入装饰器# 从 LangChain 的 Agent 中间件模块中导入以下组件fromlangchain.agents.middlewareimport(before_agent,# 装饰器在 Agent 开始执行前触发一次。适合初始化、权限校验、日志、修改初始状态或强制跳转。after_agent,# 装饰器在 Agent 执行结束后触发一次。适合资源清理、最终日志、结果后处理等。before_model,# 装饰器每次调用模型前触发。适合修改消息、动态调整提示词、注入上下文等。after_model,# 装饰器每次模型返回后触发。适合输出校验、内容过滤、解析结果、记录日志等。wrap_model_call,# 装饰器包裹模型调用。可在模型调用前后插入逻辑如重试、缓存、限流、监控、修改请求/响应。wrap_tool_call,# 装饰器包裹工具调用。可在工具执行前后插入逻辑如参数校验、权限检查、重试、结果处理。ModelRequest,# 类型模型请求对象。通常包含 messages、tools、配置等供 wrap_model_call 中读取或修改。ModelResponse,# 类型模型响应对象。通常包含生成消息、工具调用等供 wrap_model_call 中读取或修改。AgentMiddleware,# 基类用于以类的方式定义中间件可集中组织多个钩子方法before/after/wrap 等。)# 通过 before_agent 注解设置进入Agent之前调用的函数# 它的 can_jump_to 参数表示当前函数可以跳转到什么节点中# 通过返回 jump_to 这个字段来实现跳转# can_jump_to是告诉LangChain可以跳转什么节点# 返回 jump_to 来实现跳转# 如果 不写 can_jump_to 那么 jump_to 会无效# can_jump_to 有三个值如下# tools表示可以跳转到工具节点进入Agent之前和之后不可以跳转tools# model表示可以跳转到模型节点或进入模型之前的钩子# end表示跳转到Agent末尾 或 第一个进入Agent之后的钩子也就是用来结束Agent的执行before_agent(can_jump_to[])defmanage_human_message_before_agent(state:AgentState,runtime:Runtime[Context]): 在Agent启动之前调用 Runtime:用来传递全局变量只是用来读取的内容-上下文的常量还经常用来传递数据库连接池、日志对象一些配置信息 # 从后往前找第一个类别为 HumanMessage 的消息user_contentformessageinreversed(state[messages]):ifisinstance(message,HumanMessage):user_contentmessage.content# 打印用户最新的问题print(f在before_agent中用户最新问题{user_content})# 1.处理用户敏感用词sensitive_words[TM,TMD,CNM,挂了,垃圾]ifany(wordinuser_content.upper()forwordinsensitive_words):# 发现敏感词直接构造一个 AI 响应不再交给模型思考return{messages:[AIMessage(content检测到不当言论请文明交流。)],jump_to:end# 直接结束这次对话}# 2.vip用户特殊处理# 获取用户权限user_permissionsruntime.context.user_permissionsifuser_permissionsvip:# vip权限能够进行所有知识库的访问print(我是VIP用户能够查看全部的内容)else:print(我是普通用户能够查看部分的内容)returnNone# 创建智能体agentcreate_agent(modelllm,middleware[manage_human_message_before_agent])resultagent.invoke({messages:[HumanMessage(你好我是计算机王TM)]},contextContext(user_permissionsvip,user_id1))# 获取AI回复print(result[messages][-1].content)print(result)