55 lines
4.2 KiB
Markdown
55 lines
4.2 KiB
Markdown
# ADR 0001:工作流编排运行时边界
|
||
|
||
- **状态**:Accepted(阶段 0 冻结;决策 3 已按阶段 2 实现修订,见文末修订记录)
|
||
- **日期**:2026-08-28
|
||
- **关联**:`docs/WORKFLOW_STUDIO_BACKEND_DEV_ZH.md`
|
||
|
||
## 背景
|
||
|
||
需要在 DeerFlow 中支持可持久化、可恢复、可审计的工作流运行,并用 Coze Studio 独立画布作为编辑器。可选路径包括:整包接入 Coze 后端、整包接入 ChatDev 2.0、或在 DeerFlow 内自建运行时。
|
||
|
||
## 决策
|
||
|
||
1. **Coze Studio 只负责画布与节点配置 UI**
|
||
不复用其完整后端协议、内置试运行、Trace/Debug。Gateway 仅提供薄兼容层(canvas/save/create/node_template)。
|
||
|
||
2. **ChatDev 2.0 只作语义参考**
|
||
可参考 DAG、并行、循环、动态边、会话执行边界;**不**引入其 WebSocket、SQLite 存储、宿主机 `subprocess` 代码执行、自有 Agent/模型 runtime。
|
||
|
||
3. **执行内核 = DeerFlow 自建 DAG 调度器;LangGraph 只作智能体内核**
|
||
见下方「阶段 2 修订」。智能体 / 技能 / 沙箱 / 模型 / 制品全部复用现有 harness 能力。`deerflow.workflows` 不得导入 `app.*`。
|
||
|
||
4. **流式协议 = 持久事件日志 + SSE**
|
||
先写 `workflow_run_events`,再推 live;断线用 `Last-Event-ID` / `after_seq` 补放。不与 ChatDev WebSocket 并存。
|
||
|
||
## 阶段 0 配套确认
|
||
|
||
| 议题 | 结论 |
|
||
|------|------|
|
||
| SQL 节点驱动 | 首期仅 **MySQL 和/或 PostgreSQL**(与项目实际库一致);不抽象全数据库 |
|
||
| 凭据存储 | 画布只存 `credentialRef` / `dataSourceId`;明文密钥进服务端凭据存储,不进 JSON / SSE / 日志 |
|
||
| iframe 域名 | 由 `config.yaml` → `workflows.embed.allowed_origins`(阶段 6 落地配置项);票据绑定 origin + workflow + user + actions,约 60s 一次性兑换 |
|
||
| 应用库 vs 业务查询库 | DeerFlow 自身业务库 **不得**直接暴露给 SQL 节点;必须管理员登记独立只读数据源 |
|
||
|
||
## 阶段 2 修订:工作流级编排不编译成 LangGraph
|
||
|
||
阶段 0 原定「标准图编译为 `StateGraph`」。实现阶段 2 时改为**自建 DAG 调度器**(`deerflow/workflows/runtime/engine.py`),LangGraph 退到**单个 `agent` / `skill` 节点内部**继续做智能体内核。
|
||
|
||
**原因**:运行状态必须只有一个权威来源。工作流的可恢复性建立在 `workflow_node_runs`(已完成节点的输出)+ `workflow_run_events`(事件日志)之上——重新租约或人工恢复时,执行器从这两张表回放,只跑缺失的节点。若同时用 LangGraph checkpoint 保存工作流级状态,就会出现两份状态需要保持一致(checkpoint 与 node_runs 谁说了算?租约被抢走后 checkpoint 归谁?),恢复语义无法自证。此外 `human_input` 的暂停需要把 `resume_token` 与 `pending_input` 暴露到 HTTP/SSE 层,条件分支需要「未选中的端口整条子图跳过」的显式边状态,循环需要按 `bodyEntry` 精确失效 body 内的 node_runs——这些都要求调度器直接读写运行存储。
|
||
|
||
**代价**:调度、并行度、重试、超时、循环上限这些机制要自己实现和测试(`tests/test_workflow_engine.py`、`tests/test_workflow_runs.py`)。**收益**:崩溃恢复、取消、暂停/恢复都只有一条真相路径,且不需要为工作流额外引入一套 checkpoint 生命周期。
|
||
|
||
调度规则本身很小:每条边有 `pending` / `active` / `pruned` 三态,节点在「非回边入边都已定型且至少一条 `active`」时就绪,全部 `pruned` 则跳过并继续下推剪枝。`loop` 节点的 `continue` 回边是唯一允许的环,不参与就绪判定。
|
||
|
||
## 后果
|
||
|
||
- 短期需自建 schema / store / dispatcher / SSE,工作量高于“整包移植”。
|
||
- 长期只维护一套模型调用、鉴权、沙箱与审计,避免双运行时分叉。
|
||
- 前端时间线必须与本仓库冻结的事件 envelope(`deerflow.workflows.events`)契约一致。
|
||
|
||
## 否决方案
|
||
|
||
- 把 Coze `workflow_api` 全量试运行当作执行引擎。
|
||
- 把 ChatDev `python_executor.py`(宿主机 subprocess)当作代码节点。
|
||
- 在画布 JSON 或 URL query 中传递 JWT / DB 密码 / API Key。
|