返回博客列表

Deep Agents 深度解析:LangChain 的 Agent Harness 到底解决了什么

2026-10-16T22:20:00+08:00
Deep AgentsLangChainLangGraphAI AgentContext EngineeringMCP

又一个 Agent 框架?先别划走——它管的不是工具调用,是失控。

过去一年我写了太多「Agent 框架」,多到有点麻木。大多数框架做的事情高度雷同:把 LLM 包一层,注册几个 tool,跑一个 while 循环,然后告诉你「这就是 Agent」。

但真正把 Agent 放出去干活的开发都知道,难点从来不在那个循环。难点在于:任务跑到第 20 轮,上下文窗口炸了;派出去的子任务回来一堆垃圾信息,把主对话污染了;改一个文件之前没人拦着,Agent 直接把生产配置改了。

LangChain 的 Deep Agents 直接把这些「跑起来之后才会疼」的问题做进了框架层。它不是又一个 tool-calling 循环,而是一个 agent harness——装好了一整套让 Agent 在真实任务里不翻车的脚手架。

这篇文章会把它的四大能力支柱拆开讲清楚,配上完整的 create_deep_agent API、代码示例和取舍分析。看完你应该能判断:它到底值不值得换掉你手写的那套循环。

本文提纲

  1. 什么是 Deep Agents:harness 与 framework 的区别
  2. 快速上手:十行代码跑起来
  3. 执行环境:Agent 在哪里干活
  4. 上下文管理:Agent 怎么不撑爆窗口
  5. 委派:任务规划与 Subagent
  6. 人工介入:Agent 什么时候该停下来问你
  7. 与 Claude Agent SDK 的正面对比
  8. 什么时候该用,什么时候别用

什么是 Deep Agents:harness 与 framework 的区别

先厘清一个容易混淆的概念。LangChain 生态里现在有三层东西,职责完全不同:

  • LangChain:提供 Agent 的核心构建块——model、tool、message、middleware。
  • LangGraph:提供运行时——durable execution(持久化执行)、streaming、human-in-the-loop、checkpointer。
  • Deep Agents:提供 harness——在上述两者之上,把「文件系统做上下文管理」「派生 subagent」「长期记忆」这些能力预先装配好。

用官方文档的原话:Deep Agents 用的还是和其他框架一样的核心 tool-calling 循环,差别在于它内置了一堆让 Agent 在真实任务里变得可靠的能力。所以它不是替代 LangChain,而是 LangChain 官方给出的一套「开箱即用的最佳装配方案」。

如果你只是想自己手搓一个最小 Agent,官方建议直接用 LangChain 的 create_agent,或者拿 LangGraph 搭自定义 workflow。Deep Agents 的价值在于:你不想再自己实现一遍上下文压缩、子代理隔离、权限控制这些脚手架。

它内置六大能力,可以归到四个支柱里:

graph TB
    subgraph Harness["Deep Agents Harness"]
        EE["Execution Environment
Tools / MCP / Virtual Filesystem / Permissions / Code Exec"] CM["Context Management
Skills / Memory / Summarization / Prompt Caching"] DG["Delegation
Task Planning / Subagents"] ST["Steering
Human-in-the-loop / Interrupts"] end LC["LangChain Core
models / tools / messages / middleware"] --> Harness Harness --> LG["LangGraph Runtime
durable execution / streaming / checkpointer"] LG --> LLM["LLM Providers
OpenAI / Anthropic / Google / Ollama"]

一句话概括这四层分别解决什么:

  • Execution environment:Agent 能做什么(调工具、读写文件、执行代码)。
  • Context management:Agent 知道什么、能跑多久、跨会话记住什么。
  • Delegation:Agent 怎么把大任务拆开、分给谁。
  • Steering:Agent 什么时候停下来等人类批准。

快速上手:十行代码跑起来

安装和最小示例都很直接。model 用 provider:model 的字符串格式,具体写哪种取决于你接哪家。

pip install deepagents
from deepagents import create_deep_agent

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="openai:gpt-5.5",
    tools=[get_weather],
    system_prompt="You are a helpful assistant",
)

# Run the agent
agent.invoke(
    {"messages": [{"role": "user", "content": "what is the weather in sf"}]}
)

换个模型只改一行字符串——anthropic:claude-sonnet-5、google_genai:gemini-3.6-flash、openrouter:z-ai/glm-5.2、ollama:north-mini-code-1.0 都行。对国内用户来说,openrouter: 接第三方模型、ollama: 跑本地模型是两条现实路径。

这里有个容易忽略的点:你写几行代码,框架就偷偷替你装配了第一支柱的虚拟文件系统。上面这个 Agent 看起来只会调 get_weather,实际上它同时还拥有一整套 ls、read_file、write_file、grep 等文件工具,以及自动派生 subagent 的 task 工具。想关掉得显式配置,后面细说。

如果你关心可观测性,接上 LangSmith 就能看到完整的 trace,包括每次工具调用、每次上下文压缩、每个 subagent 的独立轨迹。这在调试「Agent 为什么在第 15 轮开始胡说」时几乎是无价的。

执行环境:Agent 在哪里干活

执行环境是 Agent 真正动手的地方,分成四层:工具、虚拟文件系统、文件权限、代码执行。

工具与 MCP

tools= 参数接受自定义函数、LangChain tool,或者任何 MCP server 提供的工具。MCP(Model Context Protocol)现在基本是 Agent 接外部世界的标准接口,Deep Agents 对它的支持是完整的——数据库、API、文件系统都能通过统一协议接进来。

from deepagents import create_deep_agent

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[search, fetch_page, run_query],
)

虚拟文件系统

这是整个 harness 的地基。很多能力——context offloading、skills、memory、code execution——底层都靠这个虚拟文件系统串起来。它由可插拔的 backend 支撑:内存 state、本地磁盘、LangGraph store、组合路由,或者你自定义的 backend。

内置的文件操作工具:

Tool 说明
ls 列目录,带 size、modified time 等元信息
read_file 读文件内容(带行号),支持 offset/limit 读大文件;非文本文件会返回多模态内容块
write_file 新建文件,或覆盖已有文件
edit_file 精确字符串替换(支持全局替换模式)
delete 删除文件,或递归删除目录(需 deepagents>=0.7)
glob 按模式找文件,如 **/*.py
grep 搜索文件内容,支持只列文件、带上下文、计数等输出模式
execute 在环境中跑 shell 命令(仅在 sandbox backend 下可用)

read_file 的多模态支持覆盖得比想象中广:图片(.png/.jpg/.jpeg/.gif/.webp/.heic/.heif)、视频(.mp4/.mov/.avi/.webm 等)、音频(.wav/.mp3/.flac 等)、文档(.pdf/.ppt/.pptx)。也就是说 Agent 拿到一个 PDF 或一张截图,不需要你额外写解析工具,直接 read_file 就行。

如果你只想要一部分文件工具(比如做一个只读的代码分析 Agent),可以给 FilesystemMiddleware 传一个 tools 白名单:

from deepagents import create_deep_agent
from deepagents.middleware import FilesystemMiddleware

# Read-only agent: write_file, edit_file, delete, execute never shown
agent = create_deep_agent(
    model="claude-sonnet-4-6",
    middleware=[
        FilesystemMiddleware(backend=backend, tools=["read_file", "ls", "glob", "grep"]),
    ],
)

有个反直觉的细节:白名单里必须包含 read_file,否则创建 Agent 时直接抛 ValueError。原因是 FilesystemMiddleware 本身是 Deep Agents 栈里的必需脚手架,不能整个摘掉,只能裁剪它对模型可见的工具面。

文件权限

权限是一组声明式规则,控制 Agent 能读写哪些路径。注意它是首匹配优先(first-match-wins):规则从上往下扫,第一条命中的生效;如果一条都没命中,默认放行。

每条规则三个字段:

  • operations:"read" 和/或 "write"
  • paths:glob 模式,匹配文件或目录
  • mode:"allow" 或 "deny"

这套机制的实际用途很明确:把 Agent 锁在 /workspace/ 里、保护 .env 和凭证文件、给 subagent 比父 Agent 更窄的权限。

一个必须知道的边界:权限对 sandbox backend 不生效。因为 sandbox 本身就能通过 execute 跑任意命令,绕过文件工具的规则轻而易举。需要更复杂的校验逻辑,得走 backend 的 policy hooks。

代码执行

两条路径,用途完全不同:

  • Sandbox backend:暴露 execute 工具,在隔离环境里跑 shell 命令。当 Agent 需要装依赖、跑测试、调 CLI、操作真实文件系统时用它。它实现了 SandboxBackendProtocolV2,harness 检测到就自动把 execute 加进工具列表。
  • Interpreter:暴露 eval 工具,在作用域化的 QuickJS 运行时里跑 JavaScript。适合循环、批处理、确定性的数据转换、程序化工具调用。它不提供 shell、装包、文件系统和网络访问。

选择逻辑很简单:需要真环境就用 sandbox,只需要一层轻量可编程能力就用 interpreter。别指望 interpreter 能干 sandbox 的活——设计上它就不给。

Streaming

事件流把 Agent 的运行暴露成带类型的投影:messages、tool calls、values、output。Deep Agents 额外加了 stream.subagents,每个被委派的任务都有独立句柄,消息流、工具调用流、嵌套的 subagent 流互不干扰。做前端实时渲染时,这个设计省掉大量手动拆解。

上下文管理:Agent 怎么不撑爆窗口

这是 Deep Agents 相对大多数框架最有价值的部分。上下文管理分四层。

Skills:按需加载的领域知识

Skill 把专门的工作流、领域知识、自定义指令打包起来。每个 skill 遵循 Agent Skills 标准,放在一个带 SKILL.md 的目录里,还可以附带脚本、模板、参考文档。

关键在于渐进式披露(progressive disclosure):Agent 启动时只读 SKILL.md 的 frontmatter,等任务真正需要时才读完整内容。这解决了一个实际矛盾——你想给 Agent 塞很多领域知识,又不想把它们全部灌进启动上下文。用渐进披露,启动上下文始终保持精简,能力却随取随用。

Memory:跨会话的持久上下文

Memory 用来存编码风格、偏好、约定、项目规范这类需要跨会话保留的信息,通过 memory= 参数传入 AGENTS.md 文件。

它和 Skills 的核心差别是:memory 永远加载,没有渐进披露。内容存在配置的 backend 里(StateBackend、StoreBackend 或 FilesystemBackend)。Agent 还能根据交互和反馈更新 memory,这样偏好和模式能自动延续,不用每个 thread 重新交代一遍。

这也意味着一个取舍:往 AGENTS.md 里塞太多东西会直接吃掉每次请求的上下文预算。它是「必读手册」,不是「知识库」。知识库那部分应该交给 Skills。

摘要与上下文卸载

Agent 跑长任务时上下文会不断膨胀。官方把整套上下文流转拆成四部分:

  • Input context:system prompt、memory、skills、tool prompts,决定 Agent 一开始知道什么。
  • Compression:内置的卸载(offloading)和摘要(summarization),压缩对话历史和大型中间结果。
  • Isolation:用 subagent 隔离重活,只把最终结果带回主线程。
  • Long-term storage:借虚拟文件系统做跨 thread 的持久化,让信息在不同会话之间延续。

压缩这一步的机制值得展开。大块的 tool 结果会被卸载到文件系统,上下文里只留下一个文件路径加少量预览;对话历史接近窗口上限时,触发摘要——用 LLM 生成一段结构化摘要替换掉完整历史,而原始消息并不销毁,而是写进文件系统存档。

这个「卸载而非丢弃」的设计很聪明:丢掉信息是不可逆的,卸载是可逆的。Agent 后面发现需要细节,还能 read_file 按 offset 把原文读回来。这也是为什么虚拟文件系统是整个 harness 的地基——它同时承载了压缩、skills、memory 和 code execution。

Prompt caching

静态的 prompt 段落是 cache-eligible 的。在支持的模型上,这能明显加速推理、降低成本。对长 system prompt(Deep Agents 的 system prompt 会由多个部分拼成)来说,缓存命中率的差别直接体现在账单上。

顺带一提,Deep Agents 的最终 system prompt 是按固定顺序拼起来的:自定义 system_prompt → base agent prompt → memory prompt → skills prompt → virtual filesystem prompt → subagent prompt → 你注册的 middleware prompts → HITL prompt。理解这个顺序,才好判断该把内容放在哪一层。

委派:任务规划与 Subagent

任务规划(Task planning)

这是一个可选项。把 TodoListMiddleware 传进 middleware=,Agent 就获得一个 write_todos 工具,用来在执行过程中维护结构化的任务列表。在多步任务开始前和执行中,Agent 会被提示用这个工具记录「正在做什么」「还剩什么」。

它本质上是把 Claude Code 那种「先写 To-Do 再动手」的行为搬进了框架。对复杂任务,这能显著降低 Agent 跑到一半忘记目标、或者把事情做完一半就宣布完成的情况。

Subagent

Subagent 是整个 harness 里第二个关键设计。核心价值是上下文隔离:一个复杂子任务(比如「遍历这个仓库找出所有用了废弃 API 的地方」)会在独立的上下文窗口里跑,只把最终结论带回主对话,中间的几十次工具调用不会污染主线程。

默认情况下,Deep Agents 会自动加上一个 general-purpose 子代理。你可以用 GeneralPurposeSubagentProfile(enabled=False) 关掉它。

subagents= 参数接受 SubAgent dict,字段包括:

  • name / description:名称与用途描述(主 Agent 靠 description 决定派谁)
  • system_prompt:子代理的系统提示
  • mode:"isolated"(默认,独立上下文)或 "fork"(继承父对话)
  • tools / model / middleware / skills / permissions
  • interrupt_on:子代理级别的中断配置
  • response_format:结构化输出

mode: "fork" 是个有意思的选项——它让子代理继承父对话的完整上下文。适合那些「必须知道前面聊了啥」的复查类任务,代价是失去了上下文隔离带来的省 token 优势。

除了声明式 SubAgent,还有 CompiledSubAgent(字段更少:name/description/runnable/mode),可以直接挂一个已经编译好的 LangGraph graph 当子代理,适合复用已有的工作流。

人工介入:Agent 什么时候该停下来问你

这是「Steering」支柱。核心 API 是 interrupt_on,控制哪些工具调用前需要人类批准:

# {tool_name: True/False/InterruptOnConfig}

决策类型有四种:

Decision 含义
approve 原样执行
edit 修改工具参数后执行
reject 拒绝,并把原因回传给 Agent
respond 由人类直接提供工具结果

allowed_decisions 可以限制允许哪些决策——比如只允许 approve / reject,禁止人类替 Agent 编造结果。

还有条件中断:可以给中断配一个 when 谓词,只在满足条件时才触发(需要 langchain>=1.3.3)。比如「写文件不用拦,但删文件必须拦」,比一刀切地拦下所有写操作合理得多。

两个必须记住的实践要点:

  1. 一定要配 checkpointer(比如 MemorySaver)。中断会把状态挂起,没有 checkpointer 就恢复不了。
  2. 恢复时必须用相同的 thread_id。否则你接不回原来那个挂起的执行。

这也是 LangGraph 运行时的价值所在——durable execution 让「暂停几天后继续」成为可能,而不是只能暂停几秒。

与 Claude Agent SDK 的正面对比

Deep Agents 经常被拿来和 Anthropic 的 Claude Agent SDK 比,因为两者都是「给 Agent 装脚手架」的思路。官方文档专门写了一页对比,主要差异集中在几个维度:

维度 Deep Agents Claude Agent SDK
执行环境 虚拟文件系统 + sandbox + interpreter,backend 可插拔 绑定 Claude Code 的执行模型
模型 任意 provider(OpenAI / Anthropic / Google / 本地) 绑定 Claude
多租户 内置 需自建
生产部署 可托管(LangSmith)或自托管 需自建 server / auth / 多租户
生态 LangChain / LangGraph 生态 Claude 生态

一句话总结:Claude Agent SDK 是「用 Anthropic 的方式做 Agent」,Deep Agents 是「你自己选模型和基础设施,框架负责把脚手架装好」。

许可证上两者都是 MIT(注意 Claude Code 本体是专有的,和 Agent SDK 不是一回事)。

选型的现实判断:如果你的团队已经深度绑定 Claude,且愿意自己搭 Agent server、鉴权、多租户,Claude Agent SDK 更顺手;如果你要接国内模型、要自托管、或者不想自己实现上下文管理和多租户,Deep Agents 省下的工作量是实打实的。

生产环境的参考案例:LangChain 自己开源的 OpenSWE 就是基于 Deep Agents 构建的。

什么时候该用,什么时候别用

Deep Agents 不是银弹,它的 sweet spot 和失效边界都很清楚。

值得用的场景:

  • 多步、长链路任务,上下文必然会膨胀(深度研究、代码库级重构、长流程数据处理)
  • 需要子任务隔离,不想让中间过程污染主线程
  • 需要人在关键节点把关(改生产配置、删数据、发消息)
  • 需要跨会话记住用户偏好和项目约定

可能不值得的场景:

  • 单轮问答、简单的 tool-calling(用 LangChain create_agent 就够,别为一个函数调用装整套 harness)
  • 极简部署、不想引入 LangGraph 运行时依赖的轻量场景
  • 子任务之间高度耦合、必须共享全部上下文(这时 subagent 的隔离反而是负担,fork 模式也不算完美解)

有个成本维度值得单独提:harness 帮你自动装配了文件系统工具、subagent 工具、各种 middleware,这些都会占用 tool 定义和 system prompt 的 token。对追求极致 token 效率的场景,记得用白名单和 profile 把不需要的能力关掉——省下的每一段 prompt,都会乘以你所有的请求数。

想动手的话,最快的路径是:装 deepagents,跑一遍官方 quickstart 那个 get_weather 例子,然后加一个 interrupt_on 拦住某个危险工具,再派一个 subagent 去做调研。三个动作跑下来,这套 harness 的设计取舍你就有体感了。

参考文档与链接

你的 Agent 现在卡在哪一层?上下文、委派,还是权限?评论区聊聊你的踩坑,觉得有用点个赞让更多人看到。


作者: itech001
来源: 公众号:AI人工智能时代(the-ai-era)
网站: https://www.theaiera.top/ 关注每日最新AI新闻和技术博客,主页有更多的文章的AI 技术参考:https://www.theaiera.top

本文首发于 AI人工智能时代,转载请注明出处。

分享给朋友