> Discover all available pages from the documentation index: https://mastra.zisheng.pro/llms.txt # 定时 Workflow 在 Workflow 上声明 `schedule` 字段,Mastra 就会按你指定的 cron 触发它。同一个 Workflow 仍可通过 `workflow.start()` 直接调用;定时触发和手动 Run 共用一条执行路径。 ## 快速开始 以下 Workflow 每天纽约时间上午 9 点运行。像其他 Workflow 一样将其注册到 `Mastra`,Scheduler 会自动发现它。 ```typescript import { createWorkflow, createStep } from '@mastra/core/workflows' import { z } from 'zod' const sendReport = createStep({ id: 'send-report', inputSchema: z.object({ userId: z.string() }), outputSchema: z.object({ ok: z.boolean() }), execute: async ({ inputData }) => { // ...send the report for inputData.userId return { ok: true } }, }) export const dailyReport = createWorkflow({ id: 'daily-report', inputSchema: z.object({ userId: z.string() }), outputSchema: z.object({ ok: z.boolean() }), schedule: { cron: '0 9 * * *', timezone: 'America/New_York', inputData: { userId: 'system' }, }, }) .then(sendReport) .commit() ``` 不会再发生单独的“注册计划”调用。`Mastra` 启动时,Scheduler 会直接读取 Workflow 上的 `schedule`。 ## `schedule` 会改变什么 声明 `schedule` 的 Workflow 会自动提升到**事件驱动执行引擎**。公共 API(`workflow.start()`、`workflow.startAsync()`、`streamLegacy()`、`resume()`)保持不变;`EventedWorkflow extends Workflow` 并以相同签名覆盖每个方法。从代码角度看,定时触发与手动 Run 没有区别。 这种提升有一项实际影响:事件驱动 Run 需要支持并发更新的 Storage Adapter,例如 `@mastra/libsql`。如果 Adapter 不支持,`createRun()` 会抛出明确错误并指向 `schedule` 字段。请更换 Adapter 或移除计划。 ## 单个计划 对于只按一种周期触发的 Workflow,请向 `schedule` 传入对象: ```typescript const dailyReport = createWorkflow({ id: 'daily-report', schedule: { cron: '0 9 * * *', timezone: 'America/New_York', inputData: { userId: 'system' }, }, // ... }) ``` 字段: - `cron`(必填):由 5、6 或 7 部分组成的 cron 表达式。在构造 Workflow 时验证。 - `timezone`(可选):IANA 时区,例如 `America/New_York`。默认为宿主的本地时区。生产环境请显式设置,避免触发时间依赖 Server Locale。 - `inputData`(可选):每次触发时作为 Workflow 输入传入的载荷。 - `initialState`(可选):Run 的初始状态。 - `requestContext`(可选):附加到 Run 的 Request Context。 - `metadata`(可选):与计划行一同持久化的任意元数据。 ## 多个计划 传入数组,可以按多个周期触发同一个 Workflow。每个条目都需要唯一且稳定的 `id`: ```typescript const statusCheck = createWorkflow({ id: 'status-check', schedule: [ { id: 'morning', cron: '0 9 * * *', inputData: { window: 'morning' } }, { id: 'evening', cron: '0 18 * * *', inputData: { window: 'evening' } }, ], // ... }) ``` 每个条目都会创建独立的计划行,按各自 cron 触发,并在 Studio Schedules 视图中单独显示。 ## 在 Studio 中查看计划 Studio 将计划显示为顶层区域,而不是 Workflow 内的选项卡: - **所有计划**:打开 `/workflows/schedules` 查看跨 Workflow 列表。每行显示 Workflow ID、cron、下次触发时间和最近 Run 的状态,因此可以一眼看出“是否有故障”。 - **按 Workflow 筛选**:追加 `?workflowId=`,将列表限定为单个 Workflow,例如 `/workflows/schedules?workflowId=daily-report`。 - **计划详情**:选择任意行,打开 `/workflows/schedules/:scheduleId`。页面显示计划元数据和 **Pause** / **Resume** 控件,随后是完整触发历史。 如果 Workflow 至少有一个计划,其标题区会包含 **Schedules** 操作: - 只有一个匹配计划时,操作会直接链接到详情页。 - 有多个计划时,操作链接到 `/workflows/schedules?workflowId=` 的 Workflow 筛选列表。 - 没有计划时,操作隐藏。 ### 触发历史 每次触发都会记录一行,其中包含 Run ID、计划时间、实际触发时间和发布状态。计划详情页会将每次触发与对应 Workflow Run 连接,并显示: - Run 状态(`running`、`success`、`failed`、`suspended`、`canceled`)徽章。 - Run 的开始时间和持续时长。 - 指向 `/workflows/:workflowId/graph/:runId` 完整 Run 图视图的链接。 - 对于因触发发布与 Run Snapshot 之间存在竞态而尚未写入 Run 记录的触发,显示 `pending` 徽章。 - Scheduler 完全无法将 Run 加入队列时,显示带发布错误的 `publish failed` 徽章。 非终止状态的触发会使面板每 5 秒轮询一次,直到达到终止状态。列表支持分页,因此长期运行的计划不会一次加载数千行。 ## 在运行时暂停计划 定时 Workflow 在生产环境错误触发时,无需重新部署或手动编辑数据库。可通过 SDK 暂停: ```typescript import { MastraClient } from '@mastra/client-js' const client = new MastraClient({ baseUrl: 'http://localhost:4111' }) // Schedule ids are derived from the workflow id: `wf_` for a // single declarative schedule, or `wf___` when you // declare multiple schedules per workflow as an array. await client.pauseSchedule('wf_daily-report') // ...investigate, ship a fix, then: await client.resumeSchedule('wf_daily-report') ``` 在 Studio 中打开计划详情页,然后选择标题区的 **Pause** 或 **Resume**。 需要了解的规则: - 暂停是持久的。状态会写入 schedules 表,并在进程重启和重新部署后继续保留。即使更改 `cron`、`timezone` 或其他字段,声明式配置 Upsert 也绝不会覆盖用户设置的状态。 - 恢复会从当前时间重新计算 `nextFireAt`。暂停一周的计划不会在恢复时立即触发积压的 7 次 Run,而会在下一个正常 cron 时间点触发。 - 使用 `resumeSchedule` 或 Studio 的 **Resume** 按钮取消暂停。编辑 Workflow 的 `schedule` 配置不会取消已暂停行。 - 暂停和恢复具有幂等性。对已暂停计划调用暂停不会产生任何操作。 - 此运行时覆盖控制现有计划。声明式计划应在代码中编写,通过 `createWorkflow` 的 `schedule` 字段创建、删除和编辑。要在运行时以命令式方式创建计划,请使用统一的 [`mastra.schedules`](https://mastra.zisheng.pro/docs/long-running-agents/schedules) 服务并提供 `workflowId`。 底层 HTTP 路由为 `POST /api/schedules/:scheduleId/pause` 和 `POST /api/schedules/:scheduleId/resume`,两者都需要 `schedules:write` 权限。 ## 重新部署更改 更改 `schedule` 配置并重新部署时,Mastra 会比较现有计划行与新配置: - 如果 `cron` 或 `timezone` 发生变化,会重新计算 `nextFireAt`。 - 如果只有 `inputData`、`initialState` 或 `metadata` 发生变化,会原地修补计划行并保留下次触发时间。 - 用户设置的状态(例如通过 `client.pauseSchedule` 暂停)和触发历史绝不会被覆盖。 从 Workflow 的 `schedule` 数组中移除计划条目后,下次启动时会删除对应行。 ## 部署拓扑 内置 Scheduler 使用 `setInterval` tick 循环轮询 schedules 表并认领到期行,再通过进程内 PubSub 分发 Workflow Run。它假定宿主进程长期运行。 ### 长期运行的宿主(推荐) Fly Machines、Railway、Render、AWS ECS、GKE 或你自己的 Server 等部署目标会在 cron tick 之间保持 Mastra 进程活动,计划无需额外设置即可运行。生产部署可将 Scheduler 作为[专用 Worker 进程](https://mastra.zisheng.pro/docs/deployment/workers)运行,使其与 API 层隔离。 ### Serverless 平台 Vercel、Netlify、AWS Lambda 和 Cloudflare Workers 等函数即服务平台会在每次请求后关闭进程。由于 tick 循环不会迎来第二个 tick,目前在这些平台上,代码中声明的计划无法通过内置 Scheduler 触发。 请在这些平台上改用 [`@mastra/inngest`](#inngest-workflows)。Inngest 原生支持 Serverless,并会替你保存 cron 状态。 ## Inngest Workflow 本页所述 `schedule` 字段驱动 Mastra 内置 Scheduler。使用 `@mastra/inngest` 时,定时 Workflow 通过 `createFunction` 上 Inngest 自己的 `cron` 字段配置,并由 Inngest Scheduler 触发。 实际影响: - Inngest 计划不会出现在 Studio 的 `/workflows/schedules` 视图中。 - Inngest Workflow 的标题区不会显示 **Schedules** 操作。 - `client.pauseSchedule` 和 `client.resumeSchedule` 无法控制 Inngest 计划。 请从 [Inngest Dashboard](https://www.inngest.com/docs/guides/scheduled-functions) 管理 Inngest 计划。如果希望由 Mastra 端到端负责计划,请使用 Mastra 计划。 ## 相关内容 - [Workflow 概览](https://mastra.zisheng.pro/docs/workflows/overview) - [挂起与恢复](https://mastra.zisheng.pro/docs/workflows/suspend-and-resume) - [Worker](https://mastra.zisheng.pro/docs/deployment/workers):[Scheduler Worker](https://mastra.zisheng.pro/docs/deployment/workers)在专用进程中运行 cron 计划 - [Agent 计划](https://mastra.zisheng.pro/docs/long-running-agents/schedules):按 cron 计划运行 Agent 而不是 Workflow,并通过 `mastra.schedules` 在运行时管理两类计划。