Trigger.dev 工作流:让长时 AI 任务跑到结束也不丢状态
📌 适用场景:长时 AI 任务与后台工作流的持久化执行
用 TypeScript 写长时 AI 任务与工作流:持久化执行、重试、并发、等待与运行 trace 内建,可云端或自托管;定价与额度按官方页面现读。
📋 完整步骤
- 1
在现有 TypeScript 项目里初始化
用 CLI init 建立 /trigger 目录、SDK 依赖与 trigger.config.ts,先不接业务写操作。
- 2
写第一个可恢复的长时任务
用 task() 定义 id 与 run,明确输入输出和成功判据,不设超时也能跑。
- 3
幂等地触发任务
用 idempotencyKey 去重触发,重复请求返回同一个 run,避免副作用重复。
- 4
设计失败与重试
按任务设置 maxAttempts、退避与随机抖动,区分可重试错误和应直接失败的错误。
- 5
用队列与并发上限保护下游
用 concurrencyLimit 共享名额,按租户设 perKey,避免把模型或数据库打满。
- 6
加入等待与人工介入
用 wait.for、waitpoint 令牌或 webhook waiter 暂停运行,长时间等待不计入计算。
- 7
部署并核对环境
部署前补齐环境变量,确认 CLI 与 SDK 版本一致,再跑一次受控输入验证。
- 8
复核可观测性与成本
看 run 的 trace、失败重试与日志保留期,按机器规格与调用次数核对账单口径。
Trigger.dev 工作流:让长时 AI 任务跑到结束也不丢状态
这是什么?适合谁?
Trigger.dev 是一个用 TypeScript 写后台任务与 AI 工作流的平台。它解决的问题很具体: 你在自己的应用里调用模型、爬页面、生成文档,这类活动辄跑几分钟到几小时, 放在普通 HTTP 请求里会被超时掐断,放在自己写的队列里又得处理重试、并发、失败恢复和「跑到一半机器没了」。
它的做法是把任务写成普通 async 函数,交给平台执行:运行有记录、失败会重试、等待会挂起而不是空转、 并发可以按租户限流、每次运行都留下一条可回放的 trace。平台核心是 Apache-2.0 开源、 SDK 是 MIT,可以自托管,也可以直接用云服务。
适合谁:已经用 TypeScript/Node 写业务、需要把「长时任务」从请求生命周期里剥出来的开发团队; 构建 AI Agent 或文档处理流水线、需要幂等与重试语义的人;对日志、失败可见性有要求的运维/后端角色。
不适合谁:只想写一个五分钟能跑完的脚本;不能接受把运行数据放到第三方(又还没准备好自托管)的团队; 不使用 TypeScript 生态的项目——官方主线和文档都围绕 TS/JS 展开。
核验日期:2026-10-31。功能与定价依据官网定价页、 快速开始、任务概览、 幂等、等待与 自托管说明。本站未部署运行,也未接入真实业务系统。
准备工作
- Node 与包管理器(npm / pnpm / yarn 均可,官方对三者都给了命令)。
- 一个现有的 TypeScript 项目;或者接受照着快速开始新建一个空壳练手项目。
- 决定走哪条部署路线:云(注册 cloud.trigger.dev,有免费额度) 或自托管(自己准备 Postgres、Redis 与容器编排,见自托管概览)。
- 一份「哪些环境变量会被任务用到」的清单。部署时这些变量必须先在环境里配置,否则部署后的代码跑不起来。
- 时间预算:首次初始化通常几分钟;把重试、并发、幂等与成本口径想清楚, 并做一次「故意失败」的演练,建议留半天到一天。不要把这个估计当成平台性能承诺。
- 一个最小成本意识:计算按秒计费、每次运行还有固定调用费,长跑任务与高频小任务的花法完全不同。
当前定价(官方定价页,2026-10-31 核对): Free $0/月(含每月 $5 计算额度、20 并发运行、1 天日志保留、10 个定时任务、5 名成员), Hobby $10/月,Pro $50/月(并发与日志保留提升,超出部分按项加价),Enterprise 定制。 计算按秒计费(例如 0.5 vCPU / 0.5 GB 规格约 $0.0000338/秒),另按每次运行调用计 $0.000025(每 1 万次 $0.25), DEV 环境的运行不计费。这些数字以定价页为准,官方会调整。
八步核心流程
第一步:在现有项目里初始化
在项目根目录跑:
npx trigger.dev@latest init
CLI 会:登录(没有账号就先注册)、让你选择或新建项目、安装所需 SDK 包、
问你 /trigger 目录放哪并生成一个示例任务、在项目根写 trigger.config.ts。
它还会问要不要装 MCP 服务端或 Agent skills——如果你想让 AI 助手帮你写任务,可以装;
不想引入额外组件就跳过。
这一步的产出不是「装好了」,而是「目录结构对了」:/trigger 存任务,trigger.config.ts 存项目级默认值
(默认重试、默认机器规格等)。先用示例任务,别急着写自己的业务逻辑。
第二步:写第一个可恢复的长时任务
任务就是一个带 id 的 async 函数:
import { task } from "@trigger.dev/sdk";
export const summarizeDoc = task({
id: "summarize-doc",
run: async (payload: { docUrl: string }) => {
const text = await fetchDoc(payload.docUrl);
return await callModel(text);
},
});
要点有三个:id 是运行记录与重试的锚点,改名会让历史运行对不上;run 的输入输出要能序列化;
默认没有最大时长限制,这既是它的卖点(长任务不会被打断),也是成本风险(写错循环会一直跑),
所以建议顺手设一个 maxDuration(单位秒)作为保险。
成功判据:在本地 dev 环境里触发一次,能在运行面板看到这次运行、能看到输入与返回值, 并且失败时能看到完整堆栈。
第三步:幂等地触发
长时任务的入口往往来自 webhook、表单或另一个任务,重复触发很常见。
Trigger.dev 的做法是给触发带一个 idempotencyKey:同 key 的第二次请求不会新建运行,
而是返回第一次运行的 handle。
import { idempotencyKeys, task, tasks } from "@trigger.dev/sdk";
export const onOrder = task({
id: "on-order",
run: async (payload: { orderId: string }) => {
const key = await idempotencyKeys.create(`refund-${payload.orderId}`);
return tasks.trigger("send-receipt", { orderId: payload.orderId }, { idempotencyKey: key });
},
});
设计口径:key 要来自业务唯一标识(订单号、文档 ID),不要用时间戳;
在任务内部触发子任务时,SDK 默认会把当前 run id 注入 key 作用域,
要跨运行去重就显式传 { scope: "global" }。
第四步:设计失败与重试
默认行为是失败重试 3 次。可以在 trigger.config.ts 里改全局默认,也可以在单个任务上覆盖(任务级优先):
export const callModelTask = task({
id: "call-model",
retry: {
maxAttempts: 6,
factor: 1.8,
minTimeoutInMs: 500,
randomize: true,
},
run: async (payload: { prompt: string }) => {
// 失败就 throw,平台按上面的策略重试
},
});
判定口径要提前写清楚:超时、限流、5xx 属于可重试;参数错误、权限不足属于不该重试——后者应该直接抛出让运行失败, 否则你会花六倍的钱得到同样的错误。重试配合幂等才是安全的:非幂等的副作用(发信、扣款)必须有幂等键, 否则一次重试就是一次重复动作。
第五步:用队列与并发上限保护下游
并发控制有两种粒度:按任务,或按「具名名额」在多个任务之间共享。
import { concurrencyLimit, task } from "@trigger.dev/sdk";
export const openaiLimit = concurrencyLimit({ name: "openai", total: 25 });
export const fanOut = task({
id: "fan-out",
concurrency: { limit: openaiLimit },
run: async () => {
/* 同一名额下的任务共享 25 个并发 */
},
});
按租户限流用 perKey(例如每个客户 10 个并发),既能保证单个客户不会挤占全部名额,
也能给整体设上限。注意旧的 queue: { concurrencyLimit: n } 写法仍可用但已弃用,
新代码统一用 concurrency。
判断标准:如果你下游是模型 API 或数据库,先设一个保守的共享名额,压测后再放开; 并发配置错误的表现往往不是报错,而是延迟飙升与限流雪崩。
第六步:加入等待与人工介入
「等用户审批」「等外部 webhook 回调」是长时任务最常见的形态。等待期间运行会被 checkpoint,
官方文档写明:触发并等待子任务时不计入计算用量;wait.for / wait.until 超过 5 秒的等待同样不计入。
三种等待形态:固定时长(wait.for)、等到某个时刻(wait.until)、
等一个外部事件(waitpoint 令牌或 webhook waiter)。选哪种取决于「谁来推进」:
时间推进用前两种,人或其他系统推进用后两种。
这一步是成本设计的关键:把「轮询」改成「等待」,运行不占计算,账单才不会随时间线性上涨。
第七步:部署并核对环境
部署前两件事必须做完:
- 环境变量:任务里用到的变量都要在部署环境里配好(官方有专门的环境变量说明), 本地能跑不代表部署后能跑,这是最常见的「部署成功但运行失败」。
- 版本一致:CLI 与
@trigger.dev/*包版本不一致会导致部署失败;dev命令会提示更新, 自托管还要把服务端版本标签与 CLI 锁定。
部署后用受控输入跑一次,检查运行面板里这次运行的状态、耗时与日志; 不要用「部署命令返回 0」当成上线成功。
第八步:复核可观测性与成本
每次运行都有 trace;接入 Vercel AI SDK 的调用可以作为 span 记录模型、token 用量、成本与延迟, 官方提供按调用选择开启的能力。免费档日志保留 1 天、Hobby 7 天、Pro 30 天—— 保留期决定了你事后能不能查,出问题才知道要看日志就晚了。
成本复核的口径:机器规格(vCPU/GB)× 执行秒数 + 运行次数 × 单次调用费。 把「长时等待」与「长时计算」分开看:前者应该走等待挂起,后者才该付计算费。 DEV 环境运行不计费,适合压测与演练。
常见踩坑
踩坑 1:照着旧教程写 v3 任务,部署被拒。 现象:老项目升级后触发或部署报错,提示需要升级。 原因:官方明确 v3 已停止支持,4.5.0 是最后一个支持 v3 任务的版本,4.5.1 起会拒绝 v3 的触发、批量触发与部署。 解决:仍在 v3 的项目先留在 4.5.0,或按迁移指南迁到 v4;不要混跑两代任务。
踩坑 2:部署成功,第一次运行就失败在环境变量上。
现象:本地 dev 一切正常,部署后的运行报缺少配置。
原因:任务用到的环境变量需要在部署环境里单独配置,本地 .env 不会被带上去。
解决:部署前对照清单逐项核对;把「变量是否齐备」写进发布前检查,而不是靠记忆。
踩坑 3:重试把副作用做了三遍。
现象:一封通知发了两三次,或一条记录重复写入。
原因:默认失败重试 3 次,而发信、扣款这类副作用不是幂等的。
解决:给这类调用加业务唯一键,配合 idempotencyKey;或者把副作用拆到单独任务并用幂等键触发。
踩坑 4:忘了设上限,一个跑飞的循环烧掉整月额度。
现象:账单异常上升,运行记录里有一条跑了几小时的任务。
原因:任务默认没有最大时长,循环写错或外部接口挂起时会一直占着机器。
解决:给任务设 maxDuration;对外部调用加超时;把「异常长时间运行」做成告警。
踩坑 5:以为「等一小时」会很贵。
现象:为了避免等待成本,把长轮询拆成很多短任务,结果运行调用费更高。
原因:等待本身在 checkpoint 之后不计计算(wait.for 超过 5 秒的等待不计入),而每次运行都有固定调用费。
解决:用等待而不是拆任务;把「等待」和「计算」在账单上分开评估。
踩坑 6:CLI 与 SDK 版本不一致,部署反复失败。
现象:deploy 报版本不匹配。
原因:CLI 与 @trigger.dev/* 包需要对齐,版本漂移会导致部署被拒。
解决:升级时一起升,dev 提示更新就接受;自托管环境把服务端版本标签与 CLI 锁定在同一档。
踩坑 7:自托管当成「装完即生产」。 现象:自托管跑起来后,安全、升级、可用性没人管。 原因:官方说明自托管的资源、更新、安全与可靠性都由你自己负责,且不保证在你的基础设施上的表现。 解决:把备份、升级窗口、监控与限流写进运维文档;只在有明确的数据驻留或合规要求时选自托管。
踩坑 8:按「免费」规划容量,忽略日志与并发限制。 现象:上线后发现日志只留一天、定时任务数量不够、并发被卡。 原因:各档位的并发运行数、日志保留、定时任务数量与查询窗口是分开限制的(Free 为 20 并发、1 天日志、10 个定时任务)。 解决:按业务峰值选档,把保留期当作事故取证能力的一部分来预算。
常见问题 FAQ
Q1:一定要用云服务吗?能不能全自己跑?
A:可以自托管,官方给了 Docker 与 Kubernetes 路线,架构分 webapp(含 Postgres/Redis)与 worker 两部分。 代价是资源、升级、安全与可用性全部由你负责,且官方声明不对你环境里的表现作保证。云端的免费档适合先验证流程。
Q2:任务能跑多久?
A:没有最大时长限制,运行可以一直跑;你可以给任务或项目设 maxDuration,也可以显式设为不超时。
「能跑很久」同时也是成本风险,建议默认给一个上限。
Q3:失败会怎么处理?
A:默认重试 3 次,可在任务或配置里改次数、退避倍数、首次重试间隔与随机抖动。 判定口径要自己写清:可重试错误(超时、限流、5xx)交给重试,不可重试错误(参数、权限)应直接失败。
Q4:和 serverless 函数、普通队列有什么区别?
A:serverless 有请求超时,长任务会被掐断;普通队列要自己实现重试、并发、等待与可见性。 Trigger.dev 把这四件事内建,并保留每次运行的 trace。它仍然是一个需要你运维边界的系统,不是「不用管」。
Q5:免费档够做验证吗?
A:够做演示与小流量验证($5/月计算额度、20 并发、1 天日志),但日志只留一天意味着第二天就查不到旧运行; 生产前按实际任务时长与频次算一遍计算费 + 调用费,再决定档位。
Q6:中文内容或国内网络环境能用吗?
A:官方文档没有针对国内网络做说明,云端服务在境外的可达性、延迟与合规需要你自己确认; 对数据驻留有要求的团队应评估自托管,或先在 DEV 环境做连通性验证。
进阶学习建议
- 先读三篇建立心智模型:任务概览(
task()的字段:id、run、retry、concurrency、machine、maxDuration)、 运行生命周期与错误与重试。 这三篇决定你后面所有设计的边界。 - 再攻「幂等 + 等待」这一对:把一次真实业务(下单通知、文档处理、审批回传)画成「触发点 → 幂等键 → 等待点 → 副作用」, 照图写一遍,比抄示例更能暴露设计问题。
- 想控制成本,专门读机器规格、并发 与定价页的计算表,把「秒数 × 规格 + 调用次数」算成一张你自己的账单模型。
- 做 AI Agent 的话,接着看 LLM 可观测性(把模型调用记成 span)与 chat agent 的持久化/重放模式, 这两个能力决定了「会话刷新或部署后还能不能接上」。
- 想端到端跑一遍,用官方 Agent skills 或 MCP 服务端让编码助手帮你生成任务骨架, 但部署与成本口径仍要自己核对——工具能写代码,不能替你承担账单。
免责声明
本文基于官方文档和公开资料整理,AI辅助生成,MagicNetWorld 尚未完成独立实测。 定价、额度与版本信息以官方页面为准,可能随时调整;文中代码为结构示例, 未在本站环境部署运行,也未验证与真实业务系统的兼容性。
参考链接
📊 评分与标签
核验口径:已按现行口径通过,待按新证据契约复核
评分说明
总分 8.5/10 · P_优选
核验日期:2026-10-31。本项按 Workflow 维度评价「触发 → 幂等 → 重试 → 并发 → 等待 → 部署 → 成本复核」这条长时任务流程, 不按聊天 Agent 能力打分。评分依据可追溯至公开来源,每项分数均有明确理由和数据支撑;未部署运行、未接入真实业务系统、未压测。
📊 可观测社区指标(采集日期:2026-10-31)
- GitHub API:16,665 stars、1,523 forks、256 open issues,仓库未归档,主语言 TypeScript。
pushed_at为 2026-10-30T16:47:26Z(北京时间 2026-10-31 00:47),创建于 2022-11-30,属长期活跃项目。- 许可:平台核心 Apache-2.0,
@trigger.dev/sdk为 MIT(官方文档的许可说明)。
📋 流程完整性:2.6/3.0
从触发到部署的主链路都有官方支撑:任务定义(task() 的 id/run/retry/concurrency/machine/maxDuration)、
幂等触发、失败重试(默认 3 次)、队列与并发上限、等待与 checkpoint、运行 trace 与 LLM span、部署与环境变量。
「运行可以没有最大时长」加上「等待期间不计计算」,正好覆盖长时 AI 任务最容易断掉的两段。
扣分在三处:成本治理(机器规格选择、调用费测算)没有内置的预算护栏,要靠使用者自己建模型;
v3 → v4 的代际切换有硬门槛(4.5.1 起拒绝 v3 触发与部署);自托管把安全与可用性责任整体交回用户。
- 竞品对比 1(Inngest):Inngest同样以「持久化函数 + 步骤重试」为核心,事件驱动色彩更强; Trigger.dev 的差异是把运行跑在自己的 worker 上、支持自托管,且对 AI/LLM span 有专门的观测接入。本次没有同场景对跑两者的恢复行为。
- 竞品对比 2(Temporal):Temporal以工作流引擎与确定性重放见长,适合长期业务流程; Trigger.dev 更贴「在现有 TypeScript 项目里加几个后台任务」的形态,部署与心智负担更轻,但编排表达能力与生态深度不可等同。
🔄 可复用性:2.1/2.5
任务写在你的仓库里、就是普通 async 函数,配置集中在 trigger.config.ts 与任务选项上,
同一套「幂等键 + 重试策略 + 具名并发名额 + 等待点」可以平移到通知、文档处理、审批回传等不同业务。
云端与自托管共用同一套 SDK 与概念,迁移时改的是基础设施而不是业务代码。
扣分在于:跨部署复制仍要重配环境变量与并发规格;queue.concurrencyLimit 之类旧写法已弃用,
历史代码需要按新写法改写;v3 到 v4 不是无缝升级。
- 竞品对比 1(Temporal):Temporal的工作流定义更强调确定性约束,迁移与重放有严格规则; Trigger.dev 允许更自由的 async 代码,可移植性好一些,但代价是「重放语义」更多依赖平台而非语言约束。
- 竞品对比 2(Windmill):Windmill以脚本 + 低代码流程为中心,跨语言脚本都能挂; Trigger.dev 聚焦 TypeScript,代码复用更自然,但要换语言就得换工具。
📖 文档清晰度:1.8/2.0
官方文档结构完整且区分了「概念」与「操作」:快速开始三步(建账号 → init → dev)、任务概览逐字段解释、
幂等与等待各有专页,自托管单独说明 v3 停止支持与版本锁定。文档站还提供 llms.txt 与页面 Markdown 端点,
便于机器读取与检索,这是少见的工程友好度。
扣分在复杂度带来的歧义:queue 与 concurrency 两套写法并存(前者弃用)、v3/v4 两代任务需要读者自己辨别、
定价页的计算表需要自己换算成账单。
- 竞品对比 1(Inngest):Inngest的文档同样按概念分层,且 SDK 示例语言覆盖更广; 本项文档的优势在「任务字段 + 等待计费口径」写得更贴近成本决策,劣势是代际迁移说明分散在多页。
- 竞品对比 2(Temporal):Temporal 文档体量更大、概念更抽象(工作流/活动/确定性); Trigger.dev 的上手文档更短,适合先跑通再深入,但深入运维与自托管细节时仍要读不少页。
🔧 工具集成:1.2/1.5
接入面覆盖得比较实际:TypeScript SDK 与 CLI、MCP 服务端与 Agent skills(让编码助手直接写任务)、 webhook 触发与等待、实时订阅(前端接任务进度)、以及 LLM 可观测性(把 Vercel AI SDK 调用记成 span, 带模型、token 用量、成本与延迟)。对「AI 任务 + 前端 + 第三方回调」这种组合,接口是齐的。 扣分在于:具体框架的接入体验有差异,官方按框架分别给指南,跨框架复用要自己验证; 环境变量、并发名额、日志保留这些边界项都要手工配置。
- 竞品对比 1(Inngest):Inngest在事件驱动与第三方 SaaS 事件接入上生态更成熟; Trigger.dev 的优势是自己跑 worker、可自托管,集成更贴「自己的基础设施」。
- 竞品对比 2(Windmill):Windmill的优势是内置大量集成与低代码界面; Trigger.dev 没有可视化编排层,靠代码表达流程,集成深度取决于你写的 SDK 调用。
💡 创新性:0.8/1.0
把「持久化执行 + checkpoint 等待 + 每次运行 trace + LLM span」打包成 TypeScript 开发者可直接使用的形态, 在 AI 工作流这个具体场景里是有效的组合创新:等待不计计算这条计费口径,直接把「人审批」这种长等待变成便宜操作。 扣分在于范式本身并不新——持久化工作流(Temporal 一类)、事件驱动步骤(Inngest 一类)都已存在, Trigger.dev 的差异化更多体现在开发者体验与 AI 场景贴合度,而非独有算法或性能突破。
- 竞品对比 1(Temporal):Temporal的持久化执行与重放是更早、更通用的范式; Trigger.dev 的创新点在「把同一套能力做到 TS 项目里足够轻」,不在机制首创。
- 竞品对比 2(Inngest):Inngest的步骤化函数与事件模型同样成熟; 两者路线接近,差异在托管形态(自有 worker vs 平台执行)与 AI 观测深度,本次没有基准证明谁更快。
🏷️ 标签说明
- 持久化执行:任务运行有记录、可重试、可在等待处挂起并从断点继续,官方文档以「no execution timeout」与 checkpoint 描述该能力。 来源:任务概览、等待说明。
- 工作流编排:通过触发、子任务、队列与并发名额把多个任务组织成流程。 来源:队列与并发、触发。
- 开源自托管:平台核心 Apache-2.0,官方提供 Docker 与 Kubernetes 自托管路线(责任随之下放给使用者)。 来源:自托管概览、仓库许可。
- 可观测性:每次运行有 trace,LLM 调用可作为 span 记录模型、token、成本与延迟。 来源:LLM 可观测性、运行。
局限与未实测声明
未注册账号、未运行 init/dev/部署、未压测并发与重试、未接入模型或业务系统、未验证自托管。
文中定价、并发数、日志保留期与版本信息来自 2026-10-31 的官方页面,官方可随时调整。
代码片段为结构示例,未经真实编译运行;成本测算方法为通用口径,不代表你的实际账单。
未对平台做安全审计,自托管的安全责任以官方说明为准。
📋 来源核实