GitHubBlog

Search Documentation

Search for a page in the docs

Cron Scheduling

The cron engine is the scheduler behind all autonomous behavior in OpenAlice. It manages timed jobs and fires events into the EventLog when they're due. The engine itself doesn't run the jobs — it just announces them. Listeners (CronListener, Heartbeat, SnapshotScheduler) decide what to do.

Schedule Types

TypeFormatExampleDescription
atISO timestamp"2025-06-01T14:00:00Z"One-shot. Auto-disables after firing.
everyDuration string"30m", "2h", "5m30s"Recurring interval.
cron5-field expression"0 9 * * 1-5"Standard cron (minute, hour, dom, month, dow).

Duration strings support hours (h), minutes (m), and seconds (s) in combination: "1h30m", "5m30s".

How Jobs Execute

CronEngine timer fires
    ↓
EventLog.append('cron.fire', { jobId, jobName, payload })
    ↓
CronListener receives event
    ↓
AgentCenter.askWithSession(payload, cronSession)
    ↓
Alice processes with full AI pipeline (tools, reasoning)
    ↓
ConnectorCenter.notify(result) → last-interacted channel
    ↓
EventLog.append('cron.done' | 'cron.error')

The cron session (data/sessions/cron/default.jsonl) is independent from your chat sessions. Jobs run serially — if one is still processing when the next fires, the second is skipped.

AI Tools

Alice can manage cron jobs through conversation:

ToolDescription
cronAddCreate a new job with name, schedule, and payload
cronListList all jobs with runtime state (next run, last status, errors)
cronUpdateModify name, schedule, payload, or enabled state
cronRemoveDelete a job permanently
cronRunNowFire immediately (bypasses schedule, doesn't affect next run)
You: Check the ETH funding rate every 4 hours.

Alice: [calls cronAdd]
       Created "ETH Funding Rate Check" (id: a1b2c3d4)
       Schedule: every 4h
       Next run: in 4 hours
You: Show me all my scheduled jobs.

Alice: [calls cronList]
       1. ETH Funding Rate Check — every 4h — next: 2025-03-15 18:00
       2. Morning Portfolio Review — cron "0 9 * * 1-5" — next: Monday 9:00 AM
       3. __heartbeat__ — every 30m — next: 14:30 (internal)

Persistence

Jobs are stored in data/cron/jobs.json as a single JSON file with atomic writes (write to temp file, then rename). This survives crashes — on restart, the engine reloads all jobs and re-arms timers.

Error Handling

Failed jobs get exponential backoff:

Consecutive ErrorsBackoff
130 seconds
21 minute
35 minutes
415 minutes
5+1 hour

The consecutive error count resets on success. One-shot (at) jobs that fail are still disabled — they don't retry.

Internal Jobs

Jobs with double-underscore names (__heartbeat__, __snapshot__) are internal — the CronListener ignores them. They have dedicated handlers:

This separation prevents internal jobs from being routed through the AI pipeline unnecessarily.