DeerFlow 后端开发指南:CLAUDE.md 与 AGENTS.md 协同的 Agent 指导机制及 DeerFlow 后端核心约定
DeerFlow 是一个基于 LangGraph 的长周期超级 Agent 系统,其后端采用“Gateway API + 内嵌 Agent 运行时”的全栈架构。本文以 backend/CLAUDE.md 为骨架,完整解读它如何通过 @AGENTS.md 导入机制将同一份开发指南共享给 Claude Code、Codex 等多种编码 Agent,并深入拆解 backend/AGENTS.md 中定义的后端架构分层、命令体系、TDD 规范、代码风格与关键运行时约定。读完本文,你可以准确理解 DeerFlow 后端的目录职责、依赖边界与开发流程,并按仓库约定开展后端开发与 Agent 协作。
一、CLAUDE.md 的共享机制:一份指南,多个 Agent 复用
backend/CLAUDE.md 全文只有寥寥数行:
The backend agent guidance lives in AGENTS.md so it is shared across coding agents (Claude Code, Codex, and others). Claude Code imports it below.
@AGENTS.md
其设计意图非常明确:后端的 Agent 指导内容统一放在 backend/AGENTS.md,CLAUDE.md 仅作为入口,通过 Claude Code 的 @文件 导入语法引用它。这样做的收益是:
- 单一事实来源(Single Source of Truth):架构约定、命令说明、开发规范只维护一份,避免 Claude Code 与 Codex 等工具读到不一致的指南;
- 跨 Agent 共享:任何支持
AGENTS.md约定的编码 Agent 进入backend/目录时都能直接获取指导,而CLAUDE.md只为 Claude Code 提供兼容入口。
这个模式在仓库中是成套出现的:根目录 CLAUDE.md 与 AGENTS.md、前端 frontend/CLAUDE.md 与 frontend/AGENTS.md 均遵循同样的“入口文件 + 共享指南”结构。
此外,仓库用脚本对 AGENTS.md 文件链做了体量预算管控:scripts/check_agent_guidance.py 定义了分层软/硬阈值(根级 16KB/20KB、模块级 28KB/32KB、目录级 40KB/48KB、整条祖先链 80KB/96KB),由 make check-agent-guidance 触发,并通过 backend/tests/test_agent_guidance_check.py 纳入测试。这意味着 backend/AGENTS.md 本身也受到体积约束,各子系统因此把更细的说明下沉到更靠近代码目录的 AGENTS.md 中——backend/AGENTS.md 末尾明确要求:“More specific AGENTS.md files in backend code directories contain the subsystem sections split from this file. Follow the nearest file in the directory tree.”
仓库中实际存在的子目录指南包括 backend/packages/harness/deerflow/agents/AGENTS.md、backend/packages/harness/deerflow/runtime/AGENTS.md、backend/packages/harness/deerflow/mcp/AGENTS.md、backend/packages/harness/deerflow/subagents/AGENTS.md、backend/app/gateway/AGENTS.md、backend/app/channels/AGENTS.md 等,形成“根指南 + 模块指南 + 目录指南”三级体系。
二、项目总览:全栈架构与端口布局
backend/AGENTS.md 开篇给出 DeerFlow 的定位:一个基于 LangGraph 的 AI 超级 Agent 系统,后端提供具备沙箱执行、持久化记忆、子代理委派与可扩展工具集成的“超级 Agent”,全部运行在按线程隔离的环境中。
架构上由四个组件构成:
| 组件 | 端口 | 职责 |
|---|---|---|
| Gateway API | 8001 | REST API + 内嵌的 LangGraph 兼容 Agent 运行时 |
| Frontend | 3000 | Next.js Web 界面 |
| Nginx | 2026 | 统一反向代理入口 |
| Provisioner | 8002(Docker dev 中可选) | 仅当沙箱配置为 provisioner/Kubernetes 模式时启动 |
从源码结构可以印证:backend/packages/harness/deerflow/ 目录下确实存在 agents/、sandbox/、subagents/、mcp/、skills/、models/、config/、community/、runtime/ 等子包;运行时核心 RunManager + run_agent() + StreamBridge 位于 packages/harness/deerflow/runtime/(其中 runtime/runs/、runtime/stream_bridge/ 等模块可见),Nginx 将 /api/langgraph/* 暴露给外部并重写到 Gateway 原生的 /api/* 路由。
2.1 运行时关键约定(来自 AGENTS.md 的 Runtime 小节)
这段内容信息密度极高,是理解 DeerFlow 后端行为的关键,逐条继承如下:
- 统一的运行入口:
make dev、Docker dev 与生产环境都在 Gateway 内通过RunManager+run_agent()+StreamBridge运行 Agent 运行时(packages/harness/deerflow/runtime/)。 - 工具参数增量流:Gateway 会对
write_file与str_replace的参数 delta 做有界批处理流式下发(仅当客户端同时订阅values时);只消费消息的消费者保留原有按块(per-chunk)契约,而values通道保留完整的工具调用。 - 子图命名空间:开启
stream_subgraphs后,子图帧在 SSE 事件名中保留自己的命名空间(values|<ns>,LangGraph Platform 风格)而不是伪装成根帧——被委派的子代理继承父 checkpoint 命名空间,若将其values快照发布为裸values会在 SDK 客户端中整体替换线程视图(对应 issue #4399)。仅消费根帧的组件(文件工具块批处理器、子代理事件持久化、LLM 错误回退检测)会忽略带命名空间的帧;Web 前端不请求子图流式,子任务进度走根命名空间下的task_*自定义事件。 - 后台子代理身份的双轨制:provider 的
tool_call_id是ToolMessage、task_*SSE 事件、持久化生命周期事件、前端卡片以及公开契约ExtensionData.scope_id(存储为SubagentResult.external_task_id)的相关键;而SubagentExecutor.execute_async()生成的服务端完整execution_id则用于SubagentResult.task_id、进程级注册表、轮询、取消、超时与清理。由于 provider ID 在父运行之间不是全局唯一的,绝不能作为注册表的所有权键;调度器闭包保留自己的SubagentResult而不再通过可变注册表二次解析所有权。子代理终态的 token 用量走当前运行的ToolMessage.additional_kwargs,从消息状态归因,绝不经过进程级 provider-ID 缓存。 - 定时任务复用同一运行生命周期:调度器只决定“何时”运行,派发必须走既有 run 路径而非另起执行栈;
launch_scheduled_thread_run传入scheduler.recursion_limit(默认 1000,与 Web UI 的recursion_limit: 1000对齐,受max_recursion_limit钳制),该值在派发时从get_app_config()读取。 - 多实例调度约束:后台调度器默认单实例。
scheduler.multi_instance=true才启用跨 Gateway 实例的租约感知恢复,且要求共享 Postgres、run_ownership.heartbeat_enabled=true、run_events.backend=db,否则启动即拒绝该配置。多实例下:存活运行在 peer 启动时保留、过期 launch 认领回到持久队列、过期运行租约被原子接管、陈旧 launch 写入被租约所有权围栏、Postgres 咨询锁预算使max_concurrent_runs成为跨实例共享的launching/running行全局上限。 - 长时 MCP 工作使用独立持久任务运行时(
McpTaskService+mcp_tasks,租约式恢复),不把远程任务 ID 或状态轮询留在 Agent 循环内;只有 submit 对 Agent 可见,数据库是唯一事实来源,ThreadState只接收有界的当前线程投影。完整契约(租约、取消围栏、投递幂等、管理工具暴露)见 backend/packages/harness/deerflow/mcp/AGENTS.md。 extensions_config.json的运行时写入:该文件由 Gateway 在运行时写入(PUT/PATCH /api/mcp/config、MCP 开关、技能更新),因此生产 compose 将其挂载为读写,而config.yaml保持只读(:ro);Helm 会在 Gateway 启动前把 ConfigMap 种子拷贝到可写的 home 卷目录。由于进程内锁在多 worker 间会丢更新,每次读-改-写同时持有extensions_config_write_lock与伴生咨询锁extensions_config_file_lock。Docker 将 compose 文件挂为独立挂载点,Linux 在挂载点上rename()会返回EBUSY——所以atomic_write_extensions_config保留临时文件 + rename 路径,仅在EBUSY时回退为非原子就地覆盖(崩溃于写入中途会截断文件,此回退是“唯一能写成功的方式”,且每个目标仅首次以 warning 记录;其他 errno 照常抛出)。该行为由 backend/tests/test_compose_extensions_config_writable.py、backend/tests/test_extensions_config_atomic_write.py、backend/tests/test_helm_extensions_config_writable.py 三处固定。- 定时任务派发的原子状态机:
uq_scheduled_task_run_active(task_id WHERE status IN ('queued','launching','running'))保证每个任务至多一个非终态发生项;queued持久化且可跨重启,launching携带短 owner/expiry 租约且是唯一可调用正常 Gateway 派发路径的状态,running关联持久运行。每次发生项提供稳定的运行准入幂等键,使恢复后的派发重试复用同一持久运行;重用线程的ConflictError将launching退回queued,非冲突派发错误转为终态failed。等待中的行不占用max_concurrent_runs,原子队列认领强制预算;同线程 FIFO 将更旧的queued/launching/running行视为阻塞者。三个活动状态下任务定义保持不可变,PATCH/resume、暂停与删除在触碰发生项之前先在父任务行上串行化;暂停/删除原子中断既有queued行并拒绝launching/running行。恢复与多实例协调按确定性的 task-id/run-id 顺序加锁,并须在释放短 launch 认领前重建run_id、started_at与实时错误状态;launch/failure/timeout 记账在单个“父先行”事务中同时变更发生项与父任务,防止 peer 在两次写入之间认领被释放的任务;队列超时标记发生项失败并推进计划发生项,避免无限重排队;仓库写边界在绑定 SQLDateTime字段前强制序列化任务时间戳。
三、项目结构:目录树速查
backend/AGENTS.md 给出了完整目录树,这里完整继承(对源码核对后补充了实际存在的模块):
deer-flow/
├── Makefile # 根命令(check, install, dev, stop)
├── config.yaml # 主应用配置
├── extensions_config.json # MCP 服务器与技能配置
├── backend/ # 后端应用(本目录)
│ ├── Makefile # 仅后端命令(dev, gateway, lint)
│ ├── langgraph.json # LangGraph Studio 图配置
│ ├── packages/
│ │ ├── extension-api/ # 公开、宿主无关的扩展契约(import: deerflow_extension_api.*)
│ │ └── harness/ # deerflow-harness 包(import: deerflow.*)
│ │ ├── pyproject.toml
│ │ └── deerflow/
│ │ ├── agents/ # LangGraph Agent 系统
│ │ │ ├── lead_agent/ # 主 Agent(工厂 + 系统提示)
│ │ │ ├── middlewares/ # 中间件组件
│ │ │ ├── memory/ # 记忆抽取、队列、提示
│ │ │ └── thread_state.py # ThreadState schema
│ │ ├── sandbox/ # 沙箱执行系统
│ │ │ ├── local/ # 本地文件系统 provider
│ │ │ ├── sandbox.py # 抽象 Sandbox 接口
│ │ │ ├── tools.py # bash, ls, read/write/str_replace
│ │ │ └── middleware.py # 沙箱生命周期管理
│ │ ├── subagents/ # 子代理委派系统
│ │ │ ├── builtins/ # general-purpose, bash agents
│ │ │ ├── executor.py # 后台执行引擎
│ │ │ └── registry.py # Agent 注册表
│ │ ├── tools/builtins/ # 内建工具(present_files, ask_clarification, view_image, review_skill_package)
│ │ ├── mcp/ # MCP 集成(工具、缓存、客户端)
│ │ ├── integrations/ # 托管的第一方集成安装器(如 Lark CLI 技能包)
│ │ ├── extensions/ # Python 插件加载器、注册、定位与隔离
│ │ ├── models/ # 支持思考/视觉的模型工厂
│ │ ├── skills/ # 技能发现、加载、解析
│ │ ├── config/ # 配置系统(app、model、sandbox、tool 等)
│ │ ├── community/ # 社区工具(搜索/抓取、图片搜索、AIO 沙箱)
│ │ ├── reflection/ # 动态模块加载(resolve_variable, resolve_class)
│ │ ├── utils/ # 工具(网络、readability)
│ │ └── client.py # 内嵌 Python 客户端(DeerFlowClient)
│ ├── app/ # 应用层(import: app.*)
│ │ ├── gateway/ # FastAPI Gateway API
│ │ │ ├── app.py # FastAPI 应用
│ │ │ └── routers/ # 路由模块(models, mcp, memory, skills, uploads, threads, artifacts, agents, suggestions, channels)
│ │ └── channels/ # IM 平台集成
│ ├── scripts/benchmark/ # 独立可复现的后端基准
│ ├── tests/ # 测试套件
│ └── docs/ # 文档
├── frontend/ # Next.js 前端应用
└── skills/ # Agent 技能目录
├── public/ # 公开技能(已提交)
└── custom/ # 自定义技能(gitignored)
四、开发指南:文档更新策略与基准规范
4.1 文档更新策略(CRITICAL)
backend/AGENTS.md 将文档同步列为硬性要求:每次代码变更后必须更新 README.md 与 AGENTS.md:
- 面向用户的变更(功能、安装、用法)→ 更新
README.md; - 开发侧变更(架构、命令、工作流、内部系统)→ 更新
AGENTS.md;由于CLAUDE.md通过@AGENTS.md导入它,编辑AGENTS.md即同时更新两者; - 文档必须始终与代码库同步,保证准确性与时效性。
4.2 后端基准(Benchmark)规范
scripts/benchmark/ 存放针对生产后端行为的独立可复现测量与评估。核心规则:
- 基准可以导入被测生产函数,但不得复制或引入替代运行时实现;
- 外部数据集必须用不可变 revision 与 SHA-256 固定;调用方提供本地数据集路径,评估命令不得静默下载数据;
- 永不提交上游数据集文本、凭据、完整 provider 请求或响应头;提交的 manifest 只允许稳定 ID 与来源定位符,合成用例必须自我声明为合成;
- provider 凭据与端点从命名环境变量读取;模型 ID、推理参数、提示、重试规则、时钟、随机种子都要在评估配置中版本化;
- 公开的原始结果可包含用例 ID、策略决策、模型假设、评分与非秘密响应元数据;数据集问题、参考答案、记忆内容与完整 provider 载荷保留在本地忽略的运行目录中;
- 离线选择使用固定时钟与确定性排序,结果必须记录所用配置、manifest、提示、数据集与 git revision。
仓库中两个具名基准值得单独了解:
DeerMem 驱逐策略基准(scripts/benchmark/deermem_eviction/):评估 DeerMem 生产实现 select_facts_for_capacity(),仅比较历史 confidence 策略与 PR #4789 的可选 hybrid-v1,不得向该评估添加新的驱逐策略。从 backend/ 目录运行离线检查:
PYTHONPATH=. uv run python -m scripts.benchmark.deermem_eviction validate-contracts
PYTHONPATH=. uv run python -m scripts.benchmark.deermem_eviction validate --dataset "$LONGMEMEVAL_ORACLE_PATH"
PYTHONPATH=. uv run python -m scripts.benchmark.deermem_eviction run-policy \
--dataset "$LONGMEMEVAL_ORACLE_PATH" \
--output-dir /tmp/deermem-eviction-policy-run
PYTHONPATH=. uv run pytest tests/test_bench_deermem_eviction_*.py -q
离线测试套件不得依赖网络、provider 凭据或 LongMemEval 数据集;小型 LongMemEval 形状夹具必须是合成的、由测试生成。
并发基准(scripts/benchmark/concurrency/):测量多进程对 users 表的竞争(N 个独立 OS 进程,而非 asyncio 任务),对比 SQLite 与 Postgres——正是 backend/docs/CONFIGURATION.md 要求使用 Postgres 的场景。worker.py 直接通过 SQLAlchemy 连接(跳过编排器已执行一次的约 8.5 秒 Alembic bootstrap),并镜像应用的每连接 SQLite PRAGMAs;run_concurrency_bench.py 为每次运行播种一次性 Postgres schema,在计时前用 READY/GO 屏障同步 worker,遇到任何崩溃、操作数不足或 errors > 0 即非零退出。Postgres 运行需通过 --pg-url 提供一次性数据库,不触碰 public。从 backend/ 运行:
uv run python scripts/benchmark/concurrency/run_concurrency_bench.py \
--backend sqlite --workers 2,4,8,16 --ops-per-worker 50 --read-ratio 0.7
uv run pytest tests/test_bench_concurrency.py tests/test_bench_worker.py -q
五、命令体系:根目录与后端 Makefile
5.1 根目录命令(完整应用)
make check # 检查系统依赖
make install # 安装全部依赖(前端 + 后端)
make extension-install SOURCE=... # 安装并启用受信任的 Python 扩展
make extension-list # 列出已配置的 Python 扩展
make extension-enable NAME=... # 启用已安装的扩展
make extension-disable NAME=... # 禁用扩展(不卸载)
make extension-remove NAME=... # 移除托管扩展
make detect-thread-boundaries # 盘点后端 executor/线程/事件循环边界
make dev # 启动全部服务(Gateway + Frontend + Nginx),带 config.yaml 预检
make start # 本地启动生产服务
make stop # 停止全部服务
从根 Makefile 源码可以看到:extension-* 目标最终落到 uv run --frozen --no-group extensions deerflow extensions install/list/enable/disable/remove,通过环境变量传参并强制校验 SOURCE=/NAME= 必填;check 实际执行 scripts/check.py。
5.2 后端目录命令(仅后端开发)
make install # 安装后端依赖
make dev # Gateway API,热重载(端口 8001)
make gateway # 仅 Gateway API(端口 8001)
make test # 离线测试(无 live/blocking-io)
make test-live # live 测试(真实 API)
make test-blocking-io # 针对 tests/blocking_io/ 的严格 Blockbuster 门槛
make test-shard SPLITS=4 GROUP=2 # 一个时长感知的分片
make test-shard-durations # 刷新时长基线
make lint # ruff lint
make format # ruff format
make migrate-rev MSG="..." # 自动生成新的 alembic revision(见 Schema Migrations)
对照 backend/Makefile 的实现,几个细节值得注意:
make test实为pytest -m "not live" --ignore=tests/blocking_io tests/;make test-live需设置DEER_FLOW_RUN_LIVE_TESTS=1且执行-m live用例;test-shard基于 pytest-split 的least_duration算法按.test_durations文件中的真实墙钟耗时均衡分片;分片只读该文件(无--store-durations),避免并发 CI 任务写竞争,基线需在测试集有实质变更后用make test-shard-durations刷新。
make dev 的热重载陷阱:后端 dev 目标会预创建并排除 DEER_FLOW_HOME(默认 backend/.deer-flow)与 backend/sandbox 于 Uvicorn reload 监视器之外。不能替换为裸 uvicorn --reload——Agent 任务会向 DEER_FLOW_HOME 下写入 Python 等运行时文件,否则会在运行中途触发 Gateway 重启。后端 Makefile 的 dev 目标确实带 --reload-exclude="$(BACKEND_SANDBOX_HOME)" 与 --reload-exclude="$(DEER_FLOW_HOME)" 参数,与文档描述一致。
六、架构:Harness / App 严格分层
后端分为两层,依赖方向严格单向:
- Harness(
packages/harness/deerflow/):可发布的 Agent 框架包deerflow-harness,导入前缀deerflow.*。包含 Agent 编排、工具、沙箱、模型、MCP、技能、配置——构建和运行 Agent 所需的一切; - App(
app/):不发布的应用代码,导入前缀app.*。包含 FastAPI Gateway API 与 IM 渠道集成(Feishu、Slack、Telegram、DingTalk)。
依赖规则:App 可以导入 deerflow,deerflow 永不导入 app。该边界由 backend/tests/test_harness_boundary.py 强制——该测试用 AST 扫描 packages/harness/deerflow/ 下所有 Python 文件,发现任何 from app. 或 import app. 语句即失败。
导入约定示例:
# Harness 内部
from deerflow.agents import make_lead_agent
from deerflow.models import create_chat_model
# App 内部
from app.gateway.app import app
from app.channels.service import start_channel_service
# App → Harness(允许)
from deerflow.config import get_app_config
# Harness → App(禁止 — 由 test_harness_boundary.py 强制)
# from app.gateway.routers.uploads import ... # ← 会让 CI 失败
AGENTS.md 还给出两条工程细节:
- 包导入卫生:
deerflow.agents与deerflow.subagents包根惰性暴露重量级图/执行器入口点。deerflow.agents:make_lead_agent是 LangGraph Server 入口点——一个具体的薄模块级函数,因为 server 直接从模块字典解析图工厂;wrapper 把 lead-agent 与技能缓存的导入留在函数内部,使包导入保持轻量。只需要轻量类型、配置或注册表的内部模块应导入具体子模块,而不是在包根添加会拉入工具图或子代理执行器的急切导入。 ThreadMetaStore.search()的 JSON 过滤语义:在 memory、SQLite、PostgreSQL 三种后端保持一致——missing 与 null 不同、bool 与 int 不同,浮点过滤通过json_value_matches接受整数或实数 JSON 数值。
七、开发工作流:TDD 强制与测试策略
TDD 是强制要求:每个新功能或 Bug 修复必须附带单元测试,无例外。
- 测试写在
backend/tests/,遵循test_<feature>.py命名约定; - 变更前后都要运行
make test与make test-blocking-io两个离线目标; - 测试通过之前功能不算完成;
- 轻量配置/工具模块优先写无外部依赖的纯单元测试;
- 若模块在测试中引发循环导入,在
tests/conftest.py加sys.modulesmock(参考 backend/tests/conftest.py 中deerflow.subagents.executor的既有示例)。
# 默认离线测试
make test
# 严格阻塞 I/O 测试
make test-blocking-io
# 显式 live 集成测试(需要 config.yaml 与凭据;调用真实 API,可能产生本地副作用)
make test-live
# 运行某个测试文件
PYTHONPATH=. uv run pytest tests/test_<feature>.py -v
两个附加约定:直接 pytest 收集或执行 tests/test_client_live.py 在设置 DEER_FLOW_RUN_LIVE_TESTS=1 之前保持跳过,不得把该 opt-in 加进默认 CI 工作流;Jina 请求失败日志测试设置 dummy API key,以避免进程级一次性 missing-key 警告让断言依赖测试顺序或分片位置(missing-key 行为另有 backend/tests/test_jina_client.py 覆盖)。
八、运行应用:启动模式矩阵与 Nginx 路由
8.1 全量启动
从项目根运行 make dev,应用即在 http://localhost:2026 可用。全部启动模式:
| 本地前台 | 本地守护 | Docker Dev | Docker Prod | |
|---|---|---|---|---|
| Dev | ./scripts/serve.sh --dev / make dev |
./scripts/serve.sh --dev --daemon / make dev-daemon |
./scripts/docker.sh start / make docker-start |
— |
| Prod | ./scripts/serve.sh --prod / make start |
./scripts/serve.sh --prod --daemon / make start-daemon |
— | ./scripts/deploy.sh / make up |
| 动作 | 本地 | Docker Dev | Docker Prod |
|---|---|---|---|
| Stop | ./scripts/serve.sh --stop / make stop |
./scripts/docker.sh stop / make docker-stop |
./scripts/deploy.sh down / make down |
| Restart | ./scripts/serve.sh --restart [flags] |
./scripts/docker.sh restart |
— |
Nginx 路由规则:
/api/langgraph/*→ Gateway 内嵌运行时(8001),重写为/api/*;/api/*(其余)→ Gateway API(8001);/(非 API)→ 前端(3000)。
8.2 单独运行后端
从 backend 目录 make gateway 仅启动 Gateway API;不经过 Nginx 时直接访问 http://localhost:8001。
8.3 前端配置
前端用环境变量连接后端服务:
NEXT_PUBLIC_LANGGRAPH_BASE_URL:默认/api/langgraph(经 nginx);NEXT_PUBLIC_BACKEND_BASE_URL:默认为空字符串(经 nginx)。
从根目录 make dev 时,前端自动经 nginx 连接后端。
九、关键特性约定
9.1 网络搜索时效性(Web Search Recency)
DDG、Brave、Tavily、SearXNG 的 web_search 共享可选参数 time_range=day|week|month|year;省略时保持请求形状不变。映射规则:DDG → d|w|m|y,Brave → pd|pw|pm|py,Tavily/SearXNG 原样透传。对时效性搜索,DDGS 9.14.1 仅使用尊重 timelimit 的已启用 Brave、DuckDuckGo 与 Yahoo 引擎:auto/all 解析为该集合,不兼容的已配置引擎被移除,空集合回退到该集合——升级 DDGS 后需重新验证。
9.2 文件上传(File Upload)
多文件上传并自动文档转换:
- 端点:
POST /api/threads/{thread_id}/uploads; - 支持 PDF、PPT、Excel、Word 文档(经
markitdown转换); - 复制前拒绝目录输入,保证上传全有或全无;
- 从活动事件循环调用时每请求复用一个转换 worker;
- 文件存储在解析用户桶下线程隔离目录
users/{user_id}/threads/{thread_id}/user-data/uploads;IM 渠道通过user_id=关键字显式传 owner(见 IM Channels → Owner-scoped file storage),HTTP/内嵌调用方从get_effective_user_id()解析; - 同一上传请求内重复文件名自动加
_N后缀,避免后者截断前者; - Gateway HTTP 上传将字节暂存为
.upload-*.part文件,尺寸校验通过后才原子替换目标;这些暂存文件对上传列表、Agent 上传上下文、沙箱列表/搜索工具均不可见,并在 Gateway 启动时清扫(硬崩溃残留); - Gateway HTTP 上传/列表/删除处理器通过
deerflow.utils.file_io.run_file_io(专用保 ContextVar 的文件 IO 执行器)卸载文件系统工作;非挂载沙箱上传以SandboxProvider.acquire_async()获取沙箱,并把read_bytes()与sandbox.update_file()一并卸载; - 挂载上传路径同时跳过沙箱获取与按文件同步。对 AIO 远程/provisioner 部署需要显式且准确的
sandbox.thread_data_mounts: true;省略则保留后端自动检测; - Agent 经
UploadsMiddleware获得上传文件列表;标题生成继续用原始用户请求而非注入的上传上下文包装,纯附件消息回退为New Conversation。
详见 backend/docs/FILE_UPLOAD.md。
9.3 Plan Mode
面向复杂多步任务的 TodoList 中间件:
- 由运行时配置控制:
config.configurable.is_plan_mode = True; - 提供
write_todos工具做任务跟踪; - 同时只有一个任务 in_progress,实时更新。
详见 backend/docs/plan_mode_usage.md。
9.4 上下文摘要(Context Summarization)
接近 token 上限时自动摘要对话:
- 在
config.yaml的summarization键下配置; - 触发类型:tokens、messages 或最大输入的比例;
- 保留近期消息,仅摘要较早消息;
- 手动压缩使用
POST /api/threads/{id}/compact,复用同一个DeerFlowSummarizationMiddleware,写入带更新messages与summary_text的新 checkpoint,且只 bump 这些通道版本。该路由使用共享的reserve_checkpoint_write()边界(手动状态更新也用),其短生命期checkpoint_write线程操作与运行准入共享持久活动线程唯一性约束,防止 worker 本地或跨 worker 的 checkpoint 写竞争。
详见 backend/docs/summarization.md。
9.5 视觉支持(Vision Support)
对 supports_vision: true 的模型:
ViewImageMiddleware处理对话中的图片;- 向 Agent 工具集加入
view_image_tool; - 图片转 base64 后以隐藏消息追加到模型请求,携带保留 ID 前缀与服务端元数据标记;Gateway 从不可信输入中剥离该标记,中间件要求两个标识同时存在才认可是自己的消息。中间件在
wrap_model_call内部注入,载荷永不进入图状态:checkpoint 只保留轻量viewed_images元数据,客户端自选 ID 得以存活。它还在每次重建请求前清扫自己的消息,使被中断运行残留在旧 checkpoint 中的载荷停止被重发。
十、代码风格与文档索引
代码风格(与 backend/ruff.toml 一致,源码可验证):
- 使用
ruff做 lint 与格式化; - 行宽 240 字符(
line-length = 240,target-version = "py312"); - Python 3.12+ 并带类型标注;
- 双引号、空格缩进(
quote-style = "double",indent-style = "space")。
详细文档索引(backend/AGENTS.md 尾部列出,均已确认存在于 backend/docs/):
- backend/docs/CONFIGURATION.md — 配置选项;
- backend/docs/ARCHITECTURE.md — 架构细节;
- backend/docs/API.md — API 参考;
- backend/docs/SETUP.md — 安装指南;
- backend/docs/FILE_UPLOAD.md — 文件上传功能;
- backend/docs/PATH_EXAMPLES.md — 路径类型与用法;
- backend/docs/summarization.md — 上下文摘要;
- backend/docs/plan_mode_usage.md — 基于 TodoList 的 Plan 模式。
十一、小结:这套 Agent 指导机制的工程价值
回顾 backend/CLAUDE.md 的设计,DeerFlow 的后端指导体系呈现出清晰的工程化特征:以 CLAUDE.md 的 @AGENTS.md 导入实现跨 Agent 单一来源;以“根指南 + 模块指南 + 目录指南”的三级 AGENTS.md 体系配合 scripts/check_agent_guidance.py 的体量预算防止指导文件膨胀;以 backend/tests/test_harness_boundary.py 这类“可执行的架构约束”把依赖规则从文档约定提升为 CI 强制;再以完整的命令矩阵(根/后端 Makefile、分片测试、基准规范)与 TDD 强制策略,让编码 Agent 与人类开发者遵循同一套可验证的规范。这正是“写给 Agent 看的文档”从占位文件演化为仓库核心基础设施的典型范例。
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 StartedRust0623
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