Runyard Docs
Concepts

Schedules

Cron and one-shot triggers that create ordinary workflow runs on a cadence.

A schedule runs a workflow automatically: either recurring on a cron cadence or once at a fixed runAt timestamp. Each fire creates a completely ordinary run with the schedule's stored input — it appears in run lists, honors the workflow's approval policy, and is executed by whatever runner matches.

Cron expressions and timezones

Runyard uses standard 5-field cron (minute hour day-of-month month day-of-week) with ranges (a-b), lists (a,b,c), steps (*/n, a-b/n), month/weekday names (jan..dec, sun..sat), and the aliases @yearly, @monthly, @weekly, @daily, @hourly. There is no seconds field — the Hub ticks at minute granularity.

Every schedule has an IANA timezone (default UTC); the expression is evaluated against wall-clock time in that zone, so DST shifts are honored.

# Validate an expression and see the next fire times before saving anything
curl -H "Authorization: Bearer $RUNYARD_TOKEN" \
  "https://hub.example.com/api/schedules/preview?cron=0%209%20*%20*%20mon-fri&timezone=Europe/Rome"

The preview returns a human-readable description plus the next fire instants — nothing is created.

One-shot schedules

Provide runAt (an ISO timestamp) instead of cron to fire exactly once. A schedule takes one or the other.

Schedules from board definitions

A portable board definition can carry a schedules[] array. Importing the definition creates each listed schedule keyed by board:<slug>:<schedule-slug> so re-imports reconcile in-place instead of duplicating cron jobs. The optional laneId on a definition schedule marks which lane's trigger the schedule backs. The schedule itself remains durable Hub state; Git ships import/export mechanics, not concrete schedule cadences or product defaults.

Enable, disable, run now

  • Disable stops a schedule from firing without deleting it; enable resumes the cadence. Both are admin actions.
  • Run now fires the schedule immediately without changing its cadence — useful for testing input before the next scheduled fire.

Each schedule tracks nextRunAt, lastRunAt, the last run id, and the last run's current terminal status, all visible on the Schedules page (#schedules) and in the API. Enabled schedules must target an enabled workflow. If a workflow is disabled later, RunYard fails safe: dependent enabled schedules are atomically auto-disabled, keep their history, and expose state: "broken", brokenReason, disabledReason, and operatorAction in API/MCP/Web payloads. Re-enable only after editing the schedule to an enabled workflow.

What a fire produces

Every fire dispatches a normal run whose origin identifies the schedule:

{ "type": "schedule", "label": "schedule: Nightly digest", "scheduleId": "sch_123", "scheduleName": "Nightly digest", "trigger": "ticker" }

(trigger is ticker for cadence fires, manual for run-now.) The run also gets a run.scheduled event recording the schedule, cron, and timezone. If the workflow's approval policy requires it, the run starts in waiting_approval like any other run. External automation that wants first-class Scheduled provenance should call run_schedule_now; calling run_workflow directly remains a token/API/MCP-origin run.

Repair and Reconciliation

Startup runs an idempotent reconciliation pass after migrations and catalog seeding. It auto-disables any legacy enabled schedule whose workflow is missing or disabled, writes lastStatus: "broken_reference", records an audit entry, and leaves schedule/run history intact. This is the live-data repair path for stale schedules such as old nightly jobs pointing at disabled workflows; no retargeting or deletion is performed.

Weekend Maintenance

RunYard seeds three seed-owned internal schedules in Europe/Paris:

ScheduleCronWorkflow
Reliability Sheriff0 10 * * 6weekend-reliability-sheriff
Quality Gardener0 10 * * 0weekend-quality-gardener
Weekend maintenance digest0 18 * * 0weekend-maintenance-digest

The Reliability Sheriff runs as a Smithers workflow on a runyard runner. It audits the previous seven days of failures, retries, stuck or paused runs, stale decisions/Telegram cards, cleanup intents, runner and schedule drift, DB integrity signals, and the disposable pnpm dogfood:recovery canary. After the runner returns bounded redacted evidence, the Hub may repair only reversible housekeeping such as expired cleanup leases or runner active-run counters. Non-obvious defects become at most one deduplicated maintenance Factory Item.

The Quality Gardener also runs as a Smithers workflow on a runyard runner. It executes fixed bounded probes for test history and skipped/slow tests, coverage availability, lint/typecheck, dependency/security status, dead-code indicators, and OpenAPI/CLI/MCP/docs/generated-client drift. Missing coverage is reported as blocked, not clean. After completion, Learning Ledger recommendations are backtested/promoted under a hard cap of two, at most one gated implementation run may be queued, and migrations, auth, API semantics, or product-direction changes fail closed into decision work.

The Sunday evening digest is idempotent. It summarizes meaningful weekend checks, repairs, evidence, releases, and genuine decisions; routine no-op weekends are suppressed so schedules do not create decision spam.

API & MCP

EndpointMCP toolNotes
GET /api/scheduleslist_schedulesIncludes next/last run and a readable preview.
GET /api/schedules/previewpreview_scheduleQuery: cron, timezone.
GET /api/schedules/{id}get_schedule
POST /api/schedulescreate_scheduleAdmin. Body: name, workflowSlug, cron or runAt, timezone, input, enabled.
PATCH /api/schedules/{id}update_scheduleAdmin.
POST /api/schedules/{id}/enableenable_scheduleAdmin.
POST /api/schedules/{id}/disabledisable_scheduleAdmin.
POST /api/schedules/{id}/run-nowrun_schedule_nowFires immediately; rate-limited.
DELETE /api/schedules/{id}delete_scheduleAdmin.

On this page