@plugin.cron(spec) runs a task on a 5-field cron schedule in UTC. Use this when you want a job to fire at a wall-clock time (e.g. Monday 09:00) instead of a fixed interval since boot.
Spec format: "minute hour day-of-month month day-of-week" — each field supports *, */N, N, N,M,…, N-M, N-M/S. Day-of-week is 0=Sunday through 6=Saturday.
@plugin.cron("0 9 * * 1") # every Monday at 09:00 UTC
def weekly_report(ctx: Context):
ctx.log("Sending weekly report")
@plugin.cron("*/15 * * * *") # every 15 minutes
def refresh_cache(ctx: Context):
ctx.kv.increment("cache_refreshes")
@plugin.cron("30 0 1 * *") # 00:30 UTC on the 1st of each month
def monthly_rollup(ctx: Context):
...
To run in production, each task also needs a manifest entry whose name matches the function (the platform reads schedules from the manifest, not your code):
"cron": [
{"spec": "0 9 * * 1", "name": "weekly_report"},
{"spec": "*/15 * * * *", "name": "refresh_cache"}
]
- Specs firing more often than every 5 minutes are rejected at upload, and a manifest carries at most 5 cron entries.
yourbot validateapplies the same checks and warns when a decorated task has no matching manifest entry (it would never run in production). - Delivery rides the normal event pipeline per installed server: your handler gets a tenant-scoped
ctx, delivery is at-least-once (rare replays possible — keep handlers idempotent or guard withctx.ephemeral.dedup), and a missed tick is not replayed. - Invalid specs raise
ValueErrorat registration and failyourbot validate— you'll see the error before upload, not silently at the first miss.