Install
openclaw skills install cron-gatePre-checks sessions for new messages via a zero-token Python script to trigger expensive OpenClaw crons only when new activity exists, saving tokens.
openclaw skills install cron-gateStop wasting tokens on crons with nothing to do.
Every OpenClaw cron that spawns an isolated LLM session burns tokens — prompt loading, Weave files, tool calls — even when there's nothing new to process. If you run memory integration across 5 sessions twice a day, that's 10 LLM wake-ups. Most of them find nothing and go back to sleep, having burned ~40K tokens each.
Cron Gate is a zero-token Python gatekeeper that checks for new activity before triggering expensive LLM crons. No new messages? No wake-up. No tokens burned.
System crontab (free) OpenClaw cron (expensive)
│ │
gate.py runs disabled, waiting
│ │
checks sessions.json ┌───────┘
│ │
new activity? ─── yes ───► triggers cron via API
│
no ──► exits silently (0 tokens)
sessions.json to check updatedAt timestampscp gate.py /opt/scripts/cron-gate.py
chmod +x /opt/scripts/cron-gate.py
Edit the SESSION_CRONS dict in gate.py to map your session keys to their integration cron IDs:
SESSION_CRONS = {
"agent:main:telegram:group:-1234567890": {
"evening": "your-evening-cron-id-here",
"morning": "your-morning-cron-id-here",
},
"agent:main:discord:channel:9876543210": {
"evening": "another-cron-id",
"morning": None, # skip morning for this session
},
}
Finding your session keys: Look in ~/.openclaw/agents/main/sessions/sessions.json
Finding your cron IDs: Run /crons in chat or check the OpenClaw dashboard
For each integration cron you're gating, disable it (but don't delete — the gate script triggers them on-demand):
/cron update <cron-id> enabled=false
Or ask your agent: "Disable all memory integration crons — they'll be triggered by the gate script now."
# Evening integration window (adjust times to match your schedule)
5 6 * * * /usr/bin/python3 /opt/scripts/cron-gate.py evening >> /var/log/cron-gate.log 2>&1
# Morning integration window
5 18 * * * /usr/bin/python3 /opt/scripts/cron-gate.py morning >> /var/log/cron-gate.log 2>&1
# Dry run — see what would trigger without actually doing it
python3 gate.py --dry-run evening
# Force a specific slot (ignore time-of-day check)
python3 gate.py morning
# Normal operation (auto-detects slot from UTC hour)
python3 gate.py
The script auto-detects which slot to run based on UTC hour:
Override by passing evening or morning as an argument. When run from crontab with an explicit slot argument, the time window check is bypassed.
Activity timestamps are stored in /opt/scripts/cron-gate-state.json (configurable). This is how the gate knows what's "new" — it compares each session's updatedAt against the last time it triggered that cron.
To reset (re-trigger everything on next run):
rm /opt/scripts/cron-gate-state.json
Real-world numbers from the first deployment:
This pattern works for any cron that might have nothing to do:
The principle: check cheap, wake expensive only when needed.
crontab -e)