openclaw-scheduler 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/AGENTS.md +302 -0
  2. package/BEST-PRACTICES.md +506 -0
  3. package/CHANGELOG.md +82 -0
  4. package/CODE_OF_CONDUCT.md +22 -0
  5. package/CONTEXT.md +26 -0
  6. package/CONTRIBUTING.md +73 -0
  7. package/IMPLEMENTATION_SPEC.md +170 -0
  8. package/INSTALL-ADDITIONAL-HOST.md +333 -0
  9. package/INSTALL-LINUX.md +419 -0
  10. package/INSTALL-WINDOWS.md +305 -0
  11. package/INSTALL.md +364 -0
  12. package/JOB-QUICK-REF.md +222 -0
  13. package/LICENSE +21 -0
  14. package/QUICK-START.md +256 -0
  15. package/README.md +2170 -0
  16. package/SECURITY.md +34 -0
  17. package/UNINSTALL.md +129 -0
  18. package/UPGRADING.md +436 -0
  19. package/agents.js +67 -0
  20. package/approval.js +107 -0
  21. package/backup.js +390 -0
  22. package/bin/openclaw-scheduler.js +138 -0
  23. package/cli.js +1083 -0
  24. package/db.js +122 -0
  25. package/dispatch/529-recovery.mjs +204 -0
  26. package/dispatch/README.md +372 -0
  27. package/dispatch/config.example.json +24 -0
  28. package/dispatch/deliver-watcher.sh +57 -0
  29. package/dispatch/hooks.mjs +171 -0
  30. package/dispatch/index.mjs +1836 -0
  31. package/dispatch/watcher.mjs +1396 -0
  32. package/dispatch-queue.js +112 -0
  33. package/dispatcher-approvals.js +96 -0
  34. package/dispatcher-delivery.js +43 -0
  35. package/dispatcher-maintenance.js +242 -0
  36. package/dispatcher-shell.js +29 -0
  37. package/dispatcher-strategies.js +1280 -0
  38. package/dispatcher-utils.js +81 -0
  39. package/dispatcher.js +855 -0
  40. package/docs/adr-schedule-ownership.md +73 -0
  41. package/docs/gateway-contract.md +904 -0
  42. package/docs/plans/2026-03-09-fix-typescript-types.md +91 -0
  43. package/docs/plans/2026-03-09-test-coverage-gaps.md +83 -0
  44. package/docs/plans/2026-03-10-dispatcher-refactor.md +801 -0
  45. package/docs/trust-architecture.md +266 -0
  46. package/gateway.js +473 -0
  47. package/idempotency.js +119 -0
  48. package/index.d.ts +864 -0
  49. package/index.js +17 -0
  50. package/jobs.js +1224 -0
  51. package/messages.js +357 -0
  52. package/migrate-consolidate.js +694 -0
  53. package/migrate.js +125 -0
  54. package/package.json +130 -0
  55. package/paths.js +79 -0
  56. package/prompt-context.js +94 -0
  57. package/retrieval.js +176 -0
  58. package/runs.js +270 -0
  59. package/scheduler-schema.js +101 -0
  60. package/schema.sql +480 -0
  61. package/scripts/dispatch-cli-utils.mjs +65 -0
  62. package/scripts/inbox-consumer.mjs +288 -0
  63. package/scripts/stuck-detector.sh +18 -0
  64. package/scripts/stuck-run-detector.mjs +333 -0
  65. package/scripts/telegram-webhook-check.mjs +238 -0
  66. package/setup.mjs +724 -0
  67. package/shell-result.js +214 -0
  68. package/task-tracker.js +300 -0
  69. package/team-adapter.js +335 -0
  70. package/v02-runtime.js +599 -0
package/INSTALL.md ADDED
@@ -0,0 +1,364 @@
1
+ # Installing OpenClaw Scheduler on macOS
2
+
3
+ Step-by-step guide to deploy the scheduler on a macOS OpenClaw instance.
4
+
5
+ If you just want the fastest path to a working local install, start with the npm-first flow and [Five-Minute Setup in the README](README.md#five-minute-setup). This document is the full host deployment guide.
6
+
7
+ ---
8
+
9
+ ## Prerequisites
10
+
11
+ | Requirement | Notes |
12
+ |-------------|-------|
13
+ | macOS or Linux | Tested on macOS arm64 |
14
+ | Node.js >= 20 | `node --version` |
15
+ | OpenClaw gateway running | With auth token |
16
+ | Git or SCP access | To clone/copy the repo |
17
+
18
+ ---
19
+
20
+ ## Step 1: Install Scheduler Files
21
+
22
+ ```bash
23
+ cd ~/.openclaw
24
+ git clone https://github.com/amittell/openclaw-scheduler.git scheduler
25
+ cd scheduler
26
+ ```
27
+
28
+ Or copy from an existing host:
29
+ ```bash
30
+ scp -r user@source-host:~/.openclaw/scheduler ~/.openclaw/scheduler
31
+ ```
32
+
33
+ Or npm-first install (no git clone):
34
+ ```bash
35
+ mkdir -p ~/.openclaw/scheduler
36
+ npm install --prefix ~/.openclaw/scheduler openclaw-scheduler@latest
37
+ npm exec --prefix ~/.openclaw/scheduler openclaw-scheduler -- help
38
+ ```
39
+
40
+ Runtime state for npm installs defaults to `~/.openclaw/scheduler/`, not the package directory under `node_modules/`.
41
+
42
+ ---
43
+
44
+ ## Step 2: Install Dependencies
45
+
46
+ If you used the npm-first install path in Step 1, dependencies are already installed; skip to Step 3.
47
+
48
+ ```bash
49
+ cd ~/.openclaw/scheduler
50
+ npm install
51
+ ```
52
+
53
+ Installs `better-sqlite3` (native, compiles for your arch) and `croner`.
54
+
55
+ If `better-sqlite3` fails: `xcode-select --install` (macOS).
56
+
57
+ If Node changes later under this checkout, rebuild the native module before restarting the scheduler:
58
+
59
+ ```bash
60
+ cd ~/.openclaw/scheduler
61
+ npm rebuild better-sqlite3
62
+ ```
63
+
64
+ Typical cases:
65
+ - `brew upgrade node` on macOS
66
+ - switching major Node versions with `nvm`, `fnm`, or `asdf`
67
+ - distro package upgrades that replace the Node binary
68
+
69
+ On Linux, install build deps first:
70
+ ```bash
71
+ sudo apt install build-essential python3 # Ubuntu/Debian
72
+ sudo dnf install gcc gcc-c++ make python3 # Fedora/RHEL
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Step 2.5: Fix macOS shell PATH and completions
78
+
79
+ If you use `zsh` on macOS, make sure Homebrew is available to non-interactive shells too.
80
+
81
+ This matters for commands like:
82
+ - `ssh host 'node cli.js status'`
83
+ - remote admin scripts
84
+ - one-off maintenance commands that do not run inside an interactive terminal
85
+
86
+ `~/.zprofile` is not enough for that case. Put the minimal PATH bootstrap in `~/.zshenv`:
87
+
88
+ ```zsh
89
+ # ~/.zshenv — sourced by all zsh instances, including non-interactive SSH commands
90
+ if [ -x /opt/homebrew/bin/brew ]; then
91
+ eval "$(/opt/homebrew/bin/brew shellenv)"
92
+ fi
93
+
94
+ export PATH="$HOME/.local/bin:$HOME/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
95
+ ```
96
+
97
+ If you load OpenClaw completions in `~/.zshrc`, run `compinit` before sourcing them:
98
+
99
+ ```zsh
100
+ autoload -Uz compinit
101
+ compinit
102
+
103
+ if [ -f "$HOME/.openclaw/completions/openclaw.zsh" ]; then
104
+ source "$HOME/.openclaw/completions/openclaw.zsh"
105
+ fi
106
+ ```
107
+
108
+ Avoid version-pinned Node PATH entries like `/opt/homebrew/opt/node@22/bin`. Use `/opt/homebrew/bin/node` instead so normal `brew upgrade node` keeps working.
109
+
110
+ Verify:
111
+
112
+ ```bash
113
+ ssh "$HOST" 'command -v node && node -v'
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Step 3: Run Tests
119
+
120
+ ```bash
121
+ SCHEDULER_DB=:memory: node test.js
122
+ ```
123
+
124
+ **All tests must pass before proceeding.**
125
+
126
+ ---
127
+
128
+ ## Step 4: Enable Chat Completions on Gateway
129
+
130
+ ```bash
131
+ openclaw config set gateway.http.endpoints.chatCompletions.enabled true
132
+ openclaw gateway restart
133
+ ```
134
+
135
+ Verify:
136
+ ```bash
137
+ curl -s -o /dev/null -w "%{http_code}" \
138
+ -X POST \
139
+ -H "Authorization: Bearer YOUR_GATEWAY_TOKEN" \
140
+ -H "Content-Type: application/json" \
141
+ -d '{"model":"openclaw:main","messages":[{"role":"user","content":"reply OK"}]}' \
142
+ http://127.0.0.1:18789/v1/chat/completions
143
+ ```
144
+
145
+ Expected: `200`
146
+
147
+ ---
148
+
149
+ ## Step 5: Migrate Jobs from OC Cron
150
+
151
+ ```bash
152
+ cd ~/.openclaw/scheduler
153
+ node migrate.js
154
+ ```
155
+
156
+ This imports jobs from `~/.openclaw/cron/jobs.json` → SQLite, converting schedule formats:
157
+ - `cron` → direct expression
158
+ - `every` → approximate cron (e.g., 30min → `*/30 * * * *`)
159
+ - `at` → one-shot with `delete_after_run=true`
160
+
161
+ Good default approach:
162
+ - if the old job was just a script, keep it as a `shell` job
163
+ - if the old job was really “run a prompt on a schedule,” rewrite it as an `isolated` job
164
+ - if two jobs depended on manual ordering, convert them into a parent/child chain instead of two independent schedules
165
+
166
+ For copy-paste examples, see [Starter Recipes in the README](README.md#starter-recipes) and [Common Migrations](README.md#common-migrations).
167
+
168
+ Verify:
169
+ ```bash
170
+ node cli.js jobs list
171
+ node cli.js status
172
+ ```
173
+
174
+ ---
175
+
176
+ ## Step 6: Disable OC Built-in Cron
177
+
178
+ ```bash
179
+ openclaw cron list
180
+ # For each enabled job:
181
+ openclaw cron edit <job-id> --disable
182
+ openclaw config set cron.enabled false
183
+ ```
184
+
185
+ Also set `OPENCLAW_SKIP_CRON=1` in your OpenClaw gateway service environment (launchctl/systemd/pm2), then restart the gateway.
186
+
187
+ Verify: `openclaw cron list` shows no enabled jobs (or "No cron jobs").
188
+
189
+ ---
190
+
191
+ ## Step 7: Disable OC Heartbeat
192
+
193
+ ```bash
194
+ openclaw config set agents.defaults.heartbeat.every "0m"
195
+ # If you have per-agent heartbeat overrides, set/remove those too:
196
+ # agents.list[].heartbeat.every = "0m"
197
+ openclaw gateway restart
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Step 8: Choose a macOS launchd mode
203
+
204
+ OpenClaw Scheduler supports both common macOS service styles:
205
+
206
+ - **LaunchAgent**: best for a personal Mac that auto-logs in and should run the scheduler inside your user session
207
+ - **LaunchDaemon**: best for a headless Mac or for starting before login
208
+
209
+ The simplest path is to let the setup wizard install the launchd plist for you:
210
+
211
+ ```bash
212
+ cd ~/.openclaw/scheduler
213
+ node setup.mjs --service-mode agent
214
+ # or:
215
+ node setup.mjs --service-mode daemon
216
+ ```
217
+
218
+ If you installed from npm:
219
+
220
+ ```bash
221
+ npm exec --prefix ~/.openclaw/scheduler openclaw-scheduler -- setup --service-mode agent
222
+ # or:
223
+ npm exec --prefix ~/.openclaw/scheduler openclaw-scheduler -- setup --service-mode daemon
224
+ ```
225
+
226
+ What each mode does:
227
+
228
+ - `agent` writes `~/Library/LaunchAgents/ai.openclaw.scheduler.plist` and bootstraps `gui/$UID/ai.openclaw.scheduler`
229
+ - `daemon` writes `/Library/LaunchDaemons/ai.openclaw.scheduler.plist` and bootstraps `system/ai.openclaw.scheduler`
230
+
231
+ Verify the mode you chose:
232
+
233
+ ```bash
234
+ # LaunchAgent
235
+ launchctl print gui/$UID/ai.openclaw.scheduler
236
+
237
+ # LaunchDaemon
238
+ sudo launchctl print system/ai.openclaw.scheduler
239
+
240
+ # Either mode
241
+ sleep 5 && tail -5 /tmp/openclaw-scheduler.log
242
+ ```
243
+
244
+ ---
245
+
246
+ ## Step 9: Smoke Tests
247
+
248
+ > **Note:** These smoke test commands use direct file imports and are for the git-clone install path. For npm installs, use `openclaw-scheduler` CLI commands instead.
249
+
250
+ ### Isolated dispatch
251
+ ```bash
252
+ cd ~/.openclaw/scheduler
253
+ node --input-type=module -e "
254
+ import { initDb, getDb } from './db.js';
255
+ import { createJob } from './jobs.js';
256
+ initDb();
257
+ const job = createJob({
258
+ name: 'Smoke Test',
259
+ schedule_cron: '0 0 31 2 *',
260
+ payload_message: 'Reply with exactly: SCHEDULER_OK',
261
+ delivery_mode: 'none',
262
+ delete_after_run: true,
263
+ origin: 'system',
264
+ run_timeout_ms: 300000,
265
+ });
266
+ getDb().prepare(\"UPDATE jobs SET next_run_at = datetime('now', '-1 second') WHERE id = ?\").run(job.id);
267
+ console.log('Created smoke test:', job.id);
268
+ "
269
+ sleep 20 && tail -10 /tmp/openclaw-scheduler.log
270
+ ```
271
+
272
+ Look for: `Dispatching: Smoke Test` → `Completed: Smoke Test`
273
+
274
+ ### Telegram delivery
275
+ ```bash
276
+ node --input-type=module -e "
277
+ import { initDb, getDb } from './db.js';
278
+ import { createJob } from './jobs.js';
279
+ initDb();
280
+ const job = createJob({
281
+ name: 'Telegram Test',
282
+ schedule_cron: '0 0 31 2 *',
283
+ payload_message: 'Confirm scheduler is working. Send a brief greeting.',
284
+ delivery_mode: 'announce',
285
+ delivery_channel: 'telegram',
286
+ delivery_to: 'YOUR_CHAT_ID',
287
+ delete_after_run: true,
288
+ origin: 'system',
289
+ run_timeout_ms: 300000,
290
+ });
291
+ getDb().prepare(\"UPDATE jobs SET next_run_at = datetime('now', '-1 second') WHERE id = ?\").run(job.id);
292
+ console.log('Created Telegram test:', job.id);
293
+ "
294
+ ```
295
+
296
+ You should receive a Telegram message within 30 seconds.
297
+
298
+ ---
299
+
300
+ ## Step 10: Review Migrated Jobs
301
+
302
+ ```bash
303
+ node cli.js jobs list
304
+ ```
305
+
306
+ - Disable expired one-shot jobs: `node cli.js jobs disable <id>`
307
+ - Delete unwanted jobs: `node cli.js jobs delete <id>`
308
+ - Adjust timeouts: `node cli.js jobs update <id> '{"run_timeout_ms":600000}'`
309
+ - Verify cron conversions are correct for `every`-based schedules
310
+
311
+ ---
312
+
313
+ ## Step 11: Verify First Real Job
314
+
315
+ Wait for the next scheduled job and confirm:
316
+ ```bash
317
+ tail -f /tmp/openclaw-scheduler.log
318
+ # Or after it fires:
319
+ node cli.js runs list <job-id>
320
+ ```
321
+
322
+ ---
323
+
324
+ ## Rollback
325
+
326
+ If anything goes wrong:
327
+
328
+ ```bash
329
+ # 1. Stop scheduler
330
+ launchctl bootout gui/$UID/ai.openclaw.scheduler # if using LaunchAgent
331
+ sudo launchctl bootout system/ai.openclaw.scheduler # if using LaunchDaemon
332
+
333
+ # 2. Re-enable OC cron
334
+ openclaw cron edit <job-id> --enable # for each job
335
+ openclaw config set cron.enabled true
336
+ # remove OPENCLAW_SKIP_CRON=1 from gateway service env
337
+
338
+ # 3. Re-enable heartbeat
339
+ openclaw config set agents.defaults.heartbeat.every "5m"
340
+ openclaw gateway restart
341
+ ```
342
+
343
+ For a complete removal (deleting all data), see [UNINSTALL.md](UNINSTALL.md).
344
+
345
+ ---
346
+
347
+ ## Upgrading
348
+
349
+ Already have the scheduler installed and need to update to a newer version? See [UPGRADING.md](UPGRADING.md).
350
+
351
+ ---
352
+
353
+ ## Validation Checklist
354
+
355
+ - [ ] `SCHEDULER_DB=:memory: node test.js` -- all passing, 0 failed
356
+ - [ ] `node cli.js status` → shows jobs, 0 stale
357
+ - [ ] `launchctl print gui/$UID/ai.openclaw.scheduler` or `sudo launchctl print system/ai.openclaw.scheduler` → running
358
+ - [ ] Log file has startup lines, no errors
359
+ - [ ] OC cron → all disabled
360
+ - [ ] OC heartbeat → `0m`
361
+ - [ ] Chat completions → 200
362
+ - [ ] Smoke test → dispatched + completed in log
363
+ - [ ] Telegram test → message received
364
+ - [ ] First real job → fires on schedule
@@ -0,0 +1,222 @@
1
+ # Job Quick Reference
2
+
3
+ Copy-paste patterns for common scheduler jobs.
4
+
5
+ ## Shell job with cron schedule
6
+
7
+ ```json
8
+ {
9
+ "name": "Daily Backup",
10
+ "schedule_cron": "0 2 * * *",
11
+ "schedule_tz": "America/New_York",
12
+ "session_target": "shell",
13
+ "payload_kind": "shellCommand",
14
+ "payload_message": "/usr/local/bin/backup.sh",
15
+ "run_timeout_ms": 600000,
16
+ "delivery_mode": "announce",
17
+ "delivery_channel": "telegram",
18
+ "delivery_to": "YOUR_CHAT_ID",
19
+ "origin": "system"
20
+ }
21
+ ```
22
+
23
+ ## Agent task (isolated session)
24
+
25
+ ```json
26
+ {
27
+ "name": "Morning Briefing",
28
+ "schedule_cron": "0 8 * * 1-5",
29
+ "schedule_tz": "America/New_York",
30
+ "session_target": "isolated",
31
+ "agent_id": "main",
32
+ "payload_kind": "systemEvent",
33
+ "payload_message": "Prepare the morning briefing with overnight alerts.",
34
+ "run_timeout_ms": 300000,
35
+ "delivery_mode": "announce-always",
36
+ "delivery_channel": "telegram",
37
+ "delivery_to": "YOUR_CHAT_ID",
38
+ "origin": "YOUR_CHAT_ID"
39
+ }
40
+ ```
41
+
42
+ ## Main session event (inject into persistent session)
43
+
44
+ ```json
45
+ {
46
+ "name": "Pending Acks Check",
47
+ "schedule_cron": "*/30 * * * *",
48
+ "session_target": "main",
49
+ "agent_id": "main",
50
+ "payload_kind": "systemEvent",
51
+ "payload_message": "Check for unacknowledged messages and follow up.",
52
+ "run_timeout_ms": 120000,
53
+ "delivery_mode": "none",
54
+ "origin": "system"
55
+ }
56
+ ```
57
+
58
+ ## One-shot job (run once at a specific time)
59
+
60
+ ```bash
61
+ openclaw-scheduler jobs add '{
62
+ "name": "Deploy v2.1",
63
+ "session_target": "shell",
64
+ "payload_kind": "shellCommand",
65
+ "payload_message": "deploy.sh v2.1",
66
+ "run_timeout_ms": 600000,
67
+ "delivery_mode": "announce-always",
68
+ "delivery_channel": "telegram",
69
+ "delivery_to": "YOUR_CHAT_ID",
70
+ "origin": "system"
71
+ }' --at '2026-04-01T14:00:00-04:00'
72
+ ```
73
+
74
+ Or with relative time:
75
+
76
+ ```bash
77
+ openclaw-scheduler jobs add '{ ... }' --in '30m'
78
+ openclaw-scheduler jobs add '{ ... }' --in '2h'
79
+ ```
80
+
81
+ ## Workflow chain (parent triggers child)
82
+
83
+ ```json
84
+ [
85
+ {
86
+ "name": "Nightly Score Capture",
87
+ "schedule_cron": "30 0 * * *",
88
+ "session_target": "shell",
89
+ "payload_kind": "shellCommand",
90
+ "payload_message": "capture-scores.sh",
91
+ "run_timeout_ms": 300000,
92
+ "delivery_mode": "announce",
93
+ "delivery_channel": "telegram",
94
+ "delivery_to": "YOUR_CHAT_ID",
95
+ "origin": "system"
96
+ },
97
+ {
98
+ "name": "Auto-Settle Bets",
99
+ "parent_id": "<SCORE_CAPTURE_JOB_ID>",
100
+ "trigger_on": "success",
101
+ "session_target": "shell",
102
+ "payload_kind": "shellCommand",
103
+ "payload_message": "settle-bets.sh",
104
+ "run_timeout_ms": 300000,
105
+ "delivery_mode": "announce",
106
+ "delivery_channel": "telegram",
107
+ "delivery_to": "YOUR_CHAT_ID",
108
+ "origin": "system"
109
+ }
110
+ ]
111
+ ```
112
+
113
+ Create parent first, then child with `parent_id` set to the parent's ID.
114
+
115
+ ## Job with retries
116
+
117
+ ```json
118
+ {
119
+ "name": "API Sync",
120
+ "schedule_cron": "0 */4 * * *",
121
+ "session_target": "shell",
122
+ "payload_kind": "shellCommand",
123
+ "payload_message": "sync-api.sh",
124
+ "run_timeout_ms": 120000,
125
+ "max_retries": 3,
126
+ "delivery_mode": "announce",
127
+ "delivery_channel": "telegram",
128
+ "delivery_to": "YOUR_CHAT_ID",
129
+ "origin": "system"
130
+ }
131
+ ```
132
+
133
+ ## Job with approval gate
134
+
135
+ ```json
136
+ {
137
+ "name": "Production Deploy",
138
+ "session_target": "shell",
139
+ "payload_kind": "shellCommand",
140
+ "payload_message": "deploy-prod.sh",
141
+ "run_timeout_ms": 600000,
142
+ "approval_required": true,
143
+ "approval_timeout_s": 3600,
144
+ "delivery_mode": "announce-always",
145
+ "delivery_channel": "telegram",
146
+ "delivery_to": "YOUR_CHAT_ID",
147
+ "origin": "system"
148
+ }
149
+ ```
150
+
151
+ Approve or reject:
152
+
153
+ ```bash
154
+ openclaw-scheduler jobs approve <id>
155
+ openclaw-scheduler jobs reject <id> "not ready yet"
156
+ ```
157
+
158
+ ## Multi-agent job (target a specific agent)
159
+
160
+ ```json
161
+ {
162
+ "name": "Ops Agent Task",
163
+ "schedule_cron": "0 9 * * *",
164
+ "session_target": "isolated",
165
+ "agent_id": "ops",
166
+ "payload_kind": "systemEvent",
167
+ "payload_message": "Check infrastructure health.",
168
+ "run_timeout_ms": 300000,
169
+ "delivery_mode": "announce-always",
170
+ "delivery_channel": "telegram",
171
+ "delivery_to": "YOUR_CHAT_ID",
172
+ "origin": "YOUR_CHAT_ID"
173
+ }
174
+ ```
175
+
176
+ ## Trigger conditions
177
+
178
+ ```json
179
+ { "trigger_on": "success" }
180
+ { "trigger_on": "failure" }
181
+ { "trigger_on": "complete" }
182
+ { "trigger_on": "success", "trigger_condition": "contains:DEPLOYED" }
183
+ { "trigger_on": "success", "trigger_condition": "regex:status:\\s*healthy" }
184
+ { "trigger_on": "success", "trigger_delay_s": 60 }
185
+ ```
186
+
187
+ ## Field reference
188
+
189
+ | Field | Type | Required | Description |
190
+ |-------|------|----------|-------------|
191
+ | `name` | string | yes | Job name |
192
+ | `schedule_cron` | string | yes* | Cron expression (5-field). *Not needed for triggered children or at-jobs |
193
+ | `schedule_tz` | string | no | Timezone (default: UTC) |
194
+ | `session_target` | string | yes | `shell`, `isolated`, or `main` |
195
+ | `agent_id` | string | no | Target agent (default: `main`) |
196
+ | `payload_kind` | string | yes | `shellCommand`, `systemEvent`, or `agentTurn` |
197
+ | `payload_message` | string | yes | Shell command or agent prompt |
198
+ | `payload_model` | string | no | Model override for agent tasks |
199
+ | `run_timeout_ms` | integer | yes | Max run duration in ms (no default) |
200
+ | `delivery_mode` | string | no | `none`, `announce`, `announce-always` |
201
+ | `delivery_channel` | string | no | Channel name (telegram, discord, etc.) |
202
+ | `delivery_to` | string | no | Chat ID, channel ID, or @alias |
203
+ | `origin` | string | yes (root jobs only; child jobs inherit) | Source chat ID or `system` |
204
+ | `parent_id` | string | no | Parent job ID (for chains) |
205
+ | `trigger_on` | string | no | `success`, `failure`, `complete` |
206
+ | `trigger_condition` | string | no | `contains:X` or `regex:X` |
207
+ | `trigger_delay_s` | integer | no | Delay before trigger fires |
208
+ | `max_retries` | integer | no | Retry count on failure |
209
+ | `overlap_policy` | string | no | `allow`, `skip`, `queue` |
210
+ | `approval_required` | boolean | no | Require HITL approval |
211
+ | `approval_timeout_s` | integer | no | Approval window in seconds |
212
+ | `enabled` | integer | no | 1 (enabled) or 0 (disabled) |
213
+
214
+ For the full field list, run `openclaw-scheduler schema jobs`.
215
+
216
+ ## Delivery channels
217
+
218
+ All channels supported by the OpenClaw gateway work with the scheduler:
219
+ Telegram, Discord, WhatsApp, Signal, iMessage, and Slack.
220
+
221
+ Examples in this document use `telegram` as the delivery_channel.
222
+ Replace with your channel of choice.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenClaw Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.