The Heartbeat Concept Explained

Why Paperclip uses a scheduled heartbeat (pull) rather than event-driven webhooks (push), the tradeoffs in latency vs. simplicity, and the guarantee that no two heartbeats for one agent overlap.

The Heartbeat: Paperclip's Engine

What you'll learn

The mental model behind the heartbeat system, why Paperclip chose a cron-based pull model instead of event-driven push, and what happens inside one heartbeat tick.

The Core Idea

The heartbeat is a scheduled job — a clock tick — that wakes up every N minutes and asks: "Is there any open work? If so, dispatch agents to handle it."

Every 5 minutes:
  ┌─ Is company paused? → skip
  ├─ Is budget exceeded? → pause company, skip
  ├─ Find open issues per active agent
  │   ├─ Claim one issue per agent (atomic checkout)
  │   ├─ Invoke adapter (LLM call or script)
  │   └─ Record result + cost
  └─ Log heartbeat run stats

This is a pull model: agents don't run continuously; they are awakened by the clock. The work queue is the source of truth, not in-memory state.

Pull vs Push: Why Paperclip Chose Pull

Pull (heartbeat) Push (event-driven)
Simple: one cron job Complex: message broker, event bus
Durable: work survives restarts At-risk: unprocessed events lost on crash
Observable: every run logged Hard to trace: events flow through brokers
Rate-limited by design Risk of thundering herd
Slightly higher latency (max: tick interval) Low latency

For autonomous background agents, latency of a few minutes is acceptable. Durability and observability matter more.

One Tick in Detail

T=0:00  Cron fires → POST /internal/heartbeat/tick
T=0:00  Lock company row (SELECT FOR UPDATE)
T=0:00  Check: paused? over budget? → continue
T=0:01  Query open issues for each active agent
T=0:01  For each issue found:
          Atomic checkout (UPDATE...RETURNING)
          Assemble prompt (system + task)
          Invoke adapter
T=0:30  Adapter returns (LLM call took ~29s)
T=0:30  Update issue: status=resolved, result=output
T=0:30  Insert cost_event
T=0:31  Update heartbeat_run: agents=1, issues=1, cost=$0.02
T=0:31  Unlock company
T=5:00  Next tick fires

What "Active Agent" Means

An agent is eligible for the heartbeat tick if:
- status = 'active'
- monthly_spend_this_month < monthly_budget_usd
- Company is not paused

The Heartbeat Is Idempotent

If two heartbeat ticks overlap (e.g. the cron runs again before the first tick finishes), the atomic checkout prevents double-work. The second tick claims different issues or skips if none are open.

Checkpoint ✓

Sign in for progress tracking & Q&A →