Scheduling
config/cron.toml and config/heartbeat.toml let an agent run turns on a schedule.
Cron jobs
config/cron.toml defines a [[jobs]] array.
toml
[[jobs]]
id = "daily-report"
prompt = "Write a status report and send it."
delivery = "announce"
execution = "isolated"
enabled = true
target = "last"
[jobs.schedule]
every = 86400Job fields
| Field | Default | Description |
|---|---|---|
id | — | Stable job identifier (required). |
prompt | — | Job prompt (required). |
delivery | "announce" | announce, webhook, or none; webhook requires isolated execution. |
execution | "isolated" | isolated or main. |
enabled | true | Whether the job runs. |
target | "last" | Target session for announce delivery. |
provider | — | Provider override. |
model | — | Model override. |
webhookUrl | — | Absolute webhook URL; required for webhook delivery. |
schedule | — | Exactly one of every, cron, or at (required). |
Schedules
every— interval in seconds, minimum 60.cron— a five-, six-, or seven-field cron expression.at— an ISO-8601 one-shot timestamp.
Five fields are minute hour day-of-month month day-of-week, with seconds fixed to zero. Six fields add leading second; seven fields also add trailing year. An omitted year matches every year. Fields support *, comma lists, ranges (a-b), and steps (/). Expressions are parsed during dry-run and startup configuration loading.
Delivery and execution
isolated execution runs the prompt in a fresh internal session and delivers the captured response. main execution runs the prompt in the target session; announce sends responses there and none suppresses response delivery.
announce delivers output to the resolved target. webhook is supported only with execution = "isolated": it POSTs { agentSlug, content, jobId } to webhookUrl and treats a 2xx response as success. none runs without delivering.
Configurations combining execution = "main" with delivery = "webhook" are rejected. To retain webhook delivery, change execution to "isolated"; to retain the main session's history, change delivery to "announce" or "none".
The schedule tool creates one-shot isolated jobs dynamically for ordinary sessions. In remote sessions, it creates caller-attested main-session jobs against an owned remote target. Replacing an unstarted remote reminder with the same ID and caller fences the old revision; a consumed remote one-shot cannot execute again.
Heartbeats
config/heartbeat.toml controls periodic self-checks.
toml
enabled = true
interval = 1800
target = "last"
[visibility]
showOk = false
showAlerts = true
useIndicator = true| Field | Default | Description |
|---|---|---|
enabled | false | Whether heartbeats run. |
interval | 1800 | Interval in seconds. |
target | "last" | Target session. |
provider | — | Provider override. |
model | — | Model override. |
activeHours | — | Optional start/end/timezone window. |
visibility.showOk | false | Show successful heartbeat output. |
visibility.showAlerts | true | Show alert output. |
visibility.useIndicator | true | Accepted setting; currently has no effect. |
A heartbeat reads tasks/HEARTBEAT.md; if the file is absent or empty, the heartbeat is skipped. Responses equal to HEARTBEAT_OK after trimming are delivered only when showOk is enabled; other responses are delivered only when showAlerts is enabled. useIndicator is retained in configuration, but the runner does not currently emit channel indicators.
Reload
Changes to cron.toml and heartbeat.toml are applied live while the runtime is running.