编辑器:变量与数据映射

适用版本:ChengOS v0.1.0+ | 最后核对:2026-08-12 | 来源:crates/cheng-engine/src/executor/workflow_executor/node_execution.rscrates/cheng-engine/src/executor/context.rscrates/cheng-nodes/src/nodes/builtin/utils/smart_variable_node.rschengflow-ui/src/features/editor/components/VariableSelectorDrawer.tsx

数据在节点之间有三种流动方式:连线(主要机制)、节点自身配置里的 ${...} 替换,以及引擎的环境注入。它们之间有严格的优先级顺序,搞清楚这个顺序,几乎能解释所有「我的节点为什么拿到了那个值」的疑问。

连线

一条连线指明四件事:源节点、源输出端口、目标节点、目标输入端口。

节点 A ──[ text ]────────►[ user_message ] 节点 B
       source_output       target_input

执行时,引擎遍历某个节点的每条入边,读取源节点在该端口上的输出,并以目标端口名写进目标节点的输入。端口按名称匹配,因此在节点 schema 里改掉一个输出端口名,会让所有引用旧名字的连线失效。

动态数组端口

当不存在同名端口时,形如 prefix_N 的端口会去数组输出里解析。引擎先试 prefix_outputs[N],再试 prefixs[N]

branch_0  →  branch_outputs[0]   (先试这个)
          →  branches[0]         (回退)

正因如此,一个路由节点只需声明一个数组输出,却仍能在画布上暴露带编号的端口。

null 意味着「不走这条路」

若某节点的入边全部产出 null,它会被自动跳过,而不是带着空输入去运行。这正是条件路由的机制:条件节点在选中的分支上发出值、在其余分支上发出 null,未被选中的下游子树便自行跳过。跳过会级联——跳过一个节点可能解锁更下游节点的跳过判定。

输入优先级

节点运行时,输入按以下顺序装配。除非特别注明,后面的步骤不会覆盖前面的。

# 来源 是否覆盖?
1 入边 ——(第一写入者)
2 扁平执行输入(仅限无入边的起始节点) 只补空缺
3 循环虚拟输入(itemindex、上一轮值) 只补空缺
4 节点自身配置(经 ${...} 替换后) 只补空缺
5 按节点 id 指定的执行期输入 覆盖
6 AgentContext 注入到 context 仅当 context 为空
7 环境字段(workspace_idconversation_iddocument_id 只补空缺

有两个后果最容易绊人:

  • 连线永远压过你在属性面板里填的值。 配置是第 4 步,连线是第 1 步。已连接的输入在面板里不可编辑,原因正在于此。
  • 按节点的执行期输入压过一切。 这正是单节点测试能工作的原因:测试运行器按节点 id 提供输入,它们会覆盖已连好的图。

第 6 步是一道真实的防错:如果某条连线已经提供了 context——比如 RAG 检索器的结果——引擎不会用智能体上下文把它冲掉。

${...} 替换

在节点配置内部,${name} 会被替换成名为 name 的执行输入:

{ "url": "https://api.example.com/v1/${resource}",
  "header": "Bearer ${api_token}" }

规则被刻意收得很窄:

  • 只替换字符串,并递归穿过对象与数组。
  • 只有简单值会内插——字符串、数字、布尔。对象或数组值会让占位符原样保留。
  • 未知名字保留 ${name} 原样,而不是替换成空串。因此,缺失的值会在你发出的请求里显示为一个可见的占位符,而不是一段悄无声息的空白。

__env__ 为前缀的键携带由技能解析出的密钥。它们可用于 ${__env__KEY} 替换,但绝不作为直接的节点输入暴露——因为节点输入会与输出一起被持久化,密钥就会落进执行记录里。

环境字段

workspace_idconversation_iddocument_id 由引擎从智能体上下文或执行 metadata 注入。这些输入在画布上是隐藏的,通常留空。

工具调用而言,这种注入是强制覆盖而非补空:模型填进该字段的东西会被替换掉。模型无法靠编造 workspace_id 来扩大自己的作用域。见知识库与工作区上下文

值得知道的兼容处理

  • ai/llmagent/llmuser_message 为空时会回落到 raw_input。网关与对话入口把用户文本作为 raw_input 传入,因此模型节点直接接在对话输入之后就能工作,中间不需要映射节点。
  • 按节点 id 指定的执行输入若不是对象,则对 io/input_text 写入 text,对其他节点写入 content

智能变量节点

utils/smart_var 是为模板替换处理不好的场景准备的:你手上有一团 JSON、一条 curl 命令或一段 YAML,而你想把它的字段变成可连线的输入。

把文本粘进 template,节点就会提取变量名并为每个变量生成一个输入端口。连上你关心的端口,节点便输出完成替换后的文本。

提取模式

模式 行为
auto(默认) 识别键名——先把文本按 JSON 解析并递归遍历;不是合法 JSON 时回退到正则扫描
manual 只识别 {{var}} 占位符

重名会加上索引后缀(tokentoken_2……),于是两个同名字段变成两个不同端口,而不是在 map 里悄悄互相覆盖。无意义的词会从候选列表中被过滤掉。

输出

  • full_text——全部变量替换完成的模板文本;下游节点通常消费的就是它。
  • selected_vars——只包含你在 output_vars 里勾选的变量,以键值对形式给出。
  • all_variables——找到的全部名字,选择器的选项就来自它。
  • preview_content——供画布显示的格式化预览。
  • statistics——变量的总数/已连接数/取默认值数/缺失数,以及模板与输出的字符数。

statistics 这一块就是调试工具:missing_variables 大于零,说明有端口没连上——你还没看输出文本就知道了。

变量选择器

output_vars 通过一个抽屉编辑,而不是一个文本框:可按名称和描述搜索、逐个勾选,或对当前筛选结果一键全选/全不选。它还显示「已选/总数」,于是面对一个 60 字段的载荷,你一眼就能看出选了多少。

该用哪种机制

场景
一个节点的输出喂给另一个的输入 连线
固定的配置字符串里需要一个运行时值 配置里的 ${...}
一段文本里有大量字段要连 utils/smart_var
节点需要当前工作区或会话 什么都不用做——它是环境注入的

下一步

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容