Scheduled workflows
在工作流上声明 schedule 字段,Mastra 就会按你指定的 cron 触发它。同一工作流仍可直接通过 workflow.start() 调用,定时触发和手动运行共享同一条执行路径。
快速开始快速开始的直接链接
以下工作流每天纽约时间上午 9 点运行。像注册其他工作流一样在 Mastra 上注册它,调度器会自动发现。
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 启动时,调度器直接从工作流读取 schedule。
执行引擎执行引擎的直接链接
声明 schedule 不会改变工作流的运行方式。定时触发在运行调度器的主机上进程内运行,与 workflow.start() 或 HTTP 触发的运行方式相同。声明 schedule 的工作流直接运行无需额外的存储或 worker 设置。
拆分 worker 的部署是例外。当 MASTRA_WORKERS 环境变量设为任何值(包括 false)时,createWorkflow 会在事件驱动执行引擎上构建定时工作流,以便部署中的每个进程都以相同方式运行它们。此时定时触发在编排 worker 上运行,Mastra 会在创建工作流时向控制台记录一条警告。公共 API(workflow.start()、workflow.startAsync()、resume())不变。
事件驱动运行需要能够原子应用并发更新的存储适配器,例如 @mastra/libsql 或 @mastra/pg。使用其他适配器时,createRun() 会抛出错误并列出支持的适配器。
只有环境变量会触发切换,因为 createWorkflow 在 Mastra 读取其 workers 选项之前运行。如果你改为通过 workers 选项拆分 worker,请为你的定时工作流从 @mastra/core/workflows/evented 导入 createWorkflow。
单一计划单一计划的直接链接
对于只在一个节奏上触发的工作流,向 schedule 传入一个对象:
const dailyReport = createWorkflow({
id: 'daily-report',
schedule: {
cron: '0 9 * * *',
timezone: 'America/New_York',
inputData: { userId: 'system' },
},
// ...
})
字段说明:
cron(必填):5、6 或 7 段式 cron 表达式。在工作流构建时验证。timezone(可选):IANA 时区,例如America/New_York。默认使用主机的本地时区。在生产环境中请显式设置,以免触发时间依赖服务器区域设置。inputData(可选):每次触发时作为工作流输入传递的负载。initialState(可选):运行的初始状态。requestContext(可选):附加到运行的请求上下文。metadata(可选):与计划行一起持久化的任意元数据。
多个计划多个计划的直接链接
传入数组以在多个节奏上触发同一工作流。每个条目需要一个唯一且稳定的 id:
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 中查看计划的直接链接
Studio 将计划作为顶层区域呈现,而不是工作流内部的标签页:
- 所有计划:打开
/workflows/schedules查看跨工作流列表。每行显示工作流 id、cron、下次触发时间以及最近一次运行的状态。该列表让你一眼回答"有什么出问题了吗?"。 - 按工作流筛选:在列表后追加
?workflowId=<id>将范围限定为单个工作流,例如/workflows/schedules?workflowId=daily-report。 - 计划详情:选择任意行打开
/workflows/schedules/:scheduleId。页面显示计划元数据和 Pause / Resume 控件,随后是完整的触发历史。
当工作流至少有一个计划时,其头部会包含 Schedules 操作:
- 当只有一个匹配的计划时,该操作直接链接到其详情页。
- 多个计划时:该操作链接到按工作流筛选的列表
/workflows/schedules?workflowId=<id>。 - 没有计划时:该操作隐藏。
触发历史触发历史的直接链接
每次触发都会记录一行触发记录,包含 run id、计划时间、实际触发时间和发布状态。计划详情页会将每次触发与对应的工作流运行关联,并显示:
- 运行状态(
running、success、failed、suspended、canceled)徽章。 - 运行的开始时间和持续时间。
- 指向运行完整图视图的链接
/workflows/:workflowId/graph/:runId。 - 当触发已发布但运行记录尚未写入(由于触发发布与运行快照之间的竞态)时,显示
pending徽章。 - 当调度器根本无法将运行入队时,显示
publish failed徽章及发布错误。
处于非终态的触发会使面板每五秒轮询一次,直到达到终态。列表支持分页,因此长期运行的计划不会一次加载数千行。
在运行时暂停计划在运行时暂停计划的直接链接
当定时工作流在生产环境中误触发时,你不必重新部署或手动编辑数据库。可以从 SDK 暂停它:
import { MastraClient } from '@mastra/client-js'
const client = new MastraClient({ baseUrl: 'http://localhost:4111' })
// Schedule ids are derived from the workflow id: `wf_<workflowId>` for a
// single declarative schedule, or `wf_<workflowId>__<scheduleId>` 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 表,并在进程重启和重新部署后保留。声明式配置的 upsert 永远不会覆盖用户设置的状态,即使你更改了
cron、timezone或其他字段。 - 恢复会从当前时间重新计算
nextFireAt。暂停一周的计划在恢复时不会立即触发七次积压运行。它会在下一个常规 cron 时刻触发。 - 使用
resumeSchedule或 Studio 中的 Resume 按钮取消暂停。编辑工作流的schedule配置不会取消暂停已暂停的行。 - 暂停和恢复是幂等的。对已暂停的计划调用暂停是无操作。
- 此运维覆盖控制的是现有计划。请在代码中声明计划。声明式计划通过
createWorkflow上的schedule字段在代码中创建、删除和编辑。如需在运行时以命令式方式创建计划,请使用统一的mastra.schedules服务并传入workflowId。
底层 HTTP 路由是 POST /api/schedules/:scheduleId/pause 和 POST /api/schedules/:scheduleId/resume。两者都需要 schedules:write 权限。
重新部署并更改配置重新部署并更改配置的直接链接
当你更改 schedule 配置并重新部署时,Mastra 会将现有计划行与新配置进行 diff:
- 如果
cron或timezone发生变化,nextFireAt会重新计算。没有未来触发时间的节奏会使计划完成。重新计算后仍可触发的节奏会重新激活已完成的计划。 - 如果仅
inputData、initialState或metadata发生变化,行会就地修补,下次触发时间保持不变。 - 用户设置的状态(例如通过
client.pauseSchedule暂停)和触发历史永远不会被覆盖,除非上述节奏变化需要更新状态。
从工作流的 schedule 数组中移除某个计划条目,会在下次启动时删除其行。
部署拓扑部署拓扑的直接链接
内置调度器使用 setInterval tick 循环轮询 schedules 表并认领到期行。它通过进程内 pubsub 分发工作流运行。它假定有一个长期运行的主机进程。
长期运行的主机(推荐)长期运行的主机(推荐)的直接链接
Fly Machines、Railway、Render、AWS ECS、GKE 或你自己的服务器等部署目标会在 cron tick 之间保持 Mastra 进程存活。mastra build 生成的服务器会自动启动调度器,因此计划无需额外设置即可工作。
如果你使用服务器适配器运行 Mastra,请在服务器开始监听后调用 mastra.startWorkers()。适配器不会启动调度器,不调用此方法计划就永远不会触发。参见启动后台 worker。
对于生产部署,你可以将调度器作为专用 worker 进程运行,将其与 API 层隔离。
Serverless 平台Serverless 平台的直接链接
Vercel、Netlify、AWS Lambda 和 Cloudflare Workers 等函数即服务平台在每个请求后关闭进程,因此 tick 循环无法获得第二次 tick,目前代码中声明的计划不会随内置调度器触发。直接运行仍然有效:从 HTTP 路由调用 run.start() 会像其他工作流一样在进程内运行声明了 schedule 的工作流。
要在这些平台上实现 cron 触发,请改用 @mastra/inngest。Inngest 原生于 serverless,并为你持有 cron 状态。
Inngest workflowsInngest workflows的直接链接
本页记录的 schedule 字段驱动 Mastra 的内置调度器。如果你使用 @mastra/inngest,定时工作流通过 Inngest 自己的 createFunction 上的 cron 字段配置,并由 Inngest 的调度器触发。
实际影响:
- Inngest 计划不会出现在 Studio 的
/workflows/schedules视图中。 - 工作流头部的 Schedules 操作不会对 Inngest 工作流显示。
client.pauseSchedule和client.resumeSchedule不会控制 Inngest 计划。
请从 Inngest 控制台管理 Inngest 计划。当你希望 Mastra 端到端拥有调度能力时,请使用 Mastra 计划。
相关内容相关内容的直接链接
- 工作流概览
- 挂起与恢复
- Workers:调度器 worker在专用进程中运行 cron 计划
- Agent 计划:在 cron 计划上运行 agent 而非工作流,并通过
mastra.schedules在运行时管理两种计划类型