发布时间:2026/7/5 3:00:51
Agent 需要拦截模型调用?用 Middleware 给它加个“拦截器“!
咱们先从一个最简单的需求开始——记录日志。我想知道每次调用模型的时候当前有多少条消息模型又回了什么。怎么做呢很简单写一个类继承 AgentMiddleware然后实现两个方法就行。from langchain.agents.middleware import AgentMiddleware from langchain.agents import AgentState from langgraph.runtime import Runtime class LoggingMiddleware(AgentMiddleware): def before_model(self, state: AgentState, runtime: Runtime) - None: print(f[日志] 即将调用模型当前消息数: {len(state[messages])}) def after_model(self, state: AgentState, runtime: Runtime) - None: last_msg state[messages][-1] print(f[日志] 模型已响应: {last_msg.content[:50]}...)你注意看啊这里有两个方法。before_model 就是在模型调用之前执行的我打印一下当前消息的数量。after_model 是模型响应之后执行的我取最后一条消息截取前 50 个字符看看模型回了啥。关键点来了——你注意这两个方法的返回类型都是 None。为啥因为这个 Middleware 只是记录日志它不需要干预流程所以直接返回 None就是在告诉框架我完事了你继续往下走就行。好日志中间件搞定了。是不是特别简单接下来咱们上点强度——写一个安全检查中间件。第二个 Middleware安全检查这个中间件的作用是啥呢拦截危险操作。比如用户说删除所有文件你肯定不想让 Agent 傻乎乎地去执行吧同样继承 AgentMiddleware重点在 before_model 里做文章。from langchain_core.messages import AIMessage class SafetyMiddleware(AgentMiddleware): def before_model(self, state: AgentState, runtime: Runtime) - dict | None: last_msg state[messages][-1].content if 删除 in last_msg or 危险 in last_msg: return { jump_to: end, messages: [AIMessage(content检测到危险操作已终止)] } return None这里有个关键区别你一定要注意到——返回类型变了变成了 dict | None而不是单纯的 None。为什么因为这个 Middleware 有可能需要干预流程。逻辑是这样的拿到最后一条消息的内容检查一下里面有没有删除或者危险这样的关键词。如果命中了就返回一个字典jump_to 设为 end意思是跳过模型调用直接结束。同时塞一条 AIMessage 告诉用户操作被终止了。这个返回值就是在告诉框架别调用模型了直接结束并且把这条消息加进去。如果没有问题呢就返回 None意思是我没意见流程正常继续。你看这就是 Middleware 的精髓——你可以选择不管也可以选择直接接管整个流程。完整实战代码好两个 Middleware 都写好了接下来咱们把它们组装起来看看实际效果。先把需要的依赖都导入进来然后配置模型、定义工具。import os import sqlite3 from dotenv import load_dotenv from langchain.agents import create_agent, AgentState from langchain.agents.middleware import AgentMiddleware from langchain.chat_models import init_chat_model from langchain_classic.agents import Agent from langchain_community.tools import WriteFileTool, ReadFileTool, ListDirectoryTool from langchain_core.messages import AIMessage from langchain_core.tools import tool, BaseTool from langgraph.checkpoint.sqlite import SqliteSaver from langgraph.runtime import Runtime from langgraph.store.memory import InMemoryStore from langgraph.store.sqlite import SqliteStore load_dotenv() prefix QWEN model init_chat_model( model_provideropenai, configurable_fields[model, api_key, base_url], config_prefixprefix).with_config({ configurable: { f{prefix}_model: os.getenv(f{prefix}_MODEL), f{prefix}_api_key: os.getenv(f{prefix}_API_KEY), f{prefix}_base_url: os.getenv(f{prefix}_BASE_URL) }}) class CalculateTool(BaseTool): name: str calculate description: str 计算数学表达式的值 def _run(self, expression: str) - str: try: return f计算结果{eval(expression)} except Exception as e: return f计算错误{str(e)} async def _arun(self, expression: str) - str: return self._run(expression) # Middleware 1记录模型调用日志 class LoggingMiddleware(AgentMiddleware): def before_model(self, state: AgentState, runtime: Runtime) - None: print(f[日志] 即将调用模型当前消息数: {len(state[messages])}) def after_model(self, state: AgentState, runtime: Runtime) - None: last_msg state[messages][-1] print(f[日志] 模型已响应: {last_msg.content[:50]}...) # Middleware 2安全检查拦截危险操作 class SafetyMiddleware(AgentMiddleware): def before_model(self, state: AgentState, runtime: Runtime) - dict | None: last_msg state[messages][-1].content if 删除 in last_msg or 危险 in last_msg: return { jump_to: end, messages: [AIMessage(content检测到危险操作已终止)] } return None calculate CalculateTool() write_file WriteFileTool() read_file ReadFileTool() list_dir ListDirectoryTool() checkpoint_conn sqlite3.connect(agent.db, check_same_threadFalse, isolation_levelNone) checkpointer SqliteSaver(checkpoint_conn) store_conn sqlite3.connect(agent.db, check_same_threadFalse, isolation_levelNone) store SqliteStore(store_conn) agent create_agent( modelmodel, tools[calculate, write_file, read_file, list_dir], system_prompt你是一个助手会用工具计算、读写文件、列出目录。, debugTrue, checkpointercheckpointer, storestore, middleware[LoggingMiddleware(), SafetyMiddleware()] ) config {configurable: {thread_id: session-1}} store.put((user, user-1), profile, {name: 张三, role: developer, skills: [python, typescript, java]}) profile store.get((user, user-1), profile) print(f用户资料{profile.value}) queries [计算 2024*12500然后把结果保存到 result.txt, 读取 result.txt的内容, 列出当前目录文件, 刚才计算的结果是多少, 删除所有文件 ] for q in queries: print(f\n问{q}) response agent.invoke({messages: [{role: user, content: q}]}, configconfig) print(response) print(f\n答{response[messages][-1].content}) checkpoint_conn.close() store_conn.close()代码比较长但核心逻辑其实就三块模型配置、Middleware 定义、Agent 创建。你重点看 create_agent 这一行——注意 middleware 这个参数咱们把 LoggingMiddleware 和 SafetyMiddleware 两个实例一起传进去了。就这么一行Agent 就同时具备了日志记录和安全拦截的能力。然后下面准备了一些测试问题挨个发给 Agent 执行。你注意最后一个问题——删除所有文件这就是用来测试安全检查中间件的。运行效果跑起来之后你会看到什么呢首先每次模型调用前后控制台都会打印日志信息告诉你当前消息数和模型响应内容这就是 LoggingMiddleware 在干活。然后当前面几个正常问题执行的时候一切顺利。但是到了最后一个问题删除所有文件的时候Agent 直接返回检测到危险操作已终止——根本不会去调用模型。这就是 SafetyMiddleware 在拦截。总结

相关新闻

Agentic AI:换个角度,从问题拆解到交付验证
2026/7/5 3:00:51

Agentic AI:换个角度,从问题拆解到交付验证

聊《Agentic AI:换个角度,从问题拆解到交付验证》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要这篇面向关注 AI 产品化和自动化系统的开发者,但不会把“Agentic AI&#xf…

阅读更多
Gateway API:Ingress 的下一代替代方案
2026/7/5 3:00:51

Gateway API:Ingress 的下一代替代方案

文章目录前言两者之间相比部署环境操作步骤部署安装 Gateway API CRD Envoy Gateway安装metallb配 MetalLB 的 IP 池安装GatewayClass Gateway示例创建httproute添加dns解析结果展示前言 因为ingress在今年3 月就已经停止维护,后面不再发布新版本、修复漏洞或更新…

阅读更多
AI替代人力是假象?微软派6000人驻场,Ford召回老工程师,人力价值凸显!
2026/7/5 3:00:51

AI替代人力是假象?微软派6000人驻场,Ford召回老工程师,人力价值凸显!

全网热议AI替代人力,可现实却是大厂忙着招人。微软砸25亿派6000人驻场,Ford召回350老工程师,AI落地为何离不开人?大厂疯狂招人,AI产品化遇阻微软刚传裁员,就砸25亿成立Frontier Company,派6000人…

阅读更多
2026最新7款AI编程工具选型指南|Python自动化开发低成本平替权威实测
2026/7/5 4:00:51

2026最新7款AI编程工具选型指南|Python自动化开发低成本平替权威实测

我对 AI 编程工具的期望不高,就一个:别给我写有 bug 的代码。5 款工具在代码正确性上的表现差距比想象的大。我是创业公司唯一后端开发,一人包揽物流追踪系统全栈开发、自动化日志分析、批量文件处理脚本编写,日常大量使用vibe co…

阅读更多
女生喜欢听的情话有哪些 对什么比较热衷
2026/7/5 4:00:51

女生喜欢听的情话有哪些 对什么比较热衷

女生热衷的情话不在甜腻套路,而在被看见、被偏爱、被稳稳接住的细节里。说你笑起来真好看不如讲你眼睛弯成月牙的样子,像小朋友吃到糖,观察越具体,她越觉得你在认真看她这个人。女生爱听哪种情话1、说她让你安心,比如你…

阅读更多
micro:bit硬件原理与MicroPython实战指南
2026/7/5 4:00:51

micro:bit硬件原理与MicroPython实战指南

1. 项目概述:一块会呼吸的教育级硬件,为什么它值得你花20分钟拆开看透 一个月前在EuroPython大会领到那块深蓝色小板子时,我下意识把它和手边的信用卡叠在一起比了比——它确实只有半张卡大小,但指尖传来的分量感却意外扎实。背面…

阅读更多
西安本地化 AI 智能体平台选型分析
2026/7/5 4:00:51

西安本地化 AI 智能体平台选型分析

最近,我一个做餐饮连锁的朋友老张,跟我吐槽了一件事。他花了3万多块,买了一套所谓的“AI智能体”,说是能自动接打电话、处理客户投诉、生成营销文案。结果呢?对方给的平台漏洞百出,对话逻辑混乱&#xff0c…

阅读更多
跨平台B站工具箱BiliTools:从零开始掌握高效下载与管理技巧
2026/7/5 4:00:51

跨平台B站工具箱BiliTools:从零开始掌握高效下载与管理技巧

跨平台B站工具箱BiliTools:从零开始掌握高效下载与管理技巧 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

阅读更多
ARIMA 模型定阶实战:基于 ACF/PACF 图的 4 种典型模式识别与 p, q 值选择
2026/7/5 3:00:51

ARIMA 模型定阶实战:基于 ACF/PACF 图的 4 种典型模式识别与 p, q 值选择

ARIMA模型定阶实战:ACF/PACF图模式识别与参数选择指南引言:时间序列分析的基石工具在时间序列分析的广阔领域中,ARIMA模型犹如一把瑞士军刀,能够处理各种复杂的时间依赖关系。而决定这把"军刀"锋利程度的关键&#xff0…

阅读更多
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御
2026/7/5 0:00:50

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

阅读更多
3步彻底解决Windows右键菜单混乱问题:ContextMenuManager使用全攻略
2026/7/5 0:00:50

3步彻底解决Windows右键菜单混乱问题:ContextMenuManager使用全攻略

3步彻底解决Windows右键菜单混乱问题:ContextMenuManager使用全攻略 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾为Windows右键菜单中那些…

阅读更多
GXDE OS下Wayland兼容性实战:从deepin-mutter原理到VMware Tools修复
2026/7/5 0:00:50

GXDE OS下Wayland兼容性实战:从deepin-mutter原理到VMware Tools修复

如果你正在用 GXDE OS 或者任何基于 Deepin 的发行版,并且遇到了“检测到窗口系统采用 Wayland 协议,程序即将退出”这类弹窗,或者发现 VMware Tools 在 Ubuntu 24.04 这类默认 Wayland 的系统上启动失败,那这篇文章就是为你准备的…

阅读更多
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御
2026/7/5 0:00:50

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

阅读更多
3步彻底解决Windows右键菜单混乱问题:ContextMenuManager使用全攻略
2026/7/5 0:00:50

3步彻底解决Windows右键菜单混乱问题:ContextMenuManager使用全攻略

3步彻底解决Windows右键菜单混乱问题:ContextMenuManager使用全攻略 【免费下载链接】ContextMenuManager 🖱️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾为Windows右键菜单中那些…

阅读更多
GXDE OS下Wayland兼容性实战:从deepin-mutter原理到VMware Tools修复
2026/7/5 0:00:50

GXDE OS下Wayland兼容性实战:从deepin-mutter原理到VMware Tools修复

如果你正在用 GXDE OS 或者任何基于 Deepin 的发行版,并且遇到了“检测到窗口系统采用 Wayland 协议,程序即将退出”这类弹窗,或者发现 VMware Tools 在 Ubuntu 24.04 这类默认 Wayland 的系统上启动失败,那这篇文章就是为你准备的…

阅读更多
基于Dify与DeepSeek构建私有知识库问答系统实战指南
2026/7/4 11:17:16

基于Dify与DeepSeek构建私有知识库问答系统实战指南

在业务中快速构建一个能理解私有文档、准确回答专业问题的智能助手,是很多开发团队面临的共同挑战。传统方案往往需要从零开始搭建复杂的 RAG(检索增强生成)系统,涉及文档解析、向量化、检索、大模型调用等多个环节,整…

阅读更多
FAE放射组学分析工具:医学影像特征探索的完整解决方案
2026/7/4 5:24:16

FAE放射组学分析工具:医学影像特征探索的完整解决方案

FAE放射组学分析工具:医学影像特征探索的完整解决方案 【免费下载链接】FAE FeAture Explorer 项目地址: https://gitcode.com/gh_mirrors/fae/FAE 你是否曾经面对海量医学影像数据感到无从下手?想要从CT、MRI等影像中提取有价值的定量特征&#…

阅读更多
DesktopNaotu:你的终极离线思维导图解决方案,告别网络依赖!
2026/7/4 15:20:35

DesktopNaotu:你的终极离线思维导图解决方案,告别网络依赖!

DesktopNaotu:你的终极离线思维导图解决方案,告别网络依赖! 【免费下载链接】DesktopNaotu 桌面版脑图 (百度脑图离线版,思维导图) 跨平台支持 Windows/Linux/Mac OS. (A cross-platform multilingual Mind Map Tool) 项目地址:…

阅读更多