从 0 构建企业级 Deep Research Agent(1):为什么一个 Agent 不够?

4 阅读13分钟

从 0 构建企业级 Deep Research Agent(1):为什么一个 Agent 不够?

本系列将从零实现一个面向机器人、AI 与智能硬件研发团队的企业级多 Agent 技术调研系统 TechScope


一、为什么我要做这个项目?

最近一段时间我一直在学习 Agent。

从最开始的:

LLM + Tools

到:

Agent
+ Memory
+ RAG
+ MCP
+ LangGraph

再到现在比较复杂的:

Multi-Agent
Deep Research
Coding Agent
Browser Agent

我慢慢发现一个问题。

很多所谓的 Agent 项目,本质上仍然是:

用户输入
   ↓
大模型
   ↓
调用几个工具
   ↓
返回答案

如果只是为了学习 Tool Calling,这当然没有问题。

但如果希望真正理解:

  • Agent Runtime
  • State Management
  • Planning
  • Multi-Agent
  • Context Engineering
  • Long-running Task
  • Evidence
  • Evaluation

就需要一个足够复杂、但又能真正落地的项目。

于是我决定从零搭建:

TechScope

一个面向企业研发场景的:

Multi-Agent Deep Research System

整个项目预计分三个阶段开发:

Phase 1

Multi-Agent Research MVP

Phase 2

Evidence-driven Research

Phase 3

Evaluation + Production

这篇文章是整个系列的第一篇。

我们暂时不急着写 Agent。

先回答一个更重要的问题:

为什么 Deep Research 要使用 Multi-Agent?


二、先设计一个真实业务,而不是为了 Agent 而 Agent

在开始写代码之前,我不想先讨论:

LangChain

LangGraph

MCP

RAG

而是先确定一个问题:

我们到底要解决什么业务?

假设现在有一家机器人与智能硬件公司。

公司里有:

CTO

算法团队

硬件团队

产品团队

技术战略团队

研发负责人经常需要做一类工作:

技术调研

例如:

请调研 2023—2026 年
Vision + IMU 手部姿态估计技术。

要求:

1. 找出代表性论文
2. 对比主要算法路线
3. 查找公开 Dataset
4. 查找 GitHub 开源实现
5. 比较不同方案性能
6. 分析视觉遮挡问题
7. 调研相关产品
8. 分析工程落地风险

如果完全依赖工程师人工完成,通常意味着:

Google Scholar
    ↓
Google
    ↓
GitHub
    ↓
论文阅读
    ↓
整理表格
    ↓
交叉验证
    ↓
写技术报告

这实际上不是一个简单的“搜索问题”。

而是一个:

复杂、多阶段、长上下文的信息研究任务。

这也是 TechScope 要解决的问题。


三、TechScope 的业务定位

我给这个项目的完整名称是:

TechScope

Enterprise R&D Intelligence Multi-Agent System

中文可以理解为:

企业研发技术情报多 Agent 系统。

它主要服务于:

用户典型需求
CTO判断某项技术是否值得投入
算法负责人调研新的算法方向
研发工程师查论文、代码、Dataset
产品负责人对比竞品技术
技术战略团队分析技术发展趋势
硬件工程师调研芯片、传感器方案

例如:

调研 humanoid dexterous hand

调研机器人 VLA 技术路线

调研 Vision + IMU Sensor Fusion

调研机器人触觉传感器

调研 Dexterous Hand Retargeting

调研机器人遥操作系统

这些都属于 TechScope 的目标任务。


四、最简单的方案:一个 LLM 能不能完成?

最开始我们完全可以设计成:

User
 │
 ▼
LLM
 │
 ├── Search
 ├── GitHub
 ├── Paper Search
 └── Web
 │
 ▼
Report

也就是:

Single Agent

Agent 拥有所有工具:

search_web()

search_paper()

search_github()

fetch_page()

read_pdf()

然后通过类似 ReAct 的循环:

Thought
  ↓
Action
  ↓
Observation
  ↓
Thought
  ↓
Action

直到生成报告。

对于简单问题,这种方式完全可行。

但如果任务变成:

调研最近三年灵巧手技术发展

需要:

论文
GitHub
产品
硬件
Benchmark
Dataset
技术路线
成本
工程风险

问题就开始出现了。


五、问题一:Context 会越来越大

假设一次 Research 找到:

20 篇论文

15 个 GitHub Repository

30 个网页

5 个产品页面

如果所有信息全部交给同一个 Agent:

                 Main Agent

Prompt
+
用户问题
+
Research Plan
+
20 papers
+
15 GitHub README
+
30 web pages
+
Tool Result
+
历史推理
+
中间 Summary
+
最终 Report

Context 会越来越大。

问题不仅仅是:

Token 贵。

更严重的是:

有用信息在大量无关上下文中逐渐被稀释。

例如 Agent 正在分析:

IMU Drift

Context 里面同时还有:

市场价格

Github Stars

触觉传感器

竞品发布时间

机械结构

这些信息对于当前任务其实没有价值。


六、问题二:不同 Research Task 天然可以并行

假设 Planner 把问题拆成:

RQ1:
有哪些代表性论文?

RQ2:
有哪些开源项目?

RQ3:
有哪些商业产品?

RQ4:
有哪些公开 Dataset?

这四个问题实际上不存在严格依赖关系。

完全可以:

                 Supervisor
                     │
       ┌─────────────┼─────────────┐
       │             │             │
       ▼             ▼             ▼
   Paper Agent   GitHub Agent   Web Agent
       │             │             │
       ▼             ▼             ▼
    Papers          Repos        Products
       │             │             │
       └─────────────┼─────────────┘
                     ▼
                  Summary

而不是:

查论文
 ↓
等待
 ↓
查 GitHub
 ↓
等待
 ↓
查网页
 ↓
等待

所以 Research 天然适合:

Parallel Execution


七、问题三:不同信息源需要不同 Research Strategy

搜索论文和搜索产品网页,本质上并不是同一个任务。

比如:

Paper Researcher

真正关注的是:

论文标题

作者

会议 / Journal

年份

Method

Dataset

Metric

Experiment

而 GitHub Agent 更关注:

Repository

README

License

Stars

Last Commit

Installation

Dataset

Pretrained Model

Web Researcher 可能关注:

企业官网

官方技术博客

产品页面

发布日期

规格参数

技术路线

如果所有任务使用:

一个 Prompt
+
一个 Agent

就意味着这个 Agent 的 System Prompt 必须同时包含:

你是论文专家

你是 Github 分析专家

你是产品专家

你是行业研究专家

你还是报告作者

这显然越来越难维护。

更合理的方式是:

PaperResearcher

GitHubResearcher

WebResearcher

每个 Agent:

独立 Prompt

独立 Tools

独立 Context

独立 Output Schema

八、问题四:Research 不应该直接变成 Report

这是我认为很多 Deep Research Demo 非常容易出现的问题。

典型流程是:

Search
  ↓
得到网页
  ↓
LLM Summary
  ↓
Report

但这里缺少一个非常关键的问题:

这个网页真的支持报告中的结论吗?

例如报告写:

Method A 的姿态误差为 5.2°

Citation 指向某篇论文。

但是论文真正写的是:

7.8°

那么:

Citation 存在

并不等于:

Citation 正确

所以 TechScope 后面会设计一条完整链路:

Source
   ↓
Evidence
   ↓
Claim
   ↓
Citation Verification
   ↓
Report

不过这是第二阶段的内容。

第一阶段先把 Research Agent 搭起来。


九、问题五:谁负责管理这些 Agent?

如果存在:

Paper Agent

GitHub Agent

Web Agent

新的问题来了:

谁决定调用哪个 Agent?

于是我们需要:

Supervisor

完整结构变成:

                  User Query
                      │
                      ▼
             Requirement Agent
                      │
                      ▼
              Research Planner
                      │
                      ▼
                 Supervisor
                      │
       ┌──────────────┼──────────────┐
       │              │              │
       ▼              ▼              ▼
    Paper          GitHub           Web
 Researcher      Researcher      Researcher
       │              │              │
       └──────────────┼──────────────┘
                      ▼
               Research Result
                      │
                      ▼
                   Writer
                      │
                      ▼
                  Report

这就是 TechScope 第一阶段的基本架构。


十、为什么还需要 Planner?

Supervisor 解决:

谁执行任务?

Planner 解决:

到底应该研究什么?

例如用户只输入:

帮我调研机器人灵巧手

这是一个非常宽泛的问题。

Research Planner 可以生成:

RQ1:
目前灵巧手有哪些主要硬件结构?

RQ2:
有哪些驱动方式?

RQ3:
触觉传感方案有哪些?

RQ4:
控制算法有哪些主要路线?

RQ5:
有哪些代表性论文?

RQ6:
有哪些开源项目?

RQ7:
有哪些公开 Dataset?

RQ8:
目前有哪些商业产品?

RQ9:
主要工程瓶颈是什么?

然后构造:

Research Plan

RQ1 → Paper + Web

RQ2 → Paper + Web

RQ3 → Paper

RQ4 → Paper + GitHub

RQ5 → Paper

RQ6 → GitHub

RQ7 → Paper + Web

RQ8 → Web

RQ9 → Paper + Web

这时候 Supervisor 才知道该如何执行。

所以:

Planner

和:

Supervisor

不是一个东西。

可以简单理解为:

Planner
=
决定做什么


Supervisor
=
决定怎么执行

十一、为什么选择 LangGraph?

这个项目不会直接使用一个已经封装好的:

Deep Research Agent

而是希望自己控制:

State

Node

Edge

Branch

Loop

Checkpoint

Interrupt

Sub-Agent

因此我选择 LangGraph 作为底层 Runtime。

LangGraph 官方目前将其定位为面向长时间、Stateful Agent 的低层 orchestration framework,并重点提供 durable execution、streaming、human-in-the-loop 和 persistence 等能力。

这比较符合 TechScope 的目标。

我们要做的是:

LangGraph


只负责 Runtime / Orchestration


TechScope


负责 Agent Architecture

也就是:

LangGraph ≠ TechScope

真正属于我们自己的部分是:

ResearchState

Planner

Supervisor

Researcher

Evidence

Reviewer

Verifier

Evaluator

十二、TechScope 三阶段路线

整个项目不会一次全部完成。

我把它拆成三个阶段。


Phase 1:Research MVP

目标:

让 Agent 真正完成一次完整 Research。

实现:

Requirement Analyzer

Perspective Generator

Research Planner

Supervisor

Paper Researcher

GitHub Researcher

Web Researcher

Source Store

Report Writer

FastAPI

最终:

Query
 ↓
Plan
 ↓
Research
 ↓
Sources
 ↓
Report

版本:

TechScope v0.1

Phase 2:Evidence-driven Research

目标:

解决 Agent 给出的研究结果是否可信。

增加:

Evidence Store

Evidence Dedup

Source Ranking

Claim Extraction

Evidence Graph

Citation Verification

Reviewer

Context Manager

Enterprise RAG

MCP

Checkpoint

Human-in-the-loop

最终:

Source
 ↓
Evidence
 ↓
Claim
 ↓
Verification
 ↓
Report

版本:

TechScope v0.5

Phase 3:Evaluation

目标:

证明我们的 Agent 到底有没有变好。

增加:

TechScope-Bench

Rubric Evaluation

Citation Evaluation

Ablation Study

Reliability Evaluation

Cost Evaluation

Tracing

Evaluation Dashboard

比较:

Single Agent

VS

Planner + Researcher

VS

Multi-Agent

VS

Multi-Agent + Reviewer

VS

Multi-Agent + Reviewer + Verifier

版本:

TechScope v1.0

十三、这一篇正式开始搭项目

理论部分先到这里。

下面开始创建 TechScope。

我使用:

Python 3.11+

FastAPI

LangGraph

LangChain

Pydantic

Python 项目依赖管理使用:

uv

FastAPI 当前官方教程也推荐使用 uv 初始化项目并生成 uv.lock,这样可以锁定整个项目依赖。


十四、创建项目

创建目录:

mkdir techscope
cd techscope

初始化 Python 项目:

uv init --bare

此时:

techscope/
└── pyproject.toml

十五、安装基础依赖

首先安装 FastAPI:

uv add "fastapi[standard]"

然后:

uv add langgraph langchain

配置管理:

uv add pydantic-settings python-dotenv

如果使用 OpenAI:

uv add langchain-openai

如果使用 Anthropic,可以替换成对应 Provider Package。

LangGraph 基础包目前官方安装方式仍然是:

pip install -U langgraph

使用 uv 时本质上对应:

uv add langgraph

LangGraph 本身并不强制要求通过 LangChain 调用模型,因此后面我们也会把模型访问层单独抽象


十六、建立第一版目录结构

先不要创建几十个没有代码的目录。

第一阶段只建立:

techscope/
│
├── src/
│   └── techscope/
│       │
│       ├── __init__.py
│       │
│       ├── main.py
│       │
│       ├── core/
│       │   ├── __init__.py
│       │   └── config.py
│       │
│       ├── graph/
│       │   └── __init__.py
│       │
│       ├── agents/
│       │   └── __init__.py
│       │
│       ├── tools/
│       │   └── __init__.py
│       │
│       └── models/
│           └── __init__.py
│
├── tests/
│
├── .env
├── .env.example
├── .gitignore
├── pyproject.toml
└── README.md

为什么暂时只建立这些?

因为我不希望:

项目刚开始

就出现:

30 个空目录

目录应该随着架构逐渐生长。


十七、配置系统

创建:

src/techscope/core/config.py

代码:

from functools import lru_cache

from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    app_name: str = "TechScope"
    app_env: str = "development"

    llm_provider: str = "openai"
    llm_model: str = ""

    openai_api_key: str | None = None
    anthropic_api_key: str | None = None

    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        extra="ignore",
    )


@lru_cache
def get_settings() -> Settings:
    return Settings()

这里有一个设计考虑:

我不会在代码里直接:

model = ChatOpenAI(...)

然后所有 Agent 都依赖这个对象。

后面会设计:

LLM Gateway

统一负责:

Provider

Model

Temperature

Timeout

Retry

Usage

Cost

因为第三阶段需要统计不同 Agent 的:

Token

Cost

Latency

从项目一开始就应该避免模型调用散落在业务代码中。


十八、环境变量

.env.example

APP_NAME=TechScope
APP_ENV=development

LLM_PROVIDER=openai
LLM_MODEL=

OPENAI_API_KEY=
ANTHROPIC_API_KEY=

然后复制:

cp .env.example .env

Windows PowerShell:

Copy-Item .env.example .env

真正的 API Key 只写在:

.env

不要提交 Git。


十九、创建第一个 FastAPI 服务

创建:

src/techscope/main.py

代码:

from fastapi import FastAPI

from techscope.core.config import get_settings


settings = get_settings()

app = FastAPI(
    title=settings.app_name,
    version="0.1.0",
)


@app.get("/")
async def root():
    return {
        "name": settings.app_name,
        "version": "0.1.0",
        "status": "running",
    }


@app.get("/health")
async def health():
    return {
        "status": "ok",
    }

二十、配置 Python Package

pyproject.toml 至少保证存在:

[project]
name = "techscope"
version = "0.1.0"
requires-python = ">=3.11"

开发阶段可以:

uv run fastapi dev src/techscope/main.py

FastAPI 官方当前提供 fastapi dev 作为本地开发服务器启动方式。 启动后访问:

http://127.0.0.1:8000

返回:

{
  "name": "TechScope",
  "version": "0.1.0",
  "status": "running"
}

访问:

http://127.0.0.1:8000/health

返回:

{
  "status": "ok"
}

FastAPI 自动生成的 Swagger 页面位于:

http://127.0.0.1:8000/docs

至此:

TechScope 正式启动。


二十一、第一版 README

现在创建:

README.md

可以先写得非常简单:

# TechScope

TechScope is an enterprise multi-agent R&D intelligence system.

## Goal

Build a Deep Research Agent from scratch with:

- LangGraph
- Multi-Agent Research
- Evidence Tracking
- Citation Verification
- Enterprise RAG
- MCP
- Evaluation

## Roadmap

### Phase 1

Multi-Agent Research MVP

### Phase 2

Evidence-driven Research

### Phase 3

Evaluation & Production

README 后续随着项目逐渐补充。


二十二、初始化 Git

执行:

git init

创建:

.gitignore

至少加入:

.env
.venv/
__pycache__/
*.pyc
.pytest_cache/
.idea/
.vscode/
.DS_Store

提交:

git add .
git commit -m "chore: initialize TechScope project"

这个 Commit 就代表:

TechScope
Day 1

二十三、这一阶段为什么还没有写 Agent?

因为我希望整个项目遵循一个原则:

先设计 Runtime State,再写 Agent。

很多 Agent Demo 的写法是:

agent = create_agent(...)

然后:

agent.invoke(...)

确实可以很快得到结果。

但我们的目标不是:

快速做一个 Demo。

而是理解:

Agent 到底是怎么运行的?

所以下一步必须先解决:

State

因为在一个长时间运行的 Research Task 中,需要保存:

用户问题

Research Plan

Research Questions

当前执行任务

已完成任务

Sources

Research Results

Iteration

Report

这些东西最终都会进入:

ResearchState

而 LangGraph 的 Graph API 本身也是围绕:

State

Node

Edge

组织工作流。官方 Graph API 支持 sequence、branch、loop,以及用于并行 map-reduce 的 Send 等控制结构,这正是后面实现 Research Planner 和并行 Researcher 所需要的基础。


二十四、目前的系统只有这一层

到这篇文章结束,我们实际上只完成了:

┌──────────────────────────┐
│        FastAPI           │
│                          │
│   /                      │
│   /health                │
└─────────────┬────────────┘
              │
              ▼
       TechScope Core
              │
              ▼
          Config

还没有:

Planner

Supervisor

Agent

Tool

Research

这是故意的。

下一篇开始,系统才真正进入:

Agent Runtime


二十五、下一篇要做什么?

下一篇:

《从 0 构建企业级 Deep Research Agent(2):ResearchState 与 LangGraph 状态管理》

我们会解决一个非常核心的问题:

一个运行几十分钟甚至几个小时的 Research Agent,到底应该保存哪些状态?

并正式实现:

ResearchState

ResearchTask

ResearchQuestion

ResearchPlan

Source

然后创建第一个 LangGraph:

START
  │
  ▼
initialize_research
  │
  ▼
END

虽然这个 Graph 看起来非常简单,但它会成为整个 TechScope 后面:

Planner
    ↓
Supervisor
    ↓
Researcher
    ↓
Reviewer
    ↓
Writer

的基础。

后面所有 Agent 都不会通过:

互相直接调用

进行协作。

而是通过:

ResearchState

共享任务状态。

这也是我们下一篇真正开始讨论的内容。


本篇完成情况

今天完成:

  • 确定 TechScope 业务方向
  • 分析为什么需要 Multi-Agent
  • 确定三阶段开发路线
  • 确定第一版系统架构
  • 创建 Python 项目
  • 安装 LangGraph / FastAPI
  • 创建基础目录
  • 建立 Settings
  • 建立 .env
  • 启动 FastAPI
  • 初始化 Git

当前版本:

TechScope v0.0.1

当前状态:

Project Bootstrap

下一阶段:

ResearchState
+
LangGraph Runtime

最后

这个系列不会以:

“调用一个现成 API,实现一个 Agent”

为目标。

我更希望通过 TechScope 真正搞清楚几个问题:

Agent 为什么需要 State?

Agent 和 Workflow 有什么区别?

Planner 到底应该怎么设计?

Multi-Agent 怎么通信?

Supervisor 怎么调度任务?

Context 爆炸怎么解决?

Agent 失败如何恢复?

Citation 怎么验证?

为什么相信 Agent 的结果?

Agent 到底应该怎么 Evaluation?

如果这些问题最后都能通过 TechScope 的源码回答出来,那么这个项目真正有价值的就不只是:

一个 Deep Research 应用

而是一套完整的:

Agent Engineering 实践。

下一篇,我们正式开始写第一个 LangGraph。

《从 0 构建企业级 Deep Research Agent(2):ResearchState 与 LangGraph 状态管理》