对比目的:以 Dify
1.16.0开源参考实现(详见docs/dify-readme.md)为坐标系,定位本仓库(agent-management)工作流引擎的能力边界、创新点与可借鉴的演进方向。对比维度:节点类型与编排、调度与执行、信封化与校验、变量与输入解析、智能体集成、画布编辑器、HITL、可观测、外部 API、生态扩展。
信息来源:
- 本仓库需求与设计:
prompt.md、docs/workflow-*.md、docs/context-passing-architecture.md、docs/external-workflow-api-spec.md、docs/hermes-*.md- 本仓库实现:
backend/src/main/java/com/agent/management/engine/**- Dify 实现:
dify/api/core/workflow/**、dify/dify-agent/src/**、dify/dify-agent-runtime/**
| 维度 | 量化对比 |
|---|---|
| 本仓库独有特性 | 21 项(详见 §2) |
| Dify 独有特性 | 21 项(详见 §3) |
| 实现方法差异 | 15 项(详见 §4) |
| 设计哲学 | 本仓库:单体 + 强一致 envelope + 引擎层统一治理(适合企业内部可控场景) Dify:微服务 + 插件化生态 + 多形态应用(适合多租户 SaaS / 开源社区) |
| 维度 | agent-management | Dify |
|---|---|---|
| 项目类型 | 企业内部 AI 编码助手平台 | 开源 LLMOSS(LLM Operating System / Stack) |
| 后端实现 | Java 17 + Spring Boot 单体 | Python + Flask + Celery + 多服务编排 |
| 节点类型 | 硬编码 8 种 | 内置 + 插件扩展(plugin_daemon) |
| 应用形态 | Workflow 一种 | Workflow / Chat / AdvancedChat / Completion / AgentChat 五种 |
| 部署形态 | 单 JAR + MySQL + Redis | 11 个 docker-compose 服务(含 Plugin Daemon / Agent Backend / Local Sandbox 等) |
| Agent 引擎 | Hermes Bridge(Python 子进程)+ Spring AI ChatClient | CotAgentRunner / FunctionCallAgentRunner / dify-agent(pydantic-ai) |
| 沙箱实现 | Python 三层 monkey-patch(路径白名单) | Go Landlock LSM + tmux + sanitize-pty |
核心差异:本仓库追求轻量、强一致、企业内部可控;Dify 追求生态、可扩展、多形态覆盖。
| # | 特性 | 关键行为 | 实现位置 |
|---|---|---|---|
| 1 | 统一 envelope 全节点强制 | 所有节点(LLM / Agent / SmartAction / Hermes* / Knowledge / Condition / UserInput / Output)严格产出 {status, message, data} 三段式结构,多余字段丢弃;Dify 仅 Agent v2 节点强制 declared outputs,其他节点"尽力推断" |
engine/NodeOutputEnvelope.java、docs/workflow-node-output-envelope.md 2.6 |
| 2 | 统一 failStrategy(abort/skip) | 引擎层 WorkflowLevelExecutor 提供节点级 failStrategy 配置;Dify 没有此配置,失败处理散落各节点内部(Agent v2 有 OutputFailureOrchestrator,但仅限该节点) |
engine/WorkflowLevelExecutor.java、docs/workflow-node-output-envelope.md 2.10 |
| 3 | Dataflow 调度 + SKIPPED 状态 | 从 BSP(层同步)改造为 Dataflow:节点完成即触发后继(基于 pendingInputs: Map<nodeId, AtomicInteger> 入度计数),不被同层慢节点阻塞;条件分支未选路径自动标记 SKIPPED;Dify 的 NodeOutputStatus 枚举无 SKIPPED 状态(只有 PENDING/RUNNING/READY/TYPE_CHECK_FAILED/OUTPUT_CHECK_FAILED/NOT_PRODUCED/FAILED) |
docs/workflow-dataflow-execution-plan.md、dify/api/services/workflow/node_output_inspector_service.py:84-103 |
| 4 | 节点级 abort 取消在飞节点 | abortFlag(AtomicBoolean)+ inFlightFutures Map,失败时 CAS 设置并 cancel(true) 所有在飞节点;Dify 节点失败后是否取消兄弟节点由 GraphEngine 图级策略决定,Dify 侧不可见也无显式 API |
engine/WorkflowLevelExecutor.java 阶段 3 |
| 5 | envelope 失败自动升级 | result.status == SUCCESS && envelope.isFailure() 时引擎自动升级为 NodeExecutionResult.failed,按 failStrategy 处理;失败 envelope 仍写入上下文供下游感知 |
docs/hermes-error-detection-plan.md 方案 D |
| # | 特性 | 关键行为 | 实现位置 |
|---|---|---|---|
| 6 | 四级模糊匹配 fallback | 节点输入解析按拓扑逆序遍历可达前驱,依次尝试:①精确同名 → ②模糊同名(忽略 - _ 和大小写)→ ③JSON 嵌套精确同名 → ④JSON 嵌套模糊同名;Dify 通过 variable_pool 直接寻址,无模糊匹配 |
docs/workflow-variable-scope-design.md 4.3、dify/api/core/workflow/variable_pool_initializer.py |
| 7 | envelope.data 穿透取值 | 四级匹配全部穿透 envelope.data 内部取值,不再读扁平 Map 顶层;Dify 没有这种 envelope-aware 的输入解析 | docs/workflow-node-output-envelope.md 2.9 |
| 8 | NodeWorkspace 仅含可达前驱 | 节点开始执行前构建工作区,仅包含可达前驱(反向 BFS 计算)的输出,避免无关变量污染;Dify 通过共享 variable_pool,无显式工作区隔离 | docs/workflow-variable-scope-design.md 2.1 |
| 9 | 前驱变量删除后自动回退关联 | 边变化导致前驱不再是可达前驱时,节点 inputs/output fields 的显式 mapping 自动回退为「自动推断」(autoMapped=true);Dify 通过手动 variable selector 重新选择,无自动回退 | docs/workflow-variable-scope-design.md 3.2 |
| 10 | 运行工作目录 + .agentignore |
每次运行分配 <data-dir>/workflow-runs/{workflowId}/{runId}/,所有节点共享;.agentignore 排除 .hermes/、*.log、*.tmp 等;可打包下载 zip;Dify 有 Local Sandbox 沙箱但没有 .agentignore 机制 |
docs/external-workflow-api-spec.md 3.5 |
| # | 特性 | 关键行为 | 实现位置 |
|---|---|---|---|
| 11 | 错误回注 prompt 的自我修正重试 | StructuredOutputHelper.extractWithRetry 校验失败时把 lastError(如"缺少 required 字段 xxx")注入 prompt 让 LLM 自我修正;Dify 没有这种"错误回注"的统一机制 |
engine/StructuredOutputHelper.java、docs/workflow-node-output-envelope.md 2.2 |
| 12 | 三级 JSON 提取容错 | ①直接 JSON 解析 → ②`json 代码块提取 → ③首尾 {} 子串提取;适配 LLM 不稳定输出;Dify 通过 litellm + json-repair 0.60 在底层处理 |
engine/StructuredOutputHelper.java |
| 13 | 类型静默自动转换 | 声明 number + 字符串数字 → 静默转换;boolean + "true"/"1"/"yes" → true;array/object + JSON 文本 → 解析;Dify 类型校验在 OutputTypeChecker 但更严格,无静默转换 | engine/OutputValidator.java、dify/api/core/workflow/nodes/agent_v2/output_type_checker.py |
| 14 | 双循环重试(计划中) | 外层 runtime retry(重新完整推理,默认 2 次)+ 内层 format retry(仅重组 JSON,不重跑业务,默认 2 次);内层耗尽升级为外层;Dify 无此分层 | docs/workflow-envelope-strict-validation-plan.md 阶段 3 |
| 15 | 节点级 retry 配置覆盖全局 | RetryPolicy.fromNodeData 解析节点 data.maxRetries / retryOn*,覆盖 application.yml 默认值;Dify Agent v2 的重试在节点内部硬编码(OutputFailureOrchestrator) |
engine/RetryPolicy.java |
| # | 特性 | 关键行为 | 实现位置 |
|---|---|---|---|
| 16 | Hermes Bridge(Python 子进程) | HermesProcessManager 启动 Python bridge 子进程,注入 HERMES_BRIDGE_BASE_URL/API_KEY/MODEL 等环境变量,通过 SSE 通信(思考流 / 工具调用 / 最终结果);Dify Agent v2 通过独立 FastAPI 服务(pydantic-ai),架构不同 |
engine/hermes/HermesProcessManager.java、backend/hermes-bridge/hermes_bridge.py |
| 17 | Hermes Error Pattern 错误检测 | 内置错误模式数据模型(HermesErrorPattern)+ Java Client 嗅探(parseSseResponse 在 done 分支后 substring 匹配)+ 前端管理页(/hermes-errors);内置"访问量过大"、"无效的 api"等中文模式;Dify 没有 LLM 错误响应的模式化识别 |
service/impl/HermesErrorPatternServiceImpl.java、docs/hermes-error-detection-plan.md |
| 18 | 三层 monkey-patch 沙箱 | sandbox_patch.py 对 hermes-agent 的 _resolve_path_for_task(路径白名单)、_resolve_base_dir(相对路径锚定)、_git_root(阻断外层项目根注入)打补丁;通过 _SESSION_CWD contextvar 线程隔离;Dify 沙箱是 Go Landlock LSM + tmux(更底层但与 Hermes 无关) |
backend/hermes-bridge/sandbox_patch.py、docs/hermes-sandbox.md |
| 19 | 默认模型实时路由 | AiModelService.getDefaultModel 实时查询,application.yml 切换默认模型后立即生效,不再回退到旧默认;模型管理可设置调用顺序 fallback;Dify 模型在节点级硬绑定,无统一默认路由 |
service/AiModelService.java |
| 20 | Skill 文件预同步(方案 A) | SkillFileSyncer.syncTo 在每次工作流执行前将 uploads/skills 下所有 skill 复制到工作目录 .hermes/skills,不复制历史版本文件;Dify 插件化体系不同,无此同步需求 |
engine/SkillFileSyncer.java |
| 21 | 技能生成(Skill 生成 Skill) | 技能编辑页可选「该技能具备生成其他技能的能力」;技能生成菜单选择生成器技能 → 调 hermes-bridge → 在工作目录生成 → 复制到全局技能目录 → 跳转编辑页;Dify 无"工具生成工具"的概念 | service/impl/SkillGenerationServiceImpl.java、prompt.md 855-952 行 |
| # | 特性 | 关键行为 | 实现位置 |
|---|---|---|---|
| 22 | 字段「引入」双向关联 | 节点 inputs 从前驱 outputs 引入、节点 outputs 从后继 inputs 引入;输入节点输入变量从后继输入引入(业务输入语义);输出节点输出变量从前驱输出引入(业务输出语义);引入后自动填入变量名/中文名/类型/描述;Dify 通过 variable selector 单向引用,无"输出字段反向关联后继" | frontend/src/utils/ioInference.js、prompt.md 1188-1192 行 |
| 23 | LLM 语义「自动关联」 | 点击「自动关联」按钮用 LLM 语义识别(非字符串匹配)哪些 Skill 的 SKILL.md 或智能操作工作流程中隐式调用了其他 Skill;识别结果以虚线框 + 虚线箭头画在画布上,技能节点位于虚线框中可拖动;Dify 无此"自动发现隐式依赖"能力 | prompt.md 357、776 行 |
| 24 | 模板变量动态识别(无碎片) | 在 {{}} 中按顺序输入变量名时实时识别,区分「自动字段」(从 {{}} 识别)和「手动字段」(用户显式添加),避免中间变量碎片(a、ab、abc 三个变量);Dify 使用变量选择器 UI,无模板动态识别 |
prompt.md 1195、1200 行 |
| 25 | 画布级变量/字段/节点名唯一性校验 | 节点内变量名不能重复、画布节点名不能重复,保存时拦截并列出具体节点与变量;Dify 通过 variable selector 引用,名称冲突由用户自行管理 | prompt.md 1265、1270 行 |
| 26 | 节点动态斥力 | 拖动节点后过近节点动态推开达到平衡(非生成时距离);Dify 用 ReactFlow + ELK.js 自动布局,无交互式斥力 | prompt.md 806-818 行 |
| 27 | 运行对话框变量导出/导入 | 导出已填入变量为 JSON 文件(命名 工作流名称-节点名-输入变量.json),强制选择保存位置;导入时填入对应表单;Dify 表单提交,无导入导出 |
prompt.md 1276-1285 行 |
| 28 | 输入/输出节点变量标签颜色语义 | 输入节点变量蓝色(业务输入)、输出节点变量绿色(业务输出)、其他节点前置数据蓝/输出变量绿;Dify 节点端口样式统一 | prompt.md 1264 行 |
| 29 | 思考过程折叠 + 流式继续 | 运行记录中思考过程支持折叠,折叠后仍接收流式响应只是不显示,展开后可继续输出;Dify Trace 工具(Langfuse 等)有类似能力但非画布原生 | prompt.md 626 行 |
| 30 | 节点名称与类型双行显示 | 画布节点显示「节点名称 节点类型」,名称字体与类型字体区分;空时只显示节点类型;节点名称画布内唯一;Dify 节点显示样式不同 | prompt.md 66、156 行 |
| # | 特性 | 关键行为 | 实现位置 |
|---|---|---|---|
| 31 | kebab-case 唯一标识 + 中文 displayName 分离 | name 为 kebab-case(^[a-z0-9]+(-[a-z0-9]+)*$),URL 按 name 寻址;displayName 可任意字符(含中文);翻译只翻译 displayName 与正文,不破坏 name;Dify 工作流标识为 UUID |
service/WorkflowNameNormalizer.java、docs/workflow-crud-api.md |
| 32 | 外部 API 三段式调用 | 创建运行(POST /runs)→ 启动(POST /runs/{runId}/start)→ 订阅(GET /runs/{runId}/stream);同步阻塞模式 async=false 直接 SSE;Dify 通过 Service API 单次调用,无"创建-启动-订阅"三段式 |
docs/external-workflow-api-spec.md 3.1-3.2 |
| 33 | 断线重连 SSE(Last-Event-ID) | 通过 Last-Event-ID 头部续传,事件缓存窗口默认 1000 条或运行结束保留 1 小时;Dify 通过 socket.io 自动重连,但 SSE 模式无 Last-Event-ID 续传 |
docs/external-workflow-api-spec.md 5 |
| 34 | 工作目录 ZIP 打包下载 | GET /runs/{runId}/workspace 返回 zip(应用 .agentignore);Dify Agent 沙箱内文件通过 drive API 单文件上传/下载,无打包下载 |
docs/external-workflow-api-spec.md 3.5 |
| 35 | 目录结构保留上传 | 通过 X-Relative-Path part header 保留目录结构,含 ZIP slip 防护;Dify 文件上传扁平化 |
docs/external-workflow-api-spec.md |
| # | 特性 | Dify 实现 | 本仓库状态 |
|---|---|---|---|
| 1 | 迭代节点(iteration) | core/workflow/nodes/iteration/ 支持数组迭代执行子图 |
❌ 不支持 |
| 2 | 显式并行节点 / 并行分支 | 通过 GraphEngine 线程池 + 并行边 | ⚠️ 仅同层并行(Dataflow 模式),无显式并行节点 |
| 3 | 问题分类器节点 | question-classifier 节点用 LLM 把输入分类到不同分支 |
❌ 可用条件分支节点近似但不能 LLM 自动分类 |
| 4 | 模板转换节点 | template-transform 节点专门做 Jinja2 渲染 |
❌ 无独立节点,模板渲染内嵌于各节点 |
| 5 | 参数提取器节点 | parameter-extractor 节点用 LLM 从自然语言提取结构化参数 |
❌ 无 |
| 6 | 变量聚合器节点 | variable-aggregator 节点把多个分支的变量合并 |
❌ 由 envelope 自动聚合,无显式节点 |
| 7 | HTTP Request 节点 | 独立节点支持任意 HTTP 调用 | ❌ 由 SmartAction 节点近似但非通用 HTTP |
| 8 | Code 节点(沙箱化代码执行) | 独立 dify-sandbox 容器执行 Python / JS 代码 |
❌ 不支持任意代码执行 |
| 9 | Knowledge Index 节点(索引而非检索) | core/workflow/nodes/knowledge_index/ 在工作流中增量索引文档 |
❌ 知识库索引在管理后台,非工作流节点 |
| 10 | 三种触发器节点(plugin / schedule / webhook) | trigger_plugin/、trigger_schedule/、trigger_webhook/ 支持事件驱动工作流 |
❌ 仅同步 API 触发 |
| # | 特性 | Dify 实现 | 本仓库状态 |
|---|---|---|---|
| 11 | 运行中 HITL 暂停-恢复 | PauseStatePersistenceLayer 全量序列化(generate_entity + graph_runtime_state + response_stream_filter_state + pause_reasons)+ 恢复重建;两条路径:独立 Human Input 节点 / Agent v2 内部 ask_human 延迟工具调用 |
❌ 仅支持运行前一次性收集 userInput |
| 12 | Agent 内部 ask_human 延迟工具调用 | pydantic-ai external deferred tool,让 Agent 在执行中请求人工输入后继续原上下文 | ❌ 不支持 |
| 13 | 子工作流嵌套 | _WorkflowChildEngineBuilder 创建隔离的 child GraphEngine,复用父图 variable_pool |
❌ 工作流作为工具是外部 API 模式(通过 skill 调用),无内嵌子工作流 |
| # | 特性 | Dify 实现 | 本仓库状态 |
|---|---|---|---|
| 14 | ReAct(CoT)推理循环 | CotAgentRunner 实现 Thought/Action/Observation 文本协议 |
⚠️ 通过 Hermes Bridge 间接支持(hermes-agent 内部),但本仓库引擎不直接实现 |
| 15 | Function Calling 推理循环 | FunctionCallAgentRunner 使用 LLM 原生 tool_calls |
⚠️ 同上 |
| 16 | Agent v2 推理循环外包给 pydantic-ai | 完全外包给独立 dify-agent-backend 服务 |
❌ Agent 在引擎内部执行 |
| 17 | litellm 统一 LLM 接入 | 通过 litellm 1.83 收敛 100+ provider | ⚠️ 通过 Spring AI + 自定义 AiModelService,覆盖面窄 |
| 18 | Plugin Daemon 插件化(模型 / 工具 / 节点) | 所有 provider 外置为插件,第三方可贡献;28 种向量库 + 8 种 trace 后端 + 10 种对象存储 | ❌ 节点/模型/工具硬编码 |
| # | 特性 | Dify 实现 | 本仓库状态 |
|---|---|---|---|
| 19 | 画布多人协同编辑 | loro-crdt 1.13 + python-socketio 实现工作流画布多人实时协同 | ❌ 单人编辑 |
| 20 | OpenTelemetry 全链路追踪 | OTel distro + 五种 instrumentation(celery/flask/httpx/redis/sqlalchemy)+ B3 传播 | ❌ 仅节点级 logs,无 OTel |
| 21 | 8 种 Trace 后端插件化 | Langfuse / LangSmith / Phoenix / MLflow / Arize / Opik / Weave / 阿里云 / 腾讯云 | ❌ 无 trace 后端集成 |
| 22 | MCP 客户端/服务端 | core/mcp/ 内置 MCP 协议支持(auth / client / server / session) |
❌ 未涉及 |
| 23 | Agent 沙箱化 Shell 工作区(tmux + Landlock) | Go 实现的 dify-agent-runtime,通过 tmux 控制持久化 Shell,Landlock LSM 文件系统隔离,sanitize-pty ANSI 清洗 |
⚠️ Python monkey-patch 实现路径白名单,无 Landlock 级隔离 |
| 24 | 多语言 i18next(11 种语言) | i18next 26 + react-i18next 17 + 11 种语言包 | ⚠️ 中文为主,仅 displayName 翻译 |
| # | 特性 | Dify 实现 | 本仓库状态 |
|---|---|---|---|
| 25 | 五种应用形态 | Workflow / Chat / AdvancedChat / Completion / AgentChat | ⚠️ 仅 Workflow 一种 |
| 26 | OpenAPI 自动生成(fastopenapi) | fastopenapi[flask] 0.7.0 自动生成 OpenAPI 规范 |
⚠️ 通过 springdoc 生成(功能等价) |
| 27 | 结构化 output_type 契约(pydantic-ai) | Agent v2 通过 pydantic-ai output_type 强制 JSON Schema 输出契约 | ⚠️ envelope 校验类似但基于 declared outputs 字段列表,非完整 JSON Schema |
| 28 | 多租户与 RBAC | core/rbac/ + tenant 隔离 + 套餐优先级(QueueDispatcherManager) |
⚠️ 单租户,无套餐优先级 |
| 29 | Sentry / Amplitude 前端可观测 | Sentry 10.66 + Amplitude(含 session-replay) | ❌ 未涉及 |
| 30 | 流式工具调用(streaming tool call) | FunctionCallAgentRunner.stream_tool_call 支持流式工具调用 |
⚠️ 通过 Hermes Bridge SSE 间接支持 |
| 维度 | agent-management | Dify |
|---|---|---|
| 语言 | Java 17 + Spring Boot | Python 3.12 + Flask + 外部 graphon 包 |
| 调度模型 | Dataflow(入度计数 pendingInputs: Map<nodeId, AtomicInteger>) |
GraphEngine 线程池(min/max workers + scale up/down threshold) |
| 并发 | CompletableFuture + nodeExecutor 线程池 | graphon 内部线程池 |
| 失败取消 | abortFlag(AtomicBoolean)+ inFlightFutures Map,显式 cancel(true) |
graphon 图级策略(Dify 侧不可见) |
| 文件位置 | engine/WorkflowLevelExecutor.java |
dify/api/core/workflow/workflow_entry.py:213-225 |
| 维度 | agent-management | Dify |
|---|---|---|
| 强制范围 | 所有节点强制 {status, message, data} |
仅 Agent v2 节点 declared outputs 校验,其他节点"尽力推断" |
| 校验器 | OutputValidator 统一校验(required / typeMismatch + 静默自动转换) |
OutputTypeChecker(Agent v2 专用)+ NodeOutputInspectorService(声明输出视图) |
| 失败处理 | envelope.isFailure() 自动升级为 NodeExecutionResult.failed | Agent v2 通过 OutputFailureOrchestrator 决策 RETRY/USE_DEFAULT/TAKE_FAIL_BRANCH/FAIL |
| 文件位置 | engine/NodeOutputEnvelope.java、engine/OutputValidator.java |
dify/api/core/workflow/nodes/agent_v2/output_failure_orchestrator.py |
| 维度 | agent-management | Dify |
|---|---|---|
| 配置层级 | 引擎层 failStrategy: abort/skip(节点级) + 全局 application.yml retry 配置 + 节点级 retry 覆盖 |
无统一 failStrategy;Agent v2 节点内部 OutputFailureOrchestrator |
| 重试触发 | retryOnParseError / retryOnMissingRequired / retryOnTypeMismatch / retryOnKeyNameMismatch(计划中) | 由 OutputFailureOrchestrator 内部决策 |
| 重试方式 | 错误回注 prompt 自我修正;双循环(runtime retry + format retry,计划中) | 节点内部 RETRY 决策(重新调用 agent backend) |
| 文件位置 | engine/RetryPolicy.java、engine/StructuredOutputHelper.java |
dify/api/core/workflow/nodes/agent_v2/output_failure_orchestrator.py |
| 维度 | agent-management | Dify |
|---|---|---|
| 老版 Agent | AgentExecutor 直接 Spring AI ChatClient(无 ReAct 循环,单次调用) |
CotAgentRunner(ReAct 文本协议)+ FunctionCallAgentRunner(FC) |
| 新版 Agent | HermesAgentExecutor 通过 Hermes Bridge Python 子进程(hermes-agent 内部实现推理循环) |
Agent v2 通过 dify-agent-backend(pydantic-ai)服务 |
| 最大迭代 | 由 hermes-agent 控制(不在本仓库引擎层) | min(max_iteration, 99) + 1 |
| 文件位置 | engine/executor/HermesAgentExecutor.java |
dify/api/core/agent/cot_agent_runner.py:80 |
| 维度 | agent-management | Dify |
|---|---|---|
| 触发条件 | 节点 data.outputs 非空即触发(不再要求 size > 1) |
Agent v2 通过 pydantic-ai output_type 原生支持;其他节点 litellm + json-repair |
| 指令构造 | StructuredOutputHelper.buildInstruction(字段名+类型+描述追加 userPrompt) |
pydantic-ai 内部根据 output_type 自动构造 |
| 容错 | 三级 JSON 提取(直接 / json / 首尾 {}) |
json-repair 0.60 底层修复 |
| 文件位置 | engine/StructuredOutputHelper.java |
dify/api/core/workflow/nodes/agent_v2/agent_node.py:393-411 |
| 维度 | agent-management | Dify |
|---|---|---|
| 寻址方式 | 四级模糊匹配 fallback(精确 / 模糊 / JSON Path 精确 / JSON Path 模糊)+ 显式 mapping | variable_pool 直接寻址 + variable_prefixes 前缀解析 |
| 工作区 | NodeWorkspace(仅含可达前驱输出,反向 BFS) | 共享 variable_pool(无显式工作区隔离) |
| envelope 穿透 | 五级匹配全部穿透 envelope.data | 节点通过 variable selector 显式声明 |
| 模板渲染 | {{varName}}、{{nodeId.varName}}、{{nodeId.var.path}};变量不存在保留占位符 |
Jinja2 + variable_prefixes |
| 文件位置 | engine/NodeInputResolver.java、engine/TemplateRenderer.java |
dify/api/core/workflow/variable_pool_initializer.py、dify/api/core/workflow/variable_prefixes.py |
| 维度 | agent-management | Dify |
|---|---|---|
| 入口 | userInput 节点(运行前一次性收集) | 独立 Human Input 节点 + Agent v2 ask_human 延迟工具 |
| 暂停机制 | ❌ 无运行中暂停 | PauseRequestedEvent + PauseStatePersistenceLayer 全量序列化 |
| 恢复机制 | ❌ 无 | 从 DB 加载 WorkflowResumptionContext,重建 GraphRuntimeState |
| 持久化 | ❌ 无 | generate_entity + graph_runtime_state + response_stream_filter_state + pause_reasons |
| 文件位置 | engine/executor/UserInputExecutor.java |
dify/api/core/app/layers/pause_state_persist_layer.py:77-177 |
| 维度 | agent-management | Dify |
|---|---|---|
| 语言 | Python(hermes-bridge 内) | Go(dify-agent-runtime) |
| 隔离机制 | 三层 monkey-patch(路径白名单 + 相对路径锚定 + Git 根阻断)+ contextvar 线程隔离 | Linux Landlock LSM(内核级文件系统隔离)+ tmux(持久化 Shell)+ sanitize-pty(ANSI 清洗) |
| 隔离强度 | 应用层(依赖 Python 进程内约束) | 内核层(依赖 Linux LSM) |
| 状态持久化 | 工作目录 <data-dir>/workflow-runs/{workflowId}/{runId}/ |
SQLite(modernc.org/sqlite 纯 Go)记录 job 状态与退出码 |
| 文件位置 | backend/hermes-bridge/sandbox_patch.py |
dify/dify-agent-runtime/internal/landlock/、dify/dify-agent-runtime/internal/sanitize/ |
| 维度 | agent-management | Dify |
|---|---|---|
| 框架 | Vue + vue-flow 风格画布 | React + ReactFlow 11.11 + ELK.js(图布局) |
| 协同 | ❌ 单人编辑 | loro-crdt 1.13 + python-socketio 多人实时协同 |
| 自动布局 | ❌ 手动 + 节点动态斥力(拖动后推开过近节点) | ELK.js 自动布局 |
| 字段关联 | 「引入」双向(input 从前驱 / output 从后继)+ LLM 语义「自动关联」(虚线框发现 Skill 隐式依赖) | variable selector 单向引用 |
| 文件位置 | frontend/src/views/workflow/WorkflowEditor.vue、frontend/src/utils/ioInference.js |
dify/web/features/workflow/ |
| 维度 | agent-management | Dify |
|---|---|---|
| 接入层 | Spring AI ChatClient + 自定义 AiModelService | litellm 1.83 统一收敛 100+ provider |
| 默认模型 | AiModelService.getDefaultModel 实时查询,application.yml 切换立即生效 | 节点级硬绑定,无统一默认路由 |
| Provider 管理 | 模型管理页设置调用顺序 + fallback | 通过 plugin_daemon 加载 provider 插件 |
| 文件位置 | service/AiModelService.java |
dify/api/core/model_manager.py、dify/api/core/provider_manager.py |
| 维度 | agent-management | Dify |
|---|---|---|
| 节点执行历史 | WorkflowRunNode.logs(thinking / tool_call / tool_result / info / error) |
节点执行记录 + OTel 全链路 trace |
| 上下文快照 | NodeExecutionResult.contextSnapshot(计划中,按节点持久化 variables) |
共享 variable_pool 状态(无显式 per-node snapshot,但 HITL 时全量序列化) |
| 调用链追踪 | 节点级 logs API:GET /runs/{runId}/nodes/{nodeId}/logs |
OTel + 8 种 trace 后端(Langfuse / LangSmith / ...) |
| 文件位置 | model/entity/WorkflowRunNode.java、docs/context-passing-architecture.md Phase 2-3 |
dify/api/core/ops/ops_trace_manager.py |
| 维度 | agent-management | Dify |
|---|---|---|
| 扩展方式 | 硬编码 NodeTypeUtils 枚举 + Executor 工厂 |
plugin_daemon 加载第三方插件(节点 / 模型 / 工具) |
| 节点版本 | 无显式版本(通过 Executor 类区分 Hermes/非 Hermes) | 节点 version() 类方法显式版本(如 Agent v1 vs v2) |
| 动态注册 | ❌ 启动时静态注册 | ✅ 插件运行时注册 |
| 文件位置 | engine/NodeTypeUtils.java、engine/executor/*Executor.java |
dify/api/core/workflow/node_factory.py:279 |
| 维度 | agent-management | Dify |
|---|---|---|
| 范围 | 中文为主 + displayName 翻译(缓存到 JSON 文件或数据库,全文匹配调出) | i18next 26 + 11 种语言包 |
| 翻译策略 | 只翻译 displayName 与正文(含英文的段落即翻译),不翻译 name(避免 kebab-case 被破坏) | 完整 i18n 资源包切换 |
| 文件位置 | prompt.md 880-901 行 |
dify/web/i18n/、dify/web/i18n-config/ |
| 维度 | agent-management | Dify |
|---|---|---|
| 后端服务数 | 1(Java 单体) | 5(api / worker / worker_beat / plugin_daemon / agent_backend) |
| 沙箱服务数 | 0(hermes-bridge 内嵌) | 2(dify-sandbox 代码沙箱 + dify-agent-local-sandbox Agent Shell) |
| 反向代理 | 可选(用户自决) | Nginx + SSRF Proxy(Squid)必需 |
| 必需基础设施 | MySQL/PostgreSQL + Redis + 向量库 | PostgreSQL/MySQL + Redis + 向量库 + Plugin Daemon + Agent Backend + Local Sandbox + Sandbox + SSRF Proxy + Nginx |
| 文件位置 | backend/src/main/resources/application.yml.example |
dify/docker/docker-compose.yaml |
| 维度 | agent-management | Dify |
|---|---|---|
| 工作流标识 | kebab-case name(URL 寻址)+ 中文 displayName 分离 |
UUID |
| 外部调用模式 | 三段式(创建 → 启动 → 订阅)+ 同步阻塞模式 | 单次调用(Chat / Completion / Workflow 三类 API) |
| 输入形态 | 纯 JSON / JSON + 文件 / JSON + 目录(保留结构 + ZIP slip 防护) | JSON + 文件(扁平化) |
| 工作空间下载 | ZIP 打包(应用 .agentignore) |
drive API 单文件上传/下载 |
| 文件位置 | docs/external-workflow-api-spec.md |
dify/api/controllers/service_api/ |
| 能力领域 | agent-management | Dify | 备注 |
|---|---|---|---|
| DAG 调度 | ✅ Dataflow | ✅ GraphEngine | 实现方式不同(§4.1) |
| 同层并行 | ✅ Dataflow 模式 | ✅ GraphEngine 线程池 | 均支持 |
| 完成即触发后继 | ✅ 显式实现 | ⚠️ 推测支持(graphon 内部) | 本仓库可观察(§2.1 #3) |
| SKIPPED 状态 | ✅ 条件分支未选路径 | ❌ 无此状态枚举 | 本仓库独有(§2.1 #3) |
| 统一 envelope | ✅ 全节点强制 | ⚠️ 仅 Agent v2 | 本仓库更一致(§2.1 #1) |
| 统一 failStrategy | ✅ abort/skip | ❌ 无统一配置 | 本仓库独有(§2.1 #2) |
| 条件分支 | ✅ condition 节点 | ✅ if-else 节点 | 均支持 |
| 迭代 | ❌ | ✅ iteration 节点 | Dify 独有(§3.1 #1) |
| 子工作流 | ❌ 内嵌 | ✅ child_engine_builder | Dify 独有(§3.2 #13) |
| HITL 运行中暂停 | ❌ | ✅ PauseStatePersistenceLayer | Dify 独有(§3.2 #11) |
| HTTP / Code 节点 | ❌ | ✅ 独立节点 | Dify 独有(§3.1 #7、#8) |
| 触发器(Webhook/Schedule) | ❌ | ✅ 三种触发器 | Dify 独有(§3.1 #10) |
| 变量模糊匹配 | ✅ 四级 fallback | ❌ 直接寻址 | 本仓库独有(§2.2 #6) |
| LLM 结构化输出 | ✅ extractWithRetry + 错误回注 | ✅ pydantic-ai output_type | 实现方式不同(§4.5) |
| 类型静默转换 | ✅ | ⚠️ 严格校验 | 本仓库更宽容(§2.3 #13) |
| 双循环重试 | ⚠️ 计划中 | ❌ | 本仓库规划中(§2.3 #14) |
| ReAct / FC Agent | ⚠️ Hermes Bridge 间接 | ✅ 原生实现 | Dify 更直接(§3.3 #14、#15) |
| 沙箱 | ✅ Python monkey-patch | ✅ Go Landlock + tmux | 实现方式不同(§4.8) |
| 多人协同画布 | ❌ | ✅ loro-crdt | Dify 独有(§3.4 #19) |
| OTel 全链路追踪 | ❌ | ✅ + 8 种后端 | Dify 独有(§3.4 #20、#21) |
| MCP 协议 | ❌ | ✅ 客户端 + 服务端 | Dify 独有(§3.4 #22) |
| 插件化扩展 | ❌ | ✅ plugin_daemon | Dify 独有(§3.3 #18) |
| LLM 错误模式检测 | ✅ HermesErrorPattern | ❌ | 本仓库独有(§2.4 #17) |
| LLM 自动关联 | ✅ 语义识别 Skill 依赖 | ❌ | 本仓库独有(§2.5 #23) |
| 模板变量动态识别 | ✅ 无碎片 | ❌ | 本仓库独有(§2.5 #24) |
| 变量导出/导入 | ✅ JSON 文件 | ❌ | 本仓库独有(§2.5 #27) |
| 默认模型实时路由 | ✅ | ❌ | 本仓库独有(§2.4 #19) |
工作目录 + .agentignore |
✅ | ❌ | 本仓库独有(§2.2 #10) |
| 外部 API 三段式 | ✅ | ⚠️ 单次调用 | 本仓库更灵活(§4.15) |
| 维度 | agent-management | Dify |
|---|---|---|
| 核心目标 | 企业内部 AI 编码助手(Skill 驱动) | 开源 LLMOSS(多形态应用平台) |
| 一致性优先级 | 高(统一 envelope、统一 failStrategy) | 中(各节点分散处理) |
| 扩展性优先级 | 低(硬编码 8 种节点) | 高(插件化,第三方可贡献) |
| 学习曲线 | 低(节点少,强约束) | 高(节点多,配置灵活) |
| 部署复杂度 | 低(单体 JAR) | 高(11 个 docker 服务) |
| 生态丰富度 | 低(自有生态:Skill / Hermes) | 高(28 向量库 / 8 trace / 10 对象存储 / MCP) |
| 多租户 | ❌ | ✅ |
| 企业可控性 | 高(私有部署,全链路可见) | 中(开源 + 企业版分层) |
| 借鉴项 | 来源 | 价值 |
|---|---|---|
| HITL 暂停-恢复机制 | dify/api/core/app/layers/pause_state_persist_layer.py |
让 userInput 节点支持运行中暂停,扩展交互场景 |
| OTel 节点级追踪 | dify/api/core/ops/ops_trace_manager.py |
提升可观测性,便于性能调优 |
| Langfuse 集成 | dify/api/providers/trace/langfuse/ |
提供 LLM 调用全链路可视化 |
| 断线重连 SSE | Dify socket.io 自动重连机制 | 已有 Last-Event-ID 续传,可进一步参考 socket.io 思路 |
| 节点版本机制 | Dify Agent v1 vs v2 的 version() 类方法 |
未来 Hermes/非 Hermes 节点演进时可显式版本化 |
| 借鉴项 | 来源 | 价值 |
|---|---|---|
| 迭代节点 | dify/api/core/workflow/nodes/iteration/ |
支持数组迭代处理(批量任务场景) |
| 子工作流嵌套 | _WorkflowChildEngineBuilder |
复用已有工作流作为子流程 |
| HTTP Request 节点 | Dify http-request 节点 | 通用 HTTP 调用,替代 SmartAction 的部分场景 |
| Code 节点(沙箱化) | dify-sandbox 容器 |
支持任意代码执行,扩展工作流能力 |
| 触发器节点(Webhook) | trigger_webhook 节点 |
事件驱动工作流,对接外部系统 |
| 多租户与 RBAC | dify/api/core/rbac/ |
企业级权限隔离 |
| MCP 客户端集成 | dify/api/core/mcp/ |
接入 MCP 生态,复用 MCP 工具 |
| 借鉴项 | 来源 | 评估 |
|---|---|---|
| Plugin Daemon 插件化 | dify-plugin-daemon(Go) |
显著增加架构复杂度,仅当需要第三方扩展生态时考虑 |
| Landlock 沙箱 | dify-agent-runtime/internal/landlock/ |
需 Linux 内核 5.13+,企业内部场景 monkey-patch 已够用 |
| 多人协同画布(loro-crdt) | dify/web/features/workflow/ |
需引入 CRDT 与 WebSocket,仅当多人协作是核心需求时考虑 |
| 多形态应用(Chat / Completion / AgentChat) | dify/api/core/app/apps/ |
与本仓库 Workflow 单形态定位冲突,需重新评估产品方向 |
| litellm 统一 LLM 接入 | dify/api/pyproject.toml |
Python 库,Java 生态可用 Spring AI 替代 |
| Plugin 化向量库(28 种) | dify/api/providers/vdb/ |
仅当业务需要多向量库切换时考虑 |
| 特色 | 价值 |
|---|---|
| 统一 envelope 全节点强制 | 比 Dify"仅 Agent v2 强制"更一致,便于下游消费 |
| 统一 failStrategy(abort/skip) | 比 Dify"散落各节点"更清晰,运维更可控 |
| Dataflow + SKIPPED 状态机 | 完成即触发 + 条件分支可视化,比 Dify 的状态枚举更精细 |
| 四级模糊匹配 + envelope 穿透 | 容错性远超 Dify 的"直接寻址",降低用户心智负担 |
| LLM 错误回注 prompt 自我修正 | Dify 没有此机制,是结构化输出的关键创新 |
| Hermes Bridge + monkey-patch 沙箱 | 轻量级、无需多服务,适合企业内部场景 |
| LLM 语义「自动关联」 | Dify 完全没有,是 Skill 工作流的独特创新 |
| 模板变量动态识别(无碎片) | Dify 通过 variable selector 规避,体验不如本仓库 |
| 运行对话框变量导出/导入 | 实测对调试与复现非常有用,Dify 应该学 |
| 默认模型实时路由 | Dify 节点级硬绑定,本仓库更灵活 |
| 外部 API 三段式 + 工作目录下载 | 比 Dify 单次调用更适合长时间任务场景 |
| kebab-case name + 中文 displayName 分离 | 比 Dify UUID 更友好,URL 可读性强 |
详见各设计文档:
docs/workflow-node-fields.mddocs/workflow-scheduling-engine-plan.mddocs/workflow-dataflow-execution-plan.mddocs/workflow-node-output-envelope.mddocs/workflow-envelope-strict-validation-plan.mddocs/workflow-variable-scope-design.mddocs/context-passing-architecture.mddocs/workflow-crud-api.mddocs/external-workflow-api-spec.mddocs/hermes-sandbox.mddocs/hermes-error-detection-plan.md详见 docs/dify-readme.md: