1.1 智能体系统(Agent System)
这是 Sira 的核心模块。包含 6 个子页面:智能体、编排器、应用、API 服务、失败队列(DLQ)、渠道认证。其中渠道认证仅管理员可见。
进入路径:左侧主导航 → 智能体系统(展开后看到二级菜单)。
推荐阅读顺序:智能体 → 编排器 → 应用 → API 服务。这是数据流向,也是配置顺序。失败队列(DLQ)和渠道认证是运维/管理类页面。
💡 卡片视图 / 列表视图:智能体、编排器、应用三个列表页右上角都有卡片视图 / 列表视图切换按钮,系统会记忆你上次选择的视图。卡片视图适合浏览,列表视图适合在条目多时快速扫读。
1.1.1 智能体管理 [U]
页面路径:/agent-system/agents用途:管理一个个独立的 AI 个体。每个智能体绑定一个 LLM 模型、一段系统提示词、可调用的工具和可选知识库。
列表页
布局:
- 顶部操作栏:刷新 + 「创建 Agent」按钮
- 筛选区:名称搜索框、活跃状态下拉(全部/已启用/已停用)
- 主体:3 列卡片网格,每页 12 条
- 底部:分页器
卡片字段:
| 字段 | 说明 |
|---|---|
| display_name | 大字标题 |
| description | 副标题描述 |
| model_id | 绑定的 LLM 模型名 |
| is_active | 右上角徽章:绿色"活跃"/灰色"停用" |
| created_at | 创建时间 |
卡片右下角操作:编辑、删除、更多(包含"复制"等扩展操作)。
创建/编辑智能体(设计器)
入口:列表页「创建 Agent」按钮,或卡片上的「编辑」按钮。 路径:/agent-system/agents/designer/[id]
设计器采用 6 步骤分步表单,每步右上角有保存按钮。
Step 1:基本信息
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | text | ✓ | 内部标识符,小写英文+下划线,创建后不可改 |
| display_name | text | ✓ | UI 显示名称 |
| description | textarea | 给同事和你自己看的说明 | |
| is_active | toggle | 默认开启;关闭后此智能体不会被任何应用调用 |
Step 2:LLM 配置
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| model_id | select | ✓ | 从已配置的 AI 模型中选,模型由管理员维护 |
| system_prompt | editor | 系统提示词,支持模板变量(如 {user_name}) | |
| temperature | slider | 0.0 ~ 2.0,默认 0.7。值越大越发散 | |
| max_tokens | number | 单次输出上限,默认 4096 | |
| top_p | slider | 默认 1.0,核采样阈值 | |
| frequency_penalty | slider | 频率惩罚,默认 0 | |
| presence_penalty | slider | 存在惩罚,默认 0 |
💡 提示词编辑器(
TemplateEditor)右下角有"插入变量"按钮,可看到所有可用模板变量。
Step 3:MCP 工具
| 字段 | 类型 | 说明 |
|---|---|---|
| mcp_tool_ids | multi-select | 勾选可调用的 MCP 工具;空表示不调用任何工具 |
| tool_choice | select | auto(由 AI 决定)/ required(必须调用)/ none(禁止) |
Step 4:数据与运行
| 字段 | 类型 | 说明 |
|---|---|---|
| max_planning_iterations | number | ReAct 最大迭代次数,默认 25(防死循环) |
| streaming_enabled | toggle | 是否启用流式输出 |
| timeout_seconds | number | 单次调用超时,默认 60 |
| retry_config | nested | max_retries(默认 3)、retry_delay(秒)、exponential_backoff(是否指数退避) |
Step 5:知识库
| 字段 | 类型 | 说明 |
|---|---|---|
| knowledge_base_ids | multi-select | 绑定一个或多个知识库 |
| retrieval_config.mode | select | naive / local / global / hybrid(默认) / mix |
| retrieval_config.top_k | number | 默认 5 |
| retrieval_config.threshold | slider | 相似度阈值,默认 0.7 |
| retrieval_config.rerank | toggle | 启用重排序模型 |
| retrieval_config.as_tool | toggle | 把知识库当成可被 AI 主动调用的工具,而不是每次都检索 |
Step 6:技能包
| 字段 | 类型 | 说明 |
|---|---|---|
| skill_ids | multi-select | 绑定技能包(Markdown 操作手册) |
⚠️ 重要:智能体上配的
skill_ids只在它被用作 DeepAgents 的 SubAgent 时生效。如果你希望 SINGLE 编排器也能用技能包,需要把技能包配在编排器上(详见 编排器)。
智能体版本历史
设计器顶栏提供版本历史抽屉:每次保存都会生成一个快照,带已发布徽章标识当前生效版本。需要回退时,在抽屉里选某个历史版本点回滚到此即可还原。
智能体保存即生效(不分草稿/发布,与编排器不同),回滚同样立即对所有引用该智能体的编排器生效。当组织启用了资源审批时,智能体的发布/回滚也会进入审批流程。
删除智能体
🚫 冲突保护:如果某个智能体被编排器引用,直接删会返回 HTTP 409。前端弹出冲突列表对话框,显示所有引用方(编排器名 + 字段路径)。
操作步骤:
- 卡片右下角点「删除」
- 第一次确认对话框 → 「确认」
- 若有冲突 → 看清引用列表 → 决定是否「强制删除」(会让引用方下次执行报错)
1.1.2 编排器管理 [U]
页面路径:/agent-system/orchestrators用途:把一个或多个智能体按 8 种模式编排成"超级智能体"。
列表页
布局和智能体列表类似(3 列卡片 + 筛选 + 分页),区别:
- 筛选器多了编排类型下拉(8 种 + 全部)
- 卡片显示编排类型徽章(single / supervisor / collaboration / workflow / conditional / external / deep_agents / knowledge_base)
- 操作里多一个「测试」按钮,可不发布就在线试聊
编排器测试对话框
入口:卡片操作 → 「测试」。 内容:简易聊天框,输入测试消息 + 可选 session_id,直接发起一次执行并实时显示编排器输出。适合上线前快速验证。
创建/编辑编排器(设计器)
路径:/agent-system/orchestrators/designer/[id]
设计器是单页面的(不再是分步骤向导):顶栏 + 配置主体在同一个界面里。
- 顶栏:名称 / 显示名 / 描述都是点击就地编辑(inline),改完即在草稿里生效。
- 编排类型:用一个分组下拉选择(分组:推荐 / 进阶 / 外部对接),不再是 8 张大卡片铺满屏。类型一经创建即只读——创建后无法修改编排类型(要换类型只能新建一个编排器)。
可选的编排类型(下拉里按分组展示):
| 类型 | 分组 | 适用场景 |
|---|---|---|
| Single | 推荐 | 只需一个智能体的简单场景 |
| Supervisor | 推荐 | 一个"调度官"按需把任务分给下属智能体 |
| Collaboration | 推荐 | 多个智能体顺序或并行协作(无主管) |
| Workflow | 进阶 | 可视化画布:节点 + 连线编排的多步骤流水线 |
| Conditional | 进阶 | 根据规则把请求路由到不同智能体 |
| DeepAgents | 进阶 | AI 可读技能包、操作沙箱、递归分解任务 |
| KnowledgeBase | 进阶 | 直接 RAG 检索回答,不走完整推理链 |
| External | 外部对接 | 整段流程托管到 Dify / n8n |
编排配置(随类型变化)
下方主体区域随所选编排类型展示对应的配置表单:
Single
只有一个字段:agent_id(下拉选一个智能体)。
💡 隐藏特性:如果选中的智能体配置了
skill_ids,Sira 会自动把这个 Single 编排器升级为 DeepAgents 执行路径,从而让技能包能在沙箱里被运行。对用户透明,不用额外配置。
Supervisor
| 字段 | 说明 |
|---|---|
| sub_agent_ids[] | 下属(worker)智能体列表,至少 2 个 |
| model_id / temperature / max_tokens / system_prompt | 主管(调度官)自己的 LLM 与"路由提示词"。system_prompt 不填时用内置默认 |
| supervisor_agent_id | 可选:把一个现有智能体包装成主管(给了就用它,不再用上面的 LLM 字段自动生成) |
| tool_ids[] | 可选:主管自己可用的工具 |
🧷 粘性多轮 + 越界交回(Supervisor 的核心行为):主管把对话派给某个 worker 后,后续轮次会直接进上次那个 worker,不再每轮回主管重判——保持专注、对话连贯、还省一次路由开销。当用户意图明显超出该 worker 职责时,worker 会自动交回主管重新分配。这条"越界即交回"的协作规则由系统自动注入,你无需在每个 worker 的提示词里手写。想微调灵敏度,只要在 worker 的系统提示词里把职责边界写清楚即可。
⚠️ worker 智能体若配了技能包(skill_ids),在 Supervisor 模式下不生效(worker 走的是普通执行路径,不挂载技能包)。需要技能包请改用 DeepAgents 编排器把它作为 SubAgent。
📘 实战示例:健身房客服热线
用一个"健身房客服"场景,把 Supervisor 的三大行为——智能路由 / 粘性多轮 / 越界交回——一次看懂。
角色设计:1 个前台(主管)+ 3 个专员(worker)
| 角色 | 是 | 职责 |
|---|---|---|
| 前台 | Supervisor 主管 | 判断来意,派给对的专员,一次只派一个 |
cancellation | worker 智能体 | 办理会籍取消 |
credits | worker 智能体 | 查询剩余积分 / 课时 |
booking | worker 智能体 | 查课表、预约课程 |
搭建步骤(按 智能体 → 编排器 → 应用 的顺序):
- 智能体页建 3 个 worker(
cancellation/credits/booking)。每个写一段聚焦本职的系统提示词(例:"你是会籍取消专员,帮会员取消会籍;任何会员ID都视为有效,确认取消并告知可随时重新加入")。⚠️ 每个智能体的描述(description) 会被主管用来判断派单,务必把职责写清楚。 - 编排器页新建一个 Supervisor 类型,把这 3 个智能体加为 worker;主管的系统提示词写路由规则(例:"判断来意——取消会籍→cancellation,查积分→credits,约课→booking;意图不清才追问,明确就立刻派单,一次只派一个")。
- 发布编排器,在应用页接一个 Web 应用或 API 服务,即可对话。
一段真实对话(同一会话连续 4 轮):
| 轮次 | 用户说 | 系统行为 | 谁在回答 |
|---|---|---|---|
| 1 | "我想取消会籍" | 主管路由 | → cancellation 专员,问会员ID |
| 2 | "会员ID 88888,确认" | 粘住,不回前台 | cancellation 确认取消流程 |
| 3 | "顺便查下我的积分" | 越界 → 交回 → 改派 | → credits 专员,给出积分明细 |
| 4 | "那我想约节课" | 再次越界 → 交回 → 改派 | → booking 专员,展示本周课表 |
看点:
- 第 2 轮没有重新经过前台——这就是粘性:省一次路由、对话更连贯。
- 第 3、4 轮用户切换意图时,当前专员自动交回前台重新分配——你不用在专员提示词里写"什么时候该交回",系统已内置。
- 想让某专员"更容易交回"或"更倾向自己扛",在它的系统提示词里写清职责边界即可微调。
💡 这个模式适合多技能客服 / 分诊台 / 工单分流等场景:一个统一入口,背后多个领域专家,既能精准分流,又能在一次会话里平滑切换话题。
Collaboration
| 字段 | 说明 |
|---|---|
| agent_ids[] | 协作智能体列表 |
| collaboration_strategy | sequential(顺序) / parallel(并行) |
| shared_memory | 共享对话记忆 |
| enable_summarization | 协作完成后自动总结 |
Workflow
工作流是画布式可视化编排器 — 用拖拽 + 连线把多个 Agent / HTTP / 判断 / 循环串起来,适合规则清晰、节点间数据流明确的业务场景(审批、批处理、ETL、规则引擎等)。
完整搭建指南详见下文 1.1.3 工作流编辑器使用指南 章节。
Conditional
| 字段 | 说明 |
|---|---|
| routes[] | 路由规则:{condition, agent_id, priority} |
| default_agent_id | 兜底智能体 |
| enable_llm_fallback | 当无规则匹配时是否调用 LLM 兜底 |
External
| 字段 | 说明 |
|---|---|
| system_type | dify / n8n |
| api_base_url | 外部服务 URL |
| api_key | 外部服务 API Key |
| workflow_id | Dify/n8n 内部工作流 ID |
DeepAgents
| 字段 | 说明 |
|---|---|
| ai_model_id | 主智能体模型(必填) |
| vision_model_id | 视觉模型(可选) |
| system_prompt | 主智能体提示词 |
| tool_ids[] | 主智能体工具 |
| skill_ids[] | 主智能体的技能包(此处配的会在沙箱挂载到 /skills/main/) |
| subagent_default_model_id | 子智能体默认模型 |
| subagents[] | 子智能体列表,每项可以是: 预定义(name + prompt + skill_ids)或引用已有 Agent |
| backend_config | 后端类型 local_shell / filesystem / sandpod,以及对应配置 |
KnowledgeBase
| 字段 | 说明 |
|---|---|
| kb_id | 知识库 ID(必填) |
| mode | naive / local / global / hybrid / mix |
| top_k | 默认 5 |
| similarity_threshold | 默认 0.7 |
| rerank_enabled | 启用重排 |
| vlm_enhanced | 用视觉模型增强图片内容理解 |
| enable_conversation_memory | 是否保留对话上下文 |
编排器发布与版本
编排器采用草稿 → 发布两段式生命周期,顶栏工具条提供三个动作:
| 按钮 | 作用 |
|---|---|
| 保存草稿 | 把当前改动存为草稿(不影响线上)。⌘S / Ctrl+S 同效。 |
| 试运行 | 不发布就跑一次,可对草稿或已发布版本运行,用于上线前验证(详见下方"调试运行")。 |
| 发布 | 把当前草稿正式发布为新版本,弹出对话框要求填一段版本说明(version comment)。 |
- 「未发布的修改」徽章:保存草稿后顶栏出现此徽章,提示你有改动尚未发布。
- 版本历史:顶栏的版本历史 popover 列出所有已发布版本,每条带版本号 + 说明;需要回退时选某个版本点回滚到此。
⚠️ 关键模型:渠道 / Webhook / 定时任务(Cron)只运行「已发布」版本。 在设计器里改了内容只是存成草稿,不发布就不会生效——线上渠道、Webhook 触发、Cron 任务跑的始终是上一个已发布版本。改完务必点发布。
🔐 审批门(可选):当组织启用了资源审批后,发布按钮会变成提交审核;提交后编辑器显示审核中徽章并提供撤回审核按钮。审批通过才真正发布,被拒绝则草稿解锁可改后重提。详见 资源审批。
删除编排器
行为与智能体一致:如果有应用引用,会弹冲突对话框,显示引用方应用名、平台、内部名。可选强制删除。
1.1.3 工作流编辑器使用指南 [U]
适用范围:Workflow 类型编排器(Step 1 选了"工作流模式")的 Step 3 配置界面。 其它编排类型(Single / Supervisor / Conditional / 等)不走这套画布,看上文 1.1.2 对应的字段表即可。
5 分钟搭出你的第一个工作流
目标场景:用户问问题 → 调外部 HTTP 拿点数据 → Agent 总结 → 返回。
第 1 步:进入编辑器
- 编排器列表 → 点"创建编排器"
- Step 1 选 ⚙️ 工作流模式 → 下一步
- Step 2 填基本信息(名字、显示名) → 下一步
- Step 3 看到画布,默认已有 ▶️ 开始 和 ⏹️ 结束 两个节点
第 2 步:点"全屏"进入大画布
工作流复杂时内嵌 600px 画布太挤,点工具栏右上角的"全屏"进入沉浸编辑模式。强烈建议:除了快速浏览,日常编辑都用全屏。
进入全屏后界面分 3 块:
| 区域 | 位置 | 用途 |
|---|---|---|
| 节点库 | 左侧 240px | 点击或搜索添加节点。顶部有"插入循环块模板"按钮一键生成循环结构。 |
| 画布 | 中央 | React Flow 拖拽 + 连线 + 缩放。底部有控件(放大/缩小/适应视图/锁定)。 |
| 属性面板 | 右侧 360px(选中节点时出现) | 编辑节点的 agent_id / 模板 / 条件等字段。 |
第 3 步:添加节点
从左侧节点库点击想要的节点 → 自动加到画布中央。11 种可添加节点(外加默认自带的 开始 / 结束):
基础节点
| 节点 | 图标 | 作用 |
|---|---|---|
| Agent 执行 | 🤖 | 调一个已配好的 Agent 跑一次推理。最常用。 |
| 嵌套编排 | 🎛️ | 调另一个 Orchestrator(支持嵌套 workflow / supervisor 等)。 |
流程控制
| 节点 | 图标 | 作用 |
|---|---|---|
| 条件判断 | 🔀 | 按规则路由到不同分支(keyword / regex / expression)。 |
| 有界循环 | 🔁 | 计数器节点;必须配合 conditional 节点才能真正循环(下文详述)。 |
| 数组遍历 | 🔂 | 对 vars.X 数组逐元素跑模板,生成结果字符串列表。纯模板 map,无 LLM 调用。 |
| 人工确认 | 🙋 | 暂停工作流,推卡片给用户,等 approve/reject 后续跑。 |
集成 / 数据
| 节点 | 图标 | 作用 |
|---|---|---|
| HTTP 调用 | 🌐 | 调外部 REST API。支持 GET/POST/PUT/PATCH/DELETE。 |
| 数据整形 | 🔧 | 纯模板渲染,不调 LLM,适合多分支汇聚 / 数据组合 / 字符串处理。 |
| 知识库查询 | 📚 | 直接查 RAG 知识库,不调 LLM 包装层——省 token + 加速。 |
| 数据查询 | 🗃️ | 直接调用数据工具(SQL / NoSQL / 图数据库),由 Sira 内置执行器运行,省一次 LLM 往返。 |
| MCP 工具调用 | 🔌 | 直调一个 MCP 工具,参数明确时不必绕 Agent 让 LLM 决策。 |
▶️ 开始 / ⏹️ 结束 节点工作流默认自带,不需要也不允许重复添加。
第 4 步:连线
每个节点上下都有蓝色圆点(连接点 / handle):
- 上方蓝点 = 入边(target)
- 下方蓝点 = 出边(source)
从一个节点底部蓝点拖出来,放到另一个节点顶部蓝点 → 一条边就连好了。
几个特殊连线规则
- 同一个节点拖出多条线 = 并发执行所有目标节点(LangGraph 原生 fan-out)。普通节点会显示橙色 ⚡ 并发 N 路提示。
- Conditional 节点的出线自动标记成 conditional 边,显示为橙色虚线,需要在属性面板填 keyword / regex / expression 才会生效。
- Loop 节点的出线是普通顺序边(loop 只是计数器,不分支)。
- 选中边后按 Delete / Backspace 删除。
第 5 步:配置节点 — 模板与变量
点选节点 → 右侧属性面板出现 → 填字段。
三个特殊变量
工作流的所有模板字段(输入模板、HTTP 请求体、HITL 提问内容、数据整形输出模板)都支持下面三种占位符:
{{ user_message }} — 工作流最初的用户输入
{{ last_output }} — 上一节点的输出 (链式调用最常用)
{{ vars.<名字> }} — 其它节点的 output_var 命名输出变量自动补全 ⚡
在任何模板字段里输入开头的两个左大括号(占位符的起始符号)会自动弹出可用变量下拉:
- ⬆️ ⬇️ 方向键移动高亮
- Enter / Tab / 鼠标点击 → 插入
{{ <选中的变量> }},自动闭合 - Esc 关闭下拉
- 继续输入会过滤候选(例如输入
vars.s后只显示vars.summary等以 s 开头的)
每个候选项下方有灰字提示告诉你这变量来自哪个节点(比如 来自节点: 汇总分析),不会选错。
Agent 节点配置
| 字段 | 说明 |
|---|---|
| 标签 | 显示在画布上的节点名。建议起业务名(如"汇总分析") |
| Agent | 下拉选一个已配置好的 Agent |
| 输入模板(可选) | 给 Agent 的提示词。留空 = 用上一节点的最后一条 HumanMessage |
| 输出变量名(可选) | 把本节点的输出写到 vars.<名字>,后续节点用 {{ vars.<名字> }} 读取 |
第 6 步:调试运行 ▶
右上角 header 测试运行 输入框打你想测试的消息,点 ▶ 调试运行。
几个关键体验
- 画布当前状态优先:点调试运行不需要先保存,跑的就是你画布上看到的版本。header 出现蓝色"草稿"徽章确认这点。
- 实时节点徽章:每个节点跑到时上方出现 ⋯ → ✓ 状态点,直观看到流向。
- HITL 自动模拟:遇到"人工确认"节点会自动模拟一个 approve(否则调试时卡死等永远不来的卡片)。
- 取消按钮:跑的过程中点 ↻ 取消 立即停止,trace 标记为"已取消"(灰色,区别于 error 的红)。
内联保存 💾
在编辑器里改了任何字段,header 会出现橙色脉冲点 ● 未保存 + 蓝色"保存"按钮:
| 操作 | 效果 |
|---|---|
| 点 保存 按钮 | 立即保存,留在编辑器继续编辑(不跳列表) |
| 按 ⌘S / Ctrl+S | 同上 |
| 点"退出全屏"但有未保存 | 弹拦截框:[保存并退出 / 不保存退出 / 取消] |
| 按 Esc 但有未保存 | 同上拦截框 |
第 7 步:看历史执行 📜
header 右侧 ⏱️ 执行历史 下拉显示最近 50 次执行,带状态徽章:
| 徽章 | 含义 |
|---|---|
| 🟢 成功 | 所有节点完成 |
| 🔴 失败 | 至少 1 个节点 error |
| 🟡 暂停 | 还在等 HITL 回应 |
| 🔵 运行中 | 当前在跑 |
| ⚫ 已取消 | 用户主动取消(灰色,不是 error) |
点某次执行 → 画布上每个节点显示当次的状态徽章 + 持续时间。再点节点查看属性面板的"trace 详情"(输入/输出快照、错误消息、token 用量)。
节点深度指南
Agent 节点
最常用。封装一个 Agent + Agent 配置好的 LLM + MCP 工具,调用一次拿一次推理结果。
典型配置:
- 输入模板:
分析以下用户问题并总结要点:\n{{ user_message }}\n\n上下文:{{ last_output }} - 输出变量名:
summary(下游用{{ vars.summary }}读取)
Conditional 节点
按规则把流分到不同分支。3 种条件类型:
| 类型 | 表达式格式 | 例子 |
|---|---|---|
| keyword | 关键字字符串 | 紧急 — 包含此关键字时命中 |
| regex | 正则 | ^订单\d+$ — 完整匹配此正则时命中 |
| expression | Python 表达式(白名单 AST) | int(vars.score) >= 80 |
match_against 字段 决定拿什么文本做匹配:
user_message(默认)— 用户原始问题last_output— 上一节点的输出vars.<名字>— 命名变量
默认分支 default_next:所有条件都不命中时走的目标节点 id。
视觉提示
- Conditional 节点的出线自动变橙色虚线,带表达式 label
- 同一 conditional 出多条线 = 多个并列条件,按顺序命中 — 第一条满足的就走它
- 在属性面板上改 conditions 的顺序会直接影响路由
Loop 节点 — 必读
Loop 是个计数器,不是循环块。这是用户最常踩的坑:
[start] → [loop max=3] → [agent] → [end] ❌ agent 只跑 1 次,不是 3 次要真正循环 N 次,必须在下游接一个 conditional 把流连回 loop 本身:
[start] → [loop max=3] → [agent] → [check]
↑ │
└───── default ─────┘ ← 回边,直到 loop 计数达到 3
│
└── exhausted ─→ [end]check 节点的条件应该匹配 vars._loop_<loop_id>_exhausted == "true" — loop 跑满后会把这个变量置 true,conditional 据此跳出。
💡 一键模板
别手动画 4 个节点。左侧节点库顶部点 🔁 插入循环块模板 橙色按钮 — 一次性给你生成 loop + worker + check + 完整边集合,你只需把 worker 节点的 agent_id 选对就行。
缺回边告警
如果 loop 节点确实没回边,节点底部会自动显示橙色告警:
⚠️ 缺循环回边,只跑 1 次
看到这个就知道画错了。
HTTP Request 节点
调外部 REST API。
典型配置:
- Method:GET / POST / PUT / PATCH / DELETE
- URL:
https://api.example.com/users/{{ vars.user_id }}(支持模板) - Headers:JSON
{"Authorization": "Bearer {{ vars.token }}"} - 请求体模板(POST/PUT/PATCH 才显示):JSON 字符串,同样支持模板
- 超时秒数:默认 30,上限 120
- 提取 JSONPath(可选):
$.data.email— 从响应里抽字段当输出
⚠️ 安全限制
- URL 经过 SSRF 校验,默认拒绝内网地址(127.x / 10.x / 169.254.x 等)
- 响应大小限制 1 MiB,超出截断
- 不跟跨域重定向
- 失败时把状态码写到
vars._http_last_status供下游 conditional 用
Human Input 节点(HITL)
工作流暂停,推卡片给用户确认。
关键配置:
- 卡片标题(可选)
- 提问内容(必填):支持模板
- 交互类型:目前只有 confirm(approve/reject)
- 输出变量名(可选):approved 或 rejected
- 超时秒数(默认 86400 = 24h,范围 60 ~ 604800):超时后自动 reject 续跑
实跑流程
- 工作流跑到 human_input 节点 → 状态持久化到 PG checkpointer,emit interrupt
- 后端 InteractionDispatcher 推卡片到用户的当前渠道(企微 / Web / Feishu)
- 用户点 approve 或 reject → 工作流从断点续跑,
last_output=approved/rejected - 如果用户 24h 没回 → 后台 Celery 任务自动 reject(message 标记
[hitl timeout]),工作流继续走 reject 分支
Transform 节点
纯模板渲染节点,不调 LLM。适合:
- 多分支汇聚:并发的 A/B 两个 Agent 输出汇总成一个字符串
- 数据组合:
vars.user_name+vars.order_id+vars.amount拼成最终消息 - 格式调整:JSON 转 Markdown 等纯模板能搞定的事
典型配置:
- 输出模板(必填):
订单 #{{ vars.order_id }} 已确认,共 ${{ vars.amount }} - 输出变量名(可选):
final_message
💡 比 Agent 节点便宜 — 没有 LLM token 消耗,毫秒级完成。
嵌套编排节点
调另一个 Orchestrator(任何类型,包括 Workflow / Supervisor / DeepAgents)作为一步。
- 嵌套 Workflow:把复杂流程拆成可复用模块。子 workflow 跑完返回
last_output,父流程继续。 - 嵌套 DeepAgents:外层 workflow 做规则编排,内层 DeepAgents 做开放式智能体子任务。
- chained Supervisor:多专家协作模块封装成一个节点。
Knowledge Base 查询节点(kb_query)📚
直接查 RAG 知识库,不走 LLM。比"Agent + KB MCP 工具"组合省一次 LLM 调用 + 加速。
典型配置:
- 知识库:从下拉选一个已经建好的 KB
- 查询模板(可选):
{{ last_output }}中的关键词。留空就用{{ user_message }}。 - 检索模式:
hybrid(推荐)/local/global/naive/mix - top_k:1-50,默认 5
- 输出变量名:写入
vars.<名字>={answer, sources, kb_id, mode}字典
vs Agent + KB 工具
| 维度 | kb_query 节点 | Agent + KB MCP |
|---|---|---|
| LLM 调用 | 0 次 | 1 次(Agent 包装) |
| 延迟 | 快(只查 RAG) | 慢(等 LLM 思考 + 输出) |
| Token 消耗 | 0 | 数百 ~ 数千 |
| 灵活性 | 固定查询 | LLM 可改写查询 / 多步检索 |
建议:下游 Agent 自己消化检索结果的场景用 kb_query。LLM 需要主动决策"查什么 / 怎么查"的场景用 Agent + KB 工具。
MCP 工具直调节点(mcp_call)🔌
直接调一个 MCP 工具,LLM 不参与决策。 参数确定时省去 Agent 一层。
典型配置:
- MCP 工具:下拉选一个组织里已注册的工具
- 方法名(method)*:工具暴露的函数名,如
get_weather/search/send_email - 参数模板(JSON):
{"city": "{{ vars.city }}", "lang": "zh"}— JSON 字符串,渲染后会 parse - 输出变量名:写入
vars.<名字>= MCP 工具返回的原始结果
vs Agent + 工具
| 场景 | 推荐做法 |
|---|---|
| 参数从 NL 推断 | Agent + 工具 |
| 参数已确定 / 来自上游变量 | mcp_call |
| 多工具决策(让 LLM 挑) | Agent + 多工具 |
| 单工具直调 | mcp_call |
典型示例:从 HTTP 节点拿到城市名 → mcp_call 调天气工具 → Agent 节点用天气数据回答。
[start] → [http: 解析地址 → vars.city]
↓
[mcp_call: weather.get_current_weather city={{ vars.city }} → vars.weather]
↓
[agent: 根据 {{ vars.weather }} 给穿衣建议]
↓
[end]数据查询节点(data_query)🗃️
直接调用数据工具(SQL / NoSQL / 图数据库),由 Sira 内置执行器运行,省一次 LLM 往返。 参数确定时不必绕 Agent 让 LLM 拼查询。
典型配置:
- 数据工具(tool_name):从下拉选一个组织里已注册的数据工具(SQL / NoSQL / 图)
- 参数模板(JSON):按工具参数定义填,支持
{{ vars.X }}/{{ user_message }}模板 - 输出变量名:写入
vars.<名字>= 工具返回的查询结果
💡 与 MCP 工具直调类似,但走的是 Sira 内置数据执行器(toolbox 工具),专门面向数据库查询场景,不经过外部 MCP server。
数组遍历节点(for_each)🔂
对一个数组逐元素跑模板,生成结果字符串列表。 当前是纯模板 map(不调 LLM / HTTP),适合数据格式化场景。
典型配置:
- 遍历变量(items_var)*:
vars.<名字>必须是数组。例:上一节点 HTTP 拿到users数组。 - 单项模板(item_template)*:每元素的模板。特殊变量:
{{ vars._item }}— 当前元素(整个元素){{ vars._item.字段名 }}— 元素是 dict 时支持点访问 dict key{{ vars._foreach_index }}— 当前索引(0-based)- 加上所有外层
{{ vars.X }}/{{ user_message }}/{{ last_output }}
- 输出变量名(可选):默认
_foreach_results - 分隔符:默认
\n,用于把结果数组连接成last_output字符串
自动导出的 sidecar 变量(给下游 transform / conditional 用):
vars.<输出名>_count(字符串)— 数组长度,例"3"vars.<输出名>_truncated(字符串)— 截断时为"true",正常无此 key
典型场景:
[start] → [http: GET /api/users → vars.users (array)]
↓
[for_each items_var=users
item_template="Hi {{ vars._item.name }} ({{ vars._item.email }})"
output_var=greetings
separator="\n"]
↓
[transform: "共 {{ vars.greetings_count }} 位用户:\n{{ last_output }}"]
↓
[end]模板语法限制(必读)
平台模板引擎是故意非图灵完备(防 SSRF / 防注入),不支持:
- ❌
{{ vars.list.length }}— list 没.length属性。用 sidecarvars.<输出名>_count代替 - ❌
{{ vars.list[0] }}— 不支持数组索引访问 - ❌
{{ vars.x | upper }}— 无 Jinja2 filter - ❌
{% if %}/{% for %}— 无控制流
支持的就是:{{ user_message }} / {{ last_output }} / {{ vars.X }} / {{ vars.X.Y.Z }}(dict 多级访问)。
功能限制(必读)
- 上限 1000 项:超出自动截断 + 写
vars.<输出名>_truncated = "true"。再多请用 cron 流水线分批。 - 纯模板,无 LLM 调用:每元素调 Agent / HTTP 的场景目前要用 loop 计数 + conditional 模式手动绕(Dify 风容器迭代节点在路线图上)。
- scratch 变量不外泄:
_item/_foreach_index只在节点内部生效,for_each 跑完不会污染下游vars。
常见模式
模式 1:RAG → 总结 → 推送
[start] → [agent: 知识库检索] → [agent: 总结] → [http: 推 webhook] → [end]知识库检索 Agent 用 RAG MCP 工具拿原文 → 总结 Agent 用 LLM 浓缩 → HTTP 节点推 Slack / 飞书 / 企微群机器人。
模式 2:审批工作流
[start] → [agent: 解析意图]
│
▼
[conditional: 金额 > 1000]
├── yes → [human_input: 主管审批] → [conditional: 通过?]
│ ├── approved → [http: 执行操作]
│ └── rejected → [end: 通知拒绝]
└── no → [http: 直接执行] → [end]模式 3:批处理循环
用"插入循环块模板"一键生成,把 worker 节点的 agent 设成你要批量调用的 Agent:
[start] → [transform: 准备列表] → [🔁 循环 max=10]
▲
│
[worker agent] ──→ [check]
│ exhausted
▼
[end]模式 4:并发分发 + 汇总
[start] → [agent: 拆解任务]
│
├──► [agent A] ──┐
├──► [agent B] ──┤──► [transform: 汇总三方输出] → [end]
└──► [agent C] ──┘拆解任务 节点画 3 条出线 → 自动并发执行 A/B/C → transform 节点用 {{ vars.a }} / {{ vars.b }} / {{ vars.c }} 拼最终结果。
故障排查
工作流跑 1 次就停 / 循环不生效
几乎一定是 loop 节点缺回边。看 loop 节点下方是否有橙色"⚠️ 缺循环回边"告警。用"插入循环块模板"重做。
Conditional 不路由 / 总走 default_next
检查 match_against 字段:
- 你想拿
vars.score做判断,但默认 match_against 是user_message→ 永远不命中。 - 进属性面板把每个 condition 的 match_against 显式改成
vars.score或last_output。
HTTP 节点 403 / SSRF rejected
- 检查 URL 是不是指向内网(127.x, 10.x, 192.168.x, 169.254.x)— 安全策略默认拒绝。
- 真要调内网服务,联系管理员加白名单。
调试运行卡住不动
- HITL 节点忘了打开 simulate_hitl ?调试运行默认 simulate=approve,正常应该自动通过。
- 看后端日志:
docker compose logs -f backend | grep workflow
改完配置但调试运行还是老行为
- 检查 header 上"草稿" / "已保存" 徽章 — 如果显示"已保存"说明前端没把当前画布送出,这是 bug 应该上报。
- 平时正常 case 应该是"草稿"。
删了节点回不来
- 现在还没 Undo/Redo(路线图上)。建议改前先保存 — 错了可以回到列表重新打开。
- 复杂流程建议直接用"插入循环块模板"那类批量生成功能减少手工拖拽。
历史执行里看到很多"未知"状态
- 这意味着 trace 行不完整(节点开始执行但中途出问题,没写终态行)
- 多数情况是网络抖动 / Celery 重启导致,可以忽略
- 反复出现联系管理员
配了 retry 但好像没生效
最常见:节点失败但没看到重试日志。可能性:
- HTTP 4xx:业务错误不视为基础设施失败,不自动 retry(401 / 404 / 422 重试没意义)。要走 retry 改用
5xx测试或配 timeout 触发。 - 节点压根没失败:看后端日志
docker compose logs -f backend | grep "Workflow node",如果完全没"全部 N 次重试失败"日志,说明 inner 节点 return 成功了 — 检查validate_workflow时是不是把"软失败"当成功。
on_error 兜底节点跑了但拿不到错误信息
兜底节点 input_template 必须用 {{ vars._last_error.message }} 路径(注意是 vars._last_error 不是 _last_error)。模板引擎只识别 vars. / last_output / user_message 命名空间,顶层 state 字段读不到。
鲁棒性配置改了但保存按钮不亮
老版本(Sprint 2 早期)有这 bug,字段没序列化进 workflow_config。升级到最新版后保存按钮会正常感知改动并入库。
画布上 on-error 红线删不掉
红色虚线是节点 on_error.target 字段的视觉投影,不是独立 edge。要"删线"就把节点鲁棒性面板里的"失败时跳转节点"选回 — 不配置 —,红线自动消失。
节点鲁棒性:重试 / 超时 / 失败兜底
工作流里调外部服务的节点(http_request / agent / mcp_call / kb_query / transform / for_each)都会偶发失败:LLM 限流、HTTP 502、网络抖动、KB 端点临时不通。给这些节点配 🛡️ 鲁棒性,可以让单次失败不再炸整条工作流。
位置:选中节点 → 右侧属性面板底部"🛡️ 鲁棒性"折叠区。
重试 (Retry)
- 最大重试次数:默认
1(= 不重试)。改成3表示:第 1 次失败就第 2 次,第 2 次失败就第 3 次;3 次都失败才算最终失败。 - 首次失败等待:默认
1秒。后续按 2 倍指数退避(1s → 2s → 4s → ...),最多不超过下面那个上限。 - 最大等待时长:默认
60秒,防止指数退避涨太离谱。
实际行为:
- LLM 429 / 502 / 网络断开等基础设施层错误 → 自动 retry(对用户透明)
- 业务层错误(HTTP 4xx / Agent 主动报错)→ 也会 retry,但通常重试无意义(语义错了,再试一次还是错)
CancelledError(用户主动取消) → 不重试,直接退出
单次超时 (Timeout)
- 留空 = 不超时(默认行为)
- 配了
30:单次 attempt 跑超过 30s 视为失败,会消耗一次 retry。重试时再给 30s,不是叠加。
失败时跳转节点 (on_error.target)
下拉里选画布上另一个节点。全部 retry 用完仍失败时,工作流自动路由到这个兜底节点,而不是中断。
选了之后画布会自动出现一条红色虚线 + "on error" 标签,从当前节点连到兜底节点 — 让你直观看到错误路径。
兜底节点能读到错误详情(在 input_template / template 里):
{{ vars._last_error.message }} ← 错误消息字符串
{{ vars._last_error.node_id }} ← 哪个节点失败的
{{ vars._last_error.type }} ← 异常类名 (ConnectionError / RuntimeError 等)
{{ vars._last_error.attempts }} ← 一共试了几次典型兜底模式:
- 通知运营:Agent 节点拿
_last_error.message拼个钉钉/Lark 消息发出去 - 降级响应:transform 节点输出"系统繁忙,稍后再试"用户友好文案
- 写工单:http_request 节点把错误上报到工单系统
调试运行 + 运行时变量面板
全屏编辑器顶部"▶ 调试运行"按钮可以直接拿当前画布跑一次(不需要先保存)。
💡 编排器级试运行:除了画布内的调试运行,设计器顶栏还有一个编排器级的试运行按钮——它可对草稿或已发布版本运行,适合上线前确认整条编排是否符合预期。
🖼️ 附加图片(多模态):调试输入栏支持附加图片(最多 10 张,每张 ≤ 6MB),用于验证带视觉理解的多模态工作流——上传后图片会随测试消息一起进入工作流。
运行时变量面板:全屏模式右侧栏 — 不选任何节点时显示。每个节点完成时,把它本次写入的 state.variables 实时累加显示:
- 变量名 + 类型(string / array[N] / object{N})
- 长值默认折叠,点 ▶ 展开看完整内容
- 嵌套对象 / 数组可逐层展开
重试历史:如果某个节点配了 retry 且发生重试,选中该节点 → 属性面板"上次执行"下方会出现 "🔁 重试历史 (N 次重试中失败)" 折叠区,显示每次 attempt 的:
- Attempt N/M 失败
- 等待 X 秒后重试
- 错误消息(
error_message)
加上"上次执行"那条终态行,正好是 M 次 attempt 全貌。
1.1.4 应用管理 [U]
页面路径:/agent-system/applications用途:把编排器对外暴露成一个具体渠道:企业微信机器人、Web 聊天、API 服务等。
列表页
布局:4 列卡片网格(超大屏)、筛选器(搜索 + 平台 + 活跃状态)、分页。
卡片字段:
| 字段 | 说明 |
|---|---|
| 平台图标 + 名称 | 左上角 |
| display_name / description | 主标题 + 描述 |
| platform | 平台类型徽章 |
| is_active | 状态徽章 |
| 回调 URL / API 地址 | 一键复制按钮 |
| 插件连接状态 | 仅 WeCom Plugin 类型显示(WebSocket 在线状态、心跳时间) |
| 统计 | 总消息数、总用户数 |
卡片操作:编辑、删除、测试(仅 Web 类型)、API 示例(仅 API Service)、嵌入代码(仅 Web)。
支持的平台
| 平台代码 | 中文名 | 接入方式 |
|---|---|---|
wework | 企业微信 (回调) | HTTP 回调 |
wework_aibot | 企业微信 (AI Bot) | AI Bot 接口 |
wecom | 企业微信 (Plugin) | WebSocket 长连接(Channel Plugin) |
weixin_kf | 微信客服 | 微信客服 API |
feishu_bot | 飞书机器人 | 飞书事件订阅(WebSocket / Webhook) |
dingtalk | 钉钉机器人 | Stream 长连接(标准版 / 专属钉) |
webclient | Web客户端 | 嵌入到任意网页 |
api_service | API Service | OpenAI 兼容接口 |
webhook | Webhook 触发器 | 外部系统 HTTP POST 触发工作流 |
✅ 钉钉机器人(dingtalk)现已启用(Stream 长连接模式)。新增 Webhook 触发器(webhook) 平台,详见下方"Webhook 触发器"小节。
custom自定义平台暂未启用。
创建/编辑应用(设计器)
路径:/agent-system/applications/designer/[id]3 步骤:
Step 1:选择平台
平台卡片(企业微信 回调 / AI Bot / Plugin、微信客服、飞书机器人、钉钉机器人、Web客户端、API Service、Webhook 触发器),每个有描述和典型场景。
Step 2:基本信息
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | text | ✓ | 内部标识 |
| display_name | text | ✓ | UI 名称 |
| description | textarea | ||
| orchestrator_id | select | ✓ | 选择背后的编排器 |
Step 3:平台配置(随平台变化)
举几个常见例子:
WeCom / WeWork:
| 字段 | 说明 |
|---|---|
| corp_id | 企业 ID |
| agent_id | 自建应用 AgentID |
| secret | 应用 Secret(敏感) |
| token / encoding_aes_key | 回调加密配置 |
Feishu Bot:
| 字段 | 说明 |
|---|---|
| app_id / app_secret | 飞书应用凭证 |
| verification_token | 事件订阅验证 |
| encrypt_key | 加密密钥(可选) |
WebClient:
| 字段 | 说明 |
|---|---|
| share_token | 自动生成,用作公开访问令牌 |
| allowed_origins[] | CORS 白名单 |
| welcome_message | 首次进入时的欢迎语 |
API Service:基本无表单,创建后在 1.1.4 API 服务 里管理 API Key。
Webhook 触发器:让外部系统通过一次 HTTP POST 直接触发背后的工作流(编排器)。配置项:
| 字段 | 说明 |
|---|---|
| Secret(鉴权密钥) | 后端自动生成,用户不手填——只能点"生成 Secret / 重新生成"或"复制"(与 GitHub / Stripe webhook 一致)。重新生成后旧 Secret 立即失效,可轮换。 |
| user_message 提取路径 | 从 POST body JSON 抽取工作流输入的点路径。默认 user_message 取顶层字段;想取嵌套字段配 event.message.text。 |
| 每分钟最大请求数 | 限流阈值。超过返回 429;0 = 不限速(生产建议至少 60 防止外部系统失控刷接口)。 |
| 启用 HMAC 签名校验 | 高安全可选项,默认关闭。开启后还需校验签名 hmac_sha256(secret, raw_body);关闭时只校验 X-Webhook-Secret 头。 |
调用方式:
- URL 形如
/api/applications/{id}/webhook - 外部系统调用时必须带请求头
X-Webhook-Secret: <secret> - 默认 fire-and-forget(异步);加
?wait=true可同步等待结果 - 工作流用
{{ user_message }}拿到 body 里的输入,用{{ vars.webhook_metadata.X }}拿额外元数据 - 配置页提供一段可复制的测试 curl,可直接拷去外部系统对接
触发失败(异步执行报错)的请求会进入失败队列(DLQ),可在那里查看错误并重试。
⚠️ 敏感字段处理:
secret/app_secret/api_key等编辑时显示为***masked***,留空表示不修改,填新值表示覆盖。Webhook 的app_secret永不回显。
应用相关对话框
API 调用示例(仅 API Service 应用)
入口:卡片上「API 示例」按钮。
内容包含:
- 三个 Tab:cURL / JavaScript / Python
- 流式 vs 非流式两种调用代码
- 请求参数说明:
user_message(必填)、session_id、stream、自定义模板变量 - 响应格式示例
Web 嵌入代码
入口:卡片上「嵌入代码」按钮(仅 Web / API Service 类型)。 内容:一段 HTML/JS 片段,复制后粘贴到任意网页即可弹出聊天窗口。
删除应用
🚫 级联失效:删除应用是软删除,但关联的 API Key、定时任务会立即失效。删除确认对话框会显示警告。
1.1.5 API 服务 [U]
页面路径:/agent-system/api-services用途:为 api_service 类型的应用创建和管理 API Key,查看调用统计。
页面布局
- 左侧 1/4:API Service 应用列表(每个 API Service 类型的应用一张小卡片);选中后右侧切换。
- 右侧上半:
APIKeyList— 当前应用的 API Key 列表 - 右侧下半:
APICallStats— 调用次数、成功率、最近调用时间等统计
API Key 操作
| 操作 | 行为 |
|---|---|
| 创建 Key | 弹对话框输入备注 → 生成 → 完整 Key 只出现一次,务必当场复制保存 |
| 复制 Key | 列表里只显示前后几位 + 复制按钮 |
| 删除 Key | 立即失效,无法恢复 |
🔒 安全提示:API Key 应妥善保管,泄露后立即在列表中删除并重新生成。所有 Key 调用都会被记录在 审计 中。
空状态
如果当前组织还没创建任何 API Service 应用,会显示空态卡片,引导先去创建应用。
1.1.6 失败队列 (DLQ) [U]
页面路径:/agent-system/dlq用途:异步执行(Webhook / Cron / 渠道触发)失败的任务记录会落到这里,支持手动重试和放弃。前台交互对话(Web / API 同步请求)的失败不进 DLQ;只有无人值守的异步执行失败才入队。
页面布局
- 顶部统计卡片:按状态汇总数量(待处理 / 重试中 / 已解决 / 已放弃)。
- 状态标签筛选:全部 / 待处理 / 重试中 / 已解决 / 已放弃。
- 列表:每行显示用户消息、状态、重试次数等。
- 详情侧栏:点某行展开,显示用户消息、错误详情、元数据(触发上下文)、重试次数等。
操作
| 操作 | 行为 |
|---|---|
| 重试 | 调原编排器把同一条消息再跑一次。成功 → 标记已解决;再次失败 → 退回待处理。带二次确认。 |
| 放弃 | 把脏数据 / 业务无意义的记录标记为已放弃,不再重试。带二次确认。 |
💡 典型来源:Webhook 触发器异步执行报错、定时任务(Cron)失败、渠道回调处理异常。
1.1.7 渠道认证 (Channel Providers) [管理员]
页面路径:/agent-system/channel-providers(仅管理员可见) 用途:集中管理本组织的企业微信 / 飞书 / 钉钉等渠道认证源。一处配置,多个应用复用。
特点
- 动态 schema 表单:配置表单由后端
descriptor.config_schema()动态驱动——新增渠道前端零改动,字段随所选渠道自动变化。 - 部署类型:按渠道选择部署方式(如本地 / Gateway)。
- 绑定模式:为渠道选择绑定方式(随渠道 schema 给出可选项)。
- app_secret 永不回显:密钥加密存储,永不回显;编辑时留空表示保持不变。
1.1.8 常见问题
Q1:智能体保存后调试发现没生效?
检查 is_active 是否为开启状态。另外,设计器保存后会有 1 秒延迟跳回列表,如果你立即在另一个 Tab 测试,可能还在用旧配置缓存。
Q2:编排器测试能跑,但接入应用后没响应?
依次检查:
- 应用
is_active是否开启 - 平台凭证(secret / token)是否填正确
- 回调 URL 是否已配置到对应平台的后台(企微/飞书)
- 查看 审计日志 看请求是否到达后端
Q3:删除时报"AGENT_IN_USE / ORCHESTRATOR_IN_USE"?
这是正常的引用保护。看清冲突对话框列出的引用方,先在引用方那里替换或解绑,再回来删除;或直接选「强制删除」让引用方下次执行报错,然后再去修复。
Q4:模板变量在哪里?
智能体系统提示词、应用欢迎语都支持模板变量。常用变量:
{user_name}— 当前用户显示名{user_email}{current_date}/{current_time}{org_name}— 当前组织名
完整列表请展开提示词编辑器右下角的「插入变量」按钮。
