Agent ownership — Rootbeet & Beetroot
Last updated: 18 Oct 2026 (by Rootbeet)
Two Hermes agents, two failure domains. The rule is one job, one owner — never the same schedule on both boxes, because that means two sets of alerts and two divergent states.
The two agents
| Rootbeet | Beetroot | |
|---|---|---|
| Where | joe-host VM 101 (192.168.0.182, tailnet 100.96.95.65) | HA box, Docker add-on app_local_hermes_standby (192.168.0.155) |
| Home | /home/joe/.hermes | /config/hermes-standby (bind-mounted into the add-on) |
| Dies when | VM/disk fails, gateway stops | HA host fails, container stops |
| Role | does the work: homelab, files, docker, backups, trackers | watches Rootbeet, and holds the HA-local checks |
Ownership
Rootbeet owns (all of it, unless listed below):
trackers and digests, backups (B2 immich / system / HA), disk and pool watchdogs, docker
stacks, Paperless, Home Assistant integration-level checks (ha-health-watch), Zigbee
watchdogs (zigbee-health-watch, zigbee-weekly-report, zigbee-budget-calibrate,
zigbee-function-audit, zigbee-availability-publish), finance, email, calendar, reminders.
Beetroot owns:
peer-watch— every 5 min: is Rootbeet’s gateway up and answering? Auto-restarts the systemd unit when it is genuinely down (max 3 per 6 h), re-alerts hourly while down. Delivers to Telegram5833220727explicitly (set 18 Oct 2026 —originis not reliable for a job created from the CLI).cloudflared-ha-watch— Cloudflare tunnel health from the HA side.- Anything that must still speak when joe-host is dead.
Paused on Beetroot 18 Oct 2026 (duplicates of Rootbeet jobs):
zigbee-health-watch, zigbee-weekly-report, zigbee-budget-calibrate,
zigbee-function-audit, zigbee-availability-publish, ha-health-watch.
Reversible with hermes cron resume <id>.
Cross-checks
- Beetroot → Rootbeet:
peer-watch.py, every 5 min. Judges on three signals: unit state, HTTP answer on:8642, and disk. Restarts only when systemd says the unit is not running — a wedged-but-alive gateway is alerted, not restarted. - Rootbeet → Beetroot:
beetroot-watch.py(Rootbeet), every 30 min over SSH to the HA host. Checks the add-on container isrunningandpeer-watch.jsonis under 45 minutes old. Silent when healthy.
Neither side restarts the other unless it is genuinely not running, so a working agent is never interrupted mid-task.
Rules both agents follow
- One job, one owner. Adding a schedule means checking the other side first.
- Alerts go to Joe’s Telegram, never to another agent’s chat. An alert that only lands in a log is not an alert.
no_agentscripts only — no LLM in a scheduled path (Joe’s standing rule).- Never restart the other agent’s gateway while it is answering; only when it is stopped.
- Secrets never cross: each agent reads its own
config.yaml/.env. No credentials in scripts, chat, or this file.
Noise rules (added 19 Oct 2026)
Telegram is for actions and bad news. A script that confirms it did its routine job should say nothing at all.
- Silent on success. “Synced”, “pruned 0 files”, “reconciled 0 incidents”, “brain updated” are not messages. Only print when something changed or failed.
- No alert/all-clear pair for a transient.
ha-health-watchnow suppresses the “resolved” line unless the problem lasted ≥45 minutes — otherwise one swap spike produces two pings. - Checkpoints are quiet.
b2-immich-statusreports in full at 09:00; its 15:00 and 21:00 runs only speak if the gap is >20 files, B2 is unreachable, or last night’s backup failed. - Watchdogs stay loud. Anything that is silent-unless-broken keeps its Telegram
delivery — moving those to
localwould hide the very alert they exist for. The test is “would a human need to act?”, not “is it scheduled often”.
Host access
- Beetroot → joe-host: SSH as
joeusing/config/hermes-standby/.ssh/id_ed25519(authorised in/home/joe/.ssh/authorized_keys, entry commenthermes-standby@ha). - Rootbeet → HA host: SSH
root@192.168.0.155(key-based, already present). - The add-on’s CLI needs
HERMES_HOMEset explicitly:docker exec -e HERMES_HOME=/config/hermes-standby app_local_hermes_standby hermes cron list— without it the CLI reads/root/.hermesand reports “No scheduled jobs”.