有LangChain和LangGraph,为什么还要再出个Deep Agents

Deep Agents 补的不是新功能,是最后一层:把「深度智能体」这个成品形态,做成开箱即用。

先说结论
能把长任务跑下来的智能体,必须解决三件事:记得住进度(规划)、撑不爆上下文(文件卸载)、淹不没在噪声里(子代理隔离)。这三件事,用 LangGraph 都能搭,但图纸要你自己画。Deep Agents 把这三件事出厂就装好了。它们仨不是重复,是同一栋楼的三层。

一、三层楼的分工:零件、工地、精装房

先看官方给出的分层视图,这是理解一切的钥匙:

LangGraph ── 图运行时:流式 / 持久化 / 检查点 / HITL
  ↑
LangChain create_agent ── 极简 ReAct harness
  ↑
Deep Agents ── 有主见 harness:规划 + 文件系统 + 子Agent + 上下文管理 + Skills

这里有个词要先讲清楚:harness,智能体外壳。就是把一个裸模型武装成可用 Agent 的那套脚手架——循环、工具调度、上下文管理,全算。

三层的分工,用一个盖楼的比喻:

LangChain 是零件厂:模型抽象、@tool、文档加载、向量检索,组件与集成。想怎么拼,你说了算。

LangGraph 是工地:编排运行时,节点、边、循环、检查点。图纸给你,塔吊给你,房子怎么盖,你说了算。

Deep Agents 是精装交付:有主见的 harness,规划、文件、子代理出厂预装,钥匙给你,直接入住。嫌装修风格不合,任意一环都能拆了换。

注意,三层不是替代关系,是组合关系。官方留了一个狠活:任何编译好的 LangGraph 图,都能直接塞进 Deep Agents 当子代理。自己画的图和出厂默认能力,可以在一个系统里共存。

分工清楚了,下一个问题才是关键:精装房凭什么存在。毛坯自己装,不是更自由吗。

· · ·

二、长任务的三宗罪,create_agent 扛不住

短任务没这些烦恼。查个天气、算个账,create_agent 一行搞定,又快又轻。

但任务一旦拉长,超过十几步,三个问题会准时出现。我挨个撞过。

第一宗罪:任务漂移。跑到第 15 步,模型忘了第 1 步的目标,顺着中间某个细节越钻越深。没有一份显式的待办清单拉着它,它就是会跑偏。

第二宗罪:上下文爆炸。每一步的中间产物都堆在消息历史里,任务没做完,窗口先满了。长文本不卸载出去,就是在烧钱等崩。

第三宗罪:噪声淹没。每个子任务的原始数据都进主上下文,真正关键的结论反而被淹掉,模型的判断质量肉眼可见地下降。

这三个问题,LangGraph 都能解。规划就写个 todo 工具,卸载就做套文件工具,隔离就搭委派机制。

问题是,这三套脚手架,每个团队都得自己写一遍。官方有个教程仓库叫 deep-agents-from-scratch,5 个 notebook 干的事,就是带你用 LangGraph 把这三套东西手搓一遍。教程的存在本身就说明了问题:这些活又脏又重复。

Manus、Claude Code 这些产品,早把这套范式验证过了。Deep Agents 做的事,就是把它变成出厂默认。

下面三节,一张张看这三张王牌。

· · ·

三、第一张王牌:规划,write_todos 实测

约定
本文模型统一用阿里百炼 qwen-plus,通过 init_chat_model 接入。有个必踩的坑:必须设 use_responses_api=False,否则 deepagents 默认走 OpenAI Responses API,百炼不兼容,直接报错。

最简形态,一个多步任务丢进去:

from langchain.chat_models import init_chat_model
from deepagents import create_deep_agent

model = init_chat_model("openai:qwen-plus", use_responses_api=False)

agent = create_deep_agent(
    model=model,
    system_prompt="You are a methodical planner. "
                  "Always use write_todos to plan multi-step tasks.",
)

task = """完成多步任务:
1. 用 write_todos 规划步骤
2. 写文件 /tmp/deep_test_hello.txt
3. 读回验证  4. 写总结文件  5. 汇报两个文件内容"""

result = agent.invoke({"messages": [{"role": "user", "content": task}]})

注意,我没有教它怎么规划,只说了一句「你要先规划」。它的第一个动作就是调内置的 write_todos:

[ai] tool_calls: ['write_todos']
     in_progress: Write file /tmp/deep_test_hello.txt
     pending: Read the file back to verify
     pending: Write a summary file /tmp/deep_test_plan.txt
     pending: Read both files and report contents

…… write_file → read_file → write_file → read_file,逐步执行 ……

[ai] tool_calls: ['write_todos']
     completed: Write file /tmp/deep_test_hello.txt
     completed: Read the file back to verify
     completed: Write a summary file /tmp/deep_test_plan.txt
     in_progress: Read both files and report contents

关键在于:这不是一段提示词技巧,是一个带状态的内置工具。todo 清单有 pending、in_progress、completed 三种状态,模型每做完一步就回头对账,把状态改掉。

清单本身就在上下文里,等于每走一步都重读一遍自己的目标。任务漂移就是这么被摁住的。这个模式,和 Manus、Claude Code 的公开做法是同一套。

版本踩坑
v0.7 起,任务规划从默认启用改成了 opt-in,要显式传 TodoListMiddleware 才有 write_todos。升级版本后发现规划消失了,不是模型变笨,是开关变了。新库迭代快,这类行为变更以后还会有。

· · ·

四、第二张王牌:虚拟文件系统,把上下文卸出去

Deep Agents 出厂带了一整套文件工具:read_file、write_file、edit_file、ls、glob、grep。不是为了帮你管文件,是为了给上下文减肥。

逻辑是这样的。长任务的中间产物——调研抓回来的网页、清洗到一半的数据、生成的草稿——全堆在消息历史里,上下文很快就满。正确的姿势是写进文件,主上下文里只留一行文件路径。要用的时候再读,read_file 还支持 offset 和 limit,大文件分块读。

token 从线性膨胀,变成按需取用。这就是「卸载」。

但第一次跑文件写入,我被坑得结结实实:

agent = create_deep_agent(model=model)
agent.invoke({"messages": [{"role": "user",
    "content": "Write 'HELLO' to /tmp/state_only_test.txt"}]})
# → 工具返回: Updated file /tmp/state_only_test.txt
# → 去宿主机一查: os.path.exists(...) → False,文件根本不在

# 想真落盘,换 FilesystemBackend
from deepagents.backends import FilesystemBackend
fs = FilesystemBackend(root_dir="/tmp/deep_fs_test", virtual_mode=True)
agent = create_deep_agent(model=model, backend=fs)
# /workspace/v.txt → 真实落在 /tmp/deep_fs_test/workspace/v.txt
# 实测 find 可见,cat 内容一致

默认后端是 StateBackend,文件只存在 Agent 的内部状态里,不落盘。第一次看到工具说「写好了」、磁盘上却什么都没有,我差点以为它在撒谎。

想清楚了才明白这是设计:默认存状态,意味着文件跟着 checkpoint 走,天然继承 LangGraph 的持久化和断点续跑。要真落盘,显式切 FilesystemBackend;还有 CompositeBackend 支持按路径路由,敏感数据走状态、大文件走磁盘。

文件系统还带权限控制,实测有效:

permissions=[
  FilesystemPermission(operations=["read"],  paths=["/**"], mode="allow"),
  FilesystemPermission(operations=["write"], paths=["/**"], mode="deny"),
]

读取 /secret.txt → 成功
写入 /malicious.txt → Error: permission denied,宿主机确认文件未创建

一个坑要提前告诉你:路径模式必须带通配符。写 paths=["/tmp/"] 匹配不到任何子路径,底层是 glob 匹配,得写 "/tmp/**"。我配错一次,白排查半天。

五、第三张王牌:子 Agent,噪声关在门外

上下文隔离靠子代理。定义几个专职 SubAgent,主 Agent 通过内置的 task 工具派活:

from deepagents import create_deep_agent, SubAgent

text_analyst = SubAgent(
    name="text-analyst",
    description="A text analysis specialist.",
    system_prompt="You are a text analyst.",
    model=model,
    tools=[word_counter],  # 子代理可以有自己的独立工具集
)

agent = create_deep_agent(
    model=model,
    subagents=[text_analyst, math_specialist],
    system_prompt="You are an orchestrator. Use the task tool to delegate.",
)

实测两轮,结果很有意思:

# 第一轮:文本分析 → 委派了
[ai] task(subagent_type='text-analyst',
        description='Analyze the given text ...')
[tool] The text analysis shows:
      Sentiment: Strongly positive ...
[ai] The text is a concise, positive endorsement of Python...

# 第二轮:数学应用题 → 没委派,主 Agent 自己解了
[ai] This is a classic relative motion problem.
     I'll solve it step by step ...

两个观察。

第一,子代理有独立的上下文窗口。它在自己的窗口里折腾了多少轮、读了多少原始数据,主 Agent 一概不见,只收到一条结论。噪声被关在门外,主上下文保持干净。

第二,委派不是强制的,是模型自己的判断。第二轮的数学题,主 Agent 掂量了一下,觉得自己能解,就没派。这是特性不是 bug,但也提醒你:委派行为有不确定性,关键流程别把宝全押在它身上。

除这三张王牌,还有两套配件值得点名,都是实测过的:

Memory 与 Skills:memory 指定的文件(如 AGENTS.md)启动即全量加载,我塞进去「用户叫张三、回答用中文」,它开口就认出了我;skills 走渐进式披露,启动只读每个 SKILL.md 的描述,任务相关才读正文。让它写 commit message,它加载了 commit-helper 技能,严格给出 "feat(auth): 新增用户登录功能";问无关问题,技能正文碰都不碰。

HITL 直接继承:interrupt_on={"send_email": True},发邮件前整张图暂停等审批,Command(resume=...) 批准后才放行。这正是上一篇讲过的 LangGraph interrupt,一行参数就接上了。坑:恢复参数是复数的 decisions 列表,写成单数 decision 直接抛 KeyError。

看明白了吗。持久化、流式、审批,Deep Agents 一样都没重造,全部从 LangGraph 继承。它只在最上面加盖了一层「深度智能体」的默认装修。

· · ·

六、公平起见:什么时候别用 Deep Agents

夸了这么多,该泼冷水了。实测下来,有三类场景我会明确劝退。

只要极简 Agent,别上:LLM 加一两个工具的 ReAct 循环,create_agent 一行搞定。Deep Agents 的中间件栈是整套精装,对小房子来说是过度装修。

流程不是「Agent 循环」的形状,别上:确定性 DAG、复杂分支审批流,该用 LangGraph 自己画图。硬塞进 Deep Agents,等于买了成品车再去拆发动机。

对 API 稳定性极度敏感的生产线,缓一缓:2025 年才开源的新库,迭代飞快。我实测期间就撞上 v0.7 把规划改成 opt-in,delete、execute 这类工具还挑版本。引入前锁版本、做回归,别拿 0.6 的经验赌 0.8。

还有一条必须讲的安全红线。Deep Agents 采用「Trust the LLM」模型:工具允许的事,Agent 就能做。安全边界要强制在工具层、沙箱层、权限层,比如前面演示的 permissions 和 interrupt_on,不要指望模型自我约束。

老规矩,三层对照表,选型不纠结:

只用 LangChain 就够(LCEL + create_agent)

单轮链条:摘要、翻译、改写,一根管道走完。

固定 RAG 管线:检索增强问答,组件全套现成。

标准工具 Agent:查天气、查订单这种三五步以内的活,大部分 Agent 需求到这一层就够了。
要自己画 LangGraph 图的场景

自定义拓扑:反思环、多路由、确定性步骤混编 LLM 步骤。

审计与断点续跑:合规审查、风控决策,每一步可追溯可回放。

多智能体编排:supervisor、swarm、handoff,子图组合自己说了算。
直接上 Deep Agents 的场景

长时程多步骤任务:深度调研出报告、多源数据清洗分析、代码仓库级理解与改动。

开放任务要上下文管理:中间产物多、单轮窗口容易爆,需要卸载和隔离。

想要成品也要能改:规划、文件、委派拿来即用,工具、子代理、提示词、模型任意替换。

混合模型策略:主 Agent 用强模型,子代理用便宜模型,分层调度省钱。

还有个偷懒选项:官方有个预构建的终端编码 Agent 叫 Deep Agents Code,类似 Claude Code 但模型无关,想先体验成品形态的可以直接装来玩。

七、写在最后

回到开头那个问题:套娃吗。

三层楼看下来,不是。LangChain 解决「有什么零件」,LangGraph 解决「怎么把零件连成循环」,Deep Agents 解决「我就想要一台能跑长途的成品车」。

每一层都在回答上一层不回答的问题,也都在给开发者留退路。嫌成品车不合身,往下走一层自己画;嫌自己画太累,往上走一层直接用。任意编译好的图还能塞回去当子代理,三层之间是通的。

从函数调用,到链,到图,再到深度智能体。这条抽象的台阶还在往上修。方向一直没变:把验证过的范式沉淀下来,把选择的权利留在开发者手里。

组件库给你自由,运行时给你控制,成品车给你时间。选哪层,看你要什么。

posted @ 2026-09-22 10:03  当下是吾  阅读(27)  评论(0)    收藏  举报