/deep-research深度解析:Claude Code的杀手级Graph应用
一条斜杠命令,背后是四种Agent、五层Diamond、几十次并发调用——这是目前公开可见的最完整Graph工程落地
本文导航
- 为什么说/deep-research是杀手级应用
- 五阶段工作流全景
- 内部图拓扑拆解:四种Agent角色
- 状态管理:证据池、引用映射、研究笔记
- 并行策略:扇出宽度、早停与预算控制
- 复刻你自己的deep-research系统
- 小结
- 下节预告
- 互动区
为什么说/deep-research是杀手级应用
前面三节我们用Dynamic Workflows自己搭图,说实话,手搭的图多少有点"玩具感"。这一节讲一个真正经受过生产考验的图系统——Claude Code内置的/deep-research命令。
用过的人都知道它的体验:你给一个研究问题,它吭哧吭哧跑几分钟到十几分钟,最后交给你一份带完整引用来源的研究报告。但多数人没意识到,这条斜杠命令背后跑的是一个完整的多Agent图:搜索Agent、分析Agent、验证Agent、综合Agent,各有各的上下文、各有各的模型层级、各有各的终止条件。
为什么我说它是"杀手级应用"?三个理由:
- 它是Graph工程的全要素示范。我们在第33到40节讲过的拓扑模式——Diamond、Router、Verifier、Convergent Loop——它一个不落全用上了,而且是嵌套着用。
- 它解决了真实痛点。深度研究是"单Agent做不好"的典型:上下文塞不下几十个网页、单视角容易被单一信源带偏、没有验证就是幻觉复读机。这正是第6节讲的单Agent Loop五大缺陷的活体标本。
- 它是可拆解、可复刻的。它的每个设计模式都能被抽出来用在你自己的系统里,这一节最后一部分我就带大家复刻一个。
先给个直观的量级感受:一次典型的/deep-research执行,会发起20到60次子Agent调用,抓取并精读15到40个信源,全程在16并发的舰队边界内(第48节讲过的硬限制),最终产出一份几千字的带引用报告。这是一个真正意义上的"子Agent舰队作战"。
五阶段工作流全景
把/deep-research的执行过程拉直了看,是五个阶段:
逐个阶段说人话:
① Scope(范围界定):拿到研究问题后,先不急着搜,而是把问题拆解成3到6个子问题,并为每个子问题生成检索计划(关键词变体、期望信源类型、判定标准)。这一步是典型的"决策/裁决"活,判断力密度高,用Opus。规划错了,后面全是白搜——和第50节"验证点1必做"是同一个道理。
② Parallel Search(并行搜索):检索计划里的每个子问题扇出一个搜索Agent,并发执行web搜索。这是整个流程里调用次数最多的阶段,也是成本大头,所以搜索Agent用的是便宜模型(Haiku做检索式扫描、Sonnet做需要判断的相关性筛选)。
③ Fetch & Read(抓取精读):搜索命中的URL并不等于证据,必须抓取全文做精读提取。分析Agent把网页原文压缩成结构化的"证据条目"(claim + evidence + source),这一步是上下文压缩的关键——不压缩的话,几十个网页的原文会直接撑爆后续节点的上下文。
④ Adversarial Verify(对抗验证):这是全系统的灵魂。验证Agent拿着证据清单去挑刺:来源可信吗?证据支持结论吗?不同来源之间矛盾吗?不通过就带着缺口回到②补搜——这是一个Convergent Loop(第38节),有最大重试次数防止无限循环。
⑤ Synthesize(综合报告):证据充分后,综合Agent把所有证据条目编织成一份带引用的连贯报告。注意它不只是"拼接",还要做观点冲突的显式处理(“A来源认为X,B来源认为Y,证据权重更支持Y”)。
五个阶段对应五层判断力密度,模型分配正好是第50节那套框架的实例化:Opus管①④⑤,Sonnet管③和部分②,Haiku管纯检索扫描。
内部图拓扑拆解:四种Agent角色
把五阶段翻译成图拓扑,/deep-research的内核是一张多层嵌套的Diamond:
四种Agent角色的契约,我整理成一张表:
| 角色 | 职责 | 模型 | 输入 | 输出 | 扇出宽度 |
|---|---|---|---|---|---|
| 搜索Agent(Searcher) | 按检索计划搜网、筛相关性 | Haiku/Sonnet | 子问题 + 检索计划 | 候选URL列表 | 3~8 |
| 分析Agent(Analyst) | 抓全文、提取证据条目 | Sonnet | URL + 原始网页 | 结构化证据 | 5~15 |
| 验证Agent(Verifier) | 对抗审查证据与结论 | Opus | 全部证据条目 | verdict + 缺口清单 | 1 |
| 综合Agent(Synthesizer) | 织报告、显式处理冲突 | Opus | 全部通过验证的证据 | 带引用报告 | 1 |
几个拓扑设计上的门道,是我反复看它执行日志总结的:
- 验证层收敛为单节点是有意为之。扇出的搜索和分析天然多样,但裁决必须"一个人说了算"——多个Verifier投票会引入新的合并难题(第49节讲的Fan-in困境),而验证的判断力密度要求高,单点强模型比多点弱模型便宜且稳。
- 补搜回路边(V→S)是有条件边。它不是无脑循环,验证Agent输出的"缺口清单"会精确路由到具体子问题的搜索Agent——这是定向重试而不是整体重跑,和第31节失败路由的"定向修复"完全同构。
- 每层都有自己的汇聚节点(Collector),做的是"压缩+去重+结构化",不是简单收集。上下文在层与层之间被不断压缩,这是对抗Context Rot(第7节)的核心手段。
状态管理:证据池、引用映射、研究笔记
单Agent做研究最头疼的是状态:搜到的东西放哪?引用怎么跟结论挂钩?/deep-research的解法是把状态拆成三张"表",Agent之间不共享对话历史,只共享这三张表——这就是第19节"节点隔离"的教科书级实践:
| 状态表 | 内容 | 写入者 | 读取者 |
|---|---|---|---|
| 证据池(Evidence Pool) | claim / evidence / source / confidence | 分析Agent | 验证、综合Agent |
| 引用映射(Citation Map) | 结论ID → 证据ID列表 → URL | 综合Agent | 报告渲染 |
| 研究笔记(Research Log) | 每阶段的决策、缺口、重试记录 | 所有Agent | 验证Agent、人 |
用pydantic把这三张表的Schema钉死(Python侧做数据校验时的标准动作):
# schemas.py —— deep-research 状态表的 Schema 定义(pydantic 校验)frompydanticimportBaseModel,Field,HttpUrlclassEvidence(BaseModel):"""证据条目:分析Agent的产出单元"""claim:str=Field(description="一句话结论")evidence:str=Field(description="支撑原文摘录")source:HttpUrl=Field(description="来源URL,pydantic自动校验URL合法性")confidence:float=Field(ge=0,le=1,description="置信度 0~1")classCitationMap(BaseModel):"""引用映射:结论 → 证据链 → URL,保证报告可溯源"""conclusion_id:strevidence_ids:list[str]urls:list[HttpUrl]classResearchLog(BaseModel):"""研究笔记:阶段决策与缺口,供Verifier定向路由"""stage:str=Field(pattern="^(scope|search|read|verify|synth)$")gaps:list[str]=[]# 验证Agent发现的证据缺口retries:int=0# 该阶段已重试次数为什么状态要这么拆?两个字:溯源。报告里每句话都能顺着引用映射摸到证据池里的原文摘录,再摸到URL。用户质疑某条结论时,你不需要重跑整个系统,只需要打开那条证据看原文。这个设计比"把所有网页原文塞进上下文让模型自己引用"可靠一个数量级——后者的引用经常是幻觉。
并行策略:扇出宽度、早停与预算控制
/deep-research的效率有一半来自并行策略的设计,我总结成三条:
第一,扇出宽度分层设定。搜索层扇出38个(子问题数量决定),分析层扇出515个(命中URL数量决定),验证层和综合层永远是1。宽度不是拍脑袋:搜索层的瓶颈是信源多样性,够覆盖子问题就行;分析层的瓶颈是IO(抓网页),宽一点吞吐高。但所有层加起来不能突破第48节的舰队边界——并发16、总量1000,所以分析层实际执行时是分批的:
// 分析层的分批扇出:并发上限内滚动执行,批内并行、批间流水consturls=collector.pickCandidates(30);// 汇聚节点筛出的候选URLconstevidence=[];for(constbatchofchunk(urls,8)){// 每批8个,16并发留一半余量constreads=awaitparallel(batch.map((u)=>agent(`抓取并提取证据条目,输出JSON数组:${u}`,{model:"sonnet",output:"json"})),);evidence.push(...reads.filter(Boolean).flat());// 标配清洗if(verifyQuick(evidence))break;// 早停:证据已饱和就不再抓}第二,早停(early stopping)。证据池达到"饱和"就提前终止搜索和抓取。饱和的判定标准是边际收益递减:最近N个新增证据条目没有带来新的claim维度。没有早停的deep-research会把预算烧在重复证据上。
第三,预算控制三件套:阶段级timeout(搜索阶段不超过X分钟)、重试上限(补搜循环最多2轮,呼应第38节Convergent Loop的收敛设计)、成本熔断(累计花费超过阈值就带着现有证据进入综合阶段——降级交付而不是崩溃,第32节优雅降级的标准打法)。
这三条合起来回答了一个问题:为什么/deep-research快而不糙。快来自并行和早停,不糙来自验证回路和溯源状态。两者缺一不可——只并行不验证是幻觉生成器,只验证不并行是慢如老牛。
复刻你自己的deep-research系统
说了这么多别人的设计,怎么变成自己的?我把最小可运行版本浓缩成一张对照表和一段编排脚本。先看/deep-research的设计模式怎么映射到你自己的系统:
| /deep-research 的设计 | 你可以复刻的实现 |
|---|---|
| Scope规划 | Opus拆解子问题,输出JSON检索计划 |
| 并行搜索 | parallel扇出搜索Agent,接你的搜索API |
| 抓取精读 | pipeline(urls, 抓取, 提取),Sonnet压缩成证据条目 |
| 对抗验证 | 独立Verifier + 条件补搜回路(最大2轮) |
| 综合报告 | Opus按引用映射织报告 |
| 三张状态表 | JSON文件 / SQLite,pydantic校验 |
核心编排脚本骨架(约30行,就是整个系统的图结构):
// workflows/my-research.js —— 自建 deep-research 最小骨架exportdefaultasyncfunctionrun(ctx){// ① Scope:拆解子问题(判断密度高 → Opus)constplan=awaitagent(`把研究问题拆成3~5个子问题并给出检索词,输出JSON:${ctx.input}`,{model:"opus",role:"planner",output:"json"});letevidence=[];for(letround=0;round<2;round++){// Convergent Loop:最多2轮// ② Parallel Search + ③ Fetch:搜索与抓取融合成一层扇出constfound=awaitparallel(plan.queries.map((q)=>agent(`搜索并提取关于「${q}」的证据条目,输出JSON数组`,{model:"sonnet",output:"json"})));evidence.push(...found.filter(Boolean).flat());// fan-in清洗 → 证据池// ④ Adversarial Verify:带缺口清单的对抗验证(裁决密度最高 → Opus)constverdict=awaitagent(`你是独立验证员,任务是挑刺。审查证据池,输出JSON:{"pass":bool,"gaps":["..."]} 证据池:${JSON.stringify(evidence)}`,{model:"opus",role:"verifier",output:"json",tools:["Read"]});if(verdict.pass)break;// 证据充分则出环plan.queries=verdict.gaps;// 定向补搜:缺口变检索计划}// ⑤ Synthesize:带引用综合(Opus)returnawaitagent(`基于证据池写研究报告,每条结论标注来源:${JSON.stringify(evidence)}`,{model:"opus",role:"synthesizer",output:"file"});}对照第48节的三原语视角:这段脚本用了agent(5种角色)、parallel(搜索层fan-out)、手写循环实现Convergent Loop。图结构不在任何DSL里,就在这些函数组合里——这就是Dynamic Workflows"图隐含于代码"的含义。
跑自建版本时的调试建议:把每一轮的证据池快照存成文件(evidence.round1.json),验证Agent的verdict单独落日志。deep-research这类长流程最大的调试痛点是"不知道中间发生了什么",快照文件就是你的时间旅行调试器——这一招从LangGraph的Checkpointer借来的,工具不同,思想通用。
小结
这一节把/deep-research这个杀手级应用拆到了螺丝钉:
- 五阶段工作流:Scope规划 → 并行搜索 → 抓取精读 → 对抗验证 → 综合报告,本质是多层嵌套Diamond + 一个Convergent Loop。
- 四种Agent角色:搜索(Haiku/Sonnet)、分析(Sonnet)、验证(Opus,单点收敛)、综合(Opus),模型分配严格按判断力密度。
- 状态管理三张表:证据池、引用映射、研究笔记,节点间只共享结构化状态不共享对话历史,溯源能力是可靠性的来源。
- 并行三策略:分层扇出宽度、边际收益早停、预算三件套(timeout/重试上限/成本熔断),快而不糙的根本。
- 全部设计模式可复刻:30行编排脚本 + pydantic状态Schema,就能搭出你自己的深度研究系统。
下节预告
/deep-research再漂亮,也只是Claude Code能力图谱的一个亮点。下一节我们把镜头拉远,客观盘点Claude Code Graph的优势与局限:什么场景它是降维打击,什么场景它会让你在第三天就想换LangGraph?哪些坑是官方文档不会告诉你的?这一节可能有点"劝退",但每一条都是实战换来的。
互动区
你们有没有用/deep-research做过真实的研究任务?体感上它的报告质量对比人工调研能打几分?最想吐槽的是哪个环节?评论区聊聊,我打算把大家的案例汇总成一篇实战评测。
如果觉得本文对你有帮助,欢迎点赞、收藏、关注三连!
本系列持续更新中,关注不迷路~