工作流编辑器(Workflow)
Workflow 是 8 种编排模式之一,用**可视化画布(有向图 DAG)**把多个节点连成一条流程:每个节点做一件确定的事(调智能体、查知识库、调 API、人工确认…),节点之间用连线决定走向。适合"步骤明确、要可控、要省 token"的场景——审批流、数据管道、固定 SOP。
与其它编排的区别
- Single / Supervisor / Collaboration 把决策权交给 LLM;Workflow 把流程写死成图,由你掌控每一步。
- 不是所有节点都调 LLM ——
kb_query/mcp_call/data_query/transform/http_request完全不经过 LLM,省 token 又更快。
编辑器界面
在编排器设计器里把类型选为 Workflow 后进入画布编辑器。布局:
| 区域 | 作用 |
|---|---|
| 左侧 节点库 | 按分组列出可添加的节点(基础 / 流程控制 / 集成·数据),点击或拖入画布 |
| 中间 画布 | 拖拽节点、拉连线;节点右上角显示最近一次运行状态徽章 |
| 右侧 属性面板 | 选中节点后配置其字段(下文逐节点说明) |
| 底部 调试运行栏 | 输入测试消息(可附图片)直接试跑,实时看每个节点的执行 |
| 运行时变量面板 | 调试运行时实时查看 state.variables 的变化 |
顶栏提供 保存草稿 / 试运行 / 发布 / 版本历史 / 回滚(见发布与版本管理)。
通用概念
模板变量
几乎所有节点的文本字段(input_template、url、body_template、query_template、params_template、template…)都支持占位符:
| 占位符 | 含义 |
|---|---|
{{ user_message }} | 工作流的原始输入(用户这句话) |
{{ last_output }} | 上一个节点的输出 |
{{ images }} | 用户上传的图片列表(人类可读,无图为空串) |
{{ vars.X }} | 命名变量 X(由某个节点的 output_var 写入) |
输出变量(output_var)
动作类节点都有 output_var:把本节点输出写入 state.variables[output_var],下游用 {{ vars.X }} 读取。不填则只更新 last_output(链式够用,需要"具名引用"时才设)。
连线类型
| 连线 | 含义 |
|---|---|
| 普通连线(default) | 无条件流向下一节点 |
| 条件连线(conditional) | 由 conditional 节点的规则决定 |
| 失败连线(on_error,红色虚线) | 节点 on_error.target 的可视化投影(UI-only,后端按字段自动建路由) |
入口
start 是入口节点(entry_point);end 是终点。
节点总览
| 分组 | 节点 | 图标 | 一句话 |
|---|---|---|---|
| — | 开始 / 结束 | ▶️ / ⏹️ | 流程起点 / 终点 |
| 基础 | 智能体(agent) | 🤖 | AI 智能体执行一次推理 |
| 基础 | 嵌套编排(orchestrator) | 🎛️ | 嵌套调用另一个编排器 |
| 流程控制 | 条件判断(conditional) | 🔀 | 按条件路由到不同分支 |
| 流程控制 | 有界循环(loop) | 🔁 | 有界循环,配合 conditional 退出 |
| 流程控制 | 数组遍历(for_each) | 🔂 | 对 vars.X 数组每个元素套模板 |
| 流程控制 | 人工确认(human_input) | 🙋 | 暂停等待人工确认 |
| 集成·数据 | HTTP 调用(http_request) | 🌐 | 调用外部 HTTP API |
| 集成·数据 | 数据整形(transform) | 🔧 | 纯模板渲染,无 LLM |
| 集成·数据 | 知识库查询(kb_query) | 📚 | 直查知识库,省 token |
| 集成·数据 | 数据查询(data_query) | 🗃️ | 直调 Sira 数据工具(SQL/NoSQL/图) |
| 集成·数据 | MCP 工具调用(mcp_call) | 🔌 | 参数确定时直调 MCP 工具,省 Agent 包装 |
节点配置详解
智能体(agent)🤖
| 字段 | 说明 |
|---|---|
| 选择智能体(agent_id) | 必填,执行的智能体 |
| 输入模板(input_template) | 喂给智能体的内容;留空则用最近一条用户消息 |
| 输出变量(output_var) | 可选,把回答写入 vars.X |
结构化输出
若所选智能体配了结构化输出,下游可用 {{ vars.X.字段名 }} 直接取某个字段。
嵌套编排(orchestrator)🎛️
| 字段 | 说明 |
|---|---|
| 选择编排器(orchestrator_id) | 必填,被嵌套调用的编排器 |
| 输入模板 / 输出变量 | 同 agent 节点 |
嵌套调用会形成链路 trace(parent_orchestrator_id),可在执行记录里逐层下钻。
条件判断(conditional)🔀
按规则把流程路由到不同节点。
| 字段 | 说明 |
|---|---|
| 条件列表(conditions) | 每条 = 类型 + 表达式 + 命中后去向节点 |
| └ 类型(type) | keyword(包含关键词)/ regex(正则)/ expression(布尔表达式) |
| └ 匹配对象(match_against) | user_message(默认)/ last_output / images / vars.X —— 决定 keyword/regex 拿哪段文本匹配 |
| 默认去向(default_next) | 所有条件都不命中时走这里 |
数据流路由
做"基于上一步输出"的分支时,记得把 match_against 显式设为 last_output 或 vars.X,否则默认匹配的是用户原始问题。images 可用来做"有图走 OCR / 无图走文本"的分流。
有界循环(loop)🔁
| 字段 | 说明 |
|---|---|
| 最大次数(max_iterations) | 上限 50(后端硬封顶),到顶会置 vars._loop_<节点id>_exhausted = "true" 供 conditional 跳出 |
必须有回边
loop 只是"计数器+封顶",真正循环需要画一条从后续节点连回 loop 的回边。没有回边时 loop 只会跑 1 次(画布会提示"⚠️ 缺循环回边")。配合 conditional 判断退出条件,避免死循环。
数组遍历(for_each)🔂
对一个数组的每个元素套用模板,省去 loop+conditional 的样板。
| 字段 | 说明 |
|---|---|
| 数组变量(items_var) | 支持点路径,如 users / cominfo.items / vars.cominfo.items;终点必须是数组,任一段不存在按空数组优雅降级 |
| 元素模板(item_template) | 每个元素渲染一次;可读 {{ vars._item }} 和 {{ vars._foreach_index }} |
| 分隔符(separator) | 把各元素结果连成 last_output |
| 输出变量(output_var) | 结果数组写入 vars.X(默认 _foreach_results) |
人工确认(human_input)🙋
流程暂停,发一张确认卡片到渠道,等人点"通过/拒绝"再继续(HITL)。
| 字段 | 说明 |
|---|---|
| 提示模板(prompt_template) | 卡片正文,支持占位符 |
| 交互类型(interaction_type) | 当前支持 confirm(确认 / 拒绝) |
| 标题(title) | 卡片标题;不填用"工作流确认: <节点id>" |
详见人工审批 (HITL)。卡片默认 24 小时超时。
HTTP 调用(http_request)🌐
| 字段 | 说明 |
|---|---|
| 方法(method) | GET / POST / PUT / DELETE / PATCH / HEAD |
| URL(url) | 支持占位符 |
| 请求头(headers) | 键值对,值支持占位符 |
| 请求体(body_template) | 支持占位符 |
| 提取(extract_jsonpath) | 如 $.data.token,从 JSON 响应里抽字段写入输出 |
| 超时(timeout_seconds) | 单次请求超时 |
SSRF 防护
HTTP 节点带内网地址防护,访问内网/元数据地址会被拒绝(SSRF rejected)。
数据整形(transform)🔧
纯模板渲染节点,不调用任何 LLM/服务,用于并行汇聚、拼接、改写。
| 字段 | 说明 |
|---|---|
| 模板(template) | 必填,输出内容模板 |
| 输出变量(output_var) | 结果写入 vars.X(不填只更新 last_output) |
知识库查询(kb_query)📚
直接做 RAG 检索,不经过 LLM 包装,省 token。
| 字段 | 说明 |
|---|---|
| 知识库(kb_id) | 必填 |
| 查询模板(query_template) | 缺省用 user_message |
| 检索模式(mode) | local / global / naive / mix / hybrid(默认 hybrid) |
| top_k | 返回片段数,默认 5(范围 1–50) |
| 输出变量(output_var) | 得到字典 {answer, sources, kb_id, mode} |
数据查询(data_query)🗃️
直调 Sira 内置数据工具(进程内 SQL / NoSQL / 图查询),不经过 LLM,也不经过外部容器。
| 字段 | 说明 |
|---|---|
| 数据工具(tool_name) | 必填,按工具 name 派发(不用 UUID,方便跨环境复制流程) |
| 工具集(toolset_id) | 仅用于 UI 过滤,后端运行时忽略 |
| 超时覆盖(timeout_override) | 可选 |
| 行数上限覆盖(max_rows_override) | 可选 |
| 输出变量(output_var) | 查询结果写入 vars.X |
数据工具在管理后台 → 数据集成里创建。
MCP 工具调用(mcp_call)🔌
参数确定时直调 MCP 工具,省去 Agent 包装层。
| 字段 | 说明 |
|---|---|
| MCP 工具(tool_id) | 必填 |
| 方法(method) | 必填,MCP 工具暴露的函数名(编辑器可一键加载方法列表) |
| 参数模板(params_template) | JSON 字符串模板,可含占位符;选完方法可"🪄 自动生成"参数骨架 |
| 输出变量(output_var) | result 字典写入 vars.X |
节点鲁棒性(重试 / 超时 / 失败兜底)
下列动作类节点(agent / orchestrator / http_request / kb_query / mcp_call / transform / for_each)都支持统一的鲁棒性配置(loop / conditional / human_input / start / end 不适用):
| 字段 | 说明 |
|---|---|
| 重试(retry.max_attempts) | 默认 1(不重试);>1 启用。配 backoff_seconds(首次等待,默认 1)、backoff_multiplier(指数退避,默认 2)、max_backoff_seconds(上限,默认 60) |
| 超时(timeout_seconds) | 单次 attempt 超时,触发算一次失败(会消耗重试次数) |
| 失败去向(on_error.target) | 重试全部失败后路由到的兜底节点;不配则中断整条工作流 |
在兜底节点里拿错误信息
走 on_error 兜底分支时,可用 {{ vars._last_error.X }} 读取失败详情。
发布、试运行与调试
- 保存草稿 → 发布:编辑保存为草稿,渠道 / Webhook / 定时任务只运行已发布版本(详见发布与版本管理)。组织启用资源审批后,"发布"变为"提交审核"。
- 试运行:底部调试运行栏输入测试消息(可附图片)直接跑,逐节点看输入/输出与状态徽章;右侧运行时变量面板实时看
state.variables。 - 触发上下文预填:Webhook / Cron / 渠道触发的元数据会自动预填进
state.variables,可在节点里用{{ vars.X }}读取。失败的异步执行会进入失败队列 (DLQ)。
常见坑
- 循环只跑了一次 → loop 缺回边,见上文"必须有回边"。
- 条件分支总走默认 →
conditional的match_against没设对(默认匹配user_message而不是上一步输出)。 - HTTP 403 / SSRF rejected → 访问了被禁的内网/元数据地址。
- 删了节点找不回 → 删除前先保存草稿;版本历史可回滚。
相关文档
- 手把手 5 分钟教程见操作手册《1.1 智能体系统》§1.1.3 工作流编辑器使用指南(含示例与排错)。
- 编排模式详解 · 人工审批 (HITL) · 知识库 · MCP 工具 · 数据集成(GenAI Toolbox)
