本文基于 DeerFlow 开源项目bytedance/deer-flow2026 年 4 月的最新架构重构分析其后端从backend/src/单体结构拆分为packages/harness/deerflow/框架层app/应用层的设计意图、实现方式和工程收益。背景一个 AI Agent 后端的成长烦恼DeerFlow 是字节跳动开源的 LangGraph-based AI Agent 系统支持多工具调用、沙箱执行、MCP 协议集成、技能系统等能力。在早期版本中所有后端代码都放在backend/src/下用from src.*统一引用backend/ └── src/ ├── agents/ # Agent 编排、middleware、memory ├── models/ # LLM 模型工厂 ├── tools/ # 工具注册 ├── sandbox/ # 沙箱执行 ├── skills/ # 技能加载 ├── mcp/ # MCP 协议 ├── gateway/ # FastAPI REST API ├── channels/ # IM 渠道集成 └── client.py # 嵌入式 Python SDK这个结构在项目初期没有问题但随着功能膨胀三个痛点逐渐暴露痛点一复用不可能。如果你想写一个 CLI 工具或 Slack Bot 来调用 DeerFlow 的 agent 能力你必须把整个src/拉进来——包括 FastAPI、uvicorn、lark-oapi飞书 SDK、slack-sdk 这些完全不需要的依赖。client.pyDeerFlowClient SDK的存在就是这个需求的直接体现但它被困在了一个包含 Web 框架的包里。痛点二依赖方向混乱。client.py本应属于框架层但它反向 import 了src.gateway.routers.skills和src.gateway.routers.uploads中的函数。框架层依赖了应用层——这是典型的架构腐化信号。痛点三LangGraph Server 被迫安装多余依赖。LangGraph Server 只需要跑 agent但因为src/是一个整体它必须安装 FastAPI、Slack SDK、飞书 SDK 等完全无关的包。拆分方案Harness AppDeerFlow 团队的解法是把后端拆成两部分Harness线束/框架层回答如何构建和运行 agent的问题。它是一个可独立发布的 Python 包deerflow-harness包含Agent 工厂与生命周期管理Middleware pipeline工具系统内置 MCP 社区工具沙箱执行环境子 agent 委派记忆系统memory、task memory、tool memory技能加载与注入模型工厂配置系统嵌入式 Python 客户端DeerFlowClient核心设计原则对上层应用完全无感知。它不知道也不关心谁在调用它——可以是 Web App、CLI、Slack Bot、或者一个单元测试。App应用层回答如何将 agent 呈现给用户的问题。它不打包、不发布是项目内部的应用代码Gateway APIFastAPI REST 接口IM Channels飞书、Slack、Telegram、Discord、微信、企业微信自定义路由模型管理、告警分析等App 依赖 Harness但 Harness 绝不依赖 App。拆分后的目录结构backend/ ├── packages/ │ └── harness/ │ ├── pyproject.toml # deerflow-harness 包定义 │ └── deerflow/ # import 前缀: deerflow.* │ ├── agents/ # Agent 工厂、middleware、memory │ │ ├── lead_agent/ │ │ ├── middlewares/ # 20 中间件 │ │ ├── memory/ # 记忆系统 │ │ └── checkpointer/ │ ├── models/ # LLM 模型工厂 │ ├── tools/ # 工具注册与发现 │ ├── sandbox/ # 沙箱执行环境 │ ├── skills/ # 技能加载 │ ├── mcp/ # MCP 协议 │ ├── community/ # 社区工具tavily、exa、jina... │ ├── config/ # 配置系统 │ ├── runtime/ # StreamBridge、RunManager、Store │ ├── guardrails/ # 工具调用授权 │ ├── tracing/ # Langfuse 追踪 │ └── client.py # DeerFlowClient SDK │ ├── app/ # 不打包import 前缀: app.* │ ├── gateway/ │ │ ├── app.py # FastAPI 入口 │ │ ├── deps.py # LangGraph runtime 依赖注入 │ │ └── routers/ # REST API 路由 │ └── channels/ # IM 渠道集成 │ ├── pyproject.toml # uv workspace root ├── langgraph.json └── tests/工程实现uv Workspace这次拆分的技术基础是uv workspace类似 npm workspaces / Cargo workspaces 的 Python 版本。Workspace Rootbackend/pyproject.toml[project] name deer-flow version 0.1.0 dependencies [ deerflow-harness, # 依赖 harness 包 fastapi0.115.0, # App 层的依赖 uvicorn[standard]0.34.0, slack-sdk3.33.0, lark-oapi1.4.0, # ... 其他 App 层依赖 ] [tool.uv.workspace] members [packages/harness] # 声明 workspace 成员 [tool.uv.sources] deerflow-harness { workspace true } # 本地引用Harness 包packages/harness/pyproject.toml[project] name deerflow-harness version 0.1.0 description DeerFlow agent harness framework dependencies [ langgraph1.0.6,1.0.10, langchain1.2.3, langchain-openai1.1.7, tavily-python0.7.17, tiktoken0.8.0, # ... 纯 agent 框架依赖没有 FastAPI/IM SDK ] [build-system] requires [hatchling] build-backend hatchling.build [tool.hatch.build.targets.wheel] packages [deerflow] # wheel 中只包含 deerflow/ 目录关键点deerflow-harness是一个真正的 Python 包有独立的pyproject.toml可以被pip install未来可以发布到 PyPI。App 层故意不打包。它没有pyproject.toml通过PYTHONPATH.让 Python 找到app.*即可。因为 App 的唯一消费者是 DeerFlow 项目自身没有独立发布需求。依赖分离是真实的。Harness 的依赖列表里没有 FastAPI、uvicorn、Slack SDKApp 的依赖列表里没有 tavily-python、tiktoken。Import 规则两层使用不同的 import 前缀职责边界一目了然# Harness 内部互相引用fromdeerflow.agentsimportmake_lead_agentfromdeerflow.modelsimportcreate_chat_modelfromdeerflow.configimportget_app_config# App 内部互相引用fromapp.gateway.appimportappfromapp.channels.serviceimportstart_channel_service# App 调用 Harness单向依赖fromdeerflow.agentsimportmake_lead_agentfromdeerflow.skillsimportload_skills# ❌ 禁止方向Harness 绝不能 import App# from app.gateway.routers.skills import xxx ← 这在拆分前存在现在被消除了LangGraph Server 配置{graphs:{lead_agent:deerflow.agents:make_lead_agent},checkpointer:{path:./packages/harness/deerflow/agents/checkpointer/async_provider.py:make_checkpointer}}LangGraph Server 只需要 harness 包不需要加载 App 层代码。拆分前的手术解除反向依赖在物理拆分之前需要先解决client.py中两处从框架层到应用层的反向依赖问题 1client.pyimport 了src.gateway.routers.skills._validate_skill_frontmatter解决提取到deerflow/skills/validation.py。这是一个纯逻辑函数解析 YAML frontmatter、校验字段与 FastAPI 无关。问题 2client.pyimport 了src.gateway.routers.uploads.CONVERTIBLE_EXTENSIONS和convert_file_to_markdown解决提取到deerflow/uploads/manager.py。仅依赖markitdownpathlib是通用工具函数。这两步手术是拆分的前置条件——不解除反向依赖物理拆分就无法完成。实际收益1. DeerFlowClient SDK 成为一等公民fromdeerflow.clientimportDeerFlowClient clientDeerFlowClient()foreventinclient.stream(帮我分析一下这篇论文):print(event)任何 Python 项目只需pip install deerflow-harness就能嵌入式使用 DeerFlow 的全部 agent 能力——不需要启动 Web 服务器不需要安装 FastAPI。2. 部署拓扑简化Gateway 内置了 LangGraph RuntimeStreamBridge、RunManager、checkpointer、store不再需要外部的langgraph-cli进程。部署从三进程nginx langgraph-cli gateway简化为两进程nginx gateway。这在下一篇文章中详细展开。3. 依赖体积缩减LangGraph Server 运行时只安装 harness 的依赖不再被 FastAPI、IM SDK 污染。对于容器化部署这意味着更小的镜像体积和更快的启动速度。4. 下游定制更友好如果你 fork 了 DeerFlow 做定制比如加多用户隔离、加自定义路由你的定制代码自然地分布在两层框架级定制如 db 模块、通知系统放在 harness 层产品级定制如管理后台路由、告警 API放在 app 层未来上游更新 harness 层时app 层的路由基本不会被冲突影响。5. 为插件化铺路不同的 appWeb、CLI、Bot可以各自独立都依赖同一个 harness。如果 harness 继续增长还可以进一步拆出deerflow-sandbox、deerflow-mcp等子包。迁移实操要点如果你也在维护一个类似的 AI Agent 后端想做类似的拆分以下是几个关键注意事项先解除反向依赖再做物理拆分。用 grep 扫描所有从框架层到应用层的 import逐个提取到框架层。config.yaml中的use字段也要更新。DeerFlow 的工具、沙箱、模型都通过use: deerflow.sandbox.local:LocalSandboxProvider这样的字符串动态加载路径从src.*改为deerflow.*。测试中的sys.path问题。用 editable installuv sync确保deerflow可导入conftest.py中添加app/到sys.path。全局 rename 要精确。正则匹配\bsrc\.而不是简单替换src避免误伤字符串中的src。总结DeerFlow 的 Harness/App 拆分不是为了拆而拆而是解决了一个 AI Agent 项目在成长过程中必然遇到的问题agent 能力如何从 Web 应用中解耦出来成为可独立复用的基础设施。uv workspace 提供了 Python 生态中相对成熟的 monorepo 方案配合 hatchling 的 wheel 构建让框架包 应用代码的分层在工程上可落地。这个模式值得所有正在构建 AI Agent 平台的团队参考。