首页/新闻资讯/正文详情

【DeepAgents 从入门到精通】核心架构深入:Middleware 与 AgentMiddleware 配置骨架

发布时间:2026/9/26 10:58:54 来源:云帆数科 栏目:资讯中心
【DeepAgents 从入门到精通】核心架构深入:Middleware 与 AgentMiddleware 配置骨架
1. 为什么你的 DeepAgents 跑起来像“黑盒”很多人第一次接触 DeepAgents注意力都放在create_deep_agent()那一行调用上觉得把模型、工具、提示词塞进去就能跑。结果一旦 Agent 行为不符合预期——比如该规划的时候不规划、该派子代理的时候自己硬扛、对话轮次一多就失控——就完全不知道从哪下手。问题往往不在模型而在 Middleware中间件这一层。DeepAgents 的核心架构可以理解为“LangGraph 状态图 中间件栈”的组合。LangGraph 负责把 Agent 的执行拆成节点和边Middleware 则在这些节点前后插入逻辑决定 Agent 什么时候规划、什么时候读写文件、什么时候派发子代理、什么时候终止。换句话说Middleware 是 DeepAgents 的“行为开关”而AgentMiddleware就是写这些开关的基类。这篇内容面向已经能跑通最简 Agent、但想搞清楚执行链路和配置骨架的读者。我会从AgentMiddleware的 Hook 机制切入结合 LangGraph 的节点执行顺序给出一份可复制的config.toml和settings.json骨架再带你验证 Middleware 到底有没有生效。全程本地可跑不需要复杂环境。2. 前置准备TaoToken 接入与依赖安装在写 Middleware 之前得先有一个能稳定调用的模型入口。我这边习惯用 TaoToken 做统一接入它的 API 兼容 OpenAI 风格配置成本低适合拿来跑 DeepAgents 这种需要多轮调用的场景。第一步去控制台创建一个 API Key。地址是https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite创建后复制保存后面配置文件里要用。第二步安装依赖。DeepAgents 依赖 LangChain 和 LangGraph建议用虚拟环境python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install deepagents langchain langgraph langchain-openai第三步设置环境变量。TaoToken 的 API 地址是https://taotoken.net/api注意这里不加 UTM 参数直接作为 base_url 使用export TAOTOKEN_API_KEY你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你更习惯用配置文件管理可以跳过环境变量直接看下一节的config.toml和settings.json。两种方式选一种即可不要混用导致覆盖。提示模型名建议先用gpt-4o-mini这类轻量模型验证 Middleware 逻辑确认 Hook 触发顺序正确后再换成更强的模型跑真实任务能省不少调试成本。3. 可复制配置config.toml 与 settings.json 骨架DeepAgents 本身没有强制要求配置文件格式但把模型、Middleware 开关、限制参数抽出来能让调试清晰很多。下面这份config.toml是我实测下来比较顺手的骨架字段都对应到具体的 Middleware 行为# config.toml [model] provider openai name gpt-4o-mini base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY temperature 0.2 [agent] system_prompt You are a helpful assistant with planning ability. max_steps 25 [middleware.todo_list] enabled true auto_plan true [middleware.filesystem] enabled true root ./agent_workspace [middleware.sub_agent] enabled true max_sub_agents 3 [middleware.summarization] enabled true trigger_message_count 30 [middleware.human_in_the_loop] enabled false [middleware.custom.logging] enabled true max_model_calls 10对应的settings.json用于运行时覆盖适合在 CI 或不同机器上切换参数{ model: { name: gpt-4o-mini, base_url: https://taotoken.net/api, api_key_env: TAOTOKEN_API_KEY }, agent: { max_steps: 25 }, middleware: { todo_list: { enabled: true, auto_plan: true }, filesystem: { enabled: true, root: ./agent_workspace }, sub_agent: { enabled: true, max_sub_agents: 3 }, summarization: { enabled: true, trigger_message_count: 30 }, human_in_the_loop: { enabled: false }, custom: { logging: { enabled: true, max_model_calls: 10 } } } }关键字段说明middleware.todo_list.auto_plan控制是否让 Agent 自动调用write_todos做规划middleware.filesystem.root是虚拟文件系统的落盘目录middleware.sub_agent.max_sub_agents限制子代理派发数量防止递归失控middleware.custom.logging.max_model_calls是自定义中间件的调用上限超过就jump_to: end。把这些配置读进代码的方式很简单用tomllibPython 3.11或tomliimport tomllib from pathlib import Path def load_config(path: str config.toml) - dict: with open(path, rb) as f: return tomllib.load(f) cfg load_config() print(cfg[middleware][custom][logging])4. 配置骨架如何映射到 AgentMiddleware配置文件只是外壳真正决定行为的是AgentMiddleware的 Hook。DeepAgents 的中间件栈按执行顺序排列Main Agent 默认包含PatchToolCallsMiddleware、TodoListMiddleware、FilesystemMiddleware、SubAgentMiddleware、SummarizationMiddleware、HumanInTheLoopMiddleware、PromptCachingMiddleware、MemoryMiddleware。SubAgent 的栈是精简版没有TodoListMiddleware和SubAgentMiddleware因为子代理不能再派子代理。AgentMiddleware提供 6 个 Hook分两类。Node-style 的四个按时间点触发before_agent整个生命周期只跑一次before_model每次调模型前跑after_model每次模型返回后跑after_agent结束时跑一次。Wrap-style 的两个包裹调用wrap_model_call包住每次模型调用wrap_tool_call包住每次工具调用。执行顺序可以这样理解Agent 启动 →before_agent→ 进入循环 →before_model→wrap_model_call包裹模型 → 模型返回 →after_model→ 如果有工具调用 →wrap_tool_call包裹工具 → 回到循环 → 循环结束 →after_agent。把配置映射过来todo_list.enabled对应是否挂载TodoListMiddlewarefilesystem.root传给FilesystemMiddleware的初始化参数sub_agent.max_sub_agents传给SubAgentMiddlewarecustom.logging.max_model_calls传给自定义的LoggingMiddleware。下面是一个把配置转成中间件列表的骨架from deepagents import create_deep_agent from deepagents.middleware import TodoListMiddleware, FilesystemMiddleware, SubAgentMiddleware from langchain.agents.middleware import SummarizationMiddleware def build_middleware(cfg: dict): mw [] m cfg[middleware] if m[todo_list][enabled]: mw.append(TodoListMiddleware(auto_planm[todo_list][auto_plan])) if m[filesystem][enabled]: mw.append(FilesystemMiddleware(rootm[filesystem][root])) if m[sub_agent][enabled]: mw.append(SubAgentMiddleware(max_sub_agentsm[sub_agent][max_sub_agents])) if m[summarization][enabled]: mw.append(SummarizationMiddleware( trigger_message_countm[summarization][trigger_message_count] )) return mw注意顺序TodoListMiddleware要放在SubAgentMiddleware前面因为规划逻辑应该在派发子代理之前生效。如果你把限制类中间件放在日志中间件后面一旦限制先jump_to日志就不会执行了这是踩过的坑。5. 验证 Middleware 是否生效配置写完不代表生效得用具体动作验证。最直接的方式是写一个自定义LoggingMiddleware在before_model和after_model里打印状态然后跑一个会触发工具调用的任务。from typing import Any from deepagents import create_deep_agent from langchain.agents.middleware import AgentMiddleware, AgentState from langgraph.runtime import Runtime from langchain.messages import AIMessage class LoggingMiddleware(AgentMiddleware): def __init__(self, max_calls: int 10): super().__init__() self.max_calls max_calls self.call_count 0 def before_model(self, state: AgentState, runtime: Runtime) - dict[str, Any] | None: self.call_count 1 print(f[LOG] 第 {self.call_count} 次模型调用消息数: {len(state[messages])}) if self.call_count self.max_calls: return { messages: [AIMessage(content达到最大调用次数终止。)], jump_to: end, } return None def after_model(self, state: AgentState, runtime: Runtime) - dict[str, Any] | None: last state[messages][-1] has_tools hasattr(last, tool_calls) and last.tool_calls print(f[LOG] 模型返回has_tool_calls{has_tools}) return None def get_weather(city: str) - str: Get the weather for a given city. return fIts always sunny in {city}! agent create_deep_agent( modelopenai:gpt-4o-mini, tools[get_weather], system_promptYou are a helpful assistant., middleware[LoggingMiddleware(max_calls5)], ) result agent.invoke( {messages: [{role: user, content: What is the weather in Paris?}]} ) print( 最终回复 ) for msg in result[messages]: if getattr(msg, type, None) ai: print(msg.content)运行后你应该看到类似输出[LOG] 第 1 次模型调用消息数: 2 [LOG] 模型返回has_tool_callsTrue [LOG] 第 2 次模型调用消息数: 4 [LOG] 模型返回has_tool_callsFalse 最终回复 The weather in Paris is always sunny!如果before_model只打印了一次说明模型没有触发工具调用检查get_weather的 docstring 是否清晰如果after_model里has_tool_calls一直是 False可能是模型没理解工具用途。验证TodoListMiddleware是否生效可以给一个多步任务观察输出里是否出现write_todos的调用记录。验证FilesystemMiddleware看./agent_workspace目录下有没有生成文件。6. 本篇常见错误排查错误一在before_model里直接改state[messages]却不返回。这样修改不会生效因为 LangGraph 靠返回值合并状态。正确做法是返回{messages: [新消息]}。错误二jump_to值写错。只有end是 LangGraph 内置终止节点写exit或stop会报节点不存在。这个错误在日志里表现为图执行异常不容易一眼看出。错误三混淆before_agent和before_model的执行频率。before_agent整个生命周期只跑一次适合初始化数据库连接、加载配置before_model每次调模型都跑适合做动态检查。如果你把计数器放在before_agent里会发现它永远只加一次。错误四Middleware 顺序错误。限制类中间件要放在日志类前面否则限制触发jump_to后后面的日志中间件不会执行。同理TodoListMiddleware要放在SubAgentMiddleware前面。错误五自定义 Middleware 的name与默认栈冲突。如果自定义中间件的.name和默认中间件同名会替换默认实例而不是追加。想追加就换个名字想替换就保持同名。排查时建议打开 LangGraph 的调试日志或者在wrap_model_call里打印request内容能看到实际传给模型的完整消息列表比猜要快得多。7. 下一步从配置骨架到真实任务跑通最小示例后你可以把config.toml里的human_in_the_loop打开观察 Agent 在关键步骤暂停等待确认的行为也可以把max_sub_agents调大给一个需要拆解的任务看子代理如何被派发。如果想让 Agent 长期跑编码类任务建议了解一下 Coding Plan 的额度方案地址是https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite适合需要持续调用模型的场景。Middleware 的调试本质上是观察 LangGraph 状态图的流转。把每个 Hook 的输入输出打印出来对照执行顺序图很快就能定位问题。配置骨架只是起点真正的行为逻辑还是写在AgentMiddleware的子类里。

相关推荐

2K图像生成加速:LoRA与频谱注意力优化实践
2K图像生成加速:LoRA与频谱注意力优化实践

Qwen Image 2.1出来的时候,我第一反应是终于有人把2K出图当成默认需求来做了,而不是让用户先出一张小图再自行放大。但真正跑起来之后才发现,原生2K分辨率意味着注意力计算的复杂度几乎是指数级往上走,等图时间轻松突破一分钟。等… · 2026/9/26 10:58:47

从 LangChain 到 OpenClaw:AI Agent 工程化的五层拼图与生产落地全攻略(TaoToken 统一 Key 配置篇)
从 LangChain 到 OpenClaw:AI Agent 工程化的五层拼图与生产落地全攻略(TaoToken 统一 Key 配置篇)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 10:58:41

Codex App 接上微信后,我把 Bug 排查搬进了厕所:TaoToken 统一 Key 配置实战
Codex App 接上微信后,我把 Bug 排查搬进了厕所:TaoToken 统一 Key 配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 10:58:41

Phoenix 5.0.0 部署实战:从 jar 分发到 HBase 2.0 的 SQL 查询
Phoenix 5.0.0 部署实战:从 jar 分发到 HBase 2.0 的 SQL 查询

简介:apache-phoenix-5.0.0-HBase-2.0-bin.tar.gz 是面向 HBase 开发者和数据工程师的 Phoenix 二进制发行包,适合需要在 HBase 之上使用标准 SQL 进行实时查询、并希望获得毫秒至秒级响应的大数据场景。该发行包将 Phoenix 的 SQL 解析与执行能力封装为… · 2026/9/26 11:36:31

GitHub API 自动化实践:REST、GraphQL、认证与限流边界详解
GitHub API 自动化实践:REST、GraphQL、认证与限流边界详解

GitHub 官方 API 是几乎所有 CI/CD、机器人、自动化和数据统计脚本的地基。我在不同团队做开发工具这么多年,见过不少把 GitHub API 当成万能接口用的项目,也修过一堆因为不了解边界而翻车的故障:有的被限流卡到怀疑人生,有的把私… · 2026/9/26 11:36:31

家政服务管理系统实战:Spring Boot + Vue前后端分离设计与实现
家政服务管理系统实战:Spring Boot + Vue前后端分离设计与实现

家政公司最常见的办公场景,往往是一个微信排班群加一沓Excel表格。客户在群里问今天有没有空保洁,店长翻一圈阿姨排班表,记在小本子上,月底再对着微信转账记录对账。这套家政服务管理系统,本质上就是把这一套手工流程搬… · 2026/9/26 11:36:31

Gradle全量包(-all.zip)详解:离线构建与CI/CD稳定性保障
Gradle全量包(-all.zip)详解:离线构建与CI/CD稳定性保障

简介:本资源为Gradle 8.0.2全量发行版压缩包(gradle-8.0.2-all.zip),面向Java/Scala项目开发者、构建工程师及持续集成运维人员,用于快速部署稳定可靠的Gradle构建环境。该版本是Gradle 8.0系列第二个补丁更新&#xf… · 2026/9/26 11:36:31

Gradle 8.0.2-all.zip离线部署指南:解决minSdkVersion报错与CI构建失败
Gradle 8.0.2-all.zip离线部署指南:解决minSdkVersion报错与CI构建失败

简介:本资源为Gradle 8.0.2全量发行版压缩包,面向Java/Scala开发者、构建工程师及持续集成运维人员,用于快速部署稳定可靠的现代构建环境。作为Gradle 8.0系列第二个补丁版本,它重点修复了元空间耗尽、工具链兼容性异常、自定义编… · 2026/9/26 11:36:31

带可二次开发的管理配置端:非低代码场景下原生标准化 Skill 框架选型与 TaoToken 接入实践
带可二次开发的管理配置端:非低代码场景下原生标准化 Skill 框架选型与 TaoToken 接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 11:36:25

数据库课后习题答案别硬背:当测试用例集刷,效率翻倍
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍

简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21

OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40

向下兼容与向上兼容:接口设计中的兼容性策略与工程实践
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践

一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码