Heartbeat migration: convert retired monitors to automation jobs

Learn how retired heartbeat monitors become ordinary editable automation jobs through Doctor, including what carries over and which legacy settings are removed. For operators upgrading existing deployments.

Read this when

  • Upgrading an installation with heartbeat configuration or HEARTBEAT.md
  • Finding the automation that replaced an agent's heartbeat monitor
  • Updating an integration that uses legacy heartbeat commands or events

Note

Heartbeat monitoring now relies on standard automation jobs. Doctor turns existing monitors into editable jobs, each carrying its own schedule, policies, scratch, and run history.

A scheduled check is owned by an automation job. That job holds its schedule, prompt, scratch, model, session, and delivery settings. Background-command, task, hook, and restart follow-ups go through normal session execution; no periodic monitor and no enabled cron scheduler is needed for them.

Upgrade an existing monitor

Run Doctor with the upgraded CLI:

openclaw doctor --fix

Next, list every job, disabled ones included:

openclaw automations list --all

Every existing monitor becomes an ordinary editable job under Doctor. Its identity, run history, scratch bytes and revisions (deletion tombstones included), disabled or auto-disabled state, scheduling anchor, and pending scheduling slots all carry over. Legacy heartbeat-task:* jobs are converted as well, and supported HEARTBEAT.md content and task blocks are imported before their old inputs are retired.

Legacy agents.defaults.heartbeat and agents.entries.*.heartbeat settings, along with special channel heartbeat visibility configuration, are removed by Doctor only once the canonical jobs have been persisted and verified. When conversion is blocked, the diagnostic reports which input remains; fix that problem and run Doctor again instead of deleting the configuration or scratch by hand.

Once migration is done, edit the ordinary job. Your edits survive repeated Doctor runs, config reloads, and Gateway restarts, and a deleted monitor is not recreated. Because a one-time provisioning receipt outlives job deletion, removing a default monitor is a permanent decision.

Before the original file is removed, imported HEARTBEAT.md bytes are archived in the state directory at backups/heartbeat-migration/. Where the workspace and state directory sit on different filesystems, Doctor additionally preserves the original in a private HEARTBEAT.md.doctor-archived.* directory next to its former location. Writes made through an already-open file descriptor stay recoverable there. A file recreated after migration has completed is kept and reported; it never overwrites the operator-owned job.

Suppose existing scratch differs from HEARTBEAT.md and was not imported from that file. Doctor then keeps both the scratch and the original file, prints a notice, and finishes the conversion. Scratch that was explicitly unset stays unset. The automation continues with its existing scratch; check the retained file before copying any instructions you want into the job. Running Doctor again preserves both originals and still succeeds.

When migration finishes, Doctor prints this one-time note:

Migrated heartbeats now use standard Automations delivery. Heartbeat-specific duplicate suppression and no-route skipping were removed: repeated updates can be delivered, and a missing route no longer skips the run before execution. Delivery failures follow ordinary automation handling. Review the migrated jobs' delivery settings if you relied on either behavior.

Model overrides carried over by migration obey the agent's existing model policy. Should a heartbeat model fall outside that policy, Doctor removes the job's model override and reports the affected agent, job, dropped model, and configured default. Normal automation model selection then applies to the job. Doctor never widens the allowlist. To run a different model, pick an allowed one for the job, or add the model you want to the agent's modelPolicy.allow before selecting it. Overrides that are allowed are kept.

Warning

The shared-state database moves to schema 30, which means an older Gateway cannot run these jobs while ignoring their new execution or delivery policies. Keep a verified backup before upgrading. For a rollback, restore the pre-upgrade backup into a separate state directory; never lower schema version markers. See Database schemas.

No per-agent schema change comes with heartbeat migration. The current agent schema is 31; its old heartbeat_outcomes table is kept for migration. Meaningful pending results that still belong to the current session are moved into ordinary session context without a notification being sent. Facts from before the current session, or from a session that expired, are not promoted into a new conversation.

Doctor handles the heartbeat configuration and task shapes shipped from July 2026 onward. Shapes older than that fall outside this migration. When an input cannot be converted faithfully, Doctor keeps it and reports the problem rather than silently discarding its scheduling or delivery settings.

A bare tasks: line followed by ordinary checklist bullets stays as-is in the monitor's scratch, including scratch imported by an earlier Doctor. It neither creates scheduled jobs nor blocks retirement. Incomplete task declarations still need repair; update admission and Doctor share the same task validation, and Doctor leaves an incomplete HEARTBEAT.md in place before importing it.

First setup

Explicit setup provisions a single enabled Proactive check job for the ambient owner agent. It runs every 30 minutes unless the provider supplies a different initial cadence, uses the agent's main conversation, waits for idle execution, and delivers to a resolved owner DM. The job skips a scratch checklist that is explicitly empty; missing scratch still runs. Edit its schedule, prompt, model, or delivery the way you would any other automation.

Provisioning occurs once. Neither Gateway startup nor config reload creates the job, and deleting it stays a lasting choice. Other agents require jobs of their own, created explicitly.

Configure scheduled checks

Every former heartbeat monitor stays tied to its agent rather than to each chat session. You can modify, disable, or delete it like any other automation:

openclaw automations show <job-id>
openclaw automations edit <job-id> --message "Check the monitor scratch. Report only changes that need attention; otherwise reply NO_REPLY."
openclaw automations disable <job-id>
openclaw automations remove <job-id>

A shared-context check targets a named session. An isolated check begins with a fresh run context. current works differently: it runs detached, with bounded context taken from the conversation as it stood when the job was created. See Execution styles.

Optional job policies keep the monitoring behavior that matters:

  • activeHours limits execution to a timezone-aware window.
  • idleOnly gives foreground work priority via normal scheduler and session admission.
  • delivery.target: "owner" resolves an explicitly identified owner DM. Unlike channel: "last", it does not follow a group conversation.
  • delivery.directPolicy allows or blocks DM delivery.
  • payload.includeReasoning decides whether an ordinary job includes available model reasoning in delivery.
  • payload.skipIfScratchEmpty skips a check whose scratch is explicitly empty; missing scratch differs from an empty checklist.

These settings apply per job; they do not replace a global heartbeat configuration. The canonical job reference is Automations.

Monitor scratch

Scratch is private context that can be attached to any automation job and is stored in the shared state database. Keep it brief and specific to the task; a job's current scratch is part of its bounded run context.

Never store secrets in scratch: private storage does not keep them out of the model prompt. For empty-checklist behavior and revision conflicts, see Job scratch and quiet results.

openclaw automations scratch <job-id>
openclaw automations scratch <job-id> --set "Check for newly blocked work. Report only actionable changes."
openclaw automations scratch <job-id> --unset

Scratch writes are guarded by revision. Pin a known revision with --expected-revision <n>. While an automation runs, the agent can read or update its own scratch via the automations tool, without reaching other jobs.

Scratch is not a scheduler. Recurring work belongs in separate automation jobs, not in a tasks: block. Doctor imports supported legacy blocks once; at runtime they are not parsed as schedules and HEARTBEAT.md is not read.

Quiet results and run history

Return NO_REPLY when a check has no visible update. During an automation run, record a meaningful outcome without sending a message by using the self-scoped record_result action. no_change suppresses automatic delivery; execution errors still count as failures. See Job scratch and quiet results.

Scheduled checks can also end silently inside a saved internal session. A completed check that returns NO_REPLY needs no extra final-answer model request.

Immediate follow-ups

A background process finishing, a task becoming blocked, or a restart completing all use ordinary session execution. None of them needs an enabled recurring monitor. Session admission keeps the follow-up in its original conversation with its current authority. An exec completion waits behind the turn that launched it, so that turn can finish and acknowledge its automation reminders without being superseded by its own command. For a manual event, ask for immediate processing explicitly:

openclaw system event --text "Check for urgent follow-ups" --mode now

The legacy set-heartbeats control switches only the matching migrated or default jobs on and off. It never affects every automation. Compatibility event handling for last-heartbeat remains as before. When an next-heartbeat request arrives without a target, it binds to a scheduled automation that qualifies for the session; if none qualifies, the request reports the problem rather than sitting idle until some future user message appears. For work that must be delayed, favor explicit automation schedules.

Transport keepalives, presence checks, and similar infrastructure health signals sit apart from agent monitoring and retain their current configuration.

1,524 words · updated Oct 26, 2026