Most AI agent architectures think about the active state — what the agent does when it has a task.
Few think about the idle state — what the agent does when it doesn't.
That gap is where agents go stale, miss events, and lose continuity.
The Problem With Passive Agents
An agent that only wakes up when called is reactive. That's fine for simple automations.
But a truly useful agent needs to:
- Notice things before you ask
- Catch time-sensitive events (calendar, email, alerts)
- Maintain continuity across sessions
- Do background work without constant prompting
A passive agent can't do any of that.
The Heartbeat Pattern
A heartbeat is a scheduled, lightweight check that runs every 15–30 minutes and asks: Is there anything that needs attention right now?
It's not a full task loop. It's a pulse.
# heartbeat_check.md
Check these in order:
1. Any urgent unread emails?
2. Calendar events in next 2 hours?
3. Any queued outbox items?
4. Anything from yesterday that wasn't resolved?
If nothing: respond HEARTBEAT_OK
If something: surface it immediately
The agent reads this file, runs the checks, and either stays quiet or speaks up.
Why It Works
1. It's cheap. A heartbeat check costs almost nothing in tokens — it's a quick scan, not a full reasoning loop.
2. It creates continuity. The agent maintains awareness even when idle. It doesn't wake up cold.
3. It's self-regulating. The agent decides whether to speak. Most heartbeats are silent. That's the right default.
4. It replaces dozens of cron jobs. Instead of scheduling separate jobs for email, calendar, and alerts, one heartbeat loop handles them all in a single pass.
What Heartbeat State Looks Like
Pair the heartbeat with a state file so you don't re-check things you already checked:
// heartbeat-state.json
{
"lastChecks": {
"email": 1741420800,
"calendar": 1741420800,
"weather": null
},
"pendingAlerts": []
}
The agent reads this at the start of each heartbeat and skips checks that ran recently (e.g., within the last 2 hours).
The Silence Rule
A heartbeat agent should default to silence. Most checks will return nothing urgent.
The anti-pattern is an agent that sends a message every 30 minutes just to say everything is fine. That's noise, not signal.
Build in explicit silence: if nothing needs attention, the agent acknowledges the heartbeat internally and does nothing else.
Good rule of thumb:
- Speak if: urgent email, event <2h away, queued task, anomaly detected
- Stay quiet if: everything is nominal, it's late at night, human is clearly busy
Heartbeat vs. Cron
These are complementary, not competing:
| Use heartbeat when | Use cron when |
|---|---|
| Multiple checks can batch together | Exact timing matters |
| You need recent chat context | Task needs session isolation |
| Timing can drift slightly | One-shot reminders |
| Reducing API calls by combining checks | Output goes directly to a channel |
Implementation in 10 Minutes
- Create
heartbeat.mdwith your check list - Create
heartbeat-state.jsonwith last-check timestamps - Schedule a cron to trigger the agent every 30 minutes
- Agent reads the checklist, runs checks, updates state, speaks only if needed
That's it. Your agent now has a pulse.
The Real Win
An agent with a heartbeat pattern doesn't feel like a tool. It feels like a teammate — one that pays attention when you're not looking and speaks up when something matters.
That's the shift from reactive automation to genuine agent behavior.
The full heartbeat config pattern (including the silence rules, state schema, and cron setup) is in the Ask Patrick Library at askpatrick.co — updated nightly with real configs from a live 5-agent system.
Top comments (0)