菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > AI创作与模型 > 多Agent深度调研工程实战:DeepAgents可控工作流
模型技术

多Agent深度调研工程实战:DeepAgents可控工作流

2026-06-01
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

说实话,搭建一个支持联网搜索的 Agent 本身门槛不高。给大模型挂上一个 web_search 工具,

说实话,搭建一个支持联网搜索的 Agent 本身门槛不高。给大模型挂上一个 web_search 工具,让它检索几条网页,再把返回的摘要拼凑成回答——这一套操作下来,确实能跑出一个像模像样的 Demo。

DeepAgents 多 Agent 深度调研助手工程实战:从 createDeepAgent 到可控调研工作流

可一旦任务换成正经的“深度调研”,所有短板都会暴露。模型会反复搜索同一个关键词,搜到的资料没人整理归档,遇到数据计算全靠瞎猜,写出来的报告引用七零八落。更要命的是,随着上下文越堆越长,到最后连模型自己都搞不清哪一步出了岔子。更棘手的是,单个 Agent 要身兼数职——规划、搜索、算数、写报告、审稿全包——结果输出活像一篇“搜索结果改写版”,根本不可能当成可直接交付的调研简报。

先把本文的核心结论亮出来:

createDeepAgent 的价值,远不止帮你少写几行 middleware 配置。它把深度调研 Agent 所需的规划能力、文件工作区、Skill、长期记忆、子 Agent、代码执行和上下文压缩,全都整合成一个可运行的工程框架。真正的关键不在于 API 有多短,而在于你有没有把角色边界、工具权限、数据流和验收机制设计清楚。

为什么深度调研不能只靠一个 Agent

先看一个典型的任务需求。

表面上这只是个搜索问答,实际至少包含 6 类动作:

  1. 明确问题本身和输出口径。
  2. 从官方来源、媒体汇总、专业数据库这几个渠道搜集资料。
  3. 把资料归档到可随时复查的文件里。
  4. 提取关键数字并进行计算。
  5. 起草报告,并列出所有来源。
  6. 审阅报告,修正遗漏、结构问题和引用错误。

如果全交给同一个 Agent,它会遇到几个内生麻烦。

第一,搜索和写作的目标天然冲突。搜资料时需要发散,把网撒开;写报告时却要收敛,形成结构化结论。在同一个上下文里同时干两件事,模型很容易一边搜一边写,资料还没沉淀够,结论就仓促下了。

第二,计算这件事不能交给自然语言推理。GDP 加总、算占比、排增速,都应该由可复现的代码执行。靠模型“心算”,小数、百分比、排名这些细节随时出错,结果不可控。

第三,报告质量需要一个独立的审稿角色。写作者总会下意识维护自己的叙事逻辑,但审稿需要从外部视角审视:“到底有没有回答用户问题?来源够不够充分?有没有无依据断言?”这两个角色最好分开。

第四,长任务需要一个过程状态。没有 todo、文件归档和流式事件,你只能看到一个答案,根本不知道 Agent 搜过什么、写了什么、卡在了哪一步。

因此,一个正经的深度调研助手,默认架构不应该是“全能 Agent + 搜索工具”的短平快组合,而应该是“主 Agent 做编排 + 专业子 Agent 负责执行 + 文件系统传递状态 + Skill 约束流程 + 可观测事件做跟踪”。

createDeepAgent 在系统里的位置

如果你用过 LangChain 和 LangGraph,那这三者之间的关系可以这么理解:

  • LangChain 提供模型、消息、工具、middleware 这些基础能力。
  • LangGraph 提供状态图、循环、持久化和流式执行能力。
  • DeepAgents 则在这一层之上,专门为长任务提供了一套 Agent 运行时框架,把常见运行设施都预装好了。

createDeepAgent 是 DeepAgents 里更高级别的入口。比起你手动组合 createAgentcreateFilesystemMiddlewarecreateSkillsMiddlewarecreateSubAgentMiddlewarecreateMemoryMiddlewarecreateSummarizationMiddleware,它直接编排好了一批默认中间件和提示词。你需要关心的,主要是配置模型、后端、长期记忆、Skill 目录、子 Agent 和自定义系统提示词。

当前 Demo 的核心创建函数是 createIntelligenceDeskAgent(),职责非常清晰:把一个“深度调研助手”的运行环境组装出来。

export function createIntelligenceDeskAgent() {
  const apiKey = process.env.OPENAI_API_KEY?.trim()
  if (!apiKey) {
    throw new Error("未设置 OPENAI_API_KEY 环境变量")
  }  const model =
    process.env.MODEL_NAME?.trim() ||
    process.env.OPENAI_MODEL?.trim() ||
    "gpt-4o"
  const baseURL = process.env.OPENAI_BASE_URL?.trim() || undefined  const backend = new FilesystemBackend({
    rootDir: projectDir,
    virtualMode: true,
  })  const chatModel = new ChatOpenAI({
    model,
    temperature: 0,
    apiKey,
    ...(baseURL
      ? { configuration: { baseURL } }
      : {}),
  })  return createDeepAgent({
    model: chatModel,
    systemPrompt: orchestratorPrompt,
    backend,
    memory: [path.join(projectDir, "AGENTS.md")],
    skills: ["/skills/"],
    subagents: [researcherSubAgent, editorSubAgent, analystSubAgent],
  })
}

这段代码在整个链路里扮演“装配层”的角色。它没有编写具体的搜索逻辑或报告内容,而是在决定 Agent 运行时有哪些能力:

  • ChatOpenAI 负责模型调用,并支持通过 OPENAI_BASE_URL 接入兼容 OpenAI 协议的服务。
  • FilesystemBackend 负责文件系统后端,virtualMode: true 让 Agent 看到一套虚拟路径。
  • memory 按源码配置加载 AGENTS.md 作为长期记忆,注入报告偏好和工作区约定。
  • skills 指向 /skills/,使 Agent 能按需读取 web-researchreport-writer 的流程指南。
  • subagents 注册了 researcheranalysteditor 三个专业子 Agent。

如果换成手写 middleware,当然也能实现同样的能力,但你需要亲自处理默认提示词、工具组合和子 Agent 接入。createDeepAgent 的工程价值就在这里——它把长任务 Agent 的常见结构做成了默认框架,让你能把精力聚焦在“角色和流程设计”上。

整体架构:主 Agent 管流程,子 Agent 管专业动作

这个 Demo 的设计理念不是让每个 Agent 都全能,而是把分工做得清清楚楚。

主 Agent 是编排中心。它负责理解用户问题、写 todo、保存原始问题、制定调研计划、委派子 Agent、读取结果文件、起草报告、调用编辑审阅、修订并保存最终报告。主 Agent 不应该亲自包揽搜索和计算,否则多 Agent 架构就退化成“一个 Agent 自言自语”。

researcher 是调研员。它每次只聚焦一个子主题,最多搜索有限次数,然后把结果写入 findings_*.md。它的价值不在于“会搜索”,而在于把搜索过程约束成可归档的事实收集。

analyst 是数据分析师,只有涉及数字、排名、增长率、表格处理时才会被启用。它必须通过 QuickJS 的 eval 工具完成计算,并将计算逻辑写入 analysis_*.md。这解决的是“结论可复现”的问题。

editor 是编辑。它不直接动手改写报告,只负责检查准确性、结构、引用和语言,然后返回修改建议。这个设计很关键:审阅和修订彻底分离,主 Agent 仍然负责维护最终文档的一致性。

Skill 则不是子 Agent。web-researchreport-writer 本质上是流程指南,它们告诉主 Agent 做联网调研的正确姿势以及组织报告的方法,但不能被当作 subagent_type 来调用。Demo 的系统提示词专门强调了这一点,因为模型很容易把“技能名称”误认为是“子 Agent 名称”。

数据流:Agent 之间靠文件协作,而不是靠记忆猜

这个项目最值得借鉴的一个点,是它没有让子 Agent 的输出只停留在聊天历史里,而是用工作区文件来承接中间状态。

为什么要用文件,而不是直接把子 Agent 的结果塞回主上下文?

第一,文件是可复查的。你可以打开 workspace/sources/research_plan.md 看计划是否合理,打开 findings_*.md 看资料是否支撑结论,打开 analysis_*.md 看计算是否可复现。

第二,文件能有效减少上下文污染。每个子 Agent 完成自己的文件后,主 Agent 只在需要时去读取,没必要把所有搜索过程永久塞在消息历史里。

第三,文件让失败变得可恢复。如果报告写到一半因为 recursionLimit 停了,已有的计划、发现和分析结果仍然好好地躺在工作区里,下一次可以接着往下查。

本地工作区里已经生成了一次 GDP 调研的产物:

  • workspace/sources/research_plan.md:调研计划。
  • workspace/sources/findings_nbs_official.md:官方数据源调研。
  • workspace/sources/findings_economic_databases.md:专业经济数据库调研。
  • workspace/sources/analysis_results.md:GDP 前 6 省份的计算结果。
  • workspace/reports/draft_gdp_2023.md:草稿。
  • workspace/reports/report_gdp_2023_20240527.md:最终报告。

这些文件足以说明,Demo 不只是控制台输出,而是形成了一个可被审计的调研工作区。

主 Agent:不要把所有规则塞给模型,而是定义清楚流程边界

主 Agent 的系统提示词,是整个架构的“流程合同”。它规定了语言、职责、标准流程、委派规则、文件约定,以及何时给用户反馈。

下面是经过压缩后的关键结构:

const orchestratorPrompt = dedent`
  你是「深度调研助手」的主 Agent,负责协调调研、分析与编辑。  ## 标准流程
  1. 规划:用 write_todos 拆解任务,并保存用户问题
  2. 调研:按 web-research 技能写 research_plan.md,委派 researcher
  3. 分析:若涉及数字对比或数据表,委派 analyst
  4. 起草:由你亲自按 report-writer 技能写 draft_*.md
  5. 审阅:委派 editor 审稿,根据反馈修订一次
  6. 定稿:保存最终报告到 report_*_[日期].md  ## task 工具
  仅 researcher、analyst、editor、general-purpose 是合法 subagent_type。
  web-research、report-writer 是技能,不是子 Agent。  ## 委派规则
  每份报告最多 3 个调研员。
  每份报告只调用编辑一次。
  调研完成后进入起草、审阅、定稿,不要额外开调研轮次。
`

这里的重点不在于提示词写得有多长,而在于流程上设置了明确的“停止条件”。比如每份报告最多只能有 3 个调研员、编辑只调用一次、调研完成后不许再额外开调研轮次。这些约束能有效减少 Agent 在搜索阶段空转。

dedent 的作用是让你在保持代码缩进的同时,去掉模板字符串里多余的前导空格。它不是核心能力,但对于大型 Prompt 来说非常实用:至于可读性,实际传给模型的文本也能保持干净。

如果换一种写法,把这些规则分散到用户 Prompt 或 README 里,模型每次不一定能稳定遵守。系统提示词里集中定义主流程,更适合需要重复运行的 Agent 应用。

researcher:搜索工具要有硬上限和写入约束

联网搜索工具本身很简单,当前 Demo 用 Bocha API 封装了一个 web_search

export const webSearch = tool(
  async input => {
    const count = input.count ?? 10
    console.log("   搜索: ${input.query}${count} 条)")
    return bochaWebSearch(input.query, count)
  },
  {
    name: "web_search",
    description:
      "使用 Bocha 联网搜索 API 检索互联网网页。返回标题、URL、摘要、网站名称、图标和发布时间。",
    schema: z.object({
      query: z.string().min(1).describe("搜索关键词,优先使用中文"),
      count: z.number().int().min(1).max(20).optional(),
    }),
  }
)

这里的 zod schema 非常关键。query 必须非空,count 限制在 1 到 20。这个约束不是为了类型好看,而是为了让模型的工具调用空间变得可控。如果没有 schema,模型可能会传一个空字符串,或者传一个不符合 API 规范的对象。

真正决定搜索质量的,其实是 researcherSubAgent 的 Prompt:

const researcherSubAgent = {
  name: "researcher",
  description:
    "通过联网搜索调研单一子主题。每次只分配一个子主题;多个独立子主题可并行启动多个调研员。",
  systemPrompt: dedent`
    1. 可选:用 write_todos 列出最多 3 条中文执行步骤
    2. 最多调用 3 次 web_search
    3. 将搜索结果整理为结构化摘要,包含关键事实与来源 URL
    4. 调用 write_file 一次,保存到 /workspace/sources/findings_*.md
    5. 用一句话确认已完成,然后立即停止
  `,
  tools: [webSearch],
}

注意这里的两个上限:最多 3 条 todo,最多 3 次搜索。原文在 Skill 部分还提到过最多 10 次搜索,但当前源码中的 researcher Prompt 使用的是更严格的 3 次——写技术博客时必须以源码为准。

为什么要限制搜索次数?因为联网搜索是整个链条里最容易空转的工具。模型总觉得“还可以再搜一个关键词”,然后就会不断扩展主题。深度调研不是搜得越多越好,而是每一轮搜索都得服务于一个明确的子主题,并且产出可用的文件。

工程上,researcher 的输出至少应包含:

  • 子主题范围
  • 关键事实
  • 来源 URL
  • 信息冲突或不确定点
  • 与主问题的关系

如果搜索 API 返回的是摘要而不是原文全文,报告里就要明确指出信息的局限性。搜索结果只是线索,不是最终的事实。

analyst:让模型写代码,让解释器负责计算

大模型擅长解释和组织语言,但并不擅长稳定的精确计算。GDP 加总和占比这类任务,必须交给可执行代码。

Demo 里的 analyst 使用了 @langchain/quickjs

const analystSubAgent = {
  name: "analyst",
  description:
    "使用 eval REPL 进行数值计算与结构化数据分析。适用于计算、排名、同比对比或 JSON/CSV 分析。",
  systemPrompt: dedent`
    你是一名数据分析师,所有计算必须通过 eval REPL 完成,禁止猜测数字。    1. 从 /workspace/sources/ 读取数据文件
    2. 在 REPL 中编写并运行 Ja vaScript
    3. 将分析结果保存到 /workspace/sources/analysis_*.md
  `,
  middleware: [createCodeInterpreterMiddleware()],
}

这段设计背后有一个非常明确的工程判断:计算能力不应该混在自然语言推理里,而应该变成工具调用。

QuickJS 的优势是轻量、嵌入方便,适合用来运行 Ja vaScript 片段做局部计算。对于这个 Demo 来说,它足够处理 GDP 加总、占比计算、排序等任务。如果换成更复杂的数据分析——比如读取大型 CSV、做统计建模、画图——那可能就需要 Python 沙箱或专门的数据处理服务了。

本地 analysis_results.md 中已经有可复查的结果:

## 基础数据
- 全国 GDP 总量:1260583 亿元
- 广东:135673.2 亿元,增速 4.8%
- 江苏:128204.7 亿元,增速 5.8%## 计算结果
### 六省 GDP 总和
559978.1 亿元### 各省占全国 GDP 比重
- 广东:10.76%
- 江苏:10.17%

这里仍然有一个可以改进的点:报告给出了计算结果,但理想的分析文件应该同时保留实际运行的 Ja vaScript 代码。这样,审阅者不仅能看到结果,还能复现公式。在技术博客里最好点出这一点:eval 工具解决了可执行性的问题,但“保存计算代码”仍然要靠 Prompt 或额外的规范来约束。

editor:审稿不改稿,避免责任混乱

很多多 Agent 设计会让编辑子 Agent 直接去改写报告,看起来省事,实际上容易引入两个问题:一是编辑会打乱主报告的叙事结构,二是主 Agent 没办法很好地解释最终修改来自哪里。

Demo 的设计要稳妥得多:editor 只审阅,不写文件。

const editorSubAgent = {
  name: "editor",
  description:
    "审阅报告草稿的准确性、结构与完整性。在 /workspace/reports/draft_*.md 写好后使用。",
  systemPrompt: dedent`
    你是一名资深情报编辑,负责审阅报告草稿,不要亲自改写报告。    审阅要点:
    - 是否直接回答原始问题?
    - 章节结构是否清晰?
    - 是否引用来源并列出参考资料?
    - 是否有遗漏、无依据断言或缺失视角?
    - 语言是否为中文,表述是否专业?    返回具体、可操作的修改建议。
  `,
}

这个模式适用于绝大多数文档生成场景:生成者负责写,审阅者负责指出问题,最后的修订仍然由主 Agent 统一执行。它牺牲了一点点自动化程度,但换来的是更清晰的责任边界。

如果在生产系统里继续演进,可以把 editor 的输出结构化,比如:

  • severity:critical、major、minor
  • section:对应报告的哪个章节
  • issue:对问题的描述
  • suggestion:具体的修改建议

当前 Demo 没有做这个结构化输出,用来教学足够了,但如果要做成稳定的产品,编辑反馈最好变成 schema,这样主 Agent 才能逐项修订。

Skill:流程知识不等于子 Agent

项目里有两个 Skill:

  • skills/web-research/SKILL.md
  • skills/report-writer/SKILL.md

web-research 规定如何进行联网调研:先保存问题,再写 research_plan.md,再委派 researcher,最后综合 findings。

report-writer 规定怎么写报告:标题、执行摘要、背景、核心发现、分析、结论、参考资料,以及文件命名规范。

Skill 的作用是把流程知识从主 Prompt 中拆出来,做到“按需加载”。模型启动时先看到 Skill 名称和描述,真正需要的时候再读取完整的 SKILL.md。这比将所有写作规范和调研流程都塞进主系统提示词要可维护得多。

这里最常见的错误,就是把 Skill 当成子 Agent。当前系统提示词里写得很清楚:

这句话非常实用。Agent 在运行的时候,经常会把所有看起来像能力名称的东西都当作可调用对象。如果不说清楚,模型可能会去调用一个不存在的 report-writer 子 Agent,流程就必然失败。

工程实践上,更推荐把 Skill 当作“可复用工作手册”来理解,把子 Agent 当作“有独立上下文和工具的执行角色”。两者可以协作,但不能混淆。

Todo:复杂任务需要显式进度状态

createDeepAgent 内置了 todo 规划能力,底层来自 LangChain 的 todoListMiddleware。项目里还有一个独立的示例 src/todo-middleware-test.mjs,用普通的 createAgent 来验证 todo 能力:

const agent = createAgent({
  model,
  tools: [],
  systemPrompt:
    "你是生活规划助手。收到需要多步完成的请求时,先用 write_todos 列出中文执行步骤,然后简要说明你的计划。",
  middleware: [todoListMiddleware()],
})const result = await agent.invoke({
  messages: [new HumanMessage(query)],
})console.log("todos:", JSON.stringify(result.todos, null, 2))

Todo 的价值不是“让输出看起来更项目管理化”,而是给长任务一个可以持续更新的状态结构。对于深度调研来说,主 Agent 的 todo 可以覆盖规划、调研、分析、起草、审阅、定稿这几个阶段;而 researcher 子 Agent 的 todo 则只关注本子主题的搜索和写入。

有两个实践建议值得注意。

第一,todo 要分层。主 Agent 的 todo 不应该被子 Agent 重复;子 Agent 只管理自己的小任务。

第二,todo 要有停止条件。比如 researcher 写完 findings 后就必须停止,避免继续搜索;editor 审阅完之后只返回反馈,不进入改写阶段。

没有 todo 的 Agent,容易走一步想一步。有 todo 但没有停止条件的 Agent,又容易把 todo 当作不断拓展新任务的理由。

CLI:可观测性不是锦上添花

src/cli.mjs 不只是简单地调用 Agent,它做了一个非常重要的工作:把流式更新、子图执行、工具调用和输出文件都列了出来。

for await (const [namespace, chunk] of await agent.stream(
  { messages: [new HumanMessage(query)] },
  { streamMode: "updates", subgraphs: true, recursionLimit }
)) {
  for (const [node, data] of Object.entries(chunk)) {
    if (node === "model_request") {
      trackFileCalls(data, pending)
      trackEvalCalls(data, pendingEval)
      console.log(stepLabel(namespace, node))
    } else if (node === "tools") {
      logToolResults(data, pending, pendingEval)
    } else if (node === "todoListMiddleware.after_model") {
      console.log(stepLabel(namespace, node))
    }
  }
}

这段代码的作用是让你能观察到运行过程:

  • streamMode: "updates" 让你看到每一轮的状态更新。
  • subgraphs: true 让子 Agent 的执行也能出现在流里。
  • recursionLimit 控制最大循环步数,避免无限调用工具。
  • trackFileCalls 记录读写文件工具的调用情况。
  • trackEvalCalls 记录 QuickJS 代码执行情况。
  • logToolResults 打印工具结果的预览。

如果没有这层可观测性,深度调研 Agent 一旦出错就很难排查。你不知道它有没有写计划、有没有调用 researcher、有没有执行 eval、写了哪些文件、是不是卡在了递归限制上。

这也是为什么 LangSmith 这类链路追踪工具非常有价值。控制台日志在本地 Demo 里够用,但生产环境需要更完整的 trace、工具调用过滤、失败原因、耗时和 token 统计。

上下文压缩:依赖模型 profile,也要理解默认值

长任务一定会遇到上下文膨胀的问题。DeepAgents 内置了 summarization 逻辑,会根据模型上下文信息来决定什么时候压缩历史。当前 Demo 里有 src/max-input-tokens-test.mjs,用于说明如何覆盖模型的 profile:

const model = new ChatOpenAI({
  model: process.env.MODEL_NAME,
  apiKey: process.env.OPENAI_API_KEY,
  temperature: 0,
  configuration: {
    baseURL: process.env.OPENAI_BASE_URL,
  },
})console.log(model.profile.maxInputTokens)Object.defineProperty(model, "profile", {
  get: () => ({ maxInputTokens: 1_024 }),
})console.log(model.profile.maxInputTokens)

为什么要改 profile.maxInputTokens?因为有些兼容 OpenAI 协议的模型服务,并不一定能提供准确的模型上下文 profile。DeepAgents 的默认摘要策略会参考模型上下文窗口;如果 profile 缺失,fraction 类型的阈值就可能无法按预期工作。

本地类型声明显示,DeepAgents 的摘要默认计算逻辑会根据模型 profile 来选择基于比例的设置;如果没有 maxInputTokens,就会退回到固定 token 或消息数量策略。LangChain 的 summarization middleware 内部也会通过 model.profile.maxInputTokens 或模型名来查询上下文大小。

这里需要注意一个边界:上下文压缩不是长期记忆,更不是事实库。它只是把旧的对话变成摘要,帮助后续继续执行。需要精确引用的数据、来源、计算代码,都应该写入文件,而不是只留在摘要里。

参数和配置:每个值都对应一个工程取舍

这个项目的参数不算多,但每一个都直接影响了系统行为。

配置位置工程含义
OPENAI_API_KEY.env模型服务认证。缺失时 createIntelligenceDeskAgent() 直接抛错。
OPENAI_BASE_URL.env接入兼容 OpenAI 协议的模型服务,例如 DashScope compatible mode。
MODEL_NAME / OPENAI_MODEL.env当前源码优先读取 MODEL_NAME,再读 OPENAI_MODEL,最后默认 gpt-4o
BOCHA_API_KEY.env联网搜索 API Key。缺失时 web_search 返回可读错误,不直接抛异常。
RECURSION_LIMIT.env / cli.mjs控制 Agent 最大递归步数,默认 300。长任务可调高,但不应无限。
virtualModeFilesystemBackend将项目目录映射成虚拟根路径,减少真实路径暴露和路径穿透风险。
memorycreateDeepAgent源码配置加载 AGENTS.md 长期记忆,注入报告偏好和工作区约定。当前目录里实际文件名是 AGENT.md,运行前应统一文件名或修改配置。
skillscreateDeepAgent加载 Skill 目录,支持按需读取流程指南。
subagentscreateDeepAgent注册专业子 Agent,是多 Agent 分工的核心接口。
countweb_search schema控制搜索返回数量,默认 10,最大 20。
profile.maxInputTokens模型 profile影响上下文压缩触发阈值。兼容模型缺失 profile 时需要显式补。

一个容易被忽略的问题是:当前 FilesystemBackend 没有配置 permissionsvirtualMode 能限制虚拟路径映射到 rootDir 内部,但它并不是业务层面的权限策略。生产场景下,如果只允许写 /workspace/reports/**/workspace/sources/**,那就应该显式配置 permissions,而不是单靠一条 Prompt 说“禁止写其他目录”。

方案对比:什么时候用 createDeepAgent,什么时候不用

可以把 Agent 方案分成三档。

方案适合场景优点代价
createAgent + tools单轮问答、简单工具调用简单、可控、启动快长任务能力要自己补
createAgent + middleware需要自定义状态、todo、guardrail、工具包装组合灵活,适合渐进增强要自己设计 middleware 栈
createDeepAgent深度调研、代码助手、报告生成、多步骤任务内置规划、文件系统、Skill、子 Agent、摘要需要理解默认行为和边界
原生 LangGraph强流程、审批、事务、复杂状态机控制力最强,可审计性最好开发成本最高

这篇文章里的深度调研助手,默认就适合 createDeepAgent。因为它天然就需要文件状态、Skill、子 Agent、todo 和上下文压缩这些能力。如果从 createAgent 开始搭,会花大量代码去搞运行时基建;如果直接用原生 LangGraph,又会在一开始就承担过重的图编排成本。

createDeepAgent 也不是万能的。如果你的任务是严格的业务流程——比如贷款审批、订单支付、医疗建议审核——那就不应该把关键路径完全交给 Agent 自主规划。更稳妥的做法是用 LangGraph 或业务工作流来控制状态,把 Agent 放在某些分析和生成节点里。

当前 demo 的真实效果与可改进点

本地工作区已经生成了一份 2023 年省级 GDP 前 6 名省份的调研简报,最终报告包含了 GDP 总量、同比增速、六省总和、占全国比重和增速排名。这说明整个链路已经跑通了:计划、调研、分析、起草、定稿,每一步都有文件产物。

不过,从工程质量的角度来看,还有几个地方可以继续加强。

第一,调研文件的来源深度不足。findings_nbs_official.md 的内容更像是在介绍国家统计局的数据平台,并没有直接摘出 GDP 前 6 省份的原始表格。正式的调研应该要求 researcher 必须产出与主问题直接相关的数据来源,而不是泛泛地介绍一下数据平台。

第二,专业数据库调研文件偏向百科化。findings_economic_databases.md 罗列了 CSMAR、Wind、CEIC 等数据库,但没有直接支撑本次 GDP 数值的提取。一个对报告真正有帮助的 findings,应该围绕主问题展开,而不是变成背景资料的堆砌。

第三,分析结果里缺少可执行的代码。analysis_results.md 有计算结果,但没有保留 Ja vaScript 计算片段。更好的 analyst 规范应该是“写入输入数据、计算代码、输出结果、解释说明”,这样才是真正意义上的可复现。

第四,最终报告的参考资料还不够完整。报告提到了国家统计局和各省的统计公报,但没有给出完整的 URL 列表。report-writer Skill 已经要求了参考资料章节,后续应该强化编辑的检查力度。

第五,长期记忆的文件名存在不一致。在 src/agent.mjs 中配置的是 memory: [path.join(projectDir, "AGENTS.md")],但当前项目目录里实际文件名是 AGENT.md。如果直接运行,长期记忆可能不会按预期加载。工程上应该统一为 AGENTS.md,或者把代码里的路径改成真实文件名。

这些问题并不会否定 Demo 本身的价值,反而说明了一个事实:真实的 Agent 工程不能停留在“跑通链路”这个层面。你需要用实际的产出物去反查 Prompt、Skill 和子 Agent 的约束是否足够强硬。

常见误区

误区一:以为多 Agent 就等于质量更高。
多 Agent 只是提供了角色隔离。如果 researcher 搜不到关键资料,analyst 没有可靠的输入,editor 没有结构化的审阅标准,那么多 Agent 只会制造出更多的中间文本。

误区二:把 Skill 当成工具或子 Agent。
Skill 是按需加载的流程说明,不是可执行的工具,也不是 subagent_type。执行动作仍然要靠主 Agent、子 Agent 和工具来完成。

误区三:让模型自己算数。
只要涉及排名、占比、同比、总和,就应该通过代码解释器或确定性工具来完成。自然语言的解释可以由模型来写,但数字结果应该由代码来计算。

误区四:只看最终报告,不看中间文件。
深度调研的质量取决于资料链路的完整性。research_plan.mdfindings_*.mdanalysis_*.md 这些文件,比最终的答案更能暴露问题所在。

误区五:把虚拟文件系统当成完整的安全边界。
virtualMode 非常实用,但生产环境仍然需要配置 permissions、执行沙箱、密钥隔离和审计日志。

误区六:上下文摘要等于长期记忆。
摘要只是当前会话的压缩,不保证细节无损;长期记忆是稳定的约定;事实数据应该写入文件或数据库。

误区七:搜索结果摘要就是事实。
搜索 API 返回的摘要只是线索。重要的结论要优先引用官方来源,至少用多个独立来源做交叉验证,并标注时间。

工程建议:把深度调研助手做成可验收系统

如果要把这个 Demo 继续演进成一个可以长期使用的调研助手,我会按下面的顺序来推进。

第一,先强化输出的验收标准。给最终报告定义固定验收项:是否回答了原始问题?是否有执行摘要?是否有参考资料 URL?是否列出了局限性?是否有计算过程?不能只看语言是否流畅。

第二,强化 researcher 的产物格式。要求每个 findings_*.md 至少包含“结论、证据、来源 URL、可信度、与主问题关系、信息缺口”。泛泛的背景资料不算完成。

第三,强化 analyst 的可复现性。analysis_*.md 必须包含输入数据表、实际 JS 代码、输出结果和解释。必要时,把输入数据保存成 JSON 或 CSV。

第四,引入权限配置。限制 Agent 只能读写 /workspace/sources/**/workspace/reports/**/skills/**/AGENTS.md,避免误写项目里的其他文件。

第五,结构化 editor 的反馈。让 editor 输出 JSON 或固定格式的 Markdown 表格,主 Agent 根据问题逐项修订,减少“泛泛建议”的情况。

第六,接入可观测平台。控制台日志做演示足够,但生产环境需要 trace:每次搜索的关键词、工具耗时、模型调用、子 Agent 返回、文件变更、摘要触发,所有这些都应该是可查的。

第七,明确人工介入的节点。对于高风险调研主题——比如政策、金融、医疗、法律——最终报告应该进入人工审核流程,而不是自动发布。

总结:createDeepAgent 是起点,不是终点

DeepAgents 的 createDeepAgent 让我们用非常少的装配代码,就搭出了一个具备规划、文件工作区、Skill、长期记忆、子 Agent、代码执行和上下文压缩能力的深度调研助手。这确实比从零组合 middleware 更快,也更适合长任务 Agent 的第一版落地。

但真正决定系统质量的,不是 createDeepAgent 这一行 API,而是你如何设计运行时边界:主 Agent 管流程,researcher 管资料,analyst 管计算,editor 管审阅,Skill 管流程知识,文件系统管状态传递,CLI 和 LangSmith 管可观测性。

这也是本文的核心结论:深度调研助手不是一个“会搜索的聊天机器人”,而是一套多角色协作的调研工作流。createDeepAgent 帮你搭好了基础的运行时,但工程上仍然要补上角色边界、证据链、权限、安全和验收标准。

如果只是做 Demo,你完全可以让人工智能搜完就直接回答;但如果要做可发布、可复查、可迭代的调研系统,那就必须让每一步都有产物、每个数字都能复现、每个结论都有来源、每个角色都有边界。DeepAgents 的价值,正是在这条从“能跑”到“可控”的路上,减少了大量重复的基础设施工作。

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多