<!-- SPDX-License-Identifier: Apache-2.0 -->

# 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 = 86400
```

### Job fields

| Field | Default | Description |
| --- | --- | --- |
| `id` | — | Stable job identifier (required). |
| `prompt` | — | Job prompt (required). |
| `delivery` | `"announce"` | `announce`, `webhook`, or `none`. |
| `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-field cron expression.
- `at` — an ISO-8601 one-shot timestamp.

The cron expression supports `*`, comma lists, ranges (`a-b`), and steps (`/`) across minute, hour, day-of-month, month, and day-of-week fields.

### 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 and announces the result there.

`announce` delivers output to the resolved target.
`webhook` POSTs `{ agentSlug, content, jobId }` to `webhookUrl` and treats a 2xx response as success.
`none` runs without delivering.

The `schedule` tool creates one-shot isolated jobs dynamically.

## 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` | Use channel indicators. |

A heartbeat reads `tasks/HEARTBEAT.md`; if the file is absent or empty, the heartbeat is skipped.
Heartbeats deliver output only when the checklist result differs from `HEARTBEAT_OK` or `showOk` is enabled.

## Reload

Changes to `cron.toml` and `heartbeat.toml` are applied live while the runtime is running.
