ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Deep Agents 学习笔记(一):从 Agent Harness 到第一个 Deep Agent

Deep Agents 学习笔记(一):从 Agent Harness 到第一个 Deep Agent

最近开始系统学习 Datawhale 的《Deep Agents in Action》。前两章主要解决两个问题:

  1. Deep Agents 到底是什么?它和 LangChain、LangGraph 有什么区别?

  2. 一个最简单的 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 和人工审批等能力同样需要按需求配置。

所以三层可以总结成:

层次代表核心问题
RuntimeLangGraphAgent 怎么可靠运行?
FrameworkLangChainAgent 怎么构建?
HarnessDeep 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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进