Deer-Flow 的 Harness/App 分层架构
Deer-Flow 的 Harness/App 分层架构
学习目标
- 理解 Deer-Flow 后端的两层拆分及其依赖方向
- 掌握导入防火墙的 CI 强制执行机制
- 学会分析分层架构对可嵌入性的影响
项目实践
两层拆分
Deer-Flow 的后端拆分为两个层次,依赖方向严格单向:
| 层 | 包名 | 导入前缀 | 可发布性 |
|---|---|---|---|
| Harness | deerflow-harness | deerflow.* | 可发布为 PyPI 包 |
| App | 未发布 | app.* | 内部使用 |
导入防火墙
tests/test_harness_boundary.py 在 CI 中强制执行导入方向检查:
- 扫描
packages/harness/deerflow/下的所有 Python 文件 - 检测是否存在
from app.*或import app语句 - 发现违规 → CI 失败
效果:Harness 层可以独立作为 Python 库使用,不依赖 App 层的 FastAPI 或 IM 渠道代码。
为什么这样拆分
背景:Deer-Flow 的嵌入式 Python 客户端(DeerFlowClient)需要直接使用 Harness 层的能力,不经过 HTTP Gateway。
拆分的好处:
DeerFlowClient仅导入 Harness,不引入 FastAPI 等 Web 依赖- Harness 可独立发布为
deerflow-harnessPyPI 包 - App 层可以替换(如用 gRPC 替代 FastAPI)而不影响 Harness
问题与规避
循环导入
Harness 和 App 之间如果存在双向依赖,可能导致循环导入。
规避:test_harness_boundary.py 在 CI 中拦截违规导入。开发时使用 PYTHONPATH=. uv run pytest tests/test_harness_boundary.py 本地验证。
共享配置的归属
配置解析模块(deerflow.config)属于 Harness 层,因为 App 和嵌入式客户端都需要读取配置。
设计取舍
Harness/App 拆分 vs 单体
| 方案 | 优势 | 代价 |
|---|---|---|
| 拆分 | Harness 可独立发布和嵌入 | 增加一层抽象,需要维护导入防火墙 |
| 单体 | 简单、无额外抽象 | 无法嵌入使用,测试时需要完整 Web 栈 |
Deer-Flow 选择拆分,因为嵌入式客户端是其核心能力之一。
参考来源
- Deer-Flow CLAUDE.md — Harness / App Split 章节
tests/test_harness_boundary.py— 导入防火墙测试