UNPKG

@mastra/core

Version:
201 lines (147 loc) 9.05 kB
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt # Schedules **Added in:** `@mastra/core@1.50.0` > **Beta:** This feature is in beta. Breaking changes may occur without a major version bump until the API is stable. A schedule runs an agent on a cron cadence. On each fire, Mastra sends a prompt to the agent, either as a [signal](https://mastra.ai/docs/long-running-agents/signals) into a thread or as a threadless [`agent.generate()`](https://mastra.ai/reference/agents/generate) run. Use schedules for recurring agent work such as daily summaries, periodic checks, or scheduled nudges into a conversation. Schedules are persisted, so they survive restarts and redeploys. Manage them at runtime through [`mastra.schedules`](https://mastra.ai/reference/schedules/overview), the canonical create, read, update, and delete (CRUD) surface. The same surface also manages [workflow schedules](https://mastra.ai/docs/workflows/scheduled-workflows) (pass `workflowId` instead of `agentId` to schedule a workflow). > **Note:** Schedules require a [storage](https://mastra.ai/docs/memory/storage) adapter that implements the schedules domain. See the [`mastra.schedules` reference](https://mastra.ai/reference/schedules/overview) for supported adapters and API behavior. ## Quickstart The following schedule runs the `pinger` agent every hour. It has no thread, so each fire is an isolated `agent.generate()` run. ```typescript import { Mastra } from '@mastra/core' import { Agent } from '@mastra/core/agent' import { LibSQLStore } from '@mastra/libsql' const pinger = new Agent({ id: 'pinger', name: 'Pinger', instructions: 'Report the current system status in one sentence.', model: 'openai/gpt-5.5', }) const mastra = new Mastra({ agents: { pinger }, storage: new LibSQLStore({ url: 'file:./mastra.db' }), }) await mastra.schedules.create({ agentId: 'pinger', cron: '0 * * * *', prompt: 'Give me a status update.', }) ``` Mastra starts the scheduler the first time a schedule is created, then fires the agent on the cron you specify. ## Cadence Schedules fire on a cron expression. The `cron` field accepts a standard 5-, 6-, or 7-part cron expression, and it's validated when you create or update the schedule. `croner` nicknames also work, for example `@hourly`, `@daily`, `@weekly`, `@monthly`, and `@midnight`. For day-and-time combinations, write the cron field directly: ```typescript // Every weekday at 9am await mastra.schedules.create({ agentId: 'pinger', cron: '0 9 * * 1-5', prompt: 'Start-of-day check.', }) ``` Set `timezone` to an IANA timezone, for example `America/New_York`, so fire times don't depend on the host's locale. When omitted, the cron resolves against the host's local timezone. For more readable cron construction, you can use a userland builder such as [`cron-time-generator`](https://www.npmjs.com/package/cron-time-generator) and pass its output to `cron`. ## Threadless and threaded schedules An agent schedule fires in one of two modes, decided by whether you pass a `threadId`. ### Threadless Without a `threadId`, each fire is an isolated `agent.generate()` run. Nothing is written to a conversation thread. This is the simplest mode and suits status checks, reports, and other work that doesn't need conversation context. ### Threaded With a `threadId`, the schedule sends a [signal](https://mastra.ai/docs/long-running-agents/signals) into that thread, so the prompt joins the agent's conversation. Threaded schedules require a `resourceId` alongside the `threadId`. ```typescript await mastra.schedules.create({ agentId: 'pinger', cron: '0 9 * * *', prompt: 'Summarize anything new since yesterday.', threadId: 'thread-123', resourceId: 'user-456', }) ``` Threaded schedules accept extra fields that control how the signal behaves, including the signal type, XML tag, tag attributes, and active-or-idle delivery behavior. They mirror the options [`agent.sendSignal()`](https://mastra.ai/docs/long-running-agents/signals) accepts and stay JSON-serializable so they persist with the schedule. These fields require a `threadId`. For the full threaded input shape, see the [agent schedule input reference](https://mastra.ai/reference/schedules/overview). ```typescript await mastra.schedules.create({ agentId: 'pinger', cron: '0 9 * * *', prompt: 'Summarize anything new since yesterday.', threadId: 'thread-123', resourceId: 'user-456', tagName: 'check-in', // renders as <check-in>…</check-in> attributes: { source: 'cron' }, ifActive: { behavior: 'discard' }, // skip if the thread is mid-stream ifIdle: { behavior: 'wake', // wake the agent if the thread is idle streamOptions: { requestContext: { locale: 'en-US' } }, }, }) ``` `providerOptions` are merged into the signal payload on every fire and apply to both threaded and threadless schedules. ## Managing schedules Use `mastra.schedules` for all schedule operations. The service can create, read, update, pause, resume, manually run, and delete schedules. ```typescript const schedule = await mastra.schedules.create({ agentId: 'pinger', cron: '0 * * * *', prompt: 'Status check.', }) await mastra.schedules.pause(schedule.id) await mastra.schedules.resume(schedule.id) await mastra.schedules.run(schedule.id) // Fire once now, off-schedule ``` `pause` and `resume` are durable. `run` fires the schedule once immediately without affecting its cadence. For the complete method list, filters, and patch fields, see the [`mastra.schedules` reference](https://mastra.ai/reference/schedules/overview). ### Workflow schedules The same service creates schedules that run a workflow instead of an agent. Pass `workflowId` and the workflow-shaped fields: ```typescript await mastra.schedules.create({ workflowId: 'daily-report', cron: '0 9 * * *', inputData: { userId: 'system' }, }) ``` Workflow schedules created this way are independent of the declarative `schedule` field on `createWorkflow` — see [scheduled workflows](https://mastra.ai/docs/workflows/scheduled-workflows) for the declarative form and Studio views. ### Custom IDs Pass `id` when you need a predictable handle to look up, update, or delete later. ```typescript await mastra.schedules.create({ id: 'nightly-summary', agentId: 'pinger', cron: '0 9 * * *', prompt: 'Summarize anything new since yesterday.', }) ``` See the [`create(input)` reference](https://mastra.ai/reference/schedules/overview) for ID normalization rules and duplicate ID behavior. ### From the client The same operations are available from `@mastra/client-js` over the `/api/schedules` routes, so you can manage schedules from a separate process or a UI. See the [client-js agent schedules reference](https://mastra.ai/reference/client-js/agents) for the client method list. ## Lifecycle hooks Hooks let you run code at key points in an agent schedule's lifecycle, for example to compute fire-time parameters or react to the outcome. Configure them on the `Mastra` constructor under `schedules`. The hooks are a single flat bundle that runs for every agent's schedules; each hook context carries the firing `agentId`, so branch on it when you need per-agent behavior. Hooks live at the `Mastra` level so they apply to both code-defined and stored agents. ```typescript const mastra = new Mastra({ agents: { pinger }, storage: new LibSQLStore({ url: 'file:./mastra.db' }), schedules: { prepare: async ({ agentId, schedule, trigger }) => { // Return overrides, null to skip this fire, or undefined for defaults return { prompt: `Status as of ${trigger.firedAt.toISOString()}` } }, onFinish: async ({ agentId, outcome, runId }) => { // Runs on any non-error, non-abort outcome }, onError: async ({ agentId, phase, error }) => { // Runs when prepare, the signal, or the agent run threw }, onAbort: async ({ agentId, runId }) => { // Runs when the run was aborted mid-stream }, }, }) ``` The hooks are: - `prepare`: runs before the fire. Return an object to override fire-time parameters such as `prompt` or `threadId`, `null` to skip the fire, or `undefined` to use the stored defaults. - `onFinish`: runs once per trigger that reached a non-error, non-abort terminal state. - `onError`: runs when `prepare`, the signal, or the agent run threw. - `onAbort`: runs when the run was aborted mid-stream. Every hook context includes `agentId` (the agent the schedule fired for) alongside `schedule` and `trigger`. Hook exceptions are caught and logged. They never re-route the worker or trigger another hook. ## Related - [`mastra.schedules`](https://mastra.ai/reference/schedules/overview): API reference for creating and managing schedules. - [Signals](https://mastra.ai/docs/long-running-agents/signals): the delivery mechanism behind threaded schedules. - [Scheduled workflows](https://mastra.ai/docs/workflows/scheduled-workflows): declare a cron schedule on a workflow definition.