04 · DeepAgents:把 Claude Code 的套路抽成框架
| 仓库 | langchain-ai/deepagents |
| Star | 27.9k(2026-08-19) |
| 版本 | 0.7.7 |
| 语言 | Python(deepagentsjs 提供 TS 版) |
| 许可证 | MIT |
| 层级 | Harness 脚手架(跑在 LangChain create_agent → LangGraph 之上) |
| 一句话 | 一个开箱即用的「深度 Agent」,把长时任务需要的规划、文件系统、子智能体、上下文压缩全给你配好了 |
README 里的自述很直白:「Inspired by Claude Code: an attempt to identify what makes it general-purpose, and push that further.」
一、它想解决什么:上下文,而不是编排
前面三篇讲的都是「怎么组织流程」。DeepAgents 换了个问题:当一个 Agent 要连续跑 100 轮、调 300 次工具时,上下文窗口会先爆掉 —— 怎么办?
这是所有长时 Agent 的真实死因:
DeepAgents 给的答案是四件事,全部开箱:
| 能力 | 做什么 | 解决什么 |
|---|---|---|
| 规划(Planning) | 内置 todo 工具,让模型自己列任务清单 | 长任务不跑偏、不遗漏 |
| 文件系统(Filesystem) | ls / read_file / write_file / edit_file / glob / grep | 大结果写到「磁盘」,上下文只留文件名 |
| 子智能体(Subagents) | 委派给独立上下文窗口的子 Agent | 脏活的中间过程不污染主上下文 |
| 上下文管理 | 自动摘要历史 + 卸载超大工具结果 | 撑住 100+ 轮 |
二、最小可用代码
from deepagents import create_deep_agent
# 普通 Python 函数就是工具,docstring 会作为工具描述给模型看
def get_weather(city: str) -> str:
"""Get weather for a given city."""
return f"It's always sunny in {city}!"
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6", # 任意模型:openai: / google_genai: / 本地 vLLM 都行
tools=[get_weather], # 你自己的业务工具
system_prompt="You are a helpful assistant",
)
# 注意:除了你给的 get_weather,这个 agent 还 自动带上了一整套内置能力——
# · todo 规划工具 (让模型自己列任务清单)
# · 文件系统工具 (ls / read_file / write_file / edit_file / glob / grep)
# · task 委派工具 (把活分给独立上下文的子 Agent)
# · 一段调好的系统提示词 (教模型怎么用上面这些)
# 这就是「Harness」和「Framework」的区别:不用你自己设计这些。
agent.invoke({"messages": [{"role": "user", "content": "what is the weather in sf"}]})
注意这段代码和 LangChain 的 create_agent 几乎一模一样 —— 差别在于这个 agent 已经默认带上了 todo 工具、文件系统工具、task 委派工具和一段调过的系统提示词。模型是任意的(openai: / anthropic: / google_genai: / openrouter: / 本地 vLLM 都行)。
三、核心机制一:把工具结果卸载到磁盘
这是整个框架最值钱的一招。搜索工具返回 50KB HTML?不进上下文,写成文件,上下文里只留一行「结果已保存到 /results/search_1.md」。

图片来源:Deep Agents Docs
模型真需要细节时,自己 read_file 读回来 —— 而且可以只读需要的那几行。这就是「上下文工程」的核心操作:让上下文成为索引,而不是仓库。
同样的逻辑也用在超大输入上:

配合自动摘要,长对话被压成结构化的历史:

「文件系统」不一定是文件系统
backend 参数决定这些文件到底存在哪 —— 这是 DeepAgents 设计上最灵活的一点:
| Backend | 存在哪 | 作用域 | 什么时候用 |
|---|---|---|---|
StateBackend(默认) | LangGraph state 里 | 线程内,跟着 checkpointer 走 | 默认,什么都不用配 |
FilesystemBackend(root_dir=...) | 真实本地磁盘 | 进程可见范围 | 让 Agent 改你的代码库 |
StoreBackend() | LangGraph Store | 跨线程持久 | 长期记忆 |
ContextHubBackend("my-agent") | LangSmith Hub 仓库 | 跨线程持久 | 不想自己开 store |
| Sandbox(LangSmith / Daytona / AgentCore) | 隔离容器 | 一次会话 | 需要 execute 跑 shell |
LocalShellBackend | 宿主机直接执行 | 无隔离 | 只在受控开发环境 |
CompositeBackend | 按路径路由到不同 backend | 混合 | 生产推荐 |
CompositeBackend 是生产里最常见的形态:/memories/ 路由到跨线程的 store,其余路径留在线程内 state,Agent 的临时草稿和长期记忆天然分开。
DeepAgents 官方明说自己是 「trust the LLM」 模型:Agent 能做它的工具允许它做的任何事。边界必须在工具 / 沙箱层强制,不要指望模型自律。 用 LocalShellBackend 等于把 shell 交给模型,只在受控环境用。
四、核心机制二:子智能体做上下文隔离
主 Agent 通过 task() 工具委派,子 Agent 在自己的上下文窗口里跑几十轮,主 Agent 只收到最终结论。这就是所谓 context quarantine(上下文隔离)。
框架默认会自动挂一个 general-purpose 子智能体(自带文件系统工具)。自定义的话传 subagents:
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
tools=[web_search],
subagents=[
{
# name:主 Agent 调用 task() 委派时用的名字
"name": "researcher",
# description 最关键 —— 主 Agent 完全靠这段话判断「这活该不该派出去」。
# 写含糊了,委派根本不会发生;和写工具描述是同一个道理
"description": "Search the web and produce a sourced summary. Use for any factual lookup.",
# 子 Agent 有自己独立的系统提示词,可以写得比主 Agent 专业得多
"system_prompt": "You are a meticulous researcher. Always cite sources.",
# 子 Agent 自己的工具集,可以和主 Agent 不同(也可以配不同的模型)
"tools": [web_search],
},
],
)
# 运行时:子 Agent 在自己的上下文窗口里跑几十轮,
# 主 Agent 只收到最后那段结论,中间几十次搜索结果不会污染主上下文。
description 字段是给主 Agent 看的 —— 它就是靠这段话决定要不要委派。写得含糊,委派就不会发生;这和工具描述是同一个道理。
什么时候该用子智能体
| 该用 | 不该用 |
|---|---|
| 多步任务,中间过程会塞满主上下文 | 单步小任务(纯属浪费一次模型调用) |
| 需要专门指令 / 专门工具的领域 | 需要保留中间上下文给后续步骤用 |
| 想用不同能力的模型(贵的规划、便宜的执行) | 开销大于收益时 |
Subagent 和 Handoff 不是一回事
对照 01 的 D4 维度:OpenAI Agents SDK 的 Handoff 是转移控制权(我不管了,你接手对话);DeepAgents 的 Subagent 是带隔离上下文的函数调用(你帮我查,结论给我,我继续)。
五、核心机制三:Skills 渐进式披露
Skills 是可复用的行为包 —— 一段指令 + 可选脚本,Agent 需要时才加载进上下文。
思路和工具描述一样:上下文里常驻的只有「有哪些技能、各自干什么」这一行摘要,全文按需读取。 100 个技能的完整说明书可能有 50 万 token,但常驻成本只有几百。
六、人工介入:工具级审批
agent = create_deep_agent(
model="anthropic:claude-sonnet-4-6",
tools=[send_email, delete_file],
# 列在 interrupt_on 里的工具,模型每次想调都会先暂停、把参数交给人看,
# 人点了同意才真的执行。没列的工具照常直接执行。
interrupt_on={"send_email": True, "delete_file": True},
)
# 因为底下是 LangGraph 的 interrupt,暂停时状态是写进数据库的:
# 进程可以直接退出,人第二天批准了再起个新进程从断点继续。

因为底下是 LangGraph 的 interrupt,状态是落盘的:进程可以退出,人第二 天批准了再起进程恢复。这是 01 D6 维度 里最强的那一档。
七、Deep Agents Code:官方的 Claude Code 平替
DeepAgents 还附了一个终端编码 Agent,可以接任意模型:
# 安装 Deep Agents Code:一个跑在终端里的编码 Agent,模型可以随便换
curl -LsSf https://langch.in/dcode | bash

图片来源:Deep Agents Docs
对想研究「编码 Agent 到底怎么写」的人,这是一份可读的开源实现。
八、三层怎么选:官方自己的说法
| 你想要 | 用哪层 |
|---|---|
| 完整 Harness —— 规划、上下文管理、委派全给我配好 | DeepAgents |
| 更轻的 Harness,不要那些捆绑中间件 | LangChain create_agent |
| Agent Loop 本身就不是我要的形状,我要自定义图 | LangGraph |
三层可以混着用:任何 LangGraph 的 CompiledStateGraph 都能作为子智能体传给 DeepAgent。所以「外层用 DeepAgents 的规划和文件系统,某个特别复杂的子任务用手写 LangGraph 图」是官方支持的写法。
九、什 么时候用 / 什么时候别用
用它,如果
- 任务是长时、多步、开放式的 —— Deep Research、代码库重构、大规模数据整理
- 工具输出很大 —— 搜索、爬取、日志分析,卸载机制能救命
- 你想要 Claude Code 那种体验,但要换模型 / 自己托管
- 你已经在 LangGraph 生态里 —— 概念完全复用,切换成本几乎为零
别用它,如果
- 任务是短的、确定的 —— 一个 FAQ 机器人套上规划工具和文件系统,纯属给模型增加噪音和 token 成本
- 你要精确控制每一步 —— Harness 的本质是把控制权交给模型,要精确控制请回到 LangGraph
- 模型不够强 —— 「trust the LLM」的前提是模型真的能规划。小模型跑 Harness 会更糟,因为它连工具都用不明白
- 不能接受 LangChain 系依赖 —— 它是 LangChain 全家桶最上层,依赖链最长