Deep Agents 深度解析:不只是又一个 Agent 框架
拆解 LangChain 最新开源的 Deep Agents 项目,看看这个"batteries-included agent harness"到底"含"了哪些电池,以及背后的设计哲学是什么。
一、定位:它到底是什么?
Deep Agents 不是一个新的 Agent 框架,它是一个高度定制的 Agent Harness——站在 LangGraph 和 LangChain create_agent 的肩膀上,给你一套开箱即用的 Agent 实现。官方的比喻很精准:
LangGraph 是发动机,LangChain
create_agent是一台基础车,Deep Agents 是一台把所有选配都装好的高配车。
这意味着你可以直接用,也可以把任何一个部件换掉——不需要 fork,直接 override。
相比 LangChain create_agent,Deep Agents 多了什么?
| 能力 | LangChain create_agent | Deep Agents |
|---|---|---|
| 工具调用 | ✅ | ✅ |
| 多轮对话 | ✅ | ✅ |
| 子 Agent 委托 | ❌ 自己实现 | ✅ 内置 |
| 文件系统操作 | ❌ 自己实现 | ✅ 可插拔后端 |
| 上下文管理(自动压缩) | ❌ | ✅ 自动/手动 |
| Shell 执行 | ❌ | ✅ 可配置沙箱 |
| 跨会话记忆 | ❌ | ✅ 可插拔 |
| Human-in-the-Loop | ❌ | ✅ 内置 |
| Skills 技能系统 | ❌ | ✅ |
| MCP 工具 | ❌ | ✅ |
| 生产部署 | 需要自己搭 | ✅ LangSmith 全链路 |
二、核心架构:Middleware 模式
Deep Agents 的核心设计模式是 Middleware——每个功能都以中间件的方式注入到 Agent 的生命周期中。这种设计带来的好处是:
- 洋葱模型:每个中间件可以包裹模型调用前后,形成层次化的处理管道
- 可组合:任意增加、移除、替换中间件,不影响其他功能
- 关注点分离:每个中间件只做一件事,不互相耦合
from deepagents import create_deep_agent
agent = create_deep_agent(
model="openai:gpt-5.5",
middleware=[
FilesystemMiddleware(backend=my_backend),
SubAgentMiddleware(...),
SummarizationMiddleware(...),
HumanInTheLoopMiddleware(...),
],
)
默认中间件栈
当你调用 create_deep_agent() 时,它自动组装了一套完整的中间件栈,大致如下:
请求进入
│
▼
┌─────────────────────────┐
│ PromptMiddleware │ ← 注入系统提示词
├─────────────────────────┤
│ TodoListMiddleware │ ← 任务规划(TodoWrite 工具)
├─────────────────────────┤
│ FilesystemMiddleware │ ← 文件读写/编辑/搜索
├─────────────────────────┤
│ SubAgentMiddleware │ ← 子 Agent 委托
├─────────────────────────┤
│ SummarizationMiddleware │ ← 上下文压缩
├─────────────────────────┤
│ HumanInTheLoopMiddleware│ ← 人工审批
├─────────────────────────┤
│ SkillsMiddleware │ ← 动态加载技能
├─────────────────────────┤
│ ToolsMiddleware │ ← 用户自定义 + MCP 工具
└─────────────────────────┘
│
▼
LLM 调用
三、子 Agent(Sub-Agent)机制
3.1 核心问题
传统单 Agent 在复杂任务中面临两个挑战:
- 上下文窗口污染:子任务的分析过程占据大量 context,影响主任务质量
- 角色混淆:Agent 在处理不同性质的任务时,难以维持一致的角色定位
3.2 设计思想
Sub-Agent 的本质是上下文隔离 + 委托执行 + 结果回收。主 Agent 将子任务"外包"给一个拥有独立上下文窗口的子 Agent,子 Agent 完成任务后返回结果,主 Agent 继续推进。
主 Agent 上下文 子 Agent 上下文
┌──────────────────┐ ┌──────────────────┐
│ "分析项目结构" │ │ │
│ "读取 README" │ spawn │ 独立分析 │
│ "写研究报告..." │ ──────► │ 文件读写 │
│ │ │ 子任务规划 │
│ │ ◄────── │ │
│ 回收结果,继续... │ result │ │
└──────────────────┘ └──────────────────┘
3.3 实现亮点
从代码中可以看到,Sub-Agent 的创建支持非常灵活的配置:
# 预设模板
"research" # 研究型子 Agent
"coding" # 编码型子 Agent
"general" # 通用型子 Agent
# 通用创建
create_subagent(
name="my_agent",
description="做什么的",
system_prompt="自定义提示词",
tools=[...], # 子 Agent 的专属工具
middleware=[...], # 子 Agent 的专属中间件
model="...", # 可以指定不同模型
)
子 Agent 可以拥有与主 Agent 完全不同的工具集(或者共享部分工具),这意味着你可以给编码子 Agent 配备 Shell 和文件工具,而给研究子 Agent 配备搜索引擎——按需配置,不浪费 context。
四、上下文管理(Context Management)
这是 Deep Agents 最"硬核"的三个功能之一。让我从代码层面深入剖析。
4.1 问题定义
在长时间运行的 Agent 会话中,消息历史会不断膨胀。一个复杂编程任务可能产生几百条消息、几十万 tokens——远超任何模型的上下文窗口。
4.2 三层上下文压缩策略
深入读了源码后,我发现 Deep Agents 的上下文管理实际上分三个层次:
第一层:工具参数截断(Truncate Args)
在触发完整摘要之前,先对旧消息中的大参数做轻量级裁剪。代码中的 _truncate_args 方法只针对 write_file 和 edit_file 的 args 做截断:
原始: write_file(path="main.py", content="(5000行代码)")
截断: write_file(path="main.py", content="import os\nimport...(argument truncated)")
这层策略的精妙之处在于:
- 触发阈值比完整摘要低(默认 20 条消息或 10% context window)
- 只影响旧消息,最新 20 条消息保持完整
- 不需要 LLM 调用,纯计算操作,零成本
第二层:自动摘要压缩(Auto Summarization)
当 token 使用量达到触发阈值(默认 85% context window),自动触发摘要。核心流程:
1. 计算 cutoff_index(保留最近 N 条消息)
2. 将 cutoff 之前的历史 → 写入后端文件 → 生成 LLM 摘要
3. 用摘要 HumanMessage 替代所有旧消息
4. 模型看到的是: [摘要消息] + [保留的最近消息]
关键实现细节(从 wrap_model_call 代码中看到):
# Step 1: 先尝试不摘要的调用
if not should_summarize:
try:
return handler(request.override(messages=truncated_messages))
except ContextOverflowError:
# 如果模型报 context overflow,fallback 到摘要路径
pass
# Step 2: 摘要 + 重试
messages_to_summarize, preserved_messages = _partition_messages(...)
file_path = _offload_to_backend(backend, messages_to_summarize)
summary = _create_summary(messages_to_summarize)
这个设计非常聪明:
- 正常情况下走 threshold 检查
- 如果 provider 突然报
ContextOverflowError(比如 token 计算不准),自动 fallback 到摘要 - 非破坏性:使用
wrap_model_call而非直接修改state["messages"],原始消息历史完整保留 - 摘要链式支持:第二次摘要时自动过滤上一次的摘要消息,不重复存储
第三层:手动压缩工具(compact_conversation)
Agent 自己可以主动调用 compact_conversation 工具来压缩上下文。这在以下场景特别有用:
- 任务切换:上一个任务的分析过程不再需要
- 阶段性总结:提取关键信息后可以压缩
有趣的是,代码中设置了 50% 触发阈值的 eligibility gate——在上下文还没达到 auto-summarization 触发阈值的一半时,手动压缩会返回"Nothing to compact"。
4.3 大工具结果处理(Large Tool Result Offloading)
代码中的 _message_eviction.py 专门处理单个工具结果的 offload。当某个 ToolMessage 的内容过大时:
TOO_LARGE_TOOL_MSG = """Tool result too large, the result was saved at: {file_path}
Here is a preview showing the head and tail of the result:
{content_sample}
"""
- 完整结果写入后端文件(路径包含
tool_call_id供回溯) - 消息中只保留 head(前5行)+ tail(后5行)预览
- Agent 需要用
read_file工具按需读取完整结果
4.4 后端存储策略
压缩掉的消息不丢失,统一追加到:
/conversation_history/{thread_id}.md
每次压缩在文件中追加一个新 section:
## Summarized at 2026-05-30T22:04:00+00:00
Human: ...
AI: ...
Tool: ...
这个设计让 Agent 在需要时可以 read_file 回到历史中去查找细节。
五、文件系统中间件
5.1 设计哲学
Deep Agents 通过 CompositeBackend 和 FilesystemMiddleware 实现了统一的文件操作接口。核心设计:
- 三层后端体系:
StateBackend(对话级临时存储)、FilesystemBackend(本地磁盘)、StoreBackend(跨会话持久化) - 统一 API:所有后端实现
read/write/edit/ls/grep等接口,对 Agent 透明 - 资源路由:不同级别的资源(临时文件、项目文件、持久数据)自动路由到对应后端
5.2 关键机制
CompositeBackend
│
┌────────────┼────────────┐
▼ ▼ ▼
StateBackend FilesystemBackend StoreBackend
/memory_memory/ / /store/
对话级缓存 项目文件 跨会话数据
每次工具调用时,后端会根据资源路径自动选择对应的存储层。Agent 不需要关心文件存在哪里。
六、可插拔后端
6.1 协议设计
从代码中可以看到,所有后端都遵循 BackendProtocol:
# 核心接口
class BackendProtocol:
# 基础 CRUD
async def aread(paths) -> list[FileResponse]
async def awrite(path, content) -> Result
async def aedit(path, old_content, new_content) -> Result
# 列表与搜索
async def als(paths) -> list[DirectoryResponse]
async def agrep(pattern, paths) -> list[GrepMatch]
# 批量传输
async def aupload(paths) -> ...
async def adownload_files(paths) -> ...
这意味着你可以把 Deep Agents 的后端从本地文件系统一键切换到:
- StateBackend:纯内存,对话级生命周期
- FilesystemBackend:本地磁盘或沙箱
- StoreBackend:跨会话持久化(通过 LangGraph Store)
- CompositeBackend:组合多个后端,按路径前缀自动路由
- 自定义后端:实现
BackendProtocol即可接入任何存储(S3、数据库、分布式文件系统…)
6.2 CompositeBackend 的资源路由
/ → FilesystemBackend (本地/沙箱)
/conversation_history/* → StoreBackend (跨会话)
/memory_* → StateBackend (对话级)
/large_tool_results/* → FilesystemBackend (按需读取)
七、生产级特性
7.1 Human-in-the-Loop
Deep Agents 内置了工具调用审批机制。Agent 在执行敏感操作(写文件、执行 Shell 命令、发送 HTTP 请求)前,需要人工审批:
HumanInTheLoopMiddleware(
interrupts_on={
"write_file": "always", # 文件写入:总是审批
"execute": "always", # Shell:总是审批
"read_file": "never", # 文件读取:不审批
}
)
支持三种审批结果:
- Approve:批准执行
- Edit:修改参数后批准
- Reject:拒绝执行,Agent 收到拒绝反馈后调整策略
7.2 Skills 系统
Skills 是可复用的"行为包",Agent 在需要时动态加载:
# 每个 Skill 包含:
create_skill(
name="pdf-reader",
description="读取和解析 PDF 文件",
tools=[PDFTool],
middleware=[PDFMiddleware],
system_prompt="你是一个 PDF 专家...",
)
Skills 的加载方式透明——Agent 看到 load_skill 工具,调用它获得新的能力和上下文。
7.3 MCP 集成
通过 Model Context Protocol (MCP) 协议接入外部工具服务器:
from deepagents.middleware.tools import MCPToolsMiddleware
agent = create_deep_agent(
middleware=[
tools_middleware(
mcp_servers={"search": {"command": "..."}}
)
]
)
这让 Deep Agents 的工具生态可以无限扩展。
八、项目工程结构赏析
deepagents/
├── libs/
│ ├── deepagents/ # Python 核心库
│ ├── cli/ # 命令行工具
│ ├── code/ # Deep Agents Code(类 Claude Code 终端编码 Agent)
│ ├── acp/ # Agent Communication Protocol
│ ├── evals/ # 评估框架
│ └── partners/ # 合作伙伴集成
├── examples/ # 示例
└── .github/ # CI/CD + 自动评估 + SWE-bench
工程上值得注意的点:
- Monorepo 结构:多个子包共享版本和 lint 规则
- 自动化评估:
.github/workflows/evals.yml每次 PR 自动跑评估 - SWE-bench 集成:
.github/scripts/下有自动管理 SWE-bench PR 的脚本 - Release Please:自动 changelog 生成和版本发布
九、总结:Deep Agents 的价值所在
它解决了什么问题?
LangGraph 给了你做 Agent 的所有"零件",但拼装成一套生产级的 Agent 需要大量代码——上下文压缩、子 Agent 委托、沙箱隔离、人工审批……这些都不是 Agent 框架本身的范畴,但缺了这些,Agent 没法真正干活。
Deep Agents 把这些"工程化电池"装好了,让你不用从零搭。
谁适合用?
| 场景 | 适合度 |
|---|---|
| 原型验证 → 直接想用 | ⭐⭐⭐⭐⭐ |
| 复杂多步骤任务 Agent | ⭐⭐⭐⭐⭐ |
| 生产级 Agent 部署 | ⭐⭐⭐⭐⭐ |
| 只想要最小 Agent | ⭐⭐ (用 LangChain create_agent 更轻) |
| 深度定制 Agent 框架 | ⭐⭐⭐ (可 override 任何组件) |
核心设计模式
- Middleware 洋葱模型:一切功能都是中间件,组合自由
- Backend 可插拔协议:存储层完全解耦
- Sub-Agent 上下文隔离:复杂任务进行分治而不污染 context
- 三层上下文压缩:truncate → summarize → compact,渐进式处理
- 非破坏性状态管理:原始消息历史不丢失,压缩是可逆的
如果你正在构建一个需要做复杂、长周期任务的 AI Agent——研究、编码、数据分析——Deep Agents 是目前少有的把"工程化电池"装齐全的开源方案。
本文基于 Deep Agents 源码分析撰写。项目采用 MIT 协议,由 LangChain 团队维护。

浙公网安备 33010602011771号