01. n8n 总览:把工作流做成运行时
1.1 核心判断:n8n 不是“节点集合”,而是图执行平台
节点只是扩展点。n8n 真正稳定的内核是:
输入事件 → 工作流图 → 执行上下文 → 节点执行 → 运行结果 → 状态与观测
这条链路由不同包共同实现:n8n-workflow 定义跨层数据契约,n8n-core 负责图推进与节点上下文,n8n(packages/cli)负责服务边界、持久化和进程编排,n8n-editor-ui 负责编辑和手动执行体验。
1.2 四层架构
四层之间的依赖方向很重要:UI 不应该知道 Bull job 的细节;节点不应该直接操作数据库;执行器通过 IWorkflowExecuteAdditionalData、节点上下文和接口拿到需要的能力。这样同一份工作流可以被手动执行、Webhook 执行、队列执行和测试执行复用。
1.3 一次执行的最小状态机
对单次 execution,可以把状态抽象成:
new → running → waiting → running → success
↘ error / canceled
waiting 不是简单的 sleep。等待 Webhook、延迟或外部事件时,执行数据需要持久化,进程可以释放;外部事件到达后,系统根据 resume token 或执行 id 恢复上下文。因此执行记录既是审计日志,也是恢复点。
1.4 源码入口
1.5 设计取舍
为什么把类型单独放在 workflow 包? 因为节点包、编辑器、执行器和 CLI 都需要共享 INode、IConnection、IRun 等契约。类型包不持有数据库连接和 HTTP 状态,降低了循环依赖风险。
为什么执行器不直接负责排队? 执行器只关心“给我一个工作流和执行上下文,我如何运行”。是否本地运行、进入 Redis 队列、由 worker 处理,属于 CLI 编排层。这个边界让测试和手动执行不必启动完整的分布式设施。
为什么需要很多上下文接口? 节点执行时需要读取输入、解析表达式、访问凭证、发 HTTP 请求、写二进制数据、触发等待等能力。把这些能力封装到上下文,既方便给不同节点提供合适权限,也能在测试中替换为 mock。
1.6 阅读检查题
WorkflowExecute为什么返回可取消的PCancelable,而不是普通Promise?- Webhook 到达时,哪个对象决定同步响应还是异步 execution?
- 工作流图中的
main连接和ai_tool连接为什么不能使用同一个遍历规则?