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:
- The manifest declares a default
schedule(and optionallyschedule_tz). - Someone registers the schedule — either through Cori Console or by writing an entry into
~/.cori/schedules/directly. Registration is explicit: aschedule: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)
│ │ │ │ │
* * * * *| Expression | Meaning |
|---|---|
0 3 * * * | Every day at 3:00 AM |
0 9 * * 1-5 | Weekdays 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
}
EOFThe 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 workprocess (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 listScheduled runs appear in the run list with trigger: schedule in their trace. Filter by workflow in Cori Console's Runs view.

