工作流 workflow 与 step
SuperAGI 智能体不是纯放飞循环——外层是数据驱动的工作流有向图,支持分支、循环、条件路由、等待。今天读工作流模型。
工作流是有向图
AgentWorkflow(一个工作流)由多个 AgentWorkflowStep(节点)组成,节点之间用 next_steps 连成有向图。智能体绑定一个工作流(Agent.agent_workflow_id,Day 02)。
🚇 生活类比(贯穿今天):工作流图就像地铁线路图——每个 step 是一站,
next_steps 是连接站点的轨道,条件边就是"到这站按情况换乘不同线路"。想改线路?改图纸(数据库里的图)就行,不用重造整条地铁(改代码)。这也是为什么工作流能在市场"分享"——发一张别人直接能坐的线路图给他。step 节点结构
# models/workflows/agent_workflow_step.py:13
class AgentWorkflowStep(DBBaseModel):
agent_workflow_id = Column(Integer)
step_type = Column(String) # TRIGGER / NORMAL
action_type = Column(String) # TOOL / ITERATION_WORKFLOW / WAIT_STEP
action_reference_id = Column(Integer) # 指向具体 tool / 迭代工作流 / wait
next_steps = Column(JSONB) # ★ 带条件的出边:[{"step_response":"YES","step_id":"..."}]
next_steps 是 JSONB,形如"结果是 YES 就去 step5、NO 就去 step3"——这就是带条件的边,让流程能分支。条件路由 fetch_next_step
路由核心 fetch_next_step(agent_workflow_step.py:252):拿"当前步的执行结果字符串"去 next_steps 里匹配对应 step_id:
# 拿执行结果(如 "YES")匹配 next_steps 里的 step_response
# 匹配到 → 去对应 step_id
# 匹配不到 → 走 "default" 边
# step_id == "-1" → COMPLETE(工作流结束)
"NO";step6 的 next_steps = [{"step_response":"YES","step_id":"7"}, {"step_response":"NO","step_id":"5"}]→ fetch_next_step 匹配:"NO" 命中第二条 → 返回 step_id
"5"→ 输出:下一步回到 step5(形成"没通过就重来"的循环)。若结果是 "YES" 就去 step7 前进;若结果没匹配上任何边就走
default;若 step_id 是 "-1" 就 COMPLETE 收尾。if result == "YES": go_to(step7)
elif result == "NO": go_to(step5)
else: go_to(default)
问题:流程焊死在 Python 里——改流程要改代码、发版;产品经理不能自己调;没法可视化、没法分享。真实版:SuperAGI 把这张"结果 → step_id"映射表存进
next_steps(JSONB 字段),fetch_next_step 运行时查表路由。多出来的这层"查表",换来的正是流程变成可编辑、可分享、可视化的数据——设计上多花一点,产品上灵活一大截。step_id="-1" 是约定的"结束"标记。TOOL 步:LLM 当路由器
AgentToolStepHandler.execute_step(agent/agent_tool_step_handler.py:39)——TOOL 步是"编排者钦定工具"的确定性步骤(对比迭代步 LLM 自选):
# 1. 取绑定的 tool(tool_name, input_instruction, output_instruction)
# 2. _process_input_instruction:让 LLM 只为这个"指定工具"生成 args
# 3. 执行工具
# 4. 若配了 output_instruction:_process_output_instruction 再调 LLM,
# 把工具输出"归类成一个枚举结果"(从 output_options 里选一个)
# → 这个字符串就是 step_response,喂给 fetch_next_step 决定走哪条边
step_response,决定工作流走哪条边。于是 LLM 不只用来"选工具/填参",还用来"判断结果、做流程路由决策"——LLM 当路由器。这让工作流能根据 AI 对结果的理解智能地分支,而不只是固定路径。TASK_QUEUE→QueueStepHandler、WAIT_FOR_PERMISSION→人工审批是特殊工具名的分流。🏥 生活类比:这一步的 LLM 很像医院分诊台护士——先看你的症状(工具输出),判断该去哪个科室(哪条边)。它不治病,只做"看情况、分流去向"的判断。
👶 小白:fetch_next_step 拿"结果字符串"去匹配边,可 LLM 不是只会自由发挥吗?这字符串哪来的、凭什么正好匹配得上?
👨🏫 老师:关键就在 TOOL 步的第 4 步——它再调一次 LLM,让 LLM 从预先给定的 output_options 里"选一个枚举值"(比如只能答"找到了 / 没找到"),而不是随便写。这个受限的枚举字符串才是 step_response,拿去和 next_steps 里的 step_response 对号入座,自然匹配得上。是"让 LLM 判断,但把答案限定在几个选项内"——既智能又可控。
内置工作流示例
内置工作流由 workflow_seed.py 播种(Day 04 的 seeding):
- Goal Based Workflow(
:183):单个 ITERATION_WORKFLOW 步,边指回自己 + 一条 COMPLETE 边——最纯粹的"目标驱动自治循环"(就是经典 AutoGPT 式的放飞循环)。 - Dynamic/Fixed Task Workflow(
:191):先 Initialize Tasks 生成任务队列,再 Task Queue 步循环消费——任务分解型。 - 还有 Sales、Recruitment、SuperCoder 等领域工作流。
🧳 生活类比:就像出去玩——目标驱动 = 自由行(只定目的地,路线现场随机应变,灵活但可能绕路);任务分解 = 跟团游(行程表逐项列好,按表打卡,省心但不灵活)。按任务性质选团。
分支与循环
add_next_workflow_step(agent_workflow_step.py:209)建边。真实例子(workflow_seed.py:99):
AgentWorkflowStep.add_next_workflow_step(session, step6.id, step7.id, "YES")
AgentWorkflowStep.add_next_workflow_step(session, step6.id, step5.id, "NO") # NO 时回到 step5 → 循环
AgentExecution.assign_next_step_id(models/agent_execution.py:153)设置 current_agent_step_id;若下一步是 ITERATION_WORKFLOW,还会把内层迭代步设成该迭代工作流的 TRIGGER 步。两级 step 的衔接就在这里。数据驱动流程的意义
- 可配置:改流程改数据库图,不改代码。
- 可分享:工作流能在市场分享(像分享一个"最佳实践流程")。
- 可控 + 可自主:外层图精确控制大流程(分支/循环/等待/人工审批),内层迭代步让 LLM 自主发挥——两全。
- 可视化:图结构天然能画出来,GUI 可视化编辑。
if-else 里:产品想给销售智能体加一步"发邮件前先人工审批",得提需求 → 排期 → 程序员改代码 → 测试 → 发版,一周过去了;想同时上线"目标驱动版"和"任务分解版"两套流程,代码里就得塞两坨 if-else 互相打架。而数据驱动下,这些都只是"在数据库那张图上加/改几个节点和边"——运营自己在 GUI 上拖一下即可。把流程从代码里解放出来,正是为了躲开这类"改流程=改代码"的事故。今日小结 + 动手
🧠 今天你应该能回答
- 工作流为什么是"数据驱动的有向图"?
- step 节点的 next_steps 怎么表达带条件的边?
- fetch_next_step 怎么用结果字符串路由?
- TOOL 步怎么"让 LLM 当路由器"?
- Goal Based vs Task 型工作流的区别?分支/循环怎么建?
✋ 动手
P=superagi
sed -n '13,47p' $P/models/workflows/agent_workflow_step.py # step 结构
grep -n 'def fetch_next_step\|def add_next_workflow_step' $P/models/workflows/agent_workflow_step.py
sed -n '39,72p' $P/agent/agent_tool_step_handler.py # TOOL 步 LLM 路由
sed -n '183,215p' $P/agent/workflow_seed.py # 内置工作流