最近开始系统学习 Datawhale 的《Deep Agents in Action》。前两章主要解决两个问题:
-
Deep Agents 到底是什么?它和 LangChain、LangGraph 有什么区别?
-
一个最简单的 Deep Agent 是怎么构建和运行起来的?
如果只是看 API,很容易把 Deep Agents 理解成"又一个 Agent 框架"。但学习完前两章后,我目前更倾向于把它理解为:
Deep Agents 的重点不是重新定义 Agent,而是在已有 Agent Framework 和 Runtime 之上,为复杂 Agent 提供一套开箱即用的 Harness。
1. 为什么已经有 LangChain 和 LangGraph,还需要 Deep Agents?
假设现在要开发一个类似 AI Coding Agent 的系统。
它不只是需要调用一次大模型,而需要:
-
阅读代码文件;
-
搜索整个项目;
-
分析问题;
-
制定修改步骤;
-
执行多个工具;
-
保存中间结果;
-
必要时拆分子任务;
-
长任务过程中控制上下文;
-
多轮运行时保存部分状态。
理论上,这些都可以自己基于 LangChain 或 LangGraph 实现。
问题在于:
几乎每开发一个复杂 Agent,都要重复实现这些基础能力。
因此 Deep Agents 的思路不是提供一个更底层的 Agent API,而是把复杂 Agent 中反复出现的工程模式提前封装起来。
2. Agent 技术栈的三个层次
理解 Deep Agents,首先需要区分三个概念:
┌──────────────────────────────┐
│ Agent Harness │
│ Deep Agents │
│ 文件系统 / 子Agent / 上下文管理 │
├──────────────────────────────┤
│ Agent Framework │
│ LangChain │
│ Model / Tool / Agent Loop │
├──────────────────────────────┤
│ Agent Runtime │
│ LangGraph │
│ 状态 / 持久化 / 执行 / 恢复 │
└──────────────────────────────┘
它们不是竞争关系,而是一个自底向上的技术栈。
2.1 Runtime:Agent 怎么可靠地运行?
代表:LangGraph
Runtime 关注的是执行问题,例如:
-
Agent 执行到一半失败怎么办?
-
状态怎么保存?
-
如何暂停后等待用户确认?
-
如何恢复任务?
-
多轮执行中的状态如何管理?
所以 LangGraph 更接近 Agent 的执行引擎。
可以粗略理解为:
LangGraph ≈ Agent 的 Runtime / Workflow Engine
它解决的是:
Agent 怎么跑。
而不是具体告诉 Agent 应该具备什么业务能力。
3. Framework:Agent 怎么构建?
代表:LangChain
LangChain 在 Runtime 之上进一步提供:
-
Model 抽象;
-
Tool 接口;
-
Agent Loop;
-
Middleware;
-
Prompt;
-
Tool Calling 等。
例如:
agent = create_agent(
model=model,
tools=[search, calculator],
system_prompt="You are a helpful assistant."
)
开发者不用再手动实现完整的:
调用模型
↓
模型判断是否调用工具
↓
调用工具
↓
把工具结果返回模型
↓
模型继续判断
↓
最终回答
LangChain 已经帮我们抽象了这个 Agent Loop。
因此我目前的理解是:
LangGraph:负责执行 Agent
LangChain:负责构建 Agent
4. Harness:Agent 如何真正完成复杂任务?
这就是 Deep Agents 所处的位置。
Deep Agents = Agent Harness
它建立在 LangChain 和 LangGraph 之上,进一步提供复杂 Agent 常见的基础设施,例如:
| 能力 | 作用 |
|---|---|
| 文件系统 | 读取、写入、搜索和编辑文件 |
| Context Management | 控制长任务中的上下文规模 |
| SubAgent | 将子任务委派给其他 Agent |
| Skills | 按需加载专业能力 |
| Memory | 保存长期信息 |
| Todo / Planning | 维护复杂任务计划 |
| Human-in-the-loop | 高风险操作前请求人工确认 |
其中需要特别注意:**Deep Agents v0.7 并不是默认开启所有能力。**例如任务规划需要显式加入 TodoListMiddleware,Skills、Memory 和人工审批等能力同样需要按需求配置。
所以三层可以总结成:
| 层次 | 代表 | 核心问题 |
|---|---|---|
| Runtime | LangGraph | Agent 怎么可靠运行? |
| Framework | LangChain | Agent 怎么构建? |
| Harness | Deep Agents | 怎样让 Agent 更容易完成复杂长期任务? |
5. 为什么叫 Harness?
Harness 原意有"装备、套件、控制系统"的意思。
我觉得可以把 Agent 开发想象成开发一个机器人。
LangGraph 给机器人提供:
状态机
执行环境
恢复机制
LangChain 给机器人提供:
大脑接口
工具调用接口
Agent Loop
而 Deep Agents 则进一步给机器人装备:
文件系统
任务列表
长期记忆
专业技能
子 Agent
上下文管理
权限机制
所以 Deep Agents 并不是"另一个更大的 Agent"。
更加准确的说法应该是:
它给 Agent 装上一套完成复杂任务所需要的工程装备。
这也是我认为理解 Harness 最重要的一点。
6. Deep Agents 的核心思想:Context Engineering
这一部分是第一章中我认为最值得关注的内容。
传统 LLM 应用经常采用:
Prompt
+
用户问题
+
所有相关资料
+
所有历史记录
+
所有文件
全部塞入 Context。
这种方式面对复杂任务会产生几个问题:
Context 越来越大
↓
Token 消耗增加
↓
关键信息被稀释
↓
模型越来越难定位真正需要的信息
Deep Agents 更强调:
不要把所有信息一直放在上下文里,而是让 Agent 在需要的时候主动获取信息。
例如:
Agent
│
├── read_file()
├── write_file()
├── grep()
├── glob()
└── edit_file()
需要一个文件时才读取。
需要保存大量中间信息时,就:
write_file(...)
需要搜索项目时:
grep(...)
大文件则只读取局部内容。
因此:
传统方式:
所有信息
↓
Prompt
↓
LLM
Deep Agents:
┌── File System
│
LLM ←──── Context ──── Search
│
├── Memory
├── Skills
└── SubAgent
这实际上把:
Prompt Engineering
进一步扩展成了:
Context Engineering
核心问题从:
Prompt 怎么写?
变成:
模型在当前时刻到底应该看到什么信息?
Deep Agents 通过虚拟文件系统以及可插拔 Backend,使 Agent 可以按需读取和保存信息,而不是持续把所有信息堆进 Prompt。
7. Tool、Middleware 和 Backend 必须区分
这是理解 Deep Agents 架构时非常重要的一组概念。
可以先简单记:
Tool = Agent 能做什么
Middleware = Agent 的行为如何被增强/控制
Backend = 操作真正在哪里执行和存储
例如模型决定:
read_file("main.py")
表面上这是一个 Tool Calling。
背后其实是:
LLM
↓
read_file Tool
↓
FilesystemMiddleware
↓
Backend
↓
真正读取文件
因此 Backend 自身并不是 Agent,也不负责思考。
它负责:
文件存在哪里
文件怎么读取
数据如何持久化
是否使用本地磁盘
是否使用数据库
是否使用远程 Sandbox
Middleware 则处于 Agent Loop 中,可以在模型调用和工具执行等阶段加入额外逻辑。
8. 第一个 Deep Agent
理解完架构后,第二章开始真正运行 Deep Agent。
安装:
pip install deepagents langchain-openai
当前教程要求 Python 3.11+。
最核心的 API 是:
from deepagents import create_deep_agent
一个最简单的 Agent 可以写成:
from langchain_openai import ChatOpenAI
from deepagents import create_deep_agent
model = ChatOpenAI(
model="your-model",
api_key="your-api-key",
base_url="your-base-url"
)
def get_weather(city: str) -> str:
"""Get the weather information of a city."""
return f"The weather in {city} is sunny."
agent = create_deep_agent(
model=model,
tools=[get_weather],
system_prompt="You are a helpful assistant."
)
然后:
result = agent.invoke({
"messages": [
{
"role": "user",
"content": "北京天气怎么样?"
}
]
})
最终结果可以从:
result["messages"][-1].content
获取。
9. create_deep_agent() 到底做了什么?
表面上我们只写了:
agent = create_deep_agent(...)
但其内部实际上完成了更复杂的装配。
大致可以理解成:
业务配置
│
├── Model
├── Tools
├── System Prompt
├── Middleware
└── Backend
│
↓
create_deep_agent()
│
↓
装配 Deep Agent Harness
│
↓
LangChain create_agent()
│
↓
Agent Loop
│
↓
LangGraph Runtime
也就是说:
create_deep_agent()
并没有替代 LangChain
而是:
在 LangChain Agent 周围装配了一系列 Harness 能力
最终仍然由 LangGraph 执行。
这一点非常关键。
10. Tool 本质上是什么?
Deep Agents 中一个普通 Python Function 就可以作为 Tool。
例如:
def search_paper(
query: str,
max_results: int = 10
) -> list:
"""Search papers according to a research query."""
...
对于 Agent 来说,最重要的是三个东西:
1. 参数名称和类型
2. Docstring
3. 默认参数
因为 LLM 会根据这些信息判断:
这个工具是干什么的?
什么时候使用?
应该传什么参数?
哪些参数可以省略?
因此:
Tool 的 docstring 实际上就是写给 Agent 阅读的 API 文档。
工具描述写得含糊,Agent 的 Tool Calling 质量自然也会下降。
11. agent.invoke() 并不是"调用一次模型"
这一点很容易产生误解。
代码:
agent.invoke(...)
看起来只有一次调用。
实际上内部可能发生:
User
↓
LLM
↓
决定调用 Search
↓
Search Tool
↓
结果返回 LLM
↓
LLM
↓
决定读取文件
↓
read_file
↓
LLM
↓
决定调用 SubAgent
↓
task()
↓
SubAgent
↓
返回结果
↓
LLM
↓
Final Answer
所以更准确的结构是:
while True:
response = model(context)
if response.need_tool:
result = tool(response.tool_call)
context.add(result)
else:
return response
当然,实际实现比这复杂很多,因为 Middleware 还会介入模型调用、工具执行、上下文处理和审批等环节。
12. 一个 Research Agent 可能怎么工作?
如果给 Agent 一个任务:
调研 LangGraph,并生成一份研究报告
假如我们显式开启了 Todo Planning,它可能自己完成:
用户任务
↓
1. write_todos()
↓
2. internet_search()
↓
3. internet_search()
↓
4. write_file()
↓
5. task(SubAgent)
↓
6. read_file()
↓
7. 综合信息
↓
8. 输出报告
这里最有意思的是:
开发者可能只写了一句:
agent.invoke(...)
但是 Agent 内部可能进行了十几次模型和工具交互。
Harness 的价值,就是隐藏大量重复的 Agent Engineering 基础设施,同时保留配置能力。
13. Planning 并不是固定工作流
这里还有一个很重要的认识。
例如:
Planning
→ Search
→ File
→ SubAgent
→ Final Answer
只是 Agent 可能选择的一条路径。
它不是传统 Workflow:
step1()
step2()
step3()
step4()
真正执行的时候,模型可能认为任务很简单,于是直接:
User
↓
Search
↓
Answer
也可能:
User
↓
Planning
↓
Search
↓
Search
↓
File
↓
SubAgent
↓
Search
↓
Answer
所以 Agent 系统的一个重要特点就是:
开发者定义能力空间,模型在运行时决定具体路径。
这和传统 Workflow Programming 有明显区别。
14. 为什么 Agent 开发必须做 Observability?
普通程序报错通常可以看:
Exception
Stack Trace
Log
但 Agent 出现的问题可能是:
模型为什么没有调用 Search?
为什么调用了错误的 Tool?
为什么参数传错?
为什么 SubAgent 没有被调用?
为什么消耗了大量 Token?
为什么 Agent 循环十几次还没结束?
这些问题只看最终输出很难分析。
因此复杂 Agent 开发需要 Trace。
教程中使用 LangSmith,可以查看:
-
每次模型调用;
-
Tool Calling;
-
Tool 参数;
-
Tool 返回值;
-
SubAgent 执行;
-
Token 消耗;
-
执行耗时;
-
文件变化等。
所以我目前认为:
LLM Application
+
Tool Calling
+
Agent Loop
+
Trace
才构成比较完整的 Agent 开发闭环。
15. 我目前对 Deep Agents 的整体理解
学习前我容易把:
Deep Agents
理解成:
一个用于构建 Agent 的新框架。
现在感觉这种理解并不准确。
更合理的是:
Application
│
↓
┌───────────────┐
│ Deep Agents │
│ Agent Harness │
└───────┬───────┘
│
┌───────▼───────┐
│ LangChain │
│ Agent Framework│
└───────┬───────┘
│
┌───────▼───────┐
│ LangGraph │
│ Agent Runtime │
└───────────────┘
Deep Agents 真正有价值的地方,是把复杂 Agent 中已经反复被验证有效的工程模式进行了封装。
例如:
Filesystem
Planning
SubAgent
Memory
Skills
Context Management
Human-in-the-loop
Sandbox
开发者不再需要每做一个 Agent 都从零重新实现。
16. Deep Agents 和 Codex / Claude Code 应该怎么理解?
从 Harness 这个角度,再去理解 Codex、Claude Code 这类产品会清楚很多。
它们并不是:
LLM + 一个 Shell 工具
而更接近:
LLM
+
Agent Loop
+
Filesystem
+
Search
+
Shell
+
Planning
+
Context Management
+
Permission
+
Sandbox
+
Observability
也就是说:
真正复杂的 Agent 产品,核心竞争力很大一部分其实存在于模型之外的 Harness。
模型决定:
Agent 能有多聪明
Harness 决定:
这个聪明的模型能不能稳定地完成复杂任务
这是我学习这两章之后最大的认知变化。
17. 两章学习后的知识地图
最后把目前内容压缩成一张知识图:
Deep Agents
│
├── 1. Runtime
│ └── LangGraph
│ ├── State
│ ├── Persistence
│ ├── Durable Execution
│ └── Human-in-the-loop
│
├── 2. Framework
│ └── LangChain
│ ├── Model
│ ├── Tool
│ ├── Agent Loop
│ └── Middleware
│
└── 3. Harness
└── Deep Agents
├── Filesystem
├── Context Engineering
├── SubAgent
├── Planning
├── Skills
├── Memory
├── Backend
└── Human-in-the-loop
而一次实际运行可以概括成:
User
↓
Deep Agent
↓
Model
↓
判断下一步
├───────────────┐
↓ ↓
Tool Final Answer
↓
Middleware
↓
Backend / External API
↓
Result
↓
重新进入 Model
18. 小结
前两章真正需要掌握的,我认为不是 create_deep_agent() 这个 API,而是下面几个概念:
第一,区分 Runtime、Framework 和 Harness。
LangGraph → Runtime
LangChain → Framework
Deep Agents → Harness
第二,理解 Deep Agents 为什么强调 Context Engineering。
复杂 Agent 的核心问题已经不仅是 Prompt 怎么写,而是:
什么信息
在什么时间
以什么形式
进入模型 Context
第三,理解 Agent 是一个循环,而不是一次 LLM 调用。
Model
↕
Tools
会持续交互,直到模型认为任务完成。
第四,理解 Tool、Middleware、Backend 三者职责。
Tool → 能做什么
Middleware → 怎么控制和增强
Backend → 在哪里真正执行和保存
第五,Harness 才是复杂 Agent 产品非常关键的工程层。
模型能力当然重要,但一个真正能够长期、稳定执行任务的 Agent,还需要文件系统、上下文管理、权限、规划、子任务委派、Sandbox 和可观测性等大量模型之外的工程能力。
这也是继续学习 Deep Agents 时,我认为最值得保持的一条主线:
不要只学习"怎么调用 Agent API",而要理解一个复杂 Agent Harness 是如何被设计出来的。
参考资料
-
Datawhale《Deep Agents in Action》第 1 章:从 Agent Framework 到 Agent Harness
-
Datawhale《Deep Agents in Action》第 2 章:快速上手------构建第一个 Deep Agent