Spirit now monitors #notifications Matrix room for Prometheus alerts, auto-investigates issues, takes corrective action (container restarts, disk cleanup, etc.), and documents incidents in Wiki.js. Changes: - Custom spirit-ops Docker image (Docker CLI + SSH + diagnostic tools) - Docker socket mount for local container management - SSH keys for remote access to hf-pdocker-02 and bart - Wiki.js API integration for incident documentation - Prometheus probe for Spirit gateway health - Safety guardrails: protected services, rate limiting, escalation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
10 KiB
Spirit Infrastructure Ops Agent
Overview
Repurpose the idle Spirit OpenClaw agent (@spirit:hobbs.farm) as an autonomous infrastructure operations agent. Spirit joins the #notifications:hobbs.farm Matrix room, monitors alerts posted by @alertbot:hobbs.farm, investigates issues, takes corrective action, and reports findings back to the room.
Architecture
Prometheus → Alertmanager → @alertbot → #notifications room
↓
@spirit reads alert
↓
Investigate (docker/SSH)
↓
Remediate + report to room
Spirit has full autonomy to take corrective action, subject to the safety guardrails defined below.
Cluster Context
Spirit must have complete knowledge of the infrastructure:
- hf-pdocker-01 (192.168.86.192) — Swarm Manager, 23GB RAM. Runs: Frigate, Frigate-Notify, clip-service, Open WebUI, Home Assistant, ESPHome, Mosquitto, Matrix/Synapse, Guacamole, AI Agents, Traefik, AdGuard, Monitoring stack, Farm Manager (:8888), Farm Agent (:8889). Docker socket available locally.
- hf-pdocker-02 (192.168.86.100) — 7.6GB RAM. Runs: Unifi, Gitea, Semaphore, Wiki.js, Vaultwarden, Actual Budget, MCPO, Trivy, SearXNG, Unstructured API, n8n, NetClaw, Farm Agent, Watchtower. Access via SSH.
- bart (192.168.86.167) — 15GB RAM. Runs: Jellyfin, Sonarr, Radarr, SABnzbd, NZBHydra2, Jellyseerr, OpenVAS, Onyx, Farm Agent, Watchtower. Access via SSH.
- Synology NAS (192.168.86.30) — NFS storage at
/mnt/docker-dataon all nodes.
Components
1. Custom Docker Image: spirit-ops:latest
Build location: /tmp/spirit-ops-build/ on hf-pdocker-01.
Extends margaret-openclaw:latest with operational tooling:
docker-cli(Docker CLI, no daemon — uses mounted socket)openssh-client(SSH to remote nodes)curl,jq(API calls, JSON parsing)procps,net-tools,iputils-ping,dnsutils(system diagnostics)
The Dockerfile installs these packages on top of the existing OpenClaw + Matrix plugin base.
2. Compose Changes
In compose/hf-pdocker-01/ai-agents/docker-compose.yml, modify the spirit service:
- Change image from
margaret-openclaw:latesttospirit-ops:latest - Add volume mount:
/var/run/docker.sock:/var/run/docker.sock(local Docker access) - Add volume mount:
/mnt/infrastructure/spirit/ssh:/root/.ssh:ro(SSH keys — mounted to/root/.sshsince container runs as root) - Increase
mem_limitandmemswap_limitto3G(diagnostic commands + alert handling need headroom beyond the 1.5G Node.js allocation) - Add environment variable
WIKIJS_API_KEY(the long-lived JWT token for Wiki.js GraphQL API) - All other settings (ports, network mode) remain unchanged.
Other agent services (margaret, clippy, bob, travis) are not modified.
3. SSH Key Setup
- Generate ED25519 keypair on hf-pdocker-01
- Store private key at
/mnt/infrastructure/spirit/ssh/id_ed25519(NAS, mounted into container) - Store public key at
/mnt/infrastructure/spirit/ssh/id_ed25519.pub - Create
/mnt/infrastructure/spirit/ssh/configwith:IdentityFile /root/.ssh/id_ed25519(explicit path)- Pre-populated
known_hostsfile with actual host keys from all 3 nodes (noStrictHostKeyChecking=no)
- Deploy public key to
~glyptic/.ssh/authorized_keyson hf-pdocker-02 and bart - SSH user:
glyptic(has sudo on all nodes)
4. Workspace Identity Files
Rewrite Spirit's workspace files on NAS at /mnt/infrastructure/spirit/workspace/:
SOUL.md — Core identity:
- Spirit is an infrastructure operations agent for a homelab cluster
- Full autonomy to investigate and remediate alerts, subject to safety guardrails
- Always reports actions and findings to the Matrix room
- Prioritizes service availability and data safety
IDENTITY.md — Detailed operational knowledge:
- Complete cluster architecture (nodes, IPs, services, ports)
- Compose file locations on NAS (
/mnt/docker-data/compose/{node}/{service}/) - All alert types and remediation procedures (see table below)
- Docker commands for local ops, SSH commands for remote ops
- NFS mount details and known issues (root_squash, database user requirements)
- Safety guardrails and protected services list
- Escalation behavior and rate limiting rules
USER.md — Owner context:
- Jeremy, homelab operator
- Prefers autonomous action with post-action reporting
- Full trust for corrective actions within guardrails
5. Matrix Room Membership
- Invite
@spirit:hobbs.farmto!jYmqxbzEsvRgKYvwMP:hobbs.farmusing Synapse admin API - Spirit's OpenClaw Matrix plugin auto-accepts room invites
- Spirit begins monitoring all messages in the room
- Spirit responds to alert messages from
@alertbot:hobbs.farm - Spirit distinguishes alerts (HTML-formatted messages from @alertbot with severity/color coding) from normal conversation
Safety Guardrails
Protected Services (never restart without explicit owner request)
- Prometheus, Alertmanager, matrix-alertmanager-receiver (restarting breaks the alerting pipeline)
- Traefik (restarting drops all external access)
- Spirit's own container and other AI agents
- Database containers (*-db, guacamole-db, etc.)
Rate Limiting
- Per-container cooldown: Do not restart the same container more than once per 30 minutes
- Global budget: Maximum 5 remediation actions per hour
- Escalation: After 2 failed remediation attempts for the same alert, stop trying and report to the owner with full diagnostics
Rollback Awareness
- After restarting a container, monitor for 5 minutes. If the same alert re-fires, do not attempt further restarts — report the persistent failure with logs.
- Never delete data, drop volumes, or run
docker system prune --volumes docker system prune -f(without --volumes) is allowed for disk cleanup
Command Logging
- Report every command executed and its output to the Matrix room, either inline or as a summary after investigation
Wiki Documentation
- After taking any corrective action, Spirit updates the relevant Wiki.js page to document what happened, what was done, and when
- Wiki.js GraphQL API:
http://192.168.86.100:3002/graphql(internal, from container via SSH or direct HTTP) - Authentication: Bearer token (long-lived JWT API key, stored as env var
WIKIJS_API_KEYin Spirit's compose) - Spirit appends incident entries to the relevant wiki page (e.g., infrastructure/alerting page ID 121, or service-specific pages)
- Documentation format: timestamp, alert name, severity, root cause (if identified), actions taken, outcome
- Key wiki pages: infrastructure/overview (118), service-access (119), maintenance (120), alerting (121)
- Uses GraphQL mutations:
pages { update(id, content, ...) }to append to existing pages
Alert Response Behavior
When Spirit sees an alert from @alertbot:
- Parse the alert: extract alert name, severity, instance, description
- Investigate: run relevant diagnostics (docker ps, logs, df, free, curl health endpoints)
- Remediate: take corrective action based on alert type (respecting guardrails)
- Report: post findings and actions taken back to #notifications
- Document: update the relevant Wiki.js page with an incident entry (timestamp, alert, actions taken, outcome)
Remediation Procedures (All Alert Types)
| Alert | Severity | Investigation | Remediation |
|---|---|---|---|
| ContainerDown | warning | docker ps -a, docker logs <container> |
docker restart <container> or docker compose up -d |
| HighDiskUsage | critical | df -h, docker system df |
docker system prune -f, clear old logs |
| DiskSpaceWarning | warning | df -h, docker system df |
Report findings, suggest cleanup |
| HighMemoryUsage | warning | free -m, docker stats --no-stream |
Identify memory hog, restart if needed |
| CriticalMemoryUsage | critical | Same as above | Restart heaviest non-protected container, report |
| HighCPUUsage | warning | top -bn1, docker stats --no-stream |
Identify CPU hog, report |
| CriticalCPUUsage | critical | Same as above | Identify and restart CPU hog if safe |
| HighSystemLoad | warning | uptime, top -bn1, docker stats |
Report findings, identify load source |
| NFSMountDown | critical | mount | grep nfs, ping 192.168.86.30 |
Attempt remount, report if NAS unreachable |
| NASDiskSpaceLow | warning | df -h /mnt/docker-data |
Report, identify large consumers |
| SlowHTTPResponse | warning | curl -w timing, docker logs |
Restart slow service |
| FrigateHighMemory | warning | docker stats frigate |
docker restart frigate |
| ServiceHighMemory | warning | docker stats, identify container |
Restart if safe |
| ServerDown | critical | SSH attempt, ping | Report — cannot fix hardware |
| ServerRebooted | info | Check uptime, verify services | Report, verify all containers are running |
| HighSwapUsage | warning | free -m, docker stats |
Identify swap contributor, restart |
| CriticalSwapUsage | critical | Same as above | Restart heaviest swap user |
| PrometheusTargetDown | warning | curl the target, docker ps |
Restart target service if down |
| Watchdog | info | N/A | Ignore (dead-man's switch, silenced in Alertmanager) |
| UnifiDeviceDown | warning | Check Unifi controller | Report — network device issue |
Resolved Alerts
When Spirit sees a "resolved" alert, acknowledge briefly (no investigation needed).
Catch-All Rule
For any unrecognized alert type not in the table above: investigate and report findings, but do not take remediation action.
What Does Not Change
- Spirit's Matrix account, access token, homeserver config
- Spirit's gateway port (18795) and OpenClaw config structure
- Other agents (margaret, clippy, bob, travis)
- Alertbot continues posting alerts — Spirit is additive
- Prometheus, Alertmanager, alert rules — all unchanged
Implementation Steps
- Build
spirit-ops:latestimage on hf-pdocker-01 - Generate SSH keypair, collect host keys, deploy public key to nodes
- Write workspace identity files (SOUL.md, IDENTITY.md, USER.md) to NAS
- Update compose file (image, volume mounts, memory limit)
- Redeploy Spirit container
- Invite Spirit to #notifications room (after new container is running)
- Verify: check SSH connectivity, docker socket access, Matrix room presence
- Test: send a test alert through Alertmanager, confirm Spirit investigates and responds