4.2 KiB
ADR 0001:工作流编排运行时边界
- 状态:Accepted(阶段 0 冻结;决策 3 已按阶段 2 实现修订,见文末修订记录)
- 日期:2026-08-28
- 关联:
docs/WORKFLOW_STUDIO_BACKEND_DEV_ZH.md
背景
需要在 DeerFlow 中支持可持久化、可恢复、可审计的工作流运行,并用 Coze Studio 独立画布作为编辑器。可选路径包括:整包接入 Coze 后端、整包接入 ChatDev 2.0、或在 DeerFlow 内自建运行时。
决策
-
Coze Studio 只负责画布与节点配置 UI
不复用其完整后端协议、内置试运行、Trace/Debug。Gateway 仅提供薄兼容层(canvas/save/create/node_template)。 -
ChatDev 2.0 只作语义参考
可参考 DAG、并行、循环、动态边、会话执行边界;不引入其 WebSocket、SQLite 存储、宿主机subprocess代码执行、自有 Agent/模型 runtime。 -
执行内核 = DeerFlow 自建 DAG 调度器;LangGraph 只作智能体内核
见下方「阶段 2 修订」。智能体 / 技能 / 沙箱 / 模型 / 制品全部复用现有 harness 能力。deerflow.workflows不得导入app.*。 -
流式协议 = 持久事件日志 + 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。