GitHubBlog

Search Documentation

Search for a page in the docs

Heartbeat

The heartbeat is Alice's autonomous market monitoring system. Built on top of the cron engine, it periodically wakes Alice up, lets her evaluate the situation, and decides whether you need to know about anything.

How It Works

The heartbeat registers a special cron job (__heartbeat__) that fires at a configured interval. On each fire:

  1. Active hours guard — If you've set an active window, fires outside it are skipped silently
  2. AI call — Alice receives the heartbeat prompt and processes it through the full pipeline (can use all tools — check portfolio, scan news, calculate indicators)
  3. Response parsing — Alice's response is parsed for the structured protocol
  4. Dedup — Identical messages within 24 hours are suppressed
  5. Delivery — Routed through ConnectorCenter to wherever you last chatted

Response Protocol

Alice responds using a structured format:

STATUS: HEARTBEAT_OK
REASON: All positions within normal range, no notable news.
STATUS: CHAT_YES
REASON: Significant price movement detected.
CONTENT: BTC just dropped 8% in the last hour — now at $87,200.
         Your stop-loss on the long position may trigger soon.
StatusMeaningWhat Happens
HEARTBEAT_OKNothing to reportLogged silently, no notification sent
CHAT_YESWorth telling youCONTENT is delivered to your last-interacted channel

Fail-open — If Alice's response can't be parsed into the structured format, the entire text is treated as CHAT_YES and delivered. Better to over-notify than to swallow something important.

Configuration

data/config/heartbeat.json:

{
  "enabled": true,
  "every": "30m",
  "activeHours": {
    "start": "9:00",
    "end": "22:00",
    "timezone": "America/New_York"
  }
}
FieldDescription
enabledMaster switch
everyCheck interval (default: "30m")
activeHoursTime window. null = always active.

Active Hours

Restrict heartbeat checks to specific hours:

{
  "activeHours": {
    "start": "9:00",
    "end": "22:00",
    "timezone": "America/New_York"
  }
}

Overnight ranges work too: "start": "22:00", "end": "06:00" covers the overnight window.

Outside the active window, fires are skipped with a heartbeat.skip event.

Customizing the Prompt

The heartbeat prompt defines what Alice checks and how she formats her response. It lives at data/brain/heartbeat.md (gitignored). The default is copied from default/heartbeat.default.md on first run.

Edit it to change behavior — for example, you could make Alice focus on specific positions, check particular news sources, or apply different thresholds for what's worth reporting.

Dedup

If Alice would send the exact same message she sent within the last 24 hours, it's suppressed. This prevents "BTC is still down" every 30 minutes when nothing has actually changed.

Events

The heartbeat writes events to the EventLog for observability:

EventWhen
heartbeat.skipSkipped (outside active hours, HEARTBEAT_OK, empty, or duplicate)
heartbeat.doneMessage delivered (includes reply text, reason, duration)
heartbeat.errorAI call or delivery failed

Hot-Toggle

Enable or disable at runtime without restart:

You: Turn off the heartbeat.

Alice: Heartbeat disabled.

This persists to heartbeat.json and toggles the __heartbeat__ cron job. You can also toggle it from the Web UI settings panel.