Files
openclaw/docs/heartbeat.md

74 lines
3.3 KiB
Markdown
Raw Normal View History

---
summary: "Plan for heartbeat polling messages and notification rules"
read_when:
- Adjusting heartbeat cadence or messaging
---
2025-12-26 02:35:21 +01:00
# Heartbeat (Gateway)
2025-11-26 17:05:09 +01:00
2025-12-26 02:35:21 +01:00
Heartbeat runs periodic agent turns in the **main session** so the model can
surface anything that needs attention without spamming the user.
2025-11-26 17:05:09 +01:00
## Prompt contract
2025-12-26 02:35:21 +01:00
- Heartbeat body defaults to `HEARTBEAT` (configurable via `agent.heartbeat.prompt`).
- If nothing needs attention, the model should reply `HEARTBEAT_OK`.
2026-01-04 14:32:47 +00:00
- During heartbeat runs, Clawdbot treats `HEARTBEAT_OK` as an ack when it appears at
the **start or end** of the reply. Clawdbot strips the token and discards the
reply if the remaining content is **`ackMaxChars`** (default: 30).
2026-01-02 01:42:27 +01:00
- If `HEARTBEAT_OK` is in the **middle** of a reply, it is not treated specially.
2025-12-26 02:35:21 +01:00
- For alerts, do **not** include `HEARTBEAT_OK`; return only the alert text.
2026-01-02 01:42:27 +01:00
### Stray `HEARTBEAT_OK` outside heartbeats
If the model accidentally includes `HEARTBEAT_OK` at the start or end of a
2026-01-04 14:32:47 +00:00
normal (non-heartbeat) reply, Clawdbot strips the token and logs a verbose
2026-01-02 01:42:27 +01:00
message. If the reply is only `HEARTBEAT_OK`, it is dropped.
### Outbound normalization (all providers)
For **all providers** (WhatsApp/Web, Telegram, Slack, Discord, Signal, iMessage),
Clawdbot applies the same filtering to tool summaries, streaming block replies,
and final replies:
- drop payloads that are only `HEARTBEAT_OK` with no media
- strip `HEARTBEAT_OK` at the edges when mixed with other text
2025-12-26 02:35:21 +01:00
## Config
```json5
{
agent: {
heartbeat: {
every: "30m", // duration string: ms|s|m|h (0m disables)
model: "anthropic/claude-opus-4-5",
target: "last", // last | whatsapp | telegram | none
to: "+15551234567", // optional override for whatsapp/telegram
prompt: "HEARTBEAT", // optional override
ackMaxChars: 30 // max chars allowed after HEARTBEAT_OK
2025-12-26 02:35:21 +01:00
}
}
}
```
### Fields
- `every`: heartbeat interval (duration string; default unit minutes). Omit or set
to `0m` to disable.
- `model`: optional model override for heartbeat runs (`provider/model`).
- `target`: where heartbeat output is delivered.
2026-01-06 18:25:52 +00:00
- `last` (default): send to the last used external provider.
- `whatsapp` / `telegram`: force the provider (optionally set `to`).
2025-12-26 02:35:21 +01:00
- `none`: do not deliver externally; output stays in the session (WebChat-visible).
- `to`: optional recipient override (E.164 for WhatsApp, chat id for Telegram).
2025-12-26 03:02:11 +01:00
- `prompt`: optional override for the heartbeat body (default: `HEARTBEAT`).
- `ackMaxChars`: max chars allowed after `HEARTBEAT_OK` before delivery (default: 30).
2025-12-26 02:35:21 +01:00
## Behavior
2026-01-03 23:57:17 +00:00
- Runs in the main session (`main`, or `global` when scope is global).
2025-12-26 02:35:21 +01:00
- Uses the main lane queue; if requests are in flight, the wake is retried.
- Empty output or `HEARTBEAT_OK` is treated as “ok” and does **not** keep the
session alive (`updatedAt` is restored).
- If `target` resolves to no external destination (no last route or `none`), the
heartbeat still runs but no outbound message is sent.
## Wake hook
- The gateway exposes a heartbeat wake hook so cron/jobs/webhooks can request an
immediate run (`requestHeartbeatNow`).
- `wake` endpoints should enqueue system events and optionally trigger a wake; the
heartbeat runner picks those up on the next tick or immediately.