Heartbeats

A heartbeat is the difference between an assistant you have to summon and a teammate who shows up.

It's a cron-scheduled prompt attached to a persona. Every weekday at 9am, every Friday at 5pm, every hour, whatever — at that moment Cabinet wakes the agent, hands them the prompt, and lets them decide whether anything needs doing. If nothing changed, the heartbeat ends silently. If something needs your attention, it shows up in the Approval Queue or as a new page in the cabinet.

Heartbeats vs. routines vs. tasks

Three rhythms. They look similar. They're different on purpose.

WhenWhat it isWhat it produces
TaskOnceA specific piece of workA page, a draft, a result
RoutineOn a scheduleA task that recursThe same thing, every Friday
HeartbeatOn a scheduleA check-in to decide what to doMaybe nothing. Maybe a proposal. Maybe a page.

A routine knows what it'll produce. A heartbeat doesn't. The agent looks around and decides.

The shape of a heartbeat

Heartbeats live in the persona's frontmatter:

---
name: GTM Lead
heartbeats:
  - cron: "0 9 * * 1"
    label: "Monday standup"
    prompt: "Open the launch room. Report what changed since Friday."

  - cron: "0 17 * * 5"
    label: "Friday wrap"
    prompt: "Draft next Monday's launch checklist."

  - cron: "*/30 9-18 * * 1-5"
    label: "Workday pulse"
    prompt: "Skim /marketing/inbox/. Flag anything labeled 'urgent'."
---

Three fields per beat:

  • cron — standard 5-field cron expression. Use crontab.guru if you need a translator.
  • label — optional name shown in the schedule UI.
  • prompt — what the agent reads when the heartbeat fires.

Common cron patterns

PatternReads asGood for
0 9 * * 1-5weekdays at 9amMorning standup
0 17 * * 5Fridays at 5pmWeekly wrap
30 11 * * 1-5weekdays at 11:30Pre-lunch sweep
0 */4 * * *every 4 hoursInbox / feed scanner
*/15 9-18 * * 1-5every 15 min, business hours, weekdaysHigh-frequency monitoring
0 0 1 * *1st of every monthMonthly report

What a heartbeat sees

When a heartbeat fires, the agent gets:

  1. The prompt from the heartbeat.
  2. The agent's persona prompt.
  3. Their memory file.
  4. Whatever folder is in scope (their visibility).

That's it. No conversation history, no other agents, no full cabinet read. Heartbeats are intentionally tight. They run quickly, they cost less, and they're predictable.

If the agent decides work needs to happen, it can:

  • Write a page (e.g., a daily briefing).
  • Propose a task or job → goes to the Approval Queue.
  • Update memory and exit.
  • Do nothing and exit.

Designing a heartbeat that doesn't get annoying

A heartbeat that pings you every time it runs gets muted within a week. Two rules:

Tip — Default to silence. Write the prompt so the agent only escalates new or important findings. Encourage it to update its memory and stay quiet otherwise.

Tip — Anchor to a file, not a topic. "Check /sales/pipeline.csv" beats "Check on sales." A heartbeat that has a specific page to read writes a specific page back.

Bad heartbeat:

- cron: "0 9 * * *"
  prompt: "Tell me what's important today."

Better:

- cron: "0 9 * * 1-5"
  label: "Inbox triage"
  prompt: |
    Read /inbox/today.md. Group items by urgency.
    Write the result to /briefings/$DATE.md.
    If you see anything that contradicts /briefings/yesterday.md,
    flag it in a separate "Conflicts" section.
    Only @mention me if there's a P0.

Pausing a heartbeat

Three options, in order of permanence:

  1. Disable — open the agent in the AI team panel, click the heartbeat, toggle it off. Reversible in one click.
  2. Comment it out — open persona.md, prefix the YAML line with #. Git-trackable.
  3. Delete — remove the array entry. Done.

Heartbeats also auto-pause when the cabinet is closed. They resume the next time the app boots — they're not background daemons.

Read on