Files
k3s-cluster/home-manager/README.md
2026-07-25 00:54:46 +02:00

147 lines
7.4 KiB
Markdown

# 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 as `platform-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-cluster `home-assistant`
Service). 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
1. **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.*`, garage `cover.*`, risky
`climate.*` changes, or anything tagged `critical`/`security`/`safe_to_auto: false`.
2. **`tool_loop_guardrails.hard_stop_enabled: true`** — circuit-breaks a stuck
gateway.
3. **`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.
4. **Tirith scanner disabled** — it false-positives on the in-cluster plain-HTTP
HA URL and would block every query.
5. **Single replica / single-writer PVC** — never scale >1. `podAntiAffinity`
guards against an accidental co-run.
6. **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)
1. **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.
2. **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.
3. **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_PASSWORD` and `..._SECRET` — strong values.
4. **Fill in `configmap.yaml`** — replace `REPLACE_WITH_HOME_CHANNEL_ID` (two
places under `discord:`) with your numeric home channel ID. (Must match the
secret's `DISCORD_HOME_CHANNEL`.)
5. **Tailor `cron-seed.yaml`** schedules/prompts to your actual HA entities
(your sensor names, your `script.goodnight`, etc.).
6. **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 at `home-manager.rogi.casa`.
7. **Seed the cron jobs:** ArgoCD runs `cron-seed.yaml` as 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
in `cron-seed.yaml` take effect on the next sync (this overwrites any live
`hermes cron edit` changes — edit the prompts in Git instead). To re-run
it by hand: `kubectl apply -f home-manager/cron-seed.yaml`.
8. **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:
1. Enable the gateway API (port 8642) in `config.yaml` and set an auth token.
2. In HA, create a `rest` command + an automation that fires on the event and
POSTs to `http://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`):** the `cron-seed` Sync hook
re-runs on every ArgoCD sync and **deletes + recreates** each named job from
`cron-seed.yaml`, so the cron schedule IS reconciled from Git. Live edits
via `hermes cron edit` will be overwritten on the next sync — edit the
prompts in `cron-seed.yaml` and commit instead.