Flowise 的 Agent 循环与图执行引擎
学习目标
- 理解 Flowise 三种执行模式(Chatflow / AgentGraph / AgentFlow V2)的触发条件与区别
- 掌握有向图 BFS 遍历如何将 React Flow 画布转换为可执行流程
- 学会根据任务复杂度选择合适的执行模式
前置知识
本章涉及 Agent 核心循环的通用原理,建议先阅读:
下文假设你已理解 Session/Turn 模型等通用概念,直接聚焦 Flowise 的图驱动实现。
项目实践
三种执行模式的路由
Flowise 在 executeFlow 函数中根据 Flow 类型决定执行引擎:
if (chatflow.type === 'AGENTFLOW') { → executeAgentFlow() // AgentFlow V2:有向图 + 条件等待} else if (存在 Multi Agents / Sequential Agents 类别节点) { → buildAgentGraph() // AgentGraph:LangGraph StateGraph} else { → executeFlow() 直接执行 // Chatflow:简单 BFS 遍历}| 模式 | 触发条件 | 底层引擎 | 特点 |
|---|---|---|---|
| Chatflow | 默认,无 Agent 类别节点 | 自研 BFS 图遍历 | 适合简单 LLM 调用和 RAG 管线 |
| AgentGraph | 存在 Multi Agents 或 Sequential Agents 节点 | LangGraph StateGraph | 适合多 Agent 协作,支持状态持久化 |
| AgentFlow V2 | chatflow.type === 'AGENTFLOW' | 自研有向图 + IWaitingNode 条件等待 | 支持条件分支、循环、迭代、人机协作 |
图构建与 BFS 执行
Chatflow 模式的执行流程如下:
关键函数:
| 函数 | 职责 |
|---|---|
constructGraphs(nodes, edges) | 从 React Flow 的 nodes/edges 构建邻接表有向图 |
getStartingNodes(graph) | 查找入度为 0 的节点(流程起点) |
getEndingNodes(dependencies, graph, nodes) | 查找出度为 0 的节点(流程终点) |
buildFlow() | BFS 遍历,逐层执行节点 |
resolveVariables() | 解析 {{variable}} 引用链 |
变量解析管道
Flowise 的变量系统支持多种引用格式:
{{question}} → 用户输入{{chat_history}} → 会话历史{{vars.variableName}} → 全局变量$flow.sessionId → 流程配置$flow.chatId → 聊天 ID$flow.chatflowId → Flow ID$flow.state → 流程状态对象resolveVariables 函数的处理流程:
- 扫描节点输入中的
{{...}}引用 - 根据引用前缀(
question、chat_history、vars、flow)从对应数据源获取值 - 处理变量间的依赖链(变量 A 引用变量 B)
- 返回解析后的完整节点数据
问题与规避
循环依赖导致无限递归
问题:如果用户在画布中创建了环(A → B → A),BFS 遍历会陷入无限循环。
对策:Flowise 假设图为有向无环图(DAG),没有内置环检测。用户在画布中应避免创建环。在 AgentFlow V2 中,通过 loopCounts Map 限制每个节点的执行次数。
多 Ending Node 的结果选择
问题:当流程有多个出度为 0 的节点时,执行哪个?
对策:Flowise 取 reactFlowNodes 数组中的最后一个 Ending Node 执行。这意味着节点的创建顺序会影响结果。建议每个 Flow 只保留一个输出节点。
变量引用链断裂
问题:{{nodeA.output}} 引用的节点未执行或输出为空,导致下游节点收到 undefined。
对策:
- 确保引用链中每个节点都已执行
- 使用
setVariable节点的showOutput选项调试变量值 - 在 CustomFunction 中添加空值检查
设计取舍
图驱动 vs 代码驱动 Agent 循环
| 维度 | 图驱动(Flowise) | 代码驱动(传统框架) |
|---|---|---|
| 学习曲线 | 低(拖拽即可) | 高(需要编程能力) |
| 灵活性 | 受限于图结构 | 无限制 |
| 调试 | 节点级日志 | 断点调试 |
| 版本控制 | JSON 文件 diff 困难 | 代码 diff 友好 |
| 团队协作 | 非程序员可参与 | 仅限程序员 |
Flowise 选择图驱动模型的核心原因是降低 LLM 应用开发门槛。代价是图无法表达所有编程模式(如递归、动态控制流),这部分通过 CustomFunction 节点(用户自定义 JavaScript)作为逃生舱。
BFS vs DFS 遍历
| 维度 | BFS | DFS |
|---|---|---|
| 执行顺序 | 按层级,所有第 N 层节点执行完才执行第 N+1 层 | 沿一条路径深入到底 |
| 内存消耗 | 与最宽层级大小成正比 | 与最大深度成正比 |
| 并行性 | 同层节点可并行 | 天然串行 |
Flowise 选择 BFS 是因为:
- 同层节点(无依赖关系)可以并行执行
- 避免深层递归导致的栈溢出
- 更符合用户对”从左到右”流程的直觉