DeepAgents 开箱即用地搭出深度调研助手
DeepAgents 的 createDeepAgent 搭了一个多 Agent 深度调研助手——主 Agent 列 todo 清单逐步推进,调研、数据分析、报告编辑交给三个子 Agent;没写任何编排基础设施,todo 清单、长期记忆、技能、上下文压缩全是内置、只做配置。这篇拆给你看:哪些能力是开箱即用的
Leo
2026.09.04 · 更新于 2026.09.04
DeepAgents 开箱即用地搭出深度调研助手
为什么写这篇:多 Agent 的「隐形工作量」到底在哪
单 Agent 好做,多 Agent 才是分水岭。等你真的想做一个「会自己拆任务、分头干活、最后汇总」的 Agent,才发现难点根本不在「调大模型」,而在编排。回想一下要自己手写的东西:
- 让它列步骤、跟进度:写 tool、改状态、维护一张「待办清单」并在每轮回答前喂回去;
- 让主 Agent 委派子 Agent:
task工具、子 Agent 的独立上下文、怎么把结果传回来; - 让子 Agent 能干自己的活:联网搜索要注册、要跑数值计算还得给它开个代码执行环境;
- 让它记住你的偏好:每次都得手动把长串规范塞进系统提示;
- 让它会某项专业技能:技能文本什么时候注入、怎么按需触发;
- 上下文越聊越长:什么时候该摘要压缩、怎么决定保留哪段历史。
这些问题一个比一个像「地基」。我见过很多人(包括从前的我)把大量精力砸在这些地基上,Agent 的核心能力反而没时间打磨。
这篇文章记录我们最近的一次实践:基于 DeepAgents 的 createDeepAgent,搭了一个多 Agent 架构的深度调研助手。结果相当反直觉——我们没有写多少代码,就把上面这些「地基」全解决了。这篇就拆开看:哪些是框架内置的、哪些只需要写 prompt / 做配置、各是什么原理。你能直接复用这套思路,把「深度调研」换成你自己的业务。
一句话结论放前面:编排与上下文管理这类「横切基础设施」,DeepAgents 全给你内置好了;你要写的主要是分工设计(写 prompt)和少量胶水代码。 这就是它「开箱即用」的价值。
先认识主角:createDeepAgent 是什么
它是什么
createDeepAgent 是 DeepAgents 暴露的工厂函数:调用它返回一个已经编排好、可直接运行的 Agent,而不是让你从零拼工具、拼循环。它内部本质是 createAgent + 一组官方中间件(todo 清单、记忆、技能、文件系统、上下文摘要、子代理委派),所以你拿到手的就是一个功能完整的 Agent,想换哪块再拆。
最大的副产品:它返回的是一个编译好的 LangGraph 图。意味着 stream、subgraphs 子图流式、checkpointer、断点续跑这些 LangGraph 能力全都自然可用,我们 CLI 里就是靠它逐条打印「现在是哪个 Agent、在调什么工具」的实时进度。
一句话版本:createDeepAgent = 一个开箱即用、能挂子 Agent、能配记忆和技能的 Agent 工厂,返回物是 LangGraph 图。
开箱即用能力对照
| DeepAgents 内置能力 | 它帮你做了什么 | 你需要做的 |
|---|---|---|
| Todo 清单 | 内置 write_todos 工具 + todo 中间件,Agent 拆步骤、改状态都有人接 | 在系统提示里「命令」它先列清单 |
| 文件系统 | FilesystemBackend 注入读写文件/目录/搜索等工具,Agent 有了「工作记忆」 | 传一个 backend |
| 长期记忆 | 启动时加载 AGENTS.md 作为记忆上下文 | memory 指向你的记忆文件 |
| 技能 | 扫描技能目录,按需注入技能文本 | skills 指向目录 + 每个技能一份说明 |
| 子 Agent 委派 | 内置 task 工具,可并行开子 Agent,各自独立上下文 | 声明 subagents 数组 |
| 上下文压缩 | 超预算时自动摘要、裁剪工具结果 | 几乎不用做;可调阈值 |
| 流式/图能力 | 返回 LangGraph 图 | 直接用,不用写图 |
看着这张表,我们其实只做了一件事:把「分工设计」翻译成系统提示,并声明了 3 个子 Agent。
我们搭的东西长什么样
深度调研助手是一个主 Agent + 三个子 Agent的团队:
- 主 Agent(编排者):列 todo 清单、逐步推进;亲自起草报告;把专业活委派下去。
- 调研员 researcher:负责一个聚焦子主题,联网搜索,把原始资料落盘。
- 分析师 analyst:负责数值计算/数据分析,用 eval 代码执行环境算,禁止猜数字。
- 编辑 editor:只读审稿,给修订建议,不亲自改写。
整个架构长这样:
两个细节值得先说清:
- 子 Agent 也继承了 todo 能力。 调研员处理一个子主题如果也要多步(搜索、整理、写文件),它同样会自己先
write_todos拆几步、逐步执行、完了把状态标记完成——因为 todo 中间件对每个 Agent 节点都生效。你不需要为「子 Agent 会不会规划」多写任何东西,只要在它的提示里允许它这么做。 - 技能和子 Agent 是两回事。 我们的
web-research、report-writer是技能(给同一个 Agent 的写作/流程指南),不是能委派的人。主 Agent 的系统提示里明确写死:这两个只能当指南照着做,禁止当 subagent 去 task——技能是「自己的方法论」,子 Agent 是「另一个人」,这一条分清楚,架构就不乱。
第一个知识点:几十行代码把骨架搭起来
它是什么 / 解决什么
不管 Agent 内部多复杂,对外暴露的入口就一个:createDeepAgent({ ... })。下面的骨架几乎就是这个项目的全部「胶水代码」(真正长的部分只有各 Agent 的系统提示,那属于内容,不属于基础设施):
import path from "node:path";
import { ChatOpenAI } from "@langchain/openai";
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
import { createDeepAgent, FilesystemBackend } from "deepagents";
const projectDir = /* 你的项目根目录 */;
export function createResearchAgent() {
const model = new ChatOpenAI({
model: "gpt-4o",
temperature: 0,
apiKey: process.env.OPENAI_API_KEY,
});
return createDeepAgent({
model,
// 主 Agent 的分工设计:全写在提示里
systemPrompt: /* 主 Agent 的系统提示:职责、标准流程、委派规则 */,
// 文件系统作为 Agent 的工作记忆(读/写/搜)
backend: new FilesystemBackend({ rootDir: projectDir, virtualMode: true }),
// 长期记忆:启动时加载这份规范
memory: [path.join(projectDir, "AGENTS.md")],
// 技能:扫描该目录,按需注入 SKILL.md
skills: [path.join(projectDir, "skills")],
// 子 Agent 团队
subagents: [researcher, editor, analyst],
});
}
FilesystemBackend 这一行很关键:它让 Agent 拥有读写文件、ls/glob/grep 的能力,子 Agent 之间的信息就靠「把文件写到一个约定的目录,别人去读」来传递——而不是靠把超长对话历史塞给下一个 Agent。文件即工作记忆,Agent 之间靠落盘文件通信,这是它设计里的核心思想。
要点
createDeepAgent是工厂,返回编译好的 LangGraph 图,可 stream、可挂 checkpointer;backend注入文件系统工具,子 Agent 之间通过文件传信息,不依赖对话历史;memory、skills、subagents都是声明式配置,机制框架已内置;- 真正的系统设计工作在
systemPrompt——分工思路写在提示里,而非写在代码里。
第二个知识点:Todo 清单——让 Agent「列计划、跟进度」
它是什么 / 解决什么
深度调研是多步活:规划 → 分头调研 → 分析 → 起草 → 审阅 → 定稿。没有清单,长 Agent 容易跑飞或忘步骤。todo 清单机制在 createDeepAgent 里是内置的:Agent 可以调 write_todos 列出步骤、逐步执行、每完成一条就更新状态,我们在 CLI 里能实时看到它更新到第几条。
你不需要注册任何东西。只需要在系统提示里告诉主 Agent「按规矩来」,例如:
- 收到任务后,先用
write_todos把任务拆成中文步骤; - 每一步执行完,把对应 todo 状态改成完成;
- 不要跳过计划直接开干。
这样主 Agent 每轮决策前都会先「看一眼清单、决定下一步」,长任务就有了节奏感。而我们的主提示里甚至规定了每一步该写什么,例如「撰写调研计划」「委派调研员调研 LangGraph」这种粒度——清单既是进度条,也是给模型当「下一步提示词」用的。
要点
- todo 是内置机制 + 工具,主 Agent 按你提示里的规矩使用;
- 步骤粒度写细一点,能帮模型自己找到「现在该干哪步」;
- 清单写进文件系统,整个流程可追溯、可断点续跑;
- 子 Agent 同样是 todo 中间件的受益者(见下节)。
第三个知识点:子 Agent——把活委派给「各有能力」的人
它是什么 / 解决什么
主 Agent 不可能擅长一切。联网搜索、跑代码算数、当编辑挑错,这些都是不同工种。createDeepAgent 让子 Agent 是一等公民:你在 subagents 里声明几个「人」,每个可以自带工具、自带中间件、自带系统提示;主 Agent 通过内置的 task 工具把任务委派出去,每个子 Agent 有独立上下文窗口,不会互相污染。
调研员的样子大概是:
const researcher = {
name: "researcher",
description:
"通过联网搜索调研单一子主题。每次只分配一个子主题;多个独立子主题可并行多个调研员。",
systemPrompt: `
你是一名专业调研员,负责调研**一个**分配给你的子主题。
可选:先 write_todos 列出至多 3 条中文步骤,再按步骤执行。
最多调用 3 次联网搜索(硬性上限)。
把整理结果写入任务指定路径的调研文件,**只写一次**,写完整理即结束,不要再搜索或更新 todo。
`,
tools: [webSearch], // 它比别的子 Agent 多一把「联网搜索」的刀
};
分析师则靠给子 Agent 挂中间件获得另一种超能力——代码执行:
import { createCodeInterpreterMiddleware } from "@langchain/quickjs";
const analyst = {
name: "analyst",
description: "使用 eval 代码环境进行数值计算与结构化数据分析。",
systemPrompt: `
你是一名数据分析师。所有计算必须通过 eval 环境完成,禁止猜测数字。
读取数据 → 在环境里写 JS 算出结果 → 把计算逻辑与结论存成分析文件。
`,
middleware: [createCodeInterpreterMiddleware()], // 这给子 Agent 装了代码执行器
};
编辑更「纯粹」——不带任何工具,系统提示只要求它读草稿、返回意见、不亲手改:
const editor = {
name: "editor",
description: "审阅报告草稿的准确性、结构与完整性,在草稿写好后使用。",
systemPrompt: `
你是资深情报编辑,负责**审阅**草稿——不要亲自改写。
检查:是否回答了原始问题?结构是否清晰?是否引用来源?有无无依据断言?
返回简洁的审阅意见与可操作修改建议,不写入任何文件。
`,
};
三个人,三种配法,一览:
| 子 Agent | 关键能力 | 如何获得该能力 | 职责 |
|---|---|---|---|
| researcher 调研员 | 联网搜索 | tools: [webSearch] | 单子主题搜索 + 整理落盘 |
| analyst 分析师 | eval 代码执行 | middleware: [createCodeInterpreterMiddleware()] | 数值计算、数据分析 |
| editor 编辑 | 无工具(只读) | 只写系统提示 | 审稿、给修改建议 |
要点
- 子 Agent =
subagents数组里的一个对象,各配各的工具/中间件/提示; - 委派走内置
task工具,主 Agent 提示里约定好「最多并行几个、最多开几个」; - 子 Agent 独立上下文,靠文件落盘交接产物;
- 想给子 Agent 新能力 = 给它加工具或加中间件,不需要改编排代码。
第四个知识点:子 Agent 的多步活——它自己也会列 todo
它是什么 / 解决什么
很多人以为「todo 清单」只管主 Agent。其实 todo 中间件挂在每个 Agent 节点上,子 Agent 一旦被委派去干一件也要分几步的事,它同样会「先列步骤、逐步执行、更新状态」。
调研员就是这样:它被派去调研「某个框架」时,可能觉得要先搜官方文档、再搜社区评价、最后整理写入文件——那它就自己 write_todos 这三步,一步步走完再收尾。我们在调研员的系统提示里专门写了一节「write_todos 使用规则」,告诉它:
- 至多 3 条、用中文;
- 只拆它自己这一步的活,不要重复主 Agent 已做过的总体规划;
- 最后一条必须是「写入 findings 文件」,写完把所有 todo 标为完成就结束。
这背后的设计意图是:给子 Agent 的提示里必须设「刹车」——搜几次是上限、写几次文件是上限、什么时候必须停。多 Agent 系统最常见的失控,就是子 Agent 拿到任务后无限循环地「再搜一下、再补一点」。把上限写进它的提示,配合 todo 的「完成即停」,运行才收敛。
要点
- todo 机制对主 Agent、子 Agent 一视同仁,因为它挂在 Agent 节点上;
- 想让子 Agent 也会拆步骤,只需在它的提示里「允许它用 write_todos」;
- 更要紧的是写清刹车条件:调用上限、文件写入次数、结束标志;
- 子 Agent 列 todo 是「战术拆解」,主 Agent 列 todo 是「战略规划」,职责别混。
第五个知识点:技能——放一个目录进去就能「按需加载方法论」
它是什么 / 解决什么
「会联网调研」「会写报告」这种是可复用的方法论,不该写死在系统提示里(那样换任务就得改代码)。DeepAgents 的技能机制是:你准备一个技能目录,每个技能一个子目录 + 一份带 frontmatter 的说明,框架会在 Agent 运行到相关场景时按需把技能内容注入。
skills 指向目录即可,机制全内置。一份技能的说明长这样:
---
name: report-writer
description: 将调研结果整理为结构清晰、专业的中文情报报告
---
# 报告撰写技能
把调研 findings 综合为最终交付物时使用。
## 报告结构
1. 标题 2. 执行摘要(3-5 条) 3. 背景 4. 核心发现
5. 分析 6. 结论 7. 参考资料(编号列表 + 链接)
## 写作规范
- 全文中文、第三人称专业表述
- 关键论断附带来源引用
- 每节内容充实,避免一句话带过
我们的两个技能 web-research(怎么规划子主题、怎么并行委派调研员)和 report-writer(报告结构 + 写作规范),就是主 Agent 的「操作手册」:干活前它被注入这套指南照着做。改报告风格 = 改这份文件,不用动代码。
再强调一次容易混的点——技能不是子 Agent:
技能是「给同一个 Agent 加载的说明文档」,子 Agent 是「委派给另一个上下文的人」。我们特意在提示里禁止把技能名当成 subagent 去调,防止架构退化成一团乱麻。
要点
- 技能 = 目录 + 一份说明,放进去即被框架管理,按需注入;
- 一个技能目录可以放任意多个技能,命名/描述写清楚便于框架触发;
- 技能承载「方法论文档」,改风格改流程都改文件不改代码;
- 严格区分「技能(自己的指南)」与「子 Agent(委派的人)」。
第六个知识点:长期记忆——AGENTS.md 一放,偏好就记住了
它是什么 / 解决什么
不想把「报告要用中文、要有执行摘要、必须列参考资料」这类稳定偏好每次写进提示词?DeepAgents 支持 AGENTS.md 规范:框架启动时会把这份文件作为记忆加载进上下文。
注册方式已经出现在骨架里:memory: [path.join(projectDir, "AGENTS.md")]。文件内容就是你与 Agent 的「契约」,随便写一点示意:
# 深度调研助手 · 用户偏好
## 报告偏好
- 所有报告、任务列表均使用中文
- 报告顶部包含「执行摘要」(3-5 条要点)
- 每份报告末尾必须有「参考资料」章节,列出所有引用 URL
## 调研标准
- 重要结论尽量用两个以上独立来源交叉验证
- 明确标注信息冲突,区分事实与推测
于是所有子 Agent 产出的中文、报告结构、调研纪律,都不用逐条写进提示——它们共享同一份记忆规范。AGENTS.md 也因此成了「调 Agent 行为」最便宜的地方。
要点
- AGENTS.md 是启动即加载的长期记忆,
memory数组可放多个; - 稳定的偏好与规范放这里,高频变化的流程放技能,各司其职;
- 改行为 = 改这份文件,记忆对所有 Agent(含子 Agent)生效。
第七个知识点:上下文压缩——聊长了它自己会「归档」
它是什么 / 解决什么
深度调研跑下来消息会非常长:十几轮模型调用、工具结果、子 Agent 的产物摘要……不处理迟早爆上下文。上下文压缩是 createDeepAgent 的内置功能:上下文超过预算时,它会自动把早期消息做摘要、裁剪工具结果,让对话「瘦身」后继续跑——就像人聊到一半把前面的笔记归档成几行要点。
你几乎不用配。唯一常动的是触发阈值,它由模型的 profile.maxInputTokens 控制,触发点按这个值的一定比例计算:
// 想更早触发压缩,就调小这个值(示意:让模型暴露一个较小的 maxInputTokens)
Object.defineProperty(chatModel, "profile", {
get: () => ({ maxInputTokens: 8_000 }),
});
也就是说:压缩是否触发、何时触发,取决于 maxInputTokens;把值调小 = 更早触发摘要压缩。我们把它当「灵敏度旋钮」用:长任务怕爆上下文就调小些,短任务想少打扰就保持默认。
要点
- 上下文自动压缩是内置的:超预算 → 摘要历史、裁剪工具结果;
- 触发阈值看
profile.maxInputTokens,按它的比例计算触发点; - 调小 = 更早压缩,把它当灵敏度旋钮即可;
- 这条你甚至可以完全不管——默认就能保证长任务不爆上下文。
没有写很多代码,但得到了什么
复盘一下,我们实际写的东西:
- 一份主 Agent 的系统提示(分工 + 流程 + 委派规则);
- 三个子 Agent 的定义(提示 + 各自工具/中间件);
- 一份 AGENTS.md 记忆、两个技能的说明文件;
- 一个封装了模型与文件后端的工厂函数、一个打印进度的 CLI。
我们没有写的东西:todo 清单与状态机、task 委派与子 Agent 生命周期、技能加载器、AGENTS.md 记忆注入、上下文摘要压缩、文件系统后端——全由 createDeepAgent 内置。
把「如果要自己搭」的开销摊开看,差距就很直观:
| 需求 | 自研工作量 | createDeepAgent |
|---|---|---|
| 多步规划 + 进度跟踪 | 写工具、维护状态、每轮拼历史 | 内置 todo,写句「先列清单」 |
| 子 Agent 委派 + 隔离上下文 | 自己编 graph、管上下文 | subagents 数组声明 |
| 子 Agent 各配能力 | 写工具/环境接入 | 加 tools 或挂中间件 |
| 方法论文档化 | 自己写动态注入逻辑 | 放技能目录即用 |
| 长期记忆 | 自己管理启动加载 | memory 指个文件 |
| 上下文压缩 | 自己写摘要策略 | 内置,调个阈值 |
需要提醒的是,「没写很多代码」不等于「不花心思」。省下来的是基础设施代码,真正决定这个 Agent 好不好用的,是设计:每个工种怎么分工、子 Agent 的刹车条件、技能与子 Agent 的边界、todo 步骤的粒度……这些全部以提示工程的形式沉淀了下来。DeepAgents 把「如何让 Agent 能干活」的地基打好了,于是我们可以把精力全部放在「让 Agent 干得聪明」上。
怎么选、怎么用:一张速查图 + 决策表
把整个运行时串起来看,主 Agent 每轮大约都在这几个状态间流转:
落到「我该把 XX 放哪」的决策,用这张表就够了:
| 想解决的事 | 该用的机制 | 例子 |
|---|---|---|
| Agent 需要稳定偏好/纪律 | 长期记忆 AGENTS.md | 中文输出、引用规范 |
| Agent 需要一套可复用方法论 | 技能 | 报告怎么写、调研怎么规划 |
| 有一类需要独立上下文的脏活累活 | 子 Agent | 联网搜索、跑代码、审稿 |
| 需要给某子 Agent 一种专属能力 | 给它加工具 / 挂中间件 | web_search、eval 代码执行 |
| 长任务怕上下文爆 | 内置压缩,调 maxInputTokens | 把阈值调小早压缩 |
收尾
我们从「要做一个多 Agent 深度调研助手」到「跑通」,最深的体会是:当框架把 todo、记忆、技能、子 Agent、上下文压缩这些横切能力全部开箱内置后,多 Agent 的门槛就落回到了设计能力,而不是工程能力。你写的 prompt 决定 Agent 多聪明,框架负责让这个「聪明」能持续跑下去、不失控、不爆上下文。
DeepAgents 并不是唯一的选择——但「编排与上下文管理不该成为你的日常」这个思路,值得在任何 Agent 项目里坚持。下次再想「要不要自己手搓一个多 Agent 编排器」的时候,先想想:这件事,框架是不是已经替我做好了?
读者留言
COMMENTS · 0发表留言