7.4 KiB
7.4 KiB
Home Manager Agent — Deployment Plan
An autonomous Hermes Agent that runs inside the k3s cluster and takes care
of the home by talking to Home Assistant's REST API. It mirrors the
platform-engineer agent pattern but its domain is the home, not the cluster:
it watches sensors, runs routines, and notifies Roger on Discord — asking
before touching anything security-critical (locks, alarm, garage, HVAC).
Docs: https://hermes-agent.nousresearch.com/docs/user-guide/docker
1. Goal & operating model
- One Hermes container in namespace
home-manager, scheduled on the amd64 NUC (roger-nucbox-evo-x2, 24 GiB) — same node asplatform-engineer. - Hermes runs in gateway mode under s6 supervision (
gateway run), so the built-in cron scheduler is active and survives restarts. - The agent talks to the home via the Home Assistant REST API at
http://home-assistant.home-assistant:80(in-clusterhome-assistantService). Auth is a HA Long-Lived Access Token in a Secret. - The agent has NO k8s RBAC and NO git repo — it doesn't need them. Its
only write path is HA service calls. (Contrast with
platform-engineer, which remediates via git commits → ArgoCD sync.) - LLM calls route through the in-cluster LiteLLM proxy.
- Notifications go to a dedicated Discord bot (separate token from the platform engineer's bot).
- Hermes-native cron jobs make the agent run periodic checks + routines.
2. Files in this directory
| File | Purpose |
|---|---|
namespace.yaml |
namespace home-manager |
rbac.yaml |
ServiceAccount + Role for the cron-seed Job only (pods/exec on the hermes pod) |
configmap.yaml |
seed config.yaml + SOUL.md (HA REST API docs + operating rules) |
secret.yaml |
HA token, Discord token/channel, LiteLLM key, dashboard auth (PLACEHOLDERS — fill in) |
pvc.yaml |
5 Gi PVC for /opt/data (HERMES_HOME) |
deployment.yaml |
Deployment (1 replica, Recreate, pinned to amd64 NUC) + Service |
ingress.yaml |
home-manager.rogi.casa → dashboard (TLS + basic auth) |
cron-seed.yaml |
Sync-hook Job that reconciles the Hermes cron schedule from Git (deletes + recreates each job on every run so prompt/schedule changes apply on sync) |
README.md |
this file |
3. How it differs from platform-engineer
| Concern | platform-engineer |
home-manager (this) |
|---|---|---|
| Domain | k3s cluster health | the home |
| Observe via | Prometheus / Loki / ArgoCD HTTP APIs | Home Assistant REST API |
| Write path | git commit → push → ArgoCD sync | HA service calls (POST /api/services/...) |
| k8s RBAC | none | none |
| git repo | yes (cloned to /workspace/k3s-cluster) |
none |
| Discord bot | dedicated | dedicated (separate token + channel) |
HERMES_WRITE_SAFE_ROOT |
/ (needs to edit manifests) |
unset → defaults to /opt/data (tighter) |
| Image | nousresearch/hermes-agent:latest |
same |
| Model | qwen3.6 via LiteLLM |
same |
4. Safety & guardrails
- SOUL.md is the real boundary. The agent may freely toggle lights, fans,
media, and non-critical switches. It must ask Roger on Discord before
touching
lock.*,alarm_control_panel.*, garagecover.*, riskyclimate.*changes, or anything taggedcritical/security/safe_to_auto: false. tool_loop_guardrails.hard_stop_enabled: true— circuit-breaks a stuck gateway.yolo: true+approvals.mode: off— cron jobs aren't blocked waiting for a human. Safe because the blast radius is HA service calls and the SOUL.md encodes the confirmation gate for dangerous entities.- Tirith scanner disabled — it false-positives on the in-cluster plain-HTTP HA URL and would block every query.
- Single replica / single-writer PVC — never scale >1.
podAntiAffinityguards against an accidental co-run. - No real-time event bus — the terminal tool can't hold a HA WebSocket open. The agent works on cron polling + on-demand Discord commands. (See §6 for an optional real-time hook.)
5. Deployment checklist (do in this order)
- Create a Home Assistant Long-Lived Access Token. In HA UI:
Profile → Long-Lived Access Tokens → Create Token → label
home-manager-agent. Copy the token. - Create a dedicated Discord bot (separate from the platform-engineer bot), invite it to your server, and note its token + the channel ID you want it to use as its home channel.
- Fill in
secret.yaml— base64-encode each value (echo -n 'VALUE' | base64):HOMEASSISTANT_TOKEN— the HA LLAT from step 1.OPENAI_API_KEY— your LiteLLM master key.DISCORD_BOT_TOKEN,DISCORD_HOME_CHANNEL,DISCORD_FREE_RESPONSE_CHANNELS— from step 2 (channel ID is the same for both).HERMES_DASHBOARD_BASIC_AUTH_PASSWORDand..._SECRET— strong values.
- Fill in
configmap.yaml— replaceREPLACE_WITH_HOME_CHANNEL_ID(two places underdiscord:) with your numeric home channel ID. (Must match the secret'sDISCORD_HOME_CHANNEL.) - Tailor
cron-seed.yamlschedules/prompts to your actual HA entities (your sensor names, yourscript.goodnight, etc.). - Commit & push the whole change (including the regenerated
argocd/apps/home-manager.yaml). ArgoCD will create the namespace resources, deploy the pod, and bring up the ingress athome-manager.rogi.casa. - Seed the cron jobs: ArgoCD runs
cron-seed.yamlas a Sync hook automatically on every sync. The hook reconciles the cron schedule to match Git: it deletes + recreates each named job, so prompt/schedule edits incron-seed.yamltake effect on the next sync (this overwrites any livehermes cron editchanges — edit the prompts in Git instead). To re-run it by hand:kubectl apply -f home-manager/cron-seed.yaml. - Smoke test: trigger a check manually —
kubectl exec -n home-manager deploy/hermes -- hermes cron run door-window-check— and confirm the message lands in Discord (or[SILENT]if all clear).
6. Optional: real-time events from HA
The base setup is cron-poll + Discord. For real-time reaction (e.g. "front door opened → agent acts immediately"), you can have Home Assistant call the Hermes gateway API on an event:
- Enable the gateway API (port 8642) in
config.yamland set an auth token. - In HA, create a
restcommand + an automation that fires on the event and POSTs tohttp://home-manager.home-manager:80/...(the in-cluster Service).
This is not enabled by default — start with cron + Discord, add webhooks once the agent is trusted.
7. What ArgoCD owns vs. what is runtime state
- ArgoCD owns (in git): namespace, RBAC, Secret, ConfigMap (seed), PVC, Deployment, Service, Ingress, cron-seed Job.
- Runtime state (on the PVC, NOT reconciled):
config.yaml,SOUL.md,.env,sessions/,memories/,skills/. The ConfigMap only seeds these on first boot; after that, edits made via the dashboard persist on the PVC and Argo will not revert them. For a hard reset, delete the PVC and re-apply.- Exception — cron jobs (
cron/jobs.json): thecron-seedSync hook re-runs on every ArgoCD sync and deletes + recreates each named job fromcron-seed.yaml, so the cron schedule IS reconciled from Git. Live edits viahermes cron editwill be overwritten on the next sync — edit the prompts incron-seed.yamland commit instead.
- Exception — cron jobs (