Cori
Guides

Schedule a workflow

Add a cron schedule to a workflow manifest, register it via Cori Console (or the schedule store), and let the cron driver fire it.

Two things have to happen for a workflow to run on a schedule:

  1. The manifest declares a default schedule (and optionally schedule_tz).
  2. Someone registers the schedule — either through Cori Console or by writing an entry into ~/.cori/schedules/ directly. Registration is explicit: a schedule: field in the manifest is inert until something records its intent.

The cron driver — inside Cori Console (desktop app) or cori work — then fires registered schedules whose identity matches its task queue.

1. Add a schedule to the manifest

Add schedule (a cron expression) and schedule_tz (an IANA timezone) to the workflow's manifest frontmatter:

---
id: translate-product-sheets-fr
name: Translate product sheets to French
description: Reads a product CSV and translates descriptions to French.
version: "1.0.0"
created: "2025-01-15"
schedule: "0 3 * * *"
schedule_tz: "Europe/Paris"
parameters:
  - name: input_file
    type: path
    default: ./products.csv
---

This declares 3:00 AM Paris time daily as the workflow's default cadence. The fields are validated at manifest-parse time — invalid cron or unknown IANA timezone is a parse error.

Cron syntax

5-field POSIX (minute hour dom month dow) or 6-field with a leading seconds column (sec min hour dom month dow).

┌───── minute (0-59)
│ ┌───── hour (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌───── month (1-12)
│ │ │ │ ┌───── day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * *
ExpressionMeaning
0 3 * * *Every day at 3:00 AM
0 9 * * 1-5Weekdays at 9:00 AM
0 */6 * * *Every 6 hours
30 8 1 * *First of each month at 8:30 AM
*/30 * * * * *Every 30 seconds (6-field — note the leading seconds column)

2. Register the schedule

Open the Cori Console desktop app, go to Schedules, click New schedule, enter the workflow source. Cron + timezone fall back to the manifest defaults if you leave them blank. The app writes ~/.cori/schedules/<id>.json (id = sha256(source + schedule)[..12]) tagged with your current identity.

You can also create the file by hand:

mkdir -p ~/.cori/schedules
cat > ~/.cori/schedules/$(echo -n "./translate_product_sheets_fr0 3 * * *" | shasum -a 256 | cut -c1-12).json <<'EOF'
{
  "source": "./translate_product_sheets_fr",
  "schedule": "0 3 * * *",
  "schedule_tz": "Europe/Paris",
  "identity": { "Person": { "user_id": "<your-os-user>" } },
  "enabled": true
}
EOF

The cron driver picks it up on its next 30-second tick.

3. Keep a driver online

The cron driver scans ~/.cori/schedules/ every 30 seconds. For each enabled entry whose identity matches its task queue, it fires the workflow on the due cron tick via cori_run::run_workflow (the same code path as cori run).

A driver is online whenever one of these is running:

  • The Cori Console desktop app (the preferred path — tray-resident, schedules + the worker stay alive as long as the app isn't quit).
  • A terminal cori work process (headless; useful on org-infra machines).

Missed fires while no driver is online are lost. v1 does not catch up — if the laptop sleeps through 3:00 AM, the 3:00 AM run does not happen. For unattended schedules, keep Cori Console (or cori work) running on a machine that stays online, or use the operating system's keep-alive (launchd, systemd, etc.).

Identity gating

Each schedule belongs to the identity of whoever created it (your OS user → cori.user.<you>, or a service pool → cori.service.<pool>). Only a driver running under the same identity fires it. To manage shared-pool schedules, run cori work --shared <pool> on the pool host — Cori Console only manages your personal identity's schedules.

Scheduled parameters

Scheduled fires use empty parameters in v1 — the cron driver invokes cori_run::run_workflow with params: {}. The workflow then resolves defaults from the manifest's parameters: block at start time, so every parameter that doesn't have a manifest default will arrive as undefined. For scheduled workflows, give every parameter a sensible default in the manifest.

Checking scheduled run history

cori runs list

Scheduled runs appear in the run list with trigger: schedule in their trace. Filter by workflow in Cori Console's Runs view.

On this page