AgentSkillsCN

trigger

使用 Trigger.dev v4 设计和实现生产级后台任务系统。专长于创建异步任务、定时任务、子任务编排和批量操作、错误处理和重试、Zod Schema 验证以及构建扩展(ffmpeg、Playwright、Prisma)。在需要架构后台任务、实现定时任务、构建 AI 工作流或处理长时间运行的异步操作时使用。

中文原作
SKILL.md
--- frontmatter
name: trigger
description: 使用 Trigger.dev v4 设计和实现生产级后台任务系统。专长于创建异步任务、定时任务、子任务编排和批量操作、错误处理和重试、Zod Schema 验证以及构建扩展(ffmpeg、Playwright、Prisma)。在需要架构后台任务、实现定时任务、构建 AI 工作流或处理长时间运行的异步操作时使用。

示例:
- <example>
  场景:用户需要创建一个用于处理视频文件的后台任务
  user: "我需要创建一个任务来处理上传的视频、提取缩略图并进行转码"
  assistant: "我将使用 trigger-dev-expert agent 来设计一个健壮的视频处理工作流,具有适当的任务结构和 ffmpeg 配置"
  <commentary>
  由于这涉及媒体处理的后台任务创建,trigger-dev-expert agent 最适合构建工作流并配置构建扩展。
  </commentary>
</example>
- <example>
  场景:用户想要实现一个定时数据同步任务
  user: "创建一个每小时运行一次的定时任务,以从我们的 API 同步数据到数据库"
  assistant: "让我使用 trigger-dev-expert agent 创建一个结构良好的定时任务,具有错误处理"
  <commentary>
  用户需要一个定时后台任务,这是 expert agent 专长的 Trigger.dev 核心功能。
  </commentary>
</example>
- <example>
  场景:用户需要帮助进行任务编排
  user: "我有一个复杂的工作流,需要按顺序和并行运行多个 AI 模型,我应该如何构造它?"
  assistant: "我将使用 trigger-dev-expert agent 来构建一个高效的任务层次结构,使用 triggerAndWait 和 batchTriggerAndWait 模式"
  <commentary>
  使用子任务的复杂任务编排是 trigger-dev-expert agent 的专长。
  </commentary>
</example>
model: inherit
color: green

Trigger.dev 专家(v4)

精通 Trigger.dev 框架的专家,专精于生产级后台任务系统。任务运行在 Node.js 21+ 环境中,使用 @trigger.dev/sdk v4。

📚 完整文档

本 skill 文档已按主题模块化组织。详细信息请查看:

📖 指南 (Guides)

💡 示例 (Examples)

📋 参考 (Reference)

🚀 快速使用

创建基础任务

ts
import { task } from "@trigger.dev/sdk"

export const processData = task({
	id: "process-data",
	retry: { maxAttempts: 3 },
	run: async (payload: { userId: string }) => {
		// 任务逻辑 - 无超时限制,可长时间运行
		return { processed: true }
	},
})

触发任务

ts
import { tasks } from "@trigger.dev/sdk"
import type { processData } from "./trigger/tasks"

// 从 API 路由触发
const handle = await tasks.trigger<typeof processData>("process-data", {
	userId: "123",
})

Schema 验证

ts
import { schemaTask } from "@trigger.dev/sdk"
import { z } from "zod"

export const validatedTask = schemaTask({
	id: "validated-task",
	schema: z.object({
		email: z.string().email(),
		age: z.number().min(0),
	}),
	run: async (payload) => {
		// payload 自动验证和类型推断
	},
})

⚠️ 重要提醒

必须使用 v4 SDK

ts
// ✅ 正确 - v4 SDK
import { task } from "@trigger.dev/sdk"

// ❌ 错误 - v2 API (会破坏应用)
client.defineJob({ id: "job-id", run: async () => {} })

Result vs Output

ts
// triggerAndWait 返回 Result 对象,不是直接输出
const result = await childTask.triggerAndWait({ data: "value" })

if (result.ok) {
	console.log(result.output) // ✅ 正确 - 访问实际输出
} else {
	console.error(result.error)
}

// 或使用 unwrap 快速访问(失败时抛出错误)
const output = await childTask.triggerAndWait({ data: "value" }).unwrap()

🚨 常见陷阱

1. 忘记 idempotencyKey(导致任务重复执行)

ts
// ❌ 错误 - 网络问题时可能重复执行
const result = await childTask.trigger({ payload })

// ✅ 正确 - 使用幂等性 key
const result = await childTask.trigger(
	{ payload },
	{ idempotencyKey: `${ctx.run.id}-child-1` }
)

为什么重要: 如果网络故障,任务可能被触发多次。使用 idempotencyKey 确保相同操作只执行一次。

2. 不理解 Result 对象

ts
// ❌ 错误 - Result 对象不是直接输出
const output = await childTask.triggerAndWait({ data: "value" })
console.log(output.userId) // undefined!

// ✅ 正确 - 检查 ok 状态
const result = await childTask.triggerAndWait({ data: "value" })
if (result.ok) {
	console.log(result.output.userId) // ✅ 成功
} else {
	console.error(result.error) // 处理错误
}

// ✅ 或者使用 unwrap(简洁但失败时抛出)
const output = (await childTask.triggerAndWait({ data: "value" })).unwrap()

为什么重要: 参考官方指南 "⚠️ 重要提醒" > "Result vs Output" 部分。

3. 过度拆分任务(导致性能下降)

ts
// ❌ 反模式 - 太多细碎的任务
const result1 = await validateTask.triggerAndWait({ user })
const result2 = await sendEmailTask.triggerAndWait({ email })
const result3 = await logTask.triggerAndWait({ userId })
// 这会导致 3 个独立的执行和调用开销

// ✅ 最佳实践 - 合理的任务粒度
export const processUser = schemaTask({
	id: "users.process.complete",
	schema: z.object({ userId: z.string() }),
	run: async (payload) => {
		// 验证
		const user = await validateUser(payload.userId)
		// 发送邮件
		await sendEmail(user.email)
		// 日志记录
		logger.log("User processed", { userId: payload.userId })
		return { processed: true }
	},
})

为什么重要: 任务拆分应该基于可独立重试的边界,不是为了代码重用。

4. 忽视成本和性能

ts
// ❌ 反模式 - 不必要的高成本配置
export const expensiveTask = task({
	id: "expensive",
	machine: "large-2x", // 😅 不必要的大机器
	retry: { maxAttempts: 100 }, // 😅 过多重试
	run: async (payload) => {
		/* ... */
	},
})

// ✅ 最佳实践 - 选择合适的资源
export const optimizedTask = schemaTask({
	id: "optimized",
	machine: "small-1x", // 够用即可
	retry: { maxAttempts: 3 }, // 合理的重试
	schema: z.object({
		/* ... */
	}),
	run: async (payload) => {
		/* ... */
	},
})

为什么重要: 参考 machines.md 了解各机器预设的成本和性能对比。

禁止并行等待

ts
// ❌ 错误 - 不支持
await Promise.all([
	task1.triggerAndWait(payload1),
	task2.triggerAndWait(payload2),
])

// ❌ 错误 - 不支持
await Promise.all([wait.for({ seconds: 30 }), wait.for({ seconds: 60 })])

// ✅ 正确 - 使用 batchTriggerAndWait
await parentTask.batchTriggerAndWait([
	{ payload: payload1 },
	{ payload: payload2 },
])

🎯 核心设计原则

  1. 使用 schemaTask - 自动验证和类型推断
  2. 合理拆分子任务 - 可独立重试、幂等,但不过度复杂化
  3. 配置重试策略 - 设置 maxAttempts、delay、backoff
  4. 幂等性键 - 任务内触发子任务时使用 idempotencyKey
  5. 日志记录 - 关键执行点使用 logger
  6. 任务 ID 规范 - 使用 domain.action.target 模式

📂 项目结构

code
trigger/
├── index.ts              # 导出所有任务
├── tasks/                # 任务定义
│   ├── users.ts          # 用户相关任务
│   ├── payments.ts       # 支付任务
│   └── ...
└── shared/               # 共享工具
    ├── queues.ts         # 队列定义
    └── streams.ts        # Stream 定义

🚀 快速导航

任务阅读文档
第一次使用getting-started.md
创建基础任务task-basics.mdbasic-task.md
实现定时任务scheduled-tasks.md
构建复杂工作流advanced-tasks.mdworkflow-example.md
添加实时监控realtime.mdrealtime-example.md
配置构建扩展configuration.md
快速查 APIreference/api-reference.md
最佳实践reference/best-practices.md