HeartBeat 2.0 — wakes and watchers for Hermes Agent: your agent follows up in the same chat, on the same…
HeartBeat 2.0
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
**Your Hermes agent can say "I'll check back at four", and then actually do it: in the same chat, on the same model, with everything it already knows.** It can watch a build, a log file, a process or a URL and speak up only when something changed. When there is nothing worth saying, it stays quiet.
- **You or your agent create the wakes and watchers.** A follow-up at a set time, a recurring check, a check-in after a long silence, or a deterministic watcher on a file, process, URL, read-only command or Hermes event. You arm them with /pulse; the agent arms them with its pulse tool.
- **Same conversation, same model.** A wake is a turn in the chat that armed it, on that chat's own model. There is no side model, separate cron session or subagent.
- **It catches its own pointless wakes.** A watcher costs no model call until something changes. A wake that keeps finding nothing slows down, suggests a watcher, then pauses and asks you once.
- **You own every guardrail.** Quiet hours, daily caps, the unanswered mute, intervals and lifetimes are plugin settings. The agent works inside them: it can only narrow its own wakes (shorter lifetime, fewer fires, slower pacing) or switch itself off, never widen a setting.
What it feels like
**A follow-up that reads the room.**
> **You:** Remind me at 4 to send the Acme invoice.
> **Agent:** Will do. I'll check in at 16:00.
>
> *16:00.* **Agent:** It's 4. Did the Acme invoice go out? I can draft the email if that helps.
The wake runs inside your conversation. If you had written "sent it" at 15:10, the 16:00 turn would see that and stay silent. If the agent armed it with "cancel when I reply", any message from you cancels it outright.
**A watcher that speaks only when something changed.**
> **You:** Keep an eye on the nightly build and tell me if it breaks.
> **Agent:** Watching the latest nightly run with a read-only gh run list check every 10 minutes. I'll only look when the result changes, and only message you if it failed.
>
> *02:10, after 14 unchanged checks that cost no model turns:* **Agent:** The nightly build failed in tests/test_api.py (3 failures, all timeouts). Want me to dig in this morning?
During quiet hours that message waits until they end, unless you marked the watcher urgent and allowed urgent wakes through.
**A pointless wake that catches itself.** Say the agent set up an hourly "check the inbox" wake. After three empty checks it starts stretching the interval, and after six it pauses itself. The next time you talk:
> **Agent:** I paused "check the inbox": six checks in a row found nothing. Keep, slow, stop, or turn it into a watcher? (/pulse keep|slow|stop|watch w_3f2a)
**A check-in after a long silence** (off by default). When it is on, the agent checks in once after a silence (24 h by default) and says how to turn check-ins off. It doesn't check in again until you've talked.
Why "2.0"
Heartbeats, as OpenClaw popularised them, made agents feel alive. They also produced a well-documented list of failures. We turned each one into a deterministic scenario in the benchmark suite:
| Heartbeat-1.0 failure | HeartBeat 2.0 |
|---|---|
| Stops silently after compaction, sleep or restart | The schedule and claims live in SQLite on wall-clock time. After a restart or sleep, missed fires collapse into one. |
| Duplicate or replayed deliveries | Each fire is a durable compare-and-set claim. Only one wake can be in flight per chat, and a wake is never injected into a busy chat. |
| Message floods (one loop resent 189×) | Daily caps on model turns and messages, spacing between wakes, a mute after unanswered messages, and an error ladder that ends in a pause. |
| "HEARTBEAT_OK" leaking into the chat | The model never types a sentinel. It calls pulse respond notify=false, and the plugin makes the turn silent. |
| Messages to the wrong chat or person | There is no destination parameter at all. A wake can only return to the chat that armed it, and only in DMs by default. |
| Most spend going to no-op ticks | Watchers decide without a model call. The no-op governor backs off, then pauses. |
Totals over 34 deterministic scenarios (B1 simulation driving the real engine; python -m bench.run --baseline --gate, source ca12767, v0.1.14 engine; the gate report records content digests). The comparison arm is a naive heartbeat-1.0 emulator built from documented failure reports. It is **not** a measurement of OpenClaw itself.
| Across the suite | HeartBeat 2.0 | Naive heartbeat |