workflow-node-fields.md 16 KB

工作流节点自动输入输出与变量转换规范

说明:本文档基于当前代码实现梳理,覆盖后端执行器(backend/src/main/java/com/agent/management/engine/executor)与前端 IO 推断逻辑(frontend/src/utils/ioInference.js)。 文中“转换器”一栏既描述当前运行时的实际行为,也给出推荐的统一转换规则,供后续在 TemplateRenderer / ContextPromptHelper 或前置条件校验中实现。


1. 术语与上下文机制

1.1 变量存储

工作流上下文 WorkflowContext 内部维护一张扁平变量表 variables: ConcurrentHashMap<String, Object>

  • 运行开始时,把 request.inputs 全部放入。
  • 每个节点执行完成后,WorkflowLevelExecutor 调用 context.setNodeOutput(nodeId, output),把 output 中的每个 key-value 写入 variables
  • 同名 key 会覆盖上游值,并打印 WARN 日志。

1.2 变量消费方式

消费方式 触发位置 当前行为
{{变量名}} 模板渲染 TemplateRenderer variables 取值后调用 value.toString() 替换;变量不存在时保留占位符。
自动系统提示注入 ContextPromptHelper 把全部 variables 按 - key:value 格式拼接为系统提示,value 同样走 toString(),超长截断至 2000 字符。
前置条件校验 WorkflowLevelExecutor.checkPreconditions 仅校验存在性与类型兼容性,不做类型转换。
Agent / Skill 用户消息 AgentExecutor.buildUserMessage / HermesAgentExecutor.buildUserMessage 按 Skill.inputs 定义取值后 toString() 拼接。
条件分支判断 ConditionExecutor 把全部 variables 的 toString() 拼成上下文摘要,交给 LLM 判断分支编号。

1.3 类型系统

前后端统一的 IO 类型定义:

string | number | boolean | array | object | filePath | directoryPath

来源:

  • 后端:com.agent.management.model.dto.IOField
  • 前端:frontend/src/utils/ioInference.jsIO_TYPES

2. 节点类型总览

节点 type 中文名 后端执行器 前端组件
userInput 用户输入 UserInputExecutor InputNode.vue
llm 大模型处理 LlmExecutor LLMNode.vue
agent 智能体 AgentExecutor(hermes=false)/ HermesAgentExecutor(hermes=true) AgentNode.vue
skill 技能 SkillExecutor(委托给 agent 执行器) SkillNode.vue
smartAction 智能操作 SmartActionExecutor(hermes=false)/ HermesSmartActionExecutor(hermes=true) SmartActionNode.vue
knowledgeRetrieval 知识库检索 KnowledgeRetrievalExecutor KnowledgeRetrievalNode.vue
condition 条件分支 ConditionExecutor ConditionNode.vue
output 输出 OutputExecutor OutputNode.vue

3. 各节点自动输入输出字段

3.1 userInput(用户输入节点)

自动输入:无。节点本身只负责把运行时已经注入到 variables 中的初始输入值注册为可用变量。

自动生成输出

输出字段 类型 来源 说明
variables[i].name 由前端声明的类型决定 request.inputs 中同名 key 节点 data.variables 数组里每个条目的 name 字段;若运行时未提供该 key,则不写入。

例如:data.variables = [{name:"question", type:"string"}],则输出变量名为 question


3.2 llm(大模型节点)

自动输入

输入字段 类型 来源 说明
systemPrompt 中的 {{var}} string 上游 variables 模板渲染后作为系统提示。
userPrompt 中的 {{var}} string 上游 variables 模板渲染后作为用户提示。
data.inputs[] 声明的字段 任意 上游 variables 用于前端边映射校验与 checkPreconditions 前置条件校验。
全部上游 variables object/map 上下文 通过 ContextPromptHelper.merge(...) 自动追加到系统提示词末尾。

自动生成输出

输出字段 类型 来源 说明
outputs[0].nameresult string LLM 响应文本 单输出场景。若 data.outputs 为空,默认变量名为 result
outputs[i].name(i≥0) 由 outputs[i].type 决定 LLM 响应经 JSON 解析 多输出场景(outputs 长度 > 1):由 StructuredOutputHelper 注入 JSON 指令并解析。

多输出字段类型转换见第 4 节。


3.3 agent / skill(智能体 / 技能节点)

两者对外接口一致;SkillExecutorskillId 复制为 agentId 后委托给 agent 执行器。

自动输入

输入字段 类型 来源 说明
关联 Skill 的 inputs[] 由 Skill 声明 上游 variables buildUserMessage 按 Skill 输入定义从 context 取值。
全部上游 variables object/map 上下文 通过 ContextPromptHelper.merge(...) 追加到 SKILL.md 系统提示后。

注意:当前 agent/skill 节点的前端默认数据中没有 inputs/outputs 数组,依赖 Skill 元数据中的 inputs/outputs

自动生成输出

输出字段 类型 来源 说明
outputs[0].nameresult string Agent 执行返回的 finalText 当前仅支持单输出,多 outputs 时也只取第一个。

3.4 smartAction(智能操作节点)

自动输入

输入字段 类型 来源 说明
actionPrompt 中的 {{var}} string 上游 variables 模板渲染后作为操作要求。
data.inputs[] 声明的字段 任意 上游 variables 用于前端边映射校验与前置条件校验。
全部上游 variables object/map 上下文 通过 ContextPromptHelper 自动注入系统提示。

自动生成输出

输出字段 类型 来源 说明
outputs[0].nameresult string LLM / Hermes 执行结果 单输出场景,默认变量名 result

3.5 knowledgeRetrieval(知识库检索节点)

自动输入

输入字段 类型 来源 说明
query 中的 {{var}} string 上游 variables 模板渲染后作为检索语句。
data.inputs[] 声明的字段 任意 上游 variables 用于前端边映射校验与前置条件校验。
source / topK / 各类 sourceIds 配置项 节点 data 决定检索范围与来源类型。

自动生成输出

输出字段 类型 来源 说明
evidences List<RagEvidence> 检索结果 命中的证据列表,每个元素含 id / sourceType / evidenceType / title / content / score / sourceName / sourceRef / payload / metadata
evidenceCount number 检索结果 evidences.size()
sourceType string 检索结果 DOCUMENT / STRUCTURED_DATA / GRAPH / HYBRID
diagnostics object 检索结果 各来源的诊断信息,key 可能为 datasource:<id> / graph:<id> / error:...
knowledgeBaseId number 节点 data(仅 hybrid) 混合检索时指定的知识库 ID。
enabledSources object/map 后端结果(仅 hybrid) 各来源是否启用。

默认输出变量:若用户未在 data.outputs 中自定义,前端默认暴露 evidences / evidenceCount / sourceType / diagnostics


3.6 condition(条件分支节点)

自动输入

输入字段 类型 来源 说明
conditions[i].expression 中的 {{var}} string 上游 variables 条件表达式模板。
data.inputs[] 声明的字段 任意 上游 variables 用于前端边映射校验。
全部上游 variables object/map 上下文 ConditionExecutor 把 variables 摘要后交给 LLM 判断分支。

自动生成输出

条件节点不向 variables 写入任何变量。它通过 NodeExecutionResult.selectedBranch 返回分支句柄(如 branch-0branch-1),由 WorkflowLevelExecutor.activateDownstreamedge.sourceHandle 过滤下游激活节点。


3.7 output(输出节点)

自动输入

输入字段 类型 来源 说明
data.fields[] 声明的字段 任意 上游 variables 用于前端选择最终输出字段。
全部上游 variables object/map 上下文 节点执行时直接收集整个 variables 表。

自动生成输出


4. 输出字段 → 下游输入字段转换器规范

4.1 通用转换规则

当前运行时没有按目标类型做自动转换的组件,统一走 Object.toString()。为支持工作流节点之间的类型安全连接,推荐引入以下转换器语义。

基础类型转换表

输出字段 类型 来源 说明
全部上游 variables 混合 上下文 OutputExecutorcontext.getVariables() 原样放入输出。
_workingDirFiles array 工作目录扫描 工作目录中经 .agentignore 过滤后的相对文件路径列表。
_runId string 上下文 本次运行 ID。
源实际值 目标类型 string 目标类型 number 目标类型 boolean 目标类型 object 目标类型 array 目标类型 filePath / directoryPath
String 原值 尝试 Double.parseDouble;失败取 NaN "true"/"1"/"yes" 为 true,其余 false 尝试 JSON 解析为对象;失败封装为 {value: 原值} 尝试 JSON 解析为数组;失败封装为 [原值] 若值对应工作目录中合法路径则通过;否则保留字符串
Number toString() 原值 != 0 为 true {value: 数字} [数字] 不适用
Boolean toString() true→1,false→0 原值 {value: true/false} [true/false] 不适用
Map / POJO ObjectMapper.writeValueAsString 若 map 仅含数值字段可尝试;否则 NaN 非空 map 为 true 原值 [Map.Entry] 列表 不适用
Collection / Array 拼接为字符串(推荐 JSON) 长度值 非空为 true 若长度为 1 取首元素;否则 {items: 数组} 原值 不适用
RagEvidence(检索证据) content 字段内容 无意义 非空为 true 将 POJO 转为 Map(含 title/content/score...) [证据Map] 不适用

兼容性原则(与现有代码保持一致)

前后端已有的类型兼容规则:

  • filePath / directoryPath / number / boolean → 可隐式转为 string
  • array → 可隐式赋值给 object
  • 其他组合视为不兼容。

4.2 各节点输出字段的推荐转换器

4.2.1 LLM / Agent / SmartAction 的 result(string)

下游目标类型 转换器行为
string 直接传递完整文本。
number 尝试提取文本中的第一个数字;无数字返回 NaN
boolean 文本为 "true"/"1"/"yes" 返回 true; "false"/"0"/"no" 返回 false;其余按非空判断。
object ① 尝试整段 JSON 解析为 Map;② 失败则取文本前 2000 字符封装为 {result: text}
array ① 尝试 JSON 解析为 List;② 失败则按行/段落拆分后封装为 ["line1", "line2", ...]

4.2.2 LLM 结构化多输出字段

StructuredOutputHelper.convertValue 已提供基础转换:

  • numbervalue.isNumber() ? value.numberValue() : Double.parseDouble(value.asText())
  • booleanvalue.isBoolean() ? value.booleanValue() : Boolean.parseBoolean(value.asText())
  • array / objectMAPPER.treeToValue(value, Object.class)
  • 默认:文本或 toString()

4.2.3 KnowledgeRetrieval 的 evidencesList<RagEvidence>

这是用户问题中重点示例的场景。

下游目标类型 转换器行为
string 取 Top-1 证据的 content 字段;若列表为空返回 ""。推荐可配置为 "top1""concat" 两种模式。
number 返回 evidenceCount(即列表长度)。
boolean 列表非空返回 true。
object 取 Top-1 证据,将其字段(id/sourceType/evidenceType/title/content/score/sourceName/sourceRef/payload/metadata)转为 Map。
array 取 Top-K(默认全部)证据列表,每条证据转为 Map。
filePath / directoryPath 不适用,转换失败。

4.2.4 KnowledgeRetrieval 的 evidenceCount(number)

下游目标类型 转换器行为
string String.valueOf(count)
number 原值
boolean count > 0
object {evidenceCount: count}
array [count]

4.2.5 KnowledgeRetrieval 的 sourceType(string)

下游目标类型 转换器行为
string 原值,如 "DOCUMENT" / "GRAPH"
object {sourceType: value}
array [value]

4.2.6 KnowledgeRetrieval 的 diagnostics(Map)

下游目标类型 转换器行为
string ObjectMapper.writeValueAsString(diagnostics)
object 原 Map
array Map 的 entry 列表 [{key, value}, ...]

4.2.7 userInput 变量(按声明类型)

由于前端已声明类型,转换器按声明类型直接透传;若下游目标类型与声明类型不兼容,再按 4.1 通用规则转换。

4.2.8 Output 节点收集的 _workingDirFiles(array)
下游目标类型 转换器行为
string 取第一条路径;空数组返回 ""
array 原数组
object {files: array}

5. 当前代码实现速查

关注点 文件路径
节点执行器接口 backend/src/main/java/com/agent/management/engine/NodeExecutor.java
执行器注册与调度 backend/src/main/java/com/agent/management/engine/WorkflowLevelExecutor.java
上下文与变量存储 backend/src/main/java/com/agent/management/engine/WorkflowContext.java
{{变量}} 模板渲染 backend/src/main/java/com/agent/management/engine/TemplateRenderer.java
上下文系统提示注入 backend/src/main/java/com/agent/management/engine/ContextPromptHelper.java
单/多输出变量名解析 backend/src/main/java/com/agent/management/engine/NodeTypeUtils.java
LLM 结构化输出解析 backend/src/main/java/com/agent/management/engine/StructuredOutputHelper.java
前置条件类型校验 backend/src/main/java/com/agent/management/engine/WorkflowLevelExecutor.java:294
前端 IO 推断与映射 frontend/src/utils/ioInference.js
前端节点默认数据 frontend/src/utils/workflowNode.js
证据数据结构 backend/src/main/java/com/agent/management/rag/model/RagEvidence.java

6. 待实现建议

  1. 统一转换器注册表:在 TemplateRenderer 或新增 VariableConverter 中按“源字段 + 目标类型”注册转换函数,替代目前简单的 value.toString()
  2. KnowledgeRetrieval evidences 转 string 策略可配置:支持 top1concatjson 等模式,满足不同下游节点需求。
  3. 前置条件校验增强:在 checkPreconditions 中引入转换器尝试,使 array→object、number→string 等兼容组合真正可用,而非仅做类型检查。
  4. 前端类型提示:在 ioInference.jsisTypeCompatible 基础上,增加转换器说明,让用户在连线和配置 mapping 时看到自动转换规则。