Skip to main content

Autonomous Jobs on a Timer

The heartbeat is how Wolffish does things on its own — a morning briefing at 8, an inbox sweep every 15 minutes, a one-off reminder in 2 days. Jobs live in brain/brainstem/heartbeat.md, parsed by the brainstem module and run through the full agent pipeline when they fire. You rarely edit this file by hand. Just ask Wolffish — “every morning, summarize my unread emails” or “in 2 days remind me to renew my domain” — and it creates, edits, and removes jobs for you through its automations capability (automation_list, automation_create, automation_edit, automation_delete, automation_check, automation_run). Hand-editing still works, and the format is below.

How It Works

Each ## heading in heartbeat.md defines a job. The heading is the schedule (e.g. ## Daily (08:00)) — there’s no separate job name. The body below it is the instruction, sent to the agent as a user message when the schedule fires.
## Daily (08:00)

Summarize my unread emails and calendar events for today.
List any GitHub notifications. Keep it brief.

## Every (30m)

Check my open pull requests on GitHub. If any have new
reviews or comments, give me a one-line summary of each.

Schedule Formats

All times use your system’s local timezone, 24-hour format. There’s no UTC conversion — Daily (09:00) means 9 AM wherever you are.

One-time (runs once, then deletes itself)

FormatMeaningExample
Once (YYYY-MM-DD HH:MM)Once, at an absolute local date-timeOnce (2026-12-31 23:30)
In (Nm) / In (Nh) / In (Nd)Once, N minutes / hours / days from nowIn (15m) · In (2h) · In (2d)
After a one-time job runs, it removes its own entry from the file. In (...) is shorthand you use when asking Wolffish — it’s converted to an absolute Once (...) at creation (a relative delay can’t survive a restart), so what lands in the file is always a Once (...). Hand-writing In (...) directly isn’t supported; use Once (...) for an exact time.

Recurring (fires until you remove it)

FormatMeaningExample
StartupRuns once each time the brainstem initializesStartup
Every (Nm)Repeating interval in minutesEvery (5m)
Every (Nh)Repeating interval in hoursEvery (2h)
Hourly (MM)Once per hour at minute markHourly (30)
Daily (HH:MM)Once per dayDaily (09:00)
Nightly (HH:MM)Once per day (alias for Daily)Nightly (23:00)
Weekday (HH:MM)Monday through Friday onlyWeekday (08:30)
Weekly (Day HH:MM)Once per week on a named dayWeekly (Monday 09:00)
Monthly (DD HH:MM)Once per month on a day numberMonthly (1 10:00)
Cron (expression)Raw 5-field cron syntaxCron (*/15 * * * *)
Out-of-range schedules are rejected up front — Every (0m), Daily (99:99), or a Once (...) in the past won’t be silently accepted and then never fire. If you hand-edit a malformed heading, it shows up flagged when Wolffish lists your automations.

Job Execution

Heartbeat jobs run through the full agent pipeline — same brain, same capabilities, same memory. What differs from a normal conversation:
  • Auto-approval: Tool calls bypass amygdala confirmation (no approval dialogs).
  • Sealed conversation: Each run creates its own conversation, visible in history.
  • No streaming: Responses are generated in the background without UI interruption.
Because heartbeat jobs auto-approve every tool call, be careful what you schedule. A job that says “delete old files” will execute without asking. Write defensive instructions — “list files older than 30 days and tell me what you’d delete” beats “delete files older than 30 days.” See What to Schedule for the full safety decision layer.

One at a time, queued — never dropped

Jobs run one at a time. If a job fires while another is still running, it queues and runs next rather than being skipped. The queue is coalesced per job, so a slow job can’t pile up a backlog of its own ticks. You don’t need to spread jobs out to avoid collisions.

Missed runs catch up

If Wolffish was closed when a job was due, it runs once on the next launch — collapsed: a recurring job that missed several fires during the downtime runs a single catch-up, not one per missed tick. Only misses within the last 24 hours are replayed; older ones are dropped. A one-time job past its time runs if it’s within that window, then deletes itself; if it’s older, it’s quietly retired without running.

Managing Jobs

Just talk to it:
  • “What automations do I have?” → lists them with their schedule and last-run status
  • “Every weekday at 7:45, give me a morning briefing” → creates a recurring job
  • “In 2 days, remind me to renew my domain” → creates a one-time job that self-deletes
  • “Change the morning briefing to 8am” / “Delete the PR watcher” → edits or removes
  • “Run my email check now” → fires a job immediately to test it
Changes apply live — the brainstem reloads the schedule as soon as the file changes, no restart needed.

By hand

Edit heartbeat.md directly. To disable a job without deleting it, comment it out with HTML comments:
## Daily (08:00)

Summarize my unread emails and calendar events for today.

<!--
## Every (1h)

This job is disabled and won't run.
-->
The brainstem watches heartbeat.md and reloads on save, so hand edits take effect without restarting. The commented examples shipped in the file are a menu — uncomment one to activate it.

Practical Examples

Morning Briefing

## Weekday (07:45)

Give me a morning briefing:
1. Unread emails — summarize the important ones
2. Today's calendar — list meetings with times
3. GitHub — any PRs that need my review
4. Weather — current conditions and forecast

Keep each section to 2-3 lines max.

Email Triage

## Every (2h)

Check my email for anything urgent or time-sensitive.
If you find something that needs immediate attention,
flag it and write a one-sentence summary.
Ignore newsletters and marketing emails.

PR Monitoring

## Every (30m)

Check my open pull requests on GitHub.
Report only PRs with new activity since your last check:
- New reviews or approvals
- CI status changes (especially failures)
- New comments or requested changes

If nothing changed, respond with "No PR updates."

One-time Reminder

## Once (2026-12-31 23:30)

Wish me a happy new year and give me a short recap of my
biggest wins this year, drawn from my episodes and knowledge.
This fires once at 11:30 PM on Dec 31, then removes itself from the file.

Memory Compaction

Memory compaction (hippocampus consolidation) is a separate scheduled process configured in Settings > Hippocampus > Compaction, not in heartbeat.md. The brainstem runs it on its own daily/weekly schedule, and it won’t appear when Wolffish lists your automations.
Compaction consolidates daily episodes into weekly summaries and promotes important information to knowledge files. It runs independently of heartbeat jobs.

Full Example File

# Heartbeat

## Startup

Run a quick health check. Verify that all configured
providers are reachable and report any issues.

## Weekday (07:45)

Give me a morning briefing:
1. Unread emails — summarize the important ones
2. Today's calendar — list meetings with times
3. GitHub — any PRs that need my review

## Every (30m)

Check my open pull requests on GitHub for new activity.
Only report changes since last check.

## Nightly (18:00)

Write a brief end-of-day summary of completed tasks
and pending items for tomorrow.

## Once (2026-12-31 23:30)

Wish me a happy new year and recap my biggest wins this year.

See Also