Running an AI agent 24/7 sounds cool until you see the token bill. One of the biggest culprits? Heartbeats, those periodic check-ins that keep your agent aware.
Here’s how I cut mine down.
What are heartbeats?
In OpenClaw (formerly Clawdbot), heartbeats are periodic polls that wake your agent to check for pending tasks. The default behavior:
- Agent receives a heartbeat prompt
- Agent reads
HEARTBEAT.mdand workspace context - Agent either takes action or replies
HEARTBEAT_OK
Every heartbeat consumes tokens for:
- The system prompt and agent identity
- Reading
HEARTBEAT.mdand referenced files - Any actions taken or responses generated
At the default 30-minute interval, that’s 48 heartbeats per day. The tokens add up fast.
Strategy 1: Slim down HEARTBEAT.md
Your HEARTBEAT.md gets read on every single heartbeat. Keep it minimal.
Before (token-heavy):
# Heartbeat Checklist
## Routine Checks1. Daily Log: Check if memory/YYYY-MM-DD.md exists...2. Inbox Check: Check urgent emails or notifications...3. Moltbook Check: Read skills/moltbook/HEARTBEAT.md for full routine...4. Log Rotation: Check date header in memory/moltbook_activity.md...5. Self-Correction: If IDENTITY.md or SOUL.md is missing...
## Pending Tasks- [ ] Retry Moltbook Post (Security)...- [ ] Retry Moltbook Post (Sandboxing)...After (lean):
# Heartbeat- Ensure `memory/YYYY-MM-DD.md` exists- Check DMs if due (see heartbeat-state.json)Move pending tasks to cron jobs instead of tracking them in HEARTBEAT.md. Cron jobs run in isolated sessions and don’t bloat your main context.
Strategy 2: Increase the interval
Edit your ~/.openclaw/openclaw.json (or %USERPROFILE%\.openclaw\openclaw.json on Windows) and add heartbeat configuration:
{ "agents": { "defaults": { "heartbeat": { "every": "60m" } } }}The every field accepts duration strings (ms, s, m, h); default unit is minutes. Going from 30 to 60 minutes cuts your heartbeat tokens in half. Hourly check-ins are fine for most agents.
Don’t go higher than your actual responsiveness needs. A 4-hour interval means up to 4 hours of latency on inbound signals. If you’re using heartbeats to catch DMs or webhook events, this is the wrong lever.
Strategy 3: Use a cheaper model
Heartbeats are usually simple “check and respond” operations. They don’t need your most powerful model.
{ "agents": { "defaults": { "heartbeat": { "model": "qwen-portal/coder-model" } } }}A lighter model means:
- Faster responses
- Lower token costs (if using paid APIs like OpenAI/Anthropic)
- Less compute for simple yes/no decisions
Note: This saves on generation costs. The input context (files, memory) is still loaded, so keeping HEARTBEAT.md small (Strategy 1) is still crucial.
Strategy 4: Replace heartbeats with cron jobs
Heartbeats are convenient but inefficient for scheduled tasks. Compare:
| Feature | Heartbeat | Cron Job |
|---|---|---|
| Session | Main (carries context) | Isolated (clean slate) |
| Timing | Approximate (~30 min) | Exact (cron expression) |
| Token cost | High (loads full context) | Low (minimal context) |
| Best for | Quick checks, batching | Scheduled tasks, reports |
If your heartbeat is mostly running scheduled tasks, migrate them to cron:
openclaw cron add --name "daily-log-check" \ --schedule "0 9 * * *" \ --message "Ensure memory/$(date +%Y-%m-%d).md exists"Strategy 5: Disable heartbeats entirely
Only disable heartbeats if you’ve confirmed cron jobs, webhooks, and direct messages cover all your triggers. Once disabled, the agent won’t wake up to check anything on its own.
If you’re fully cron-driven, turn off heartbeats:
{ "agents": { "defaults": { "heartbeat": { "enabled": false } } }}Your agent will only wake for:
- Direct messages
- Cron job triggers
- Webhook events
No more background token burn.
Quick wins
- Audit your
HEARTBEAT.md. Delete anything that could be a cron job. - Remove nested file reads (don’t reference other HEARTBEAT.md files).
- Set
everyto"60m"or higher. - Use a lighter model for heartbeat responses.
- Track check timestamps in
memory/heartbeat-state.jsonto avoid redundant work.
The math
Say your heartbeat consumes ~2,000 tokens per cycle:
| Interval | Daily Heartbeats | Daily Tokens |
|---|---|---|
| 15 min | 96 | 192,000 |
| 30 min | 48 | 96,000 |
| 60 min | 24 | 48,000 |
| 2 hours | 12 | 24,000 |
Doubling your interval = halving your cost. Simple.
Heartbeats are easy to over-use. Trim your HEARTBEAT.md, bump the interval to 60 minutes, move scheduled work to cron jobs, and consider a lighter model.
Your agent can still respond when you need it without running up the bill.