Schedules
File-based Agent 从自身的 schedules/ 目录发现 schedule。每个文件声明一个周期性任务:一个 cron 表达式,以及触发时 Agent 应执行的操作。Mastra 会在启动时将它们注册到 schedule storage 中,因此定时运行的 Agent 不需要运行时注册代码。
本页介绍基于文件的约定。要改为在运行时创建 schedule,请参阅 Schedules。
defineSchedule 由 @mastra/core/agent 重新导出,因此 File-based Agent 只需使用一个导入路径。@mastra/core/schedules 也会导出它。
快速开始快速开始的直接链接
在 Agent 的 schedules/ 目录下添加文件:
import { defineSchedule } from '@mastra/core/agent'
export default defineSchedule({
cron: '*/5 * * * *',
prompt: 'Check system health and report any failures.',
})
Mastra 每五分钟使用该 prompt 运行一次 support Agent。
Schedule 身份Schedule 身份的直接链接
Schedule 的 id 是其相对于 schedules/ 的路径(去掉扩展名),因此可以使用嵌套目录对相关 schedule 进行分组:
src/mastra/agents/
└── support/
├── config.ts
├── instructions.md
└── schedules/
├── heartbeat.ts # id: heartbeat
├── cleanup.md # id: cleanup
└── billing/
└── sweep.ts # id: billing/sweep
该 id 在不同构建之间保持稳定,因此 Mastra 可以区分经过编辑的 schedule 和新的 schedule。重命名或移动文件会被视为删除一个 schedule 并创建另一个。
heartbeat.ts 和 heartbeat.md 会解析为相同的 id,因此同时声明两者会导致构建错误。
执行模式执行模式的直接链接
Schedule 必须且只能设置一种执行模式。同时设置两种或两种都未设置都会导致构建失败。
Prompt 模式Prompt 模式的直接链接
prompt 使用固定消息运行所属 Agent。这是即发即弃操作:不会等待结果。
import { defineSchedule } from '@mastra/core/agent'
export default defineSchedule({
cron: '0 9 * * 1',
timezone: 'America/New_York',
prompt: 'Summarize last week and post the digest.',
})
Handler 模式Handler 模式的直接链接
handler 在 schedule 触发时计算本次触发的参数。当 prompt 依赖当前状态、某些触发应被跳过,或运行需要 channel 投递上下文时,请使用此模式。
import { defineSchedule } from '@mastra/core/agent'
export default defineSchedule({
cron: '0 3 * * *',
handler: async ({ mastra, agentId }) => {
const overdue = await findOverdueInvoices()
// Returning null skips this fire; nothing runs and the trigger is
// recorded with outcome 'skipped'.
if (overdue.length === 0) return null
return {
prompt: `Chase these overdue invoices: ${overdue.join(', ')}`,
threadId: 'billing-ops',
resourceId: agentId,
}
},
})
Handler 的返回值会合并到 schedule 已存储的字段中,并覆盖同名字段。返回 undefined 不会应用任何覆盖项,因此本次触发会回退到已存储的字段。由于 handler 模式的 schedule 不能声明 prompt,该次触发随后会因缺少 prompt 而失败。要运行,请返回 prompt;要跳过,请返回 null。
Handler 是函数,因此无法持久化到已存储的 schedule 行。Schedule 触发时,Mastra 会在进程内解析它们。未提供 prompt(也未声明 prompt)的 handler 模式 schedule 会使本次触发失败并给出原因,而不会向 Agent 发送空消息。
这种进程内查找意味着运行 scheduler 的进程必须注册所属 Agent。常规部署会启动单一入口,因此自然满足这一要求。独立 worker 需要使用与 server 相同的入口。如果从精简后的入口启动 worker,它没有可调用的 handler,因此触发会失败,而不会运行。
Markdown 格式的 scheduleMarkdown 格式的 schedule的直接链接
.md schedule 使用 frontmatter 指定 cron,并以文档正文作为 prompt。这属于 prompt 模式,但提供了更多编写空间:
---
cron: '0 3 * * *'
timezone: 'UTC'
name: 'nightly cleanup'
---
Review tickets untouched for 30 days.
Close the ones that are clearly resolved and summarize the rest.
务必用引号括起 cron。开头的 * 是 YAML alias,因此 cron: */5 * * * * 会导致解析错误,而 cron: "*/5 * * * *" 可以正常解析。
Frontmatter 接受下方除 handler 以外的所有选项;该选项需要函数,因此必须使用 .ts 或 .js schedule 模块。prompt 也无法设置,因为正文就是 prompt。未知的 frontmatter 字段会导致构建失败,而不会被静默忽略,因此 ifIdel 之类的拼写错误会在构建时被发现。
选项选项的直接链接
cron:
prompt?:
handler,但不能同时设置。handler?:
null 跳过本次触发。不返回内容则不会应用覆盖项;由于 handler 模式没有已存储的 prompt,这会导致本次触发失败。设置此项或 prompt,但不能同时设置。timezone?:
America/New_York)。默认为宿主进程的时区,该时区因部署而异,因此对于任何对具体时间敏感的任务,请显式设置此项。时区规则会处理 DST 转换,因此 0 9 * * * 在转换前后都会保持为当地上午 9 点。name?:
mastra.schedules.list({ name }) 筛选。threadId?:
resourceId。resourceId?:
threadId 时必填。signalType?:
tagName?:
<schedule>…</schedule> 的形式到达 Agent。attributes?:
providerOptions?:
ifActive?:
deliver、persist 或 discard。仅适用于使用 thread 的 schedule。ifIdle?:
wake、persist 或 discard。仅适用于使用 thread 的 schedule。status?:
status,所以通过 API 暂停的状态可在重新部署后保留。之后在代码中更改此值不会影响现有 schedule。metadata?:
在开发环境中测试 schedule在开发环境中测试 schedule的直接链接
Schedule 按 cron 周期触发,这在迭代开发期间并不方便。可改为按 id 手动触发:
# List schedules to find the id
curl http://localhost:4111/api/schedules
# Fire one now, out-of-band from its cron
curl -X POST http://localhost:4111/api/schedules/<scheduleId>/run
这会记录一个 triggerKind: "manual" 的 trigger,并且不会推进 nextFireAt,因此不影响常规周期。Studio 会列出相同的 schedule 及其 trigger 历史记录。
存储的 id 带有 namespace 并经过 URL 编码。support Agent 上的 billing/sweep 会变为 fsa_support__billing%2Fsweep,因此请从列表响应中复制 id,而不要手动拼接。
注册和生命周期注册和生命周期的直接链接
Mastra 启动时会将声明的 schedule 同步到 schedule storage;之后每当注册 Agent 时也会再次同步。只需声明 schedule 即可启动 scheduler,无需设置 scheduler: { enabled: true }。
同步过程会将每个已声明的 schedule 与其已存储行进行比较,并且只写入有变更的内容:
- 新的 schedule 文件会创建一行。
- 编辑
cron或timezone会更新该行并重新计算下次触发时间,因此编辑后的 schedule 绝不会再按旧周期触发。 - 删除或重命名 schedule 文件会删除其对应行。
- 通过 API 暂停的 schedule 会在重新部署后保持暂停。同步过程会有意保留
status不变。
同步过程只会移除属于当前进程中已注册 Agent 的行,因此仅持有部分 Agent 的进程绝不会删除其他 Agent 的 schedule。当某个 Agent 从项目中彻底移除时,其遗留行会在下次触发时被清理,此时 scheduler 会发现没有可运行的 Agent。
在运行时通过 mastra.schedules.create(...) 创建的 schedule 位于单独的 namespace 中,同步过程绝不会修改它们。
限制限制的直接链接
仅限根 Agent。 Schedule 必须在顶层 Agent 上声明。subagents/ 下的 schedules/ 目录会导致构建错误,因为子 Agent 会连接到父级,而不会注册到 Mastra 实例上,所以 scheduler 无法将其解析为目标。请为父级设置 schedule,再由父级进行委派。
需要 storage。 Schedule 是持久化的行,因此实例需要配置 storage。内存 store 中的行无法在重启后保留。
托管。 Scheduler 作为后台 worker 在 Mastra 进程内运行,因此需要能让该进程持续运行的宿主环境。长期运行的 Node server 和容器均可正常工作。会在请求之间冻结或回收进程的环境(包括大多数 serverless function 平台)会错过触发。此时请改用平台自身的 cron 调用 run 端点。
代码定义的 Agent。 如果 Agent 目录中的 config.ts 导出 new Agent({...}),Mastra 会原样使用它,因此会忽略其 schedules/ 目录并发出警告。对于这类 Agent,请使用 mastra.schedules.create(...)。
示例示例的直接链接
下面是一个拥有两个 schedule 的支持 Agent:一个固定的每周摘要,以及一个仅在有任务时才运行的夜间检查。
src/mastra/agents/
└── support/
├── config.ts
├── instructions.md
└── schedules/
├── weekly-digest.md
└── billing/
└── sweep.ts
import { agentConfig } from '@mastra/core/agent'
export default agentConfig({
model: 'openai/gpt-5.6-sol',
})
---
cron: '0 9 * * 1'
timezone: 'America/New_York'
---
Summarize the past week's tickets and post the digest to the team channel.
import { defineSchedule } from '@mastra/core/agent'
export default defineSchedule({
cron: '0 3 * * *',
timezone: 'America/New_York',
handler: async () => {
const overdue = await findOverdueInvoices()
if (overdue.length === 0) return null
return { prompt: `Draft reminders for ${overdue.length} overdue invoices.` }
},
})