Cron & Heartbeat
One-line summary
The cron service manages scheduled jobs (reminders, periodic tasks) and heartbeats — the latter being the hidden token drain that sends the full session context every 10 minutes just to get "HEARTBEAT_OK" back.
Responsibilities
- Schedule and execute recurring jobs (cron expressions, interval-based, one-shot)
- Manage heartbeats — periodic health-check LLM calls on the main session
- Execute jobs in isolated agent sessions or the main session
- Handle error backoff, stuck run detection, and missed job catch-up
- Persist job state and track execution telemetry (including token usage)
Architecture diagram
Key source files
Data flow
Timer tick cycle
Heartbeat flow (the token-expensive path)
Critical constants
Error backoff schedule (timer.ts:108-114)
After 3 consecutive schedule errors → auto-disable job (MAX_SCHEDULE_ERRORS = 3).
Token optimization impact
Heartbeats are the most cost-inefficient token consumer in OpenClaw:
Why heartbeats are expensive
- Full context sent: The heartbeat uses the same code path as a regular message —
runHeartbeatOnce()triggers a full LLM call with complete system prompt, session history, tool definitions, and skills catalog - Response is minimal: The agent typically responds with just
HEARTBEAT_OK(~2 output tokens) for ~50,000+ input tokens - Grows with session: Heartbeat cost scales linearly with session history length
- 6 calls/hour default: Every 10 minutes, burning tokens for a 2-token response
Optimization opportunities
- Minimal heartbeat context: Send only identity line + "Is anything pending?" instead of full context
- Adaptive heartbeat frequency: Increase interval when session is idle, decrease when active
- Skip when session recently active: If user messaged within last N minutes, skip heartbeat
- Heartbeat-specific prompt mode: Use
PromptMode = "none"(15 tokens) instead of"full"(5,000 tokens)
Schedule types
Job payload types
How it connects to other modules
-
Depends on:
auto-reply/—runHeartbeatOnce(), isolated agent executionagents/pi-embedded-runner/— LLM execution for heartbeat and agent turnssessions/— session targeting, key resolutionconfig/— heartbeat settings, cron configurationchannels/— delivery to messaging platforms
-
Depended by:
gateway/— starts/stops cron service with gateway lifecycle- System prompt — includes heartbeat prompt instruction section
My blind spots
-
isolated-agent.ts— exact execution flow for isolated agent jobs vs main session -
delivery.ts— how delivery plans work for multi-channel delivery -
session-reaper.ts— when and how old cron sessions are cleaned up - Whether heartbeat uses prompt caching (Anthropic) — this would dramatically reduce heartbeat cost
- The exact heartbeat prompt text and whether it's customizable per agent
-
stagger.ts— stagger window logic for avoiding thundering herd
Related contributions
- None yet
Change frequency
timer.ts: Medium — backoff logic, heartbeat retry behavior, timing constants evolvejobs.ts: Medium — scheduling logic changes with new schedule typesops.ts: Medium — CRUD operations expand with new features (pagination, filtering)service.ts: Low — thin wrapper, rarely changestypes.ts: Low — type additions are additive and rare