deerflow-code/offline-backend-20260512/backend/docs/adr/0001-workflow-studio-runtime.md
2026-09-07 18:24:55 +08:00

4.2 KiB
Raw Blame History

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。