# How Heartbeats Function in Prime Agent Across Daemon Restarts

> Discover how Prime Agent's heartbeats persist through daemon restarts. Learn about cron job storage, local snapshots, and restart phases for seamless background work resumption.

- Repository: [Prime Intellect/prime-agent](https://github.com/PrimeIntellect-ai/prime-agent)
- Tags: internals
- Published: 2026-08-15

---

**Prime Agent implements heartbeat persistence through cron-based job storage, local daemon snapshots, and coordinated restart phases that ensure long-running background work survives process shutdown and resumes seamlessly after reinitialization.**

Heartbeats in PrimeIntellect-ai/prime-agent enable continuous background processing for agent sessions. When the daemon restarts—whether for updates or crashes—the system must preserve heartbeat state and resume scheduling without data loss. This article examines the complete mechanism, from job persistence to post-restart state reconstruction.

## Heartbeat Jobs as Persistent Cron Entries

Heartbeats are implemented as standard **AgentCronJob** entries in the central cron store. When a session requires periodic work, the session controller invokes `store.createRlmHeartbeat()` in [[`cron-jobs.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/cron-jobs.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/cron-jobs.ts), registering a job of type `"rlm_heartbeat"` with:

- A scheduling prompt that drives the next agent turn
- The associated `activeSessionId`
- Interval timing (`intervalMs`)

The cron store persists to disk (see [`cron-store.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/cron-store.ts)), ensuring heartbeat definitions survive daemon termination.

```typescript
// Create a heartbeat from session controller context
const hb = store.createRlmHeartbeat({
  prompt: "keep‑alive",
  intervalMs: 60_000,
  activeSessionId: sessionId,
});

```

## Daemon-Side Heartbeat Catalog and Snapshot Caching

Each daemon worker maintains a local **heartbeat snapshot** (`heartbeatSnapshot`) that mirrors active heartbeats known to that worker. The catalog implementation in [[`heartbeat-catalog.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/heartbeat-catalog.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/heartbeat-catalog.ts) handles:

- **`heartbeats_list` RPC requests**: Returns cached snapshot or fetches fresh list if stale
- **Snapshot invalidation**: Marks `heartbeatSnapshotStale = true` when heartbeat changes occur

The snapshot pattern reduces redundant store queries while ensuring eventual consistency.

## Broadcasting Heartbeat State Changes

The daemon supervisor subscribes to cron store events and propagates changes globally. As implemented in [[`daemon-mode.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-mode.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-mode.ts):

```typescript
// Broadcast heartbeat changes to all attached clients
this.cronStore.onHeartbeatChange(() =>
  this.broadcastGlobal({ type: "heartbeats_changed" })
);

```

This notification pattern keeps clients synchronized without polling, reducing latency for heartbeat-aware operations.

## Update-Restart Coordination and Phase Blocking

Before a restart, the daemon enters a **preparing phase** (`prepare_update_restart`) that blocks mutating operations. From [[`daemon-supervisor.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-supervisor.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/modes/daemon/daemon-supervisor.ts):

```typescript
// Reject heartbeat commands during update preparation
if (restartPhase === "preparing") {
  this.write(client, failure(cmd.id, cmd.type, "Daemon is preparing an update restart"));
}

```

This coordination prevents state corruption by ensuring no heartbeat modifications occur while the daemon transitions.

## State Restoration After Daemon Restart

Post-restart reconstruction follows a precise sequence in [`daemon-supervisor.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/daemon-supervisor.ts) (lines 476-483 and 3882-3883):

1. **Reinitialize from persisted store**: Load all cron jobs including heartbeat definitions
2. **Build fresh snapshot**: `heartbeatsFromResponse` constructs initial worker state
3. **Mark snapshot valid**: Clear stale flag for immediate serving
4. **Invalidate on changes**: Subsequent `heartbeats_changed` events set `heartbeatSnapshotStale = true`

The next client `heartbeats_list` request after invalidation triggers snapshot refresh, maintaining consistency.

## Session-Level Heartbeat Continuation

After daemon restoration, session logic in [[`agent-session.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/agent-session.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/agent-session.ts) detects due heartbeats by comparing `nextRunAt` timestamps. When a heartbeat is scheduled:

- The session dispatches the associated follow-up prompt
- The agent resumes its previous context
- No work is lost between daemon stopping and restarting

This seamless continuation relies entirely on the cron store's persistence guarantee rather than in-memory state.

## Summary

- **Heartbeats are cron jobs**: Leverage existing persistence infrastructure in [`cron-jobs.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/cron-jobs.ts)
- **Daemon caches locally**: Snapshot pattern in [`heartbeat-catalog.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/heartbeat-catalog.ts) optimizes read performance
- **Changes broadcast globally**: `onHeartbeatChange` event propagation keeps clients synchronized
- **Restart phases protect integrity**: Preparation phase blocks mutations during shutdown
- **Post-restart reconstruction**: Fresh snapshot built from persisted store, with invalidation for live updates
- **Session logic resumes work**: [`agent-session.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/agent-session.ts) triggers pending heartbeats without manual intervention

## Frequently Asked Questions

### How does Prime Agent prevent heartbeat loss during a daemon update?

The supervisor implements a **preparation phase** (`prepare_update_restart`) that blocks all mutating commands, including heartbeat modifications. Meanwhile, heartbeat definitions are already persisted to disk through the cron store. After restart, the daemon reloads from this store and reconstructs active snapshots.

### What triggers a heartbeat snapshot refresh in the daemon?

The `heartbeatSnapshotStale` flag is set to `true` when the daemon receives a `heartbeats_changed` broadcast. The next `heartbeats_list` RPC then fetches fresh state from the worker rather than returning cached data.

### Where is heartbeat scheduling logic implemented for agent sessions?

Session-level heartbeat handling resides in [[`agent-session.ts`](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/agent-session.ts)](https://github.com/PrimeIntellect-ai/prime-agent/blob/main/packages/coding-agent/src/core/agent-session.ts), which monitors `nextRunAt` timestamps and dispatches follow-up prompts when heartbeats become due.

### Can clients modify heartbeats while the daemon is restarting?

No. During the preparation phase, any `heartbeat_manage` or related commands receive an explicit error response: **"Daemon is preparing an update restart"**. Clients must retry after the daemon completes its restart cycle.