结论先讲:我缺的不是另一个编排工具,而是一层"控制面"(Control Plane)——统一回答"哪个流程、哪个版本、哪次运行、哪一步挂了、重试了几次、下次什么时候跑"的协调层。cron 只负责"到点喊一声",喊完就不管了。实地调研 11 个平台后,我的选择:Windmill 首选、Kestra 并列备选,n8n/Temporal/Argo 明确不选,Hermes 归位成"被调度的 Agent",而不是调度者。

先交代背景:我的自动化家底长什么样
我的自动化体系是典型的"脚本堆积"形态:17 条 cron、13 个 systemd timer、17 个 Docker 容器、分散在六七个目录里的 Python/Shell 脚本,外加一条 AI 内容管线(RSS → 抓取 → LLM 判断 → 改写 → 发布 → Telegram 通知)。它跑得起来,但有一堆结构性问题:
- 工作流非常黑盒——cron 喊完脚本,脚本里发生什么没人知道
- 工作流脚本和监控脚本是两个体系,各记各的日志
- 有次管线崩了,三天后我才从"怎么公众号没更新"倒推出来
- 同一流程出现
workflow_final / workflow_final2 / workflow_new2这种命名,生产环境跑的到底是哪版,说不清 - Agent 工作流尤其难追踪——步骤发生在 LLM 的 token 里
我把这些痛点归成四个正交问题:执行语义缺失(没有 run/task/状态的概念)、信号缺失(没有"失败即推")、世界状态失真(版本与部署脱节)、Agent 黑盒。
先分层,再选型
这次调研我坚持一个认知:不要把这些平台塞进一个排行榜,它们根本不在同一层。
| 层 | 定义 | 平台 |
|---|---|---|
| Automation / 集成 | 事件驱动的连接器编排 | n8n |
| Workflow Orchestrator(控制面) | 调度+编排+DAG+运行状态+版本+审计 | Kestra、Windmill、Prefect、Airflow |
| Data Orchestrator | 以数据资产/血缘为中心 | Dagster |
| Durable Execution | 状态持久化、精确恢复 | Temporal、Hatchet、Inngest |
| Agent Runtime | 承载 LLM 会话/工具调用 | Hermes、Claude Agent SDK |
我要的是第二层——控制面。分完层之后很多"要不要上"的问题自己就解了:n8n 不是不好,是它不在我要的那层。
调研方法论:全部事实当场联网核实
结论要经得起复核,所以这次没凭印象流:
- 11 个平台各派一个调研 agent,逐家核对 GitHub 最新发布、官方文档、架构文档,版本号全部锁定到 2026-08-22
- Top 6 再派对抗核验 agent,专门挑错。真挑出了问题:Temporal 最新版发布时间的错误——这种坑靠"印象"是查不出来的
- 核验也是递归的:初轮核验曾认定"Prefect secrets 明文存数据库",第二轮对照官方 v3 文档后发现与官方的"encrypted at rest(静态加密)“口径矛盾——我在正文里改正了这个错,并把 Prefect 的分数从 7.9 回调到 8.0(排序不变)。能抓别人的错,也要能抓自己的错
- 文章发布后有群友追问"多步骤任务”,于是补了第二轮:六个平台的多步骤语义全部从官方一手材料(schema 页 / OpenFlow 规范 / 官方仓库 docs 源码)核实,四个核验 agent 交叉裁定,我又对关键语法逐字抽查了原文——这轮真抓出错的是我自己:之前 POC 里的
{{ outputDir }}写法在现行文档已标记弃用(改用 outputFiles),脚本任务镜像字段也从docker:换成了containerImage - 自己的机器也做了一次只读盘点,迁移计划基于真实家底而非想象
核到的最新稳定版:Kestra 1.3.30(Apache-2.0)、Windmill v1.795.0(AGPL-3.0)、Prefect 3.8.3(Apache-2.0)、n8n 2.35.7(Sustainable Use License)、Dagster 1.13.19、Temporal v1.31.2、Airflow 2.10.3、Argo v4.1.2、Hatchet v0.101.27、Inngest 1.43.0。
决赛圈:加权打分与修正
我按自己的诉求设了权重:脚本复用 20%、编排 15%、可观测 15%、版本化 10%、Agent 工作流 10%、其余分散。加权结果(十分制):
| 平台 | 加权分 | 一句话 |
|---|---|---|
| Windmill | 8.2 | 脚本即一等公民,Git Sync 原生 → 首选 |
| Kestra | 7.7 | 一个 YAML 声明全部运行语义,Apache-2.0 → 并列备选 |
| Prefect | 8.0 | Python 体验最好,版本化是隐性短板 → 第三 |
| n8n | 8.3 | 分数最高,但 license 与 JSON 工作流让 git 评审成逆过程 → 不做控制面 |
| Dagster | 8.2 | 强,但资产范式与我内容管线错配 |
| Temporal | 7.9 | retry 语义冠军,代价是所有脚本重写成 activity |
| Airflow / Argo | 7.6 / 7.5 | 运维范式太重(Argo 必须 K8s) |
| Inngest | 8.0 | 补齐调研后(脚本须包 step.run,42 LOC + worker) |
| Hatchet | 7.6 | 补齐调研后(脚本须包 SDK task,8-12 LOC/条 + 常驻 worker) |
分数解释权要留给判断:初版榜单里 Inngest/Hatchet 拿了 8.3+,但那是"没算 SDK 包装成本"的分。我随后为这两家做了第二轮对抗核验 + 迁移成本实测——Hatchet 要把每条 shell 脚本包成 SDK task(实测 8-12 行胶水 + 常驻 worker 容器,而且 cron 无时区、无暂停、宕机丢调度),Inngest 要包 step.run handler(42 行胶水 + worker)——实测后修正为 7.6 和 8.0。更戏剧的是,复核还推翻了我初版自己的一个核验结论:Prefect 的 secrets,官方 v3 文档明确说"encrypted at rest(静态加密)",我此前写的"明文存库"与之矛盾,已改正并把 Prefect 回调到 8.0(排序不变)。权重表测不到的成本,只能用实测补;连核验本身都要被再核验——这恰好反证了 Windmill/Kestra 把脚本当一等公民的价值。

为什么明确不用那几个
- n8n:最强的拖拽集成平台,500+ 连接器。但我的 git 版本化诉求撞上它的 JSON 工作流定义,diff 和评审都难;Sustainable Use License 也让长期依赖不舒服。它是 Automation 层,不是控制面。
- Temporal:Durable Execution 事实标准,跨小时级任务精确续跑无出其右。但我的管线没有这个硬需求,而它的代价(全部 SDK 化 + 多服务运维)是确定的;另一个常被忽略的扣分项:它的 Web UI 只显示调度事件流,应用日志不进去,每步日志要自建导出——详见下文多步骤小节。出现硬需求时只包那一条子流程。
- Argo:很端正的 K8s 工作流,但我在 WSL2 单机 + docker-compose 上生活,为它上 K8s 是本末倒置。
Hermes 的归位:Agent,不是掌舵人
我的 Hermes(多模型 TG 网关)有内建 cron、有 WebUI,但它没有 workflow DAG、没有版本化的工作流、没有 run 语义——它天生是 Agent Runtime。正确的姿势:控制面把它当"agent 任务"调用(HTTP/CLI/MCP),调度、重试、超时、版本全部留在控制面。这样今天用 Hermes,明天换 Claude Code headless,控制面一行不改。
群友的追问:多步骤任务到底长什么样
文章发出去后,群友一句话点中了我的软肋:你给的例子只有"定时触发 → 跑一个脚本 → 重试规则 → 失败规则",没有 GitHub Actions 那样的"一个任务多个步骤"。这里的责任在我——我为了证明"纳管成本低",挑了最短的片段,结果把控制面最核心的价值藏了起来。这一节补回来,并正面回应他提出的心智模型:任务应该分步骤定义,从触发那一刻起,每一步都有运行日志,能回答"现在跑到第几步、挂在哪一步、每一步是怎么跑的"。
我先给结论:这个模型不是"额外的需求",正是控制面的定义。Kestra 与 Windmill(以及 Prefect)都原生满足;真正反常识的是,若把"每步日志开箱可查"当硬指标,retry 之王 Temporal 反而第一个出局——细节在后面讲。
五个问题,运行视图一次答完
把群友的心智模型拆成五个问题,对照两个决赛圈平台的运行视图:
| 群友的问题 | Kestra(Execution / TaskRun 两级视图) | Windmill(Run 视图) |
|---|---|---|
| 本次触发了吗 | 计划表 + Execution 列表:每次触发生成一个 execution,记录触发方式与时间 | Schedules + Runs 列表:历次运行和下次计划时间 |
| 任务完成了吗 | Execution 状态:SUCCESS / WARNING / FAILED | run 状态与总耗时 |
| 现在跑到第几步 | 每个 TaskRun 有独立状态,实时更新 | 运行树逐 module 实时标识 |
| 挂在哪一步 | 失败 TaskRun 单独标出,同页可看它上游成功到哪 | 失败 module 标红,上游绿、下游灰 |
| 每步怎么跑的 | 每个 TaskRun 独立 logs 页 + attempt 次数 + inputs/outputs 预览 | 每个 module 独立日志 + 重试次数 + 结果值 |
表中能力全在两家社区版可用(我逐条以官方文档核实过),不是 Enterprise 专属。
配上一次运行的全景(第 2 步失败时你看到的样子):

这五个问题里,cron 只能回答"下次什么时候触发",其余四个全是黑盒——这就是"控制面"三个字的全部意义。
多步骤真身:同一个管线,两种写法
Kestra——一个 YAML 声明四个步骤,每步自带重试与超时,步骤间用 outputFiles 传产物,重试耗尽后 errors 分支点名到步发告警:
| |
Windmill——现有脚本注册为资源零改动,flow 负责串接;每个 module 的 retry/timeout/数据接续都是模块级字段:
| |
步骤形态还能更丰富:并行(branchall)、循环处理(forloop)、以及"跑到某一步停下等人审批"(suspend 挂起,等回复事件再继续)——都是模块级配置,不改变脚本本身。Kestra 一侧有对应物:Parallel 任务,errors 分支里可以放任意脚本/HTTP 任务。
“用最终产物定义任务”:方向对,但要看清边界
群友的第二层主张是"用最终产物定义任务"。按字面去找,最贴的平台其实是 Dagster:它把每个产物显式建为资产(asset),资产之间用依赖连线,每次运行都留下产出记录。这也正是当初我把 Dagster 归到"数据编排层"、不选它做控制面的原因:资产建模的舒适区是数据表/数据集,而我的家底一半是"推一条 TG、重启一个容器、调一次发布 API"这类副作用型步骤——它们没有"产物",硬套资产语义是削足适履。
控制面里的"产物"以轻量形式存在,已经够用:Kestra 每个任务产出 typed outputs(UI 可预览、下游可引用),Windmill 每个模块产出 result(自动持久化,下游用 results.<id> 引用)。于是最终产物的路线很自然:大件产物(生成的 PPT、MP4、图片)由发布步骤自己上传对象存储,控制面负责"到没到那一步、那一步产出了什么、往哪儿去了"——这正是 GitHub Actions 里 upload-artifact 的职责,不必为此引入资产血缘引擎。
迁移原则:先纳管,不改脚本
现在这些脚本一行都不重写。四个阶段:平台已于 2026-08-23 单机 docker-compose 落位(Windmill,localhost:8760),本周把第一条真实管线纳进去跑 7 天;第二到四周迁完高频 cron(vendor_watch、节点探活),每迁一条、同 commit 删掉对应 cron 行;第二个月 17 条 cron 全部纳管、secrets 从 .env 迁入平台、监控脚本也变成带告警的 flow;第三个月接 Langfuse 把 LLM 的 token 花销晒出来。完整报告(含全部评分依据与核验纠错)存在私库。
十条结论
- 缺的是控制面,不是工具;2. Windmill 首选、Kestra 并列备选,二选一即可——读者要的"多步骤 + 每步独立日志/重试"是这两家的默认形态,不是加分项;3. Prefect 只在工作流 90% Python 化后才反超;4. n8n 留给"第三方 SaaS 集成"场景,现在不用;5. Temporal 出现跨小时精确续跑硬需求再上(先记住它没有内置日志聚合,每步日志要自建导出);6. Hermes 是被调度的 Agent,不是调度者;7. Langfuse 二期要(token/cost 是控制面盲区);8. Grafana/Loki 初期不装,平台原生 UI + Telegram 告警先跑顺;9. cron 只留系统维护级,业务 cron 一条不新增;10. 平台已在 2026-08-23 落位(单机 compose,localhost:8760),本周只剩一件事:把第一条真实管线纳管、打通失败告警。
调研局限性:每个平台的评分出自单一调研 agent(其中八家过了对抗核验;Hatchet/Inngest 另做了包装成本实测;Airflow/Argo 未过,分数按较宽置信区间读);多步骤语义为 2026-08-23 第二轮补齐(六平台官方文档核实 + 对抗核验,关键语法经官方 schema 页/仓库原文逐字抽查);所有版本与许可均以 2026-08-22 官方 GitHub/docs 为准。参考来源:Kestra 官方文档、Windmill 官方文档、Prefect v3 文档、Temporal Releases、n8n 文档、Dagster Releases。
