DeerFlow 系列教程 第二篇上一篇我们完成了 DeerFlow 的初体验学会了基本的对话交互。本篇将深入幕后带你理解 DeerFlow 的整体技术架构——当你发送一条消息后系统内部到底发生了什么从 Nginx 路由分发到 Lead Agent 决策执行从中间件链处理到流式事件推送我们将沿着一条消息的完整旅程逐层拆解这个 Super Agent 平台的技术骨架。一、架构总览四层三服务DeerFlow 采用四层架构设计所有外部请求通过 Nginx 统一入口进入系统再分发到三个后端服务┌────────────────────────────────────────────────┐ │ 用户浏览器 / API 客户端 │ └────────────────────────┬───────────────────────┘ │ ▼ ┌────────────────────────────────────────────────┐ │ Nginx 反向代理端口 2026 │ │ │ │ /api/langgraph/* → LangGraph Server (2024) │ │ /api/* → Gateway API (8001) │ │ /* → Frontend (3000) │ └────┬───────────────────┬───────────────────┬───┘ │ │ │ ▼ ▼ ▼ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │ LangGraph│ │ Gateway API │ │ Frontend │ │ Server │ │ (FastAPI) │ │ (Next.js)│ │ (2024) │ │ (8001) │ │ (3000) │ │ │ │ │ │ │ │ Agent 运行│ │ 模型/技能/ │ │ React UI │ │ 线程管理 │ │ 记忆/上传/ │ │ 流式渲染 │ │ SSE 流式 │ │ 制品管理 │ │ │ └──────────┘ └──────────────┘ └──────────┘1.1 四层架构详解层级技术栈职责表现层Next.js 16 / React 19 / Tailwind CSS 4用户界面渲染、流式消息展示、文件上传交互网关层FastAPI / UvicornREST API 路由、模型管理、技能管理、文件处理智能体层LangGraph / LangChainAgent 运行时、中间件链执行、工具调用、子智能体编排基础设施层Docker / Sandbox / FileSystem沙箱隔离执行、文件系统管理、状态持久化1.2 三个后端服务各司其职LangGraph Server端口 2024是 Agent 的运行时引擎创建和管理 Lead Agent 实例维护对话线程Thread的状态通过 SSEServer-Sent Events向前端推送流式响应执行中间件链和工具调用Gateway API端口 8001是配置和资源管理的 REST 接口提供模型列表、技能管理、MCP 配置等 API处理文件上传和格式转换PDF/PPT/Excel → Markdown管理对话制品Artifacts的存储和分发提供记忆系统的 CRUD 接口Frontend端口 3000是面向用户的 Web 界面基于 Next.js App Router 的页面路由通过 LangGraph SDK 与后端建立流式连接实时渲染 Agent 的消息、工具调用和子任务状态1.3 为什么需要分离 LangGraph 和 Gateway这种分离设计有明确的工程考量关注点分离LangGraph 专注于 Agent 执行和状态管理计算密集型Gateway 专注于配置管理和文件处理IO 密集型独立扩缩容在高并发场景下可以独立增加 LangGraph Worker 数量灵活替换Gateway 模式实验性可以将 LangGraph 嵌入 Gateway减少为 3 个进程两种模式的对比维度Standard 模式Gateway 模式实验性进程数4Nginx Frontend Gateway LangGraph3Nginx Frontend Gateway资源占用较高两个 Python 运行时较低单个 Python 运行时冷启动较慢较快功能完整性完全等价完全等价二、Nginx 路由层请求的第一站Nginx 是所有请求的入口端口 2026它根据 URL 路径决定将请求转发给哪个后端服务。2.1 路由规则一览以下是docker/nginx/nginx.conf中定义的核心路由规则路径模式目标服务说明/api/langgraph/*LangGraph (2024)Agent 交互、线程管理、流式响应/api/modelsGateway (8001)模型列表和配置/api/memoryGateway (8001)记忆管理/api/mcpGateway (8001)MCP 服务器配置/api/skillsGateway (8001)技能管理/api/agentsGateway (8001)自定义智能体管理/api/threads/{id}/uploadsGateway (8001)文件上传最大 100MB/api/threads/{id}/artifactsGateway (8001)制品文件服务/api/sandboxesProvisioner (8002)沙箱环境管理可选/*Frontend (3000)前端页面和静态资源2.2 流式传输支持Nginx 对 LangGraph 的请求做了特殊配置以支持 SSE 流式传输# 关闭代理缓冲确保事件实时推送 proxy_buffering off; proxy_cache off; chunked_transfer_encoding on; # 长连接超时设置600 秒 proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600;这意味着 Agent 生成的每一个 token 都能近乎实时地推送到用户浏览器而不是等全部生成完毕再发送。2.3 CORS 集中管理一个值得注意的设计决策DeerFlow 的 CORS跨域资源共享由 Nginx 统一处理后端的 FastAPI 和 LangGraph 服务都不单独配置 CORS。这避免了多层 CORS 头冲突的问题。三、前端如何连接后端3.1 URL 解析策略前端通过frontend/src/core/config/index.ts中的函数来确定后端地址// 1. 如果设置了环境变量使用环境变量// NEXT_PUBLIC_LANGGRAPH_BASE_URL// NEXT_PUBLIC_BACKEND_BASE_URL// 2. 默认情况下通过 Nginx 代理访问// LangGraph: {当前域名}/api/langgraph// Gateway: {当前域名}/api/*// 3. SSR 渲染时回退到 localhost:2026这种设计意味着在 Docker 部署中前端只需要知道 Nginx 的地址通常就是http://localhost:2026不需要直接访问内部服务端口。3.2 LangGraph SDK 客户端前端使用langchain/langgraph-sdk与 LangGraph Server 通信。客户端在frontend/src/core/api/api-client.ts中初始化functioncreateCompatibleClient():LangGraphClient{constclientnewLangGraphClient({apiUrl:getLangGraphBaseURL(),});// 拦截 runs.stream() 方法自动清理不支持的流选项constoriginalRunStreamclient.runs.stream.bind(client.runs);client.runs.stream((threadId,assistantId,payload)originalRunStream(threadId,assistantId,sanitizeRunStreamOptions(payload),))astypeofclient.runs.stream;returnclient;}客户端使用单例模式缓存避免重复创建连接。3.3 流式消息处理当用户发送消息后前端通过useThreadStreamHook 建立流式连接创建线程— 如果是新对话先通过 SDK 创建一个 Thread发起 Run— 调用client.runs.stream()发起一次 Agent 执行消费事件— 通过异步迭代器逐个处理 SSE 事件渲染更新— 每收到一个事件更新 React 状态触发界面渲染事件类型包括metadata— 运行元数据run_id 等updates— 状态增量更新messages— 消息内容AI 回复的文本流events— 工具调用、子任务状态等自定义事件end— 运行结束四、Gateway 网关层配置与资源中心4.1 FastAPI 应用初始化Gateway 的入口在backend/app/gateway/app.py使用 FastAPI 的 lifespan 机制管理生命周期asynccontextmanagerasyncdeflifespan(app:FastAPI):# 启动时# 1. 加载 config.yaml 配置# 2. 初始化 LangGraph 运行时组件# 3. 启动 IM 频道服务飞书/企微/Slack/Telegramasyncwithlanggraph_runtime(app):channel_serviceChannelService()awaitchannel_service.start()yieldawaitchannel_service.stop()4.2 四大运行时组件Gateway 通过依赖注入backend/app/gateway/deps.py提供四个核心运行时组件asyncwithAsyncExitStack()asstack:app.state.stream_bridgeawaitstack.enter_async_context(make_stream_bridge())app.state.checkpointerawaitstack.enter_async_context(make_checkpointer())app.state.storeawaitstack.enter_async_context(make_store())app.state.run_managerRunManager()组件类职责StreamBridgeMemoryStreamBridge事件流的生产者-消费者桥接支持 SSE 推送和客户端重连RunManagerRunManager管理 Agent 执行实例的生命周期创建/查询/取消/清理Checkpointer可配置对话状态的持久化内存/SQLite/PostgreSQLStore可配置长期数据存储4.3 Gateway API 路由Gateway 注册了多个路由模块覆盖所有非 Agent 执行的 API 需求/api/models ← 模型列表 /api/mcp ← MCP 服务器配置 /api/memory ← 记忆管理增删改查 导入导出 /api/skills ← 技能管理列表/启用/安装/编辑 /api/agents ← 自定义智能体管理 /api/threads/{id}/uploads ← 文件上传 /api/threads/{id}/artifacts ← 制品文件服务 /api/threads/{id}/suggestions ← 后续问题建议 /api/channels ← IM 频道配置 /health ← 健康检查五、智能体层Lead Agent 的诞生这是 DeerFlow 最核心的部分。当 LangGraph Server 收到一条用户消息后它会调用make_lead_agent()工厂函数来创建或复用Agent 实例。5.1 Agent 创建流程make_lead_agent()定义在backend/packages/harness/deerflow/agents/lead_agent/agent.py中创建过程如下make_lead_agent(config: RunnableConfig) │ ├─ 1. 解析模型名称 │ ├─ 请求级别指定 → config[model_name] │ ├─ Agent 级别配置 → agent_config.model │ └─ 全局默认 → app_config.models[0].name │ ├─ 2. 解析运行时特性 │ ├─ thinking_enabled思考模式默认 True │ ├─ reasoning_effort推理深度 │ ├─ is_plan_mode计划模式 │ ├─ subagent_enabled子智能体开关 │ └─ max_concurrent_subagents最大并发数默认 3 │ ├─ 3. 创建模型实例 │ └─ create_chat_model(name, thinking_enabled, reasoning_effort) │ ├─ 4. 加载工具集 │ └─ get_available_tools(model_name, groups, subagent_enabled) │ ├─ 配置工具web_search, bash, read_file... │ ├─ 内置工具present_file, ask_clarification, view_image │ ├─ 子智能体工具task │ ├─ MCP 工具从 extensions_config.json 加载 │ └─ ACP 工具可选 │ ├─ 5. 组装中间件链 │ └─ _build_middlewares(config, model_name, agent_name) │ ├─ 6. 构建系统提示词 │ └─ apply_prompt_template(subagent_enabled, skills, agent_name) │ └─ 7. 创建 LangGraph Agent 图 └─ create_agent(model, tools, middleware, system_prompt, state_schemaThreadState)5.2 ThreadStateAgent 的记忆容器每个对话线程都有一个ThreadState对象记录了当前线程的所有状态信息classThreadState(AgentState):messages:list[BaseMessage]# 对话消息历史sandbox:SandboxState|None# 沙箱执行环境信息thread_data:ThreadDataState|None# 工作目录路径title:str|None# 自动生成的对话标题artifacts:list[str]# 生成的制品文件路径todos:list|None# 计划模式的任务列表uploaded_files:list[dict]|None# 用户上传的文件信息viewed_images:dict[str,ViewedImageData]# 已查看的图像缓存其中ThreadDataState记录了每个线程的隔离文件路径classThreadDataState(TypedDict):workspace_path:str|None# 工作目录uploads_path:str|None# 上传文件目录outputs_path:str|None# 输出交付物目录这些路径在沙箱中映射为标准化的虚拟路径虚拟路径物理路径/mnt/user-data/workspace.deer-flow/threads/{thread_id}/user-data/workspace/mnt/user-data/uploads.deer-flow/threads/{thread_id}/user-data/uploads/mnt/user-data/outputs.deer-flow/threads/{thread_id}/user-data/outputs/mnt/skillsdeer-flow/skills/六、中间件链Agent 的生命周期管道DeerFlow 的中间件链是一个精心设计的处理管道每个中间件负责一个横切关注点。它们按严格的顺序执行确保 Agent 在每次交互中都经历一致的处理流程。6.1 完整的中间件执行顺序用户消息进入 │ ▼ ┌─ 1. ThreadDataMiddleware ──────── 创建隔离的工作目录 ├─ 2. UploadsMiddleware ─────────── 注入上传文件的元数据 ├─ 3. SandboxMiddleware ─────────── 获取沙箱执行环境 ├─ 4. DanglingToolCallMiddleware ── 修复不完整的工具调用记录 ├─ 5. ToolErrorHandlingMiddleware ─ 将工具异常转为错误消息 ├─ 6. LLMErrorHandlingMiddleware ── 处理大模型 API 错误 ├─ 7. SummarizationMiddleware ───── 压缩长对话上下文可选 ├─ 8. TodoMiddleware ────────────── 管理计划模式的任务列表可选 ├─ 9. TokenUsageMiddleware ──────── 统计 Token 使用量可选 ├─ 10. TitleMiddleware ──────────── 首轮对话后自动生成标题 ├─ 11. MemoryMiddleware ─────────── 将对话加入记忆更新队列 ├─ 12. ViewImageMiddleware ──────── 为视觉模型注入图像数据条件 ├─ 13. DeferredToolFilterMiddleware 从模型绑定中移除延迟工具条件 ├─ 14. SubagentLimitMiddleware ──── 限制子智能体并发数量条件 ├─ 15. LoopDetectionMiddleware ──── 检测工具调用死循环 ├─ 16. [自定义中间件] ───────────── 用户注入的中间件 └─ 17. ClarificationMiddleware ──── 拦截用户澄清请求始终最后 │ ▼ Agent 核心执行模型推理 工具调用 │ ▼ 响应返回逆序经过中间件链6.2 关键中间件详解ThreadDataMiddleware必须第一个执行为每个对话线程创建隔离的文件系统目录。这是所有后续文件操作的基础。{base_dir}/threads/{thread_id}/user-data/ ├── workspace/ ← Agent 的工作目录 ├── uploads/ ← 用户上传的文件 └── outputs/ ← Agent 生成的交付物MemoryMiddleware在对话的第一轮交互完成后将对话内容加入异步更新队列。后台进程会定期处理队列从对话中提取有价值的信息写入长期记忆。它还能检测用户的纠正行为如不对、重试等关键词及时调整记忆内容。LoopDetectionMiddleware使用滑动窗口和哈希比较来检测重复的工具调用。当同一工具被连续调用 3 次以上时发出警告达到硬限制后强制终止工具调用链防止 Agent 陷入死循环。ClarificationMiddleware必须最后一个执行当 Agent 调用ask_clarification()工具时该中间件会中断执行流程将问题呈现给用户等待用户回复后再恢复执行。因此它必须是最后一个中间件确保其他中间件的处理已经完成。七、流式事件系统StreamBridgeDeerFlow 使用StreamBridge模式解耦事件的生产者Agent Worker和消费者SSE 端点这是实现流式响应的关键基础设施。7.1 事件模型dataclass(frozenTrue)classStreamEvent:id:str# 单调递增的事件 ID格式时间戳-序号event:str# 事件类型metadata / updates / messages / events / enddata:Any# JSON 可序列化的载荷7.2 生产者-消费者流程Agent Worker生产者 StreamBridge SSE 端点消费者 │ │ │ │── publish(event) ──────────→ │ │ │ │← subscribe() ───────────│ │ │── yield StreamEvent ───→ │ │── publish(event) ──────────→ │ │ │ │── yield StreamEvent ───→ │ │── publish_end() ───────────→ │ │ │ │── yield END_SENTINEL ──→ │ │ │ │7.3 客户端重连支持MemoryStreamBridge 使用环形缓冲区默认 256 个事件保留历史事件。当客户端断线重连时携带Last-Event-ID请求头即可从断点继续接收事件无需重新执行整个 Agent。在没有新事件时系统每 15 秒发送一次心跳HEARTBEAT_SENTINEL防止连接超时断开。八、配置系统config.yaml 的加载链路DeerFlow 的所有核心行为都由config.yaml驱动。配置加载流程如下8.1 配置文件定位# 按以下优先级查找 config.yaml# 1. 显式传入的路径参数# 2. 环境变量 DEER_FLOW_CONFIG_PATH# 3. backend/config.yaml# 4. 项目根目录/config.yaml8.2 AppConfig 结构classAppConfig(BaseModel):log_level:str# 日志级别token_usage:TokenUsageConfig# Token 统计配置models:list[ModelConfig]# 可用模型列表sandbox:SandboxConfig# 沙箱提供者配置tools:list[ToolConfig]# 可用工具列表tool_groups:list[ToolGroupConfig]# 工具分组skills:SkillsConfig# 技能目录配置extensions:ExtensionsConfig# MCP 服务器 技能开关状态title:TitleConfig# 标题生成策略summarization:SummarizationConfig# 消息摘要策略memory:MemoryConfig# 记忆系统配置subagents:SubagentsAppConfig# 子智能体超时和限制guardrails:GuardrailsConfig# 安全防护策略checkpointer:CheckpointerConfig# 状态持久化配置stream_bridge:StreamBridgeConfig# 流式桥接配置8.3 配置文件体系DeerFlow 使用三个配置文件协同工作文件作用示例内容config.yaml主配置文件模型定义、工具列表、沙箱类型、记忆设置.env敏感信息API Key、Token 等环境变量extensions_config.json扩展状态MCP 服务器配置、各技能的启用/禁用状态九、一条消息的完整旅程让我们把上面的所有内容串起来追踪用户发送一条消息后的完整处理链路1. 用户在输入框中输入消息按下 Enter │ 2. 前端 useThreadStream Hook 调用 LangGraph SDK │ → client.runs.stream(threadId, assistantId, payload) │ 3. 请求到达 Nginx端口 2026 │ → 匹配路径 /api/langgraph/* │ → 转发到 LangGraph Server端口 2024 │ 4. LangGraph Server 创建一次 Run │ → RunManager.create_or_reject() 检查并发 │ → 加载或创建 Thread 状态 │ 5. 调用 make_lead_agent(config) 获取 Agent 实例 │ → 解析模型 → 加载工具 → 组装中间件 → 构建提示词 │ 6. 中间件链前处理1→17 顺序执行 │ → ThreadData: 创建工作目录 │ → Uploads: 注入文件信息 │ → Sandbox: 获取执行环境 │ → Memory: 注入长期记忆到系统提示词 │ → ... │ 7. Agent 核心执行 │ → 大模型推理生成文本或决定调用工具 │ → 如果调用工具执行工具 → 将结果加入消息 → 再次推理 │ → 如果委派子任务创建 Sub-Agent → 异步执行 → 轮询结果 │ → 循环直到大模型决定返回最终回复 │ 8. 中间件链后处理17→1 逆序执行 │ → Title: 生成对话标题首轮 │ → Memory: 将对话加入记忆更新队列 │ → TokenUsage: 记录 Token 消耗 │ 9. StreamBridge 发布事件流 │ → publish(messages, 消息内容) │ → publish(events, 工具调用/子任务状态) │ → publish_end() 标记完成 │ 10. 前端通过 SSE 消费事件 │ → 逐字渲染 AI 回复 │ → 展示工具调用步骤 │ → 更新子任务状态卡片 │ → 显示生成的制品文件 │ 11. 用户看到完整的 AI 回复十、项目目录结构导航最后让我们对照代码目录理解每个部分对应的位置deer-flow/ ├── backend/ # ─── Python 后端 ─── │ ├── app/ # FastAPI 应用 │ │ ├── gateway/ # Gateway API │ │ │ ├── app.py # 应用入口 生命周期 │ │ │ ├── deps.py # 依赖注入StreamBridge, RunManager... │ │ │ └── routers/ # API 路由models, skills, memory... │ │ └── channels/ # IM 频道集成飞书/企微/Slack/Telegram │ ├── packages/harness/deerflow/ # 核心框架包 │ │ ├── agents/ # Agent 系统 │ │ │ ├── lead_agent/ # Lead Agent 工厂 提示词 │ │ │ ├── middlewares/ # 15 中间件实现 │ │ │ ├── memory/ # 记忆子系统 │ │ │ ├── thread_state.py # 状态模型定义 │ │ │ └── checkpointer/ # 状态持久化 │ │ ├── tools/ # 工具系统 │ │ │ ├── tools.py # 工具加载管线 │ │ │ └── builtins/ # 内置工具task, present_file... │ │ ├── subagents/ # 子智能体系统 │ │ ├── skills/ # 技能加载/解析/安装 │ │ ├── sandbox/ # 沙箱抽象和实现 │ │ ├── models/ # LLM Provider 适配 │ │ ├── mcp/ # Model Context Protocol 集成 │ │ ├── config/ # 配置加载AppConfig │ │ ├── runtime/ # 运行时RunManager, StreamBridge │ │ └── client.py # 嵌入式 Python 客户端 │ └── docs/ # 后端文档ARCHITECTURE.md, API.md... │ ├── frontend/ # ─── Next.js 前端 ─── │ └── src/ │ ├── app/ # 页面路由App Router │ ├── components/ # UI 组件workspace, landing, ui │ └── core/ # 业务逻辑 │ ├── api/ # LangGraph SDK 客户端 │ ├── threads/ # 对话流管理hooks.ts │ ├── config/ # URL 配置 │ ├── i18n/ # 国际化中/英 │ └── settings/ # 用户设置 │ ├── docker/ # ─── 部署配置 ─── │ ├── docker-compose.yaml # 生产 Docker 编排 │ ├── docker-compose-dev.yaml # 开发 Docker 编排 │ └── nginx/nginx.conf # Nginx 路由配置 │ ├── skills/ # ─── 技能库 ─── │ ├── public/ # 20 内置公共技能 │ └── custom/ # 用户自定义技能 │ ├── config.example.yaml # 配置模板 ├── .env.example # 环境变量模板 ├── extensions_config.example.json # 扩展配置模板 └── Makefile # 构建和部署命令总结本篇我们从宏观到微观系统梳理了 DeerFlow 的技术架构四层三服务架构— Nginx 统一入口LangGraphAgent 执行 Gateway配置管理 Frontend用户界面各司其职Nginx 路由层— 基于路径的精确分发内置 SSE 流式传输和 CORS 集中管理前后端通信— 前端通过 LangGraph SDK 建立流式连接事件驱动的实时渲染Agent 创建链路— 从模型解析、工具加载到中间件组装的完整工厂流程15 层中间件— 有序执行的处理管道覆盖初始化、安全、上下文管理、错误处理等横切关注点StreamBridge 事件系统— 生产者-消费者模式支持环形缓冲和客户端重连配置驱动— 三文件协同config.yaml .env extensions_config.json集中式配置管理理解了这些架构基础你就能更好地定位问题、理解日志输出并为后续深入学习各个子系统打下基础。下篇预告下一篇我们将聚焦 DeerFlow 的五大核心概念Lead Agent、Skills、Sub-Agents、Sandbox 和 Memory深入理解每个支柱的设计理念和工作原理。