Open Deep Research 框架解读:消息流与五阶段流程

0 阅读6分钟

Open Deep Research 是一个基于 LangGraph 构建的深度研究 Agent。它接收用户的研究主题,经过澄清、规划、多轮研究,最终生成一份结构化的研究报告。本文将分析其日志和源码,梳理其核心设计理念和完整执行流程。

一、核心设计理念

1.1 三级消息体系

项目中存在三层消息记录,各司其职:

  • 主流程消息

    • 存储位置: AgentState.messages
    • 内容:Human / AI / Tool Message
    • 用途:持久化存储,回传给用户,参与 LangGraph 状态流转
  • 主管消息

    • 存储位置: SupervisorState.supervisor_messages
    • 内容:独立的 System / Human / AI / Tool Message
    • 用途:主管(Supervisor)的专属对话上下文
  • 研究员消息

    • 存储位置: ResearcherState.researcher_messages
    • 内容:独立的 Human / AI / Tool Message(System Message每次动态拼接)
    • 用途:每个研究员(Researcher)的专属对话上下文

关键点:三者各自维护独立的消息历史,互不干扰。只有message才会参与持久化,可以传递给后续平级节点,或者回传上级节点实现跨流程的信息传递。没有成为message的llm结果和prompt会即时丢弃,可能被日志记录,但不参与后续的信息流转。

1.2 LangSmith / LangGraph 的跟踪能力

LangSmith 和 LangGraph 能够跟踪比messages 更全面的内部对话记录,不足之处在于未跟踪llm client和server的原始通信。但是,通过 monkey-patch HTTP 传输层( tracing.py ),可以记录 llm 的完整原始请求与响应(包括 SSE 流),便于对agent的具体行为监控和分析。

1.3 Tool Call 的双重角色

项目大量使用 tool call 机制,但并非所有 tool call 都会真正“调用外部工具”:

  • 结构化输出 : clarify_with_user 和 write_research_brief 阶段使用 with_structured_output 将 LLM 返回约束为特定的 JSON 格式( ClarifyWithUser 、 ResearchQuestion等 ),底层依赖 tool/function calling 机制实现,但代码层面直接拿到反序列化的 Pydantic 对象,以此判断状态转移。
  • 强化思考交互 :think_tool将llm的输入原样返回,不产生任何外部操作。虽然消耗额外了token而不提供额外信息,但通过把思考变成一个需要显式调用的工具,系统迫使 llm 将思考“外露”为 Tool Call,这避免了llm过长内部思考,提高思考-执行的交互性。

二、五阶段流程详解

整个流程分为五个阶段:Input → Clarify → Brief → Research → Report,对应 LangGraph 的节点编排。前两个阶段存在用户交互;后三个阶段用户无感知,只能看到日志。

image.png

2.1 Input 阶段

用户输入研究主题,被 LangChain 自动包装为 HumanMessage,存入 AgentState.messages 。这是整个系统的起点,也是后续所有阶段的上下文来源。

2.2 Clarify 阶段

目的 :判断用户的研究主题是否需要澄清,必要时与用户进行多轮交互,直到确认信息充分。这个阶段会产生一个或多个 turn(人机对话轮次)。

实现 :

  1. 将 AgentState.messages 嵌入 clarify_with_user_instructions 模板,作为user prompt请求 LLM,获得结构化返回: need_clarification (是否需要澄清)、 question (澄清问题)、 verification (确认开始研究的声明)
  2. 若需要澄清:将 question 记录为 AI Message 写入 AgentState.messages ,结束当前轮,等待用户回复;用户回复记录为 Human Message 写入 AgentState.messages,回到步骤 1
  3. 若无需澄清:将 verification 记录为 AI Message 写入 AgentState.messages ,进入 Brief 阶段。

2.3 Brief 阶段

目的 :基于完整对话历史,生成一份详细的研究计划(Research Brief),并初始化 Supervisor。由此开始无需用户交互。

实现 :

  1. 将 AgentState.messages 嵌入 transform_messages_into_research_topic_prompt 模板,作为user prompt请求 LLM,获得 research_brief
  2. 初始化 supervisor_messages,写入两条记录: SystemMessage(lead_researcher_prompt), HumanMessage(research_brief)

2.4 Research 阶段

这是整个系统的核心,由 Supervisor 和 Researcher 两种角色协作完成。Supervisor 控制研究流程,Researcher 进行具体调研。

Supervisor

Supervisor 将 supervisor_messages 作为历史对话请求 LLM,提供三个候选工具: ConductResearch 、 ResearchComplete 、 think_tool 。收到 LLM 返回消息后,先将 tool call 记录为 AI Message 写入 supervisor_messages ,再由 supervisor_tools 节点处理:

  • think_tool :将入参 reflection 原样提取,作为 Tool Message 写入 supervisor_messages ,回到 supervisor 继续循环。
  • ConductResearch :启动 Researcher 子图执行调研。Supervisor 可同时派发多个 ConductResearch,通过 asyncio.gather 并行执行,每个 Researcher 独立运行互不干扰。完成后,各自的压缩结果作为 Tool Message 分别写入 supervisor_messages 。
  • ResearchComplete :调研结束,准备退出 supervisor 子图。

退出条件:LLM 调用了 ResearchComplete ,或迭代次数超过 max_researcher_iterations,或 LLM 返回了无 tool_call 的消息。

退出操作:退出时将 supervisor_messages 中所有 Tool Message提取为 notes ,传递给 Report 阶段。

Researcher

每个 Researcher 维护独立的 researcher_messages 。初始化时写入 HumanMessage(research_topic) 作为首条消息。

Researcher 将research_system_prompt作为system prompt,合并researcher_messages请求 LLM,提供候选工具: tavily_search 、 think_tool 、 ResearchComplete 。收到 LLM 返回后,先将 tool call 记录为 AI Message 写入 researcher_messages ,再由 researcher_tools 节点处理:

  • think_tool :将 reflection 作为 Tool Message 写入 researcher_messages ,继续循环。
  • tavily_search :调用 Tavily API 搜索网络,对每条搜索结果独立调用模型生成摘要,汇总为一条 Tool Message 写入 researcher_messages ,继续循环。正常流程下,prompt 要求 think_tool 独占,每轮只发出一个 tavily_search,形成逐轮串行节奏(搜索 → think → 搜索 → think → ...)。不过,一次tavily_search内部的多次摘要操作是并行的。
  • ResearchComplete :子调研结束,准备退出research子图。

退出条件:LLM 调用了 ResearchComplete ,或迭代次数超过 max_react_tool_calls 。

退出操作:随后进入内容压缩步骤compress_research。在 researcher_messages 最后中追加一条 Human Message( compress_research_simple_human_message ),以compress_research_system_prompt为system prompt,合并researcher_messages为历史对话请求LLM。返回 compressed_research 给 Supervisor。内容压缩失败无兜底机制,将丢失本research调研信息。

2.5 Report 阶段

目的 :汇总所有研究成果,生成最终报告。

实现 :

  1. 将 notes (所有 supervisor Tool Message 的 content)通过 f-string 嵌入 final_report_generation_prompt 模板,作为user prompt 请求 LLM 生成最终报告
  2. 报告以 AI Message 形式写入 AgentState.messages
    如果遇到 token 超限,系统会自动截断 findings 并重试(最多 3 次,每次缩减 10%)。

完成后,用户如果再次追问,则从input开始。

三、总结

Open Deep Research 通过三级消息体系隔离上下文,用工具调用驱动研究流程,借 think_tool 将推理外化为可观察的步骤,并支持并行派发多个研究员独立调研、压缩后汇总。这些设计让 Agent 在自主决策的同时,受迭代上限和工具边界约束,保持了整体的可控性。