DeerFlow Backend 深入解析:LangGraph 驱动的超长任务 SuperAgent 后端架构与实践指南
本指南以仓库 backend/README.md 为主体脉络,系统讲解 DeerFlow 后端的整体架构、核心组件(Lead Agent、中间件链、沙箱、子代理、记忆系统、工具生态、Gateway API 与 IM 渠道)、安装运行、配置体系、可观测性与开发规约,并结合 config.example.yaml 与 deerflow-harness 源码佐证底层实现。读完你将掌握:请求如何从 Nginx 路由到 Gateway 与内嵌 Agent 运行时、九层中间件如何协同支撑每轮对话、如何配置模型/沙箱/记忆/扩展,以及如何在本仓库中开发、迁移与测试。
一、整体架构与请求路由
DeerFlow 是一个基于 LangGraph 的 AI SuperAgent:支持沙箱内执行代码、浏览网页、管理文件、向子代理委派任务、在对话间保留持久记忆,并且所有执行都发生在按线程隔离的环境中。后端由内嵌运行时与 API 网关共同构成。
从 backend/README.md 的架构示意可以还原出如下拓扑:
┌──────────────────────────────────────┐
│ Nginx (Port 2026) │
│ Unified reverse proxy │
└───────┬──────────────────┬───────────┘
│
/api/langgraph/* │ /api/* (other)
rewritten to /api/* │
▼
┌────────────────────────────────────────┐
│ Gateway API (8001) │
│ FastAPI REST + agent runtime │
│ │
│ Models, MCP, Skills, Memory, Uploads, │
│ Artifacts, Threads, Runs, Streaming │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Lead Agent │ │
│ │ Middleware Chain, Tools, Subagents │ │
│ └────────────────────────────────────┘ │
└────────────────────────────────────────┘
前端(Next.js)、后端网关(FastAPI)与 LangGraph 兼容 API 统一由 Nginx(端口 2026)反向代理汇聚,内部路由规则如下:
/api/langgraph/*→ 重写为/api/*后进入 Gateway 的 LangGraph 兼容 API,负责 agent 交互、线程(threads)、流式输出(streaming);/api/*(其余请求)→ Gateway API,负责模型、MCP、技能、记忆、产物、上传以及线程本地数据清理;/(非 API 请求)→ 前端 Next.js Web 界面。
对应源码可以进一步阅读 gateway 路由模块(含 models.py、mcp.py、skills.py、memory.py、threads.py、runs.py、uploads.py、artifacts.py、channels.py 等)。需要留意的是,langgraph.json(位于 backend/langgraph.json)并不是默认服务入口——脚本与 Docker 部署走的是 Gateway 内嵌运行时,该文件仅为 LangGraph 工具链、Studio 或直接使用 LangGraph Server 时保留的兼容入口。
二、核心组件逐个拆解
2.1 Lead Agent:唯一的 LangGraph 主 Agent
后端运行时只有一个 LangGraph Agent,即 lead_agent,通过 make_lead_agent(config) 工厂创建(实现位于 agents/lead_agent/agent.py,其提示词与图装配见 lead_agent 与 agents/factory.py)。它聚合了五类能力:
- 动态模型选择:支持 thinking(思考)与 vision(视觉)能力开关;
- 中间件链:承载横切关注点,共 9 个中间件(见下节);
- 工具系统:沙箱工具、MCP 工具、社区工具与内置工具;
- 子代理委派:支持并行任务执行;
- 系统提示词:注入技能、记忆上下文与工作目录指引。
models[*] 中以 supports_thinking / supports_vision 标记模型能力;模型工厂与 providers 集中在 models。
2.2 中间件链:严格顺序的九层横切逻辑
中间件按严格顺序执行,每一层负责一个关注点。README 给出的对照表如下:
| # | Middleware | Purpose |
|---|---|---|
| 1 | ThreadDataMiddleware | 为每个线程创建隔离目录(workspace、uploads、outputs) |
| 2 | UploadsMiddleware | 将新上传的文件注入会话上下文 |
| 3 | SandboxMiddleware | 获取用于代码执行的沙箱环境 |
| 4 | SummarizationMiddleware | 接近 token 上限时压缩上下文(可选) |
| 5 | TodoListMiddleware | 在 plan 模式中跟踪多步任务(可选) |
| 6 | TitleMiddleware | 首轮交互后根据用户原始请求自动生成会话标题;纯附件消息回退为 New Conversation |
| 7 | MemoryMiddleware | 将会话排队供异步记忆抽取 |
| 8 | ViewImageMiddleware | 为支持视觉的模型注入图像数据(条件性) |
| 9 | ClarificationMiddleware | 拦截澄清请求并中断执行(必须位于最后) |
上述中间件的源码实现位于 agents/middlewares(例如 memory_middleware.py、summarization_middleware.py、clarification_middleware.py),沙箱生命周期中间件则在 sandbox/middleware.py。需要指出的是,从仓库源码结构看中间件远不止 9 个——README 所列是主链路上顺序执行的核心横切层,另有 dangling_tool_call_middleware.py、loop_detection_middleware.py、llm_error_handling_middleware.py、skill_tool_policy_middleware.py、terminal_response_middleware.py 等安全/健壮性中间件共同组成完整运行链。
2.3 沙箱系统:按线程隔离的执行环境
沙箱提供按线程隔离的执行能力,并通过虚拟路径翻译把“虚拟路径”映射到“线程专属物理目录”:
- 抽象接口:
execute_command、read_file、write_file、list_dir,定义于 sandbox/sandbox.py; - 两个 Provider:
LocalSandboxProvider(直接使用宿主机文件系统,见 sandbox/local)与AioSandboxProvider(基于 Docker,位于community/)。异步运行时路径使用异步沙箱生命周期钩子,使启动、就绪轮询与释放都不会阻塞事件循环;AioSandboxProvider在 acquire/reuse 时会校验 active-cache 与 warm-pool 中的容器,丢弃确认死亡的条目,从而在容器意外退出后仍能为线程提供全新沙箱,同时保持get()为纯内存查找。后端健康检查失败会被当作“状态未知”而非“死亡”;发现阶段无法确认的容器不会被采纳(acquire 会回退为创建而非报错)。 - 虚拟路径:
/mnt/user-data/{workspace,uploads,outputs}→ 线程专属物理目录; - 技能路径:
/mnt/skills→deer-flow/skills/目录; - 技能加载:递归发现
skills/{public,custom}下的嵌套SKILL.md,并保留嵌套容器路径; - SkillScan:在安装及 agent 管理的技能写入时,先于 LLM 技能扫描器执行原生离线确定性扫描,
CRITICAL级发现会阻断,警告级发现进入 LLM 上下文; - 文件写入安全:
str_replace按(sandbox.id, path)串行化 read-modify-write,使隔离沙箱即使虚拟路径相同也保持并发; - 工具集合:
bash、ls、read_file、write_file、str_replace。其中write_file默认覆盖并在末尾提供append选项;LocalSandboxProvider下bash默认禁用(该 Provider 不是 shell 访问的安全隔离边界),如需隔离的 shell 访问应改用AioSandboxProvider。工具实现见 sandbox/tools.py。
沙箱还支持额外的宿主目录挂载(mounts)、工具输出截断上限以及单条 bash 命令的最大墙钟时间(见后文配置)。macOS 上 AIO Sandbox 优先使用 Apple Container(可用时),其他平台使用 Docker。
2.4 子代理系统:异步并发委派
子代理让 Lead Agent 通过 task() 工具把任务异步委派给后台运行的专业 Agent:
- 内置 Agent:
general-purpose(完整工具集)与bash(命令专家,仅在具备 shell 访问时暴露); - 并发限制:每轮最多 3 个子代理(
subagent_runtime.max_running默认为 3),单个内置子代理默认超时 1800 秒(30 分钟);另有max_queued、admission_policy(queue/reject)与queue_timeout_seconds描述进程级执行容量; - 执行方式:后台线程池执行并带状态跟踪与 SSE 事件;
- 调用流:Agent 调用
task()工具 → executor 在后台运行子代理 → 轮询直至完成 → 返回结果。
实现集中于 subagents(内置定义见 subagents/builtins,执行引擎为 executor.py,注册表为 registry.py)。内置默认 max_turns:general-purpose=150、bash=60;config.yaml 可对单类 Agent 覆盖超时、轮数与 token 预算,也可定义 custom_agents(自定义提示词、工具白名单、技能白名单与模型),自定义 Agent 经 task 工具与内置类型并列可用。所有子代理默认继承 Lead Agent 的模型,可在 subagents.agents.<name>.model 中覆盖(须匹配 models: 中已定义的名称)。作为确定性兜底,max_total_per_run(默认 6,合法范围 1–50)限制单次 Lead Agent run 内允许委派子代理的总次数。
2.5 记忆系统:LLM 驱动的跨会话持久上下文
记忆机制由 LLM 驱动,把对话中提炼的用户画像、事实与偏好持久化,用于后续会话注入:
- 自动抽取:分析会话,提取用户背景、事实与偏好;
- 作用域安全写入:中间件抽取仅存储持久、描述性的用户级事实;全局摘要同样要求描述性权威;当作用域元数据缺失或属于任务/项目本地作用域时,矛盾移除与合并事实会 fail closed;
- 原子替换:与替换绑定的矛盾移除只有在替换通过作用域/置信度门槛、去重与事实数量裁剪后才执行;
- 结构化存储:用户上下文(工作/个人/置顶)、历史以及带置信度分数的事实;
- 防抖更新:批量聚合更新以最小化 LLM 调用(可配置等待时间);
- 系统提示词注入:Top 事实 + 上下文注入 Agent 提示词;
- Run 级记忆身份:
GET /api/threads/{thread_id}/runs/{run_id}/events?event_types=context:memory返回生效隐藏记忆块的 SHA-256 身份,而无需把记忆文本复制进事件存储; - 读取失败策略:严格后端策略(含历史
fail_closed)会停止当前轮次,包括 5 秒异步注入截止线;fail-open 读取在无新上下文时继续;超时处理不等待空闲 worker——超时读仍可能占用其 worker 直到后端返回; - 存储介质:JSON 文件,基于 mtime 的缓存失效。
实现位于 agents/memory。记忆后端可插拔:memory.manager_class 支持已注册后端名(如 deermem/mem0/noop)或指向 MemoryManager 子类的点分路径,后端私有参数经 memory.backend_config 透传(含 storage_path、model、debounce_seconds、max_facts、fact_confidence_threshold、max_injection_tokens、token 计数方式以及 staleness 定期清理参数组等)。
2.6 工具生态
| Category | Tools |
|---|---|
| Sandbox | bash、ls、read_file、write_file、str_replace |
| Built-in | present_files、ask_clarification、view_image、task(子代理委派) |
| Community | Tavily(网页搜索)、Jina AI(网页抓取)、Crawl4AI(网页抓取)、Firecrawl(爬取)、fastCRW(爬取)、DuckDuckGo(图片搜索) |
| MCP | 任意 Model Context Protocol 服务器(stdio、SSE、HTTP 传输) |
| Skills | 经系统提示词注入的领域专属工作流 |
内置工具源码见 tools/builtins,社区工具与第三方 Provider 位于 deerflow.community 模块树(例如 web_search 工具在 config.example.yaml 中同时提供了 DuckDuckGo、SearXNG、Serper、Serply、Brave、Tavily、InfoQuest、腾讯云、Exa、Firecrawl、GroundRoute、fastCRW 等多个可选实现,默认启用免 API key 的 DuckDuckGo 后端)。tool_groups(web、file:read、file:write、bash、browser、knowledge)用于工具组织与访问控制,tools 的每条定义都包含 name、group 与 use(模块路径)。
2.7 Gateway API:前端集成的 REST 端点
Gateway 是承载 REST 端点的 FastAPI 应用(应用装配见 gateway/app.py)。README 列出的核心路由包括:
| Route | Purpose |
|---|---|
GET /api/models |
列出可用 LLM 模型 |
GET/PUT /api/mcp/config |
管理 MCP 服务器配置 |
POST /api/mcp/cache/reset |
重置 MCP 工具缓存,使其下次使用时重新加载 |
GET/PUT /api/skills |
列出与管理技能 |
POST /api/skills/install |
从 .skill 归档安装技能 |
GET /api/memory |
读取记忆数据 |
POST /api/memory/reload |
强制重载记忆 |
GET /api/memory/config |
记忆配置 |
GET /api/memory/status |
组合配置 + 数据 |
GET /api/threads/{id}/runs/{run_id}/events |
单次 run 的调试/审计事件;event_types=context:memory 过滤出有效记忆身份 |
POST /api/threads/{id}/uploads |
上传文件(自动把 PDF/PPT/Excel/Word 转成 Markdown,拒绝目录路径,同一请求内重复文件名自动重命名) |
GET /api/threads/{id}/uploads/list |
列出已上传文件 |
DELETE /api/threads/{id} |
在 LangGraph 线程删除后清理 DeerFlow 管理的本地线程数据;意外失败记录在服务端并返回通用 500 详情 |
GET /api/threads/{id}/artifacts/{path} |
提供生成的产物文件 |
2.8 IM 渠道
IM 桥接支持 飞书(Feishu)、Slack 与 Telegram:Slack 与 Telegram 仍走最终 runs.wait() 响应路径;飞书改为经 runs.stream(["messages-tuple", "values"]) 流式返回,在渠道管理器内部串行化同线程的快速连续回合,并按源消息原位更新单张线程内卡片。飞书卡片更新时,DeerFlow 为每条入站消息保存运行中卡片的 message_id,持续 patch 同一卡片直至 run 结束,从而保留既有 OK/DONE 反应流;当既有飞书主题内出现后续消息而上一轮仍在运行时,后续消息会等待映射到的 DeerFlow thread_id,并在该精确源消息上收到排队/运行卡片,且保留紧凑的源消息引用块以区分快速连问。
Discord 在入站消息处理让出控制权之前注册每个“输入中”指示器循环,并在渠道停止后拒绝启动新的 typing 任务;typing 任务归属 Discord 专属事件循环,正常关闭会在关闭客户端前于该循环上调度有界取消、等待与映射清理,从而串行化主线程与 Discord 线程的注册/清理,同时避免关闭挂起与跨循环 RuntimeError。
三、快速上手:安装、配置与运行
3.1 环境要求
- Python 3.12+
uv包管理器(README 与 Makefile 均以 uv 为依赖安装载体)- 所选 LLM Provider 的 API key
3.2 安装步骤
cd deer-flow
# 复制配置文件
cp config.example.yaml config.yaml
# 安装后端依赖
cd backend
make install
Makefile 与 pyproject.toml 承载依赖与常用开发命令;容器化构建见 backend/Dockerfile。
3.3 最小配置与 API key
编辑项目根目录的 config.yaml(以 config.example.yaml 为蓝本)。README 给出了两个 OpenAI 示例条目:
models:
- name: gpt-4o
display_name: GPT-4o
use: langchain_openai:ChatOpenAI
model: gpt-4o
api_key: $OPENAI_API_KEY
supports_thinking: false
supports_vision: true
- name: gpt-5-responses
display_name: GPT-5 (Responses API)
use: langchain_openai:ChatOpenAI
model: gpt-5
api_key: $OPENAI_API_KEY
use_responses_api: true
output_version: responses/v1
supports_vision: true
然后导出对应的 API key:
export OPENAI_API_KEY="your-api-key-here"
3.4 模型配置要点(结合 config.example.yaml 深入)
config.example.yaml 中的注释还揭示了模型条目更完整的语义,部署前建议逐项核对:
use的格式为包名.子包.模块:类名/变量名,按模块路径引用 Provider 类。若 Provider 模块缺失,DeerFlow 会返回带安装指引的可操作错误(例如提示uv add langchain-google-genai)。max_tokens是每次调用的输出上限;context_window是提示词 + 补全的总上下文容量,驱动 UI 的实时“% context used”指示并供给summarization.trigger的fraction类型触发器解析阈值。第三方 OpenAI 兼容模型没有内置 profile,不设置context_window时 fraction 触发器会降级(丢弃并告警)而不是使 Agent 构建崩溃。- 支持添加
pricing块(单一币种,按每百万 token 计价)在控制台展示真实成本。 - 使用需 thinking 的厂商模型时,推荐用补丁 Provider 保留 reasoning 字段跨多轮工具调用回放:例如 DeepSeek 用
deerflow.models.patched_deepseek:PatchedChatDeepSeek(patched_deepseek.py)、MiMo 用PatchedChatMiMo、StepFun 用PatchedChatStepFun、MiniMax 用PatchedChatMiniMax、OpenAI 兼容网关用PatchedChatOpenAI;Anthropic 开启 thinking 时必须同时配置when_thinking_enabled.thinking.budget_tokens(最小 1024 且须小于max_tokens),否则会静默回退到非 thinking 模式。 - Ollama 请使用
langchain_ollama:ChatOllama原生 Provider(其/v1/chat/completions兼容端点不会把 reasoning 作为独立字段返回);本地/容器地址在 Docker 部署时应写host.docker.internal。 - 配置值以
$开头时解析为环境变量。
3.5 启动运行
完整应用(项目根目录执行):
make dev # 启动 Gateway + Frontend + Nginx
访问地址:http://localhost:2026
仅后端(backend 目录执行):
# Gateway API + 内嵌 Agent 运行时
make dev
Gateway 直连地址:http://localhost:8001
终端工作台(TUI)——无需任何服务的内嵌运行时终端 UI:
uv pip install 'deerflow-harness[tui]' # 可选 'textual' 依赖
deerflow # 启动 TUI
deerflow --print "summarize this repo" # 无头单次执行
deerflow --recursion-limit 250 --print "run a longer task"
TUI 中打开的会话会出现在 Web UI 侧边栏(它把共享的 threads_meta 存储写入本地默认用户之下),详见 backend/docs/TUI.md。
四、工程目录结构与 langgraph.json 的角色
deerflow-harness 是打包为 Python 库的核心运行时(以 deerflow.* 导入),目录结构如下(摘自 README 并经源码核对):
backend/
├── packages/harness/ # deerflow-harness 包(import: deerflow.*)
│ └── deerflow/
│ ├── agents/ # Agent 系统
│ │ ├── lead_agent/ # 主 Agent(工厂、提示词)
│ │ ├── middlewares/ # 中间件组件
│ │ ├── memory/ # 记忆抽取与存储
│ │ └── thread_state.py # ThreadState schema
│ ├── sandbox/ # 沙箱执行
│ │ ├── local/ # 本地文件系统 Provider
│ │ ├── sandbox.py # 抽象接口
│ │ ├── tools.py # bash、ls、read/write/str_replace
│ │ └── middleware.py # 沙箱生命周期
│ ├── subagents/ # 子代理委派
│ │ ├── builtins/ # general-purpose、bash agents
│ │ ├── executor.py # 后台执行引擎
│ │ └── registry.py # Agent 注册表
│ ├── tools/builtins/ # 内置工具
│ ├── mcp/ # MCP 协议集成
│ ├── models/ # 模型工厂
│ ├── skills/ # 技能发现与加载
│ ├── config/ # 配置系统
│ ├── runtime/ # 内嵌 run 执行(RunManager、StreamBridge)
│ ├── persistence/ # Checkpointer/store 引擎与 schema 迁移
│ ├── guardrails/ # 工具调用前授权 Provider
│ ├── tracing/ # Tracer 工厂与 trace 元数据
│ ├── uploads/ # 上传管理器
│ ├── tui/ # 终端 UI(`deerflow` console 脚本)
│ ├── community/ # 社区工具与 Provider
│ ├── reflection/ # 动态模块加载
│ └── utils/ # 工具函数
├── app/ # FastAPI Gateway + IM 渠道(import: app.*)
│ ├── gateway/ # Gateway API
│ │ ├── app.py # 应用装配
│ │ └── routers/ # 路由模块
│ └── channels/ # IM 渠道集成
├── docs/ # 文档
├── tests/ # 测试套件
├── langgraph.json # LangGraph 图注册表(供工具链/Studio 兼容)
├── pyproject.toml # Python 依赖
├── Makefile # 开发命令
└── Dockerfile # 容器构建
如需启动可选的独立开发服务器并打开其 Studio 地址:
cd backend
uv run langgraph dev --allow-blocking
需在 backend/ 下运行以便 CLI 发现 langgraph.json。要点:该内存态服务器仅面向开发与测试而非生产部署;--allow-blocking 允许 DeerFlow 在本地 Studio 请求期间执行同步配置与图工厂装配,并非生产设置;本地 Studio 认证与已注册图发现自动处理,无需自定义连接头。Assistant 归属/来源由服务器盖章,常规 assistant 版本选择仍然可用。在锁定本地运行时加载持久化开发存储前,DeerFlow 会修复遗留 assistant 行与版本历史,防止旧元数据重新激活仅服务端权限或被运行时启动清理丢弃。依赖变更后需执行 uv sync;该兼容路径要求声明的 LangGraph 运行时版本,并在持久化存储契约不符时告警。这一基于文件的 custom-app 加载路径已被后端回归测试套件覆盖。
五、配置体系详解
5.1 主配置 config.yaml
放在项目根目录,以 $ 开头的值解析为环境变量。核心小节如下:
models— 带类路径、API key、thinking/vision 标志的 LLM 配置tools— 带模块路径与分组的工具定义tool_groups— 逻辑工具分组sandbox— 执行环境 Providerskills— 技能目录路径title— 自动标题生成设置summarization— 上下文摘要设置subagents— 子代理系统(启/停)memory— 记忆系统设置(enabled、storage、debounce、facts 上限)- 其他顶层键(详见 config.example.yaml):
config_version(schema 变更时递增,旧配置可运行make config-upgrade合并新字段)、log_level、token_usage、token_budget(每 run 硬性 token 上限,可设置 warn/hard-stop 阈值)、max_recursion_limit(对客户端提交的 recursion_limit 硬性封顶,超出被钳制到该上限,非法/非正值回退服务端默认 100)、uploads(应用级上传限制与文档转换开关,如auto_convert_documents: false与pdf_converter: auto)、skill_scan、verification(结果回执)等。
沙箱小节默认选择本地沙箱(直接宿主执行),并明确关闭宿主 bash:
sandbox:
use: deerflow.sandbox.local:LocalSandboxProvider
allow_host_bash: false # 仅对完全可信的单用户本地工作流开启
bash_output_max_chars: 20000
read_file_output_max_chars: 50000
ls_output_max_chars: 20000
bash_command_timeout: 600
容器化 AIO Sandbox 版本则切换为 deerflow.community.aio_sandbox:AioSandboxProvider,并支持容器镜像钉版、replicas(默认 3,最近最少使用驱逐)、出站网络策略(open/isolated/allowlist,受限模式要求 Docker Engine 28+,私有/回环/链路本地/组播/云元数据地址始终被拒)、thread_data_mounts、环境变量注入、跨实例容器所有权(多 Gateway 实例共享一个容器后端时须设置 ownership.type: redis)等高级项。完整的参数注释见 config.example.yaml。
标题生成默认开启(max_words: 6、max_chars: 60;model_name: null 使用快速本地回退,设置模型名则改用 LLM 生成)。
摘要配置支持多触发条件(OR 逻辑):按 token 数(默认 32000)、消息数或模型输入上限比例(fraction),以及摘要后保留策略(默认保留最近 10 条消息)。详见 config.example.yaml。
5.2 扩展配置 extensions_config.json
MCP 服务器与技能状态统一放在单个文件中(仓库根目录的 extensions_config.example.json 提供模板)。README 给出的完整示例:
{
"mcpServers": {
"github": {
"enabled": true,
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_TOKEN": "$GITHUB_TOKEN"}
},
"secure-http": {
"enabled": true,
"type": "http",
"url": "https://api.example.com/mcp",
"oauth": {
"enabled": true,
"token_url": "https://auth.example.com/oauth/token",
"grant_type": "client_credentials",
"client_id": "$MCP_OAUTH_CLIENT_ID",
"client_secret": "$MCP_OAUTH_CLIENT_SECRET"
}
},
"postgres": {
"enabled": false,
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"],
"description": "PostgreSQL database access",
"routing": {
"mode": "prefer",
"priority": 50,
"keywords": ["orders", "users", "SQL", "database", "table"]
},
"tools": {
"query": {
"routing": {
"priority": 100,
"keywords": ["query database", "orders table", "metrics"]
}
}
}
}
},
"skills": {
"pdf-processing": {"enabled": true}
}
}
routing 会向 Agent 提示词注入“软性”MCP 偏好:让模型在匹配请求时优先选用配置好的 MCP 工具,但并不禁止其他工具。当 tool_search.enabled=true 推迟(defer)MCP schema 时,命中的 routing 元数据可在模型调用前把最多 tool_search.auto_promote_top_k 个被推迟的 schema 自动提升。
5.3 环境变量
DEER_FLOW_CONFIG_PATH— 覆盖 config.yaml 位置DEER_FLOW_EXTENSIONS_CONFIG_PATH— 覆盖 extensions_config.json 位置- 模型 API key:
OPENAI_API_KEY、ANTHROPIC_API_KEY、DEEPSEEK_API_KEY等 - 工具 API key:
TAVILY_API_KEY、GITHUB_TOKEN等
结合 config.example.yaml 注释还常见:DEER_FLOW_PROJECT_ROOT(显式指定项目根)、DEER_FLOW_HOME(运行时数据目录,默认项目根下的 .deer-flow)、DEER_FLOW_DATE_TIMEZONE(注入 Agent 的会话日期时区)、DEER_FLOW_SKILLS_PATH、DEER_FLOW_STREAM_BRIDGE_REDIS_URL 等。
六、可观测性:LangSmith / Langfuse / 双 Provider
DeerFlow 内置 LangSmith 集成。启用后,所有 LLM 调用、Agent 运行、工具执行与中间件处理都会被追踪并显示在 LangSmith 控制台。配置方式(写在项目根 .env 中):
LANGSMITH_TRACING=true
LANGSMITH_ENDPOINT=https://api.smith.langchain.com
LANGSMITH_API_KEY=lsv2_pt_xxxxxxxxxxxxxxxx
LANGSMITH_PROJECT=xxx
兼容旧变量:LANGCHAIN_TRACING_V2、LANGCHAIN_API_KEY、LANGCHAIN_PROJECT、LANGCHAIN_ENDPOINT 仍受支持;两者同时设置时 LANGSMITH_* 优先。
Langfuse 追踪面向 LangChain 兼容的运行:
LANGFUSE_TRACING=true
LANGFUSE_PUBLIC_KEY=pk-lf-xxxxxxxxxxxxxxxx
LANGFUSE_SECRET_KEY=sk-lf-xxxxxxxxxxxxxxxx
LANGFUSE_BASE_URL=https://cloud.langfuse.com
自托管 Langfuse 时,把 LANGFUSE_BASE_URL 指向你的 Langfuse 主机即可。
双 Provider 行为:若同时启用 LangSmith 与 Langfuse,DeerFlow 会初始化并挂接两个 callback,同一份运行数据同时上报两套系统。若某个 Provider 被显式启用但凭据缺失或 callback 无法初始化,DeerFlow 会在模型创建期间初始化追踪时报错,而不会静默禁用追踪。Docker 环境:docker-compose.yaml 默认关闭追踪(LANGSMITH_TRACING=false),请在 .env 中设置 LANGSMITH_TRACING=true 与/或 LANGFUSE_TRACING=true 及对应凭据后启用容器化部署的追踪。相关工厂与元数据实现在 deerflow/tracing。
七、开发:命令、Schema 迁移与测试
7.1 Make 目标
make install # 安装依赖
make dev # 运行 Gateway API + 内嵌 Agent 运行时(安全 reload,端口 8001)
make gateway # 运行 Gateway API(不 reload,端口 8001)
make lint # 运行 linter(ruff)
make format # 格式化代码(ruff)
make detect-blocking-io # 盘点可能阻塞后端事件循环的 blocking IO
make migrate-rev MSG="..." # 针对实时 ORM 模型自动生成新 alembic revision
注意:make dev 会预创建并把 DEER_FLOW_HOME(默认 backend/.deer-flow)与 backend/sandbox 从 Uvicorn 的 reload 监视器中排除。应使用该目标而非裸 uvicorn --reload:Agent 任务会在 DEER_FLOW_HOME 下写 Python 与其他运行时文件,监视该目录会在 run 进行中重启 Gateway。
7.2 Schema 迁移
DeerFlow 的应用表(runs、threads_meta、feedback、users、run_events 以及 channel_* 表)由 alembic 管理。Gateway 启动时通过 bootstrap_schema(engine, backend=...) 自动执行 alembic upgrade head,因此生产环境操作者不需要手动运行 alembic。Bootstrap 并发安全(跨进程使用 Postgres advisory lock;单 SQLite 进程内使用每引擎 asyncio.Lock),并且对已存在 schema(空 / 遗留 / 已版本化)幂等。
修改 ORM 模型后,把变更作为新 revision 提交到 packages/harness/deerflow/persistence/migrations/versions/:
make migrate-rev MSG="add foo column to runs"
该目标调用 backend/scripts/_autogen_revision.py:它会在 head 新建一个临时 SQLite 并与实时模型做 diff,因此干净的 checkout 无需预置 ./data/deerflow.db。提交前请审查生成的文件,并把裸的 op.add_column / op.drop_column 换成 migrations/_helpers.py 中的幂等辅助函数。项目刻意不提供 make migrate / make migrate-stamp——Gateway 启动是唯一执行路径,从而杜绝运维误操作。完整设计见 backend/CLAUDE.md。
7.3 代码风格
- Linter/Formatter:
ruff - 行长上限:240 字符
- Python:3.12+,带类型注解
- 引号:双引号
- 缩进:4 空格
对应配置见 backend/ruff.toml 与 backend/pyproject.toml。
7.4 测试
# 默认离线后端测试套件(排除实时外部 API 与 blocking-I/O 测试)
make test
# 严格 blocking-I/O 套件
make test-blocking-io
# 显式真实 API 的 DeerFlowClient 集成套件
make test-live
实时套件需要合法的根级 config.yaml 与 API 凭据,可能产生 API 费用或创建本地沙箱、产物与文件,因此不在默认测试或 CI 中运行。直接以 pytest 调用 backend/tests/test_client_live.py 还需设置 DEER_FLOW_RUN_LIVE_TESTS=1。
make detect-blocking-io 对后端业务代码做静态扫描,找出可能运行在事件循环上且未被测试覆盖的 blocking IO,向人工审查输出简洁汇总,并把完整 JSON 发现写入仓库根目录 .deer-flow/blocking-io-findings.json(无论从仓库根还是 backend/ 调用)。JSON 发现同时包含宽泛 IO 分类与审查导向字段(priority、location、blocking_call、event_loop_exposure、reason、code)。priority 是由操作类型决定的确定性审查排序,并非 bug 证明;同文件裸名调用按函数名解析,因此同一文件内重名的辅助函数可能保守地多报异步可达性。
后端测试套件位于 backend/tests,覆盖客户端合约(如 test_client.py、test_client_e2e.py)、记忆(test_memory_* 系列)、沙箱(test_aio_sandbox_*、test_local_sandbox_* 系列)、运行事件流等,可作为各模块行为的活文档。
八、技术栈
README 声明的依赖基线(以 backend/pyproject.toml 与 backend/uv.lock 为准):
- LangGraph(1.0.6+)— Agent 框架与多 Agent 编排
- LangChain(1.2.3+)— LLM 抽象与工具系统
- FastAPI(0.115.0+)— Gateway REST API
- langchain-mcp-adapters — Model Context Protocol 支持
- agent-sandbox — 沙箱化代码执行
- markitdown — 多格式文档转换
- tavily-python / firecrawl-py — 网页搜索与爬取
九、延伸阅读
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00