Plan #6 (MCP Tool Completion / bin/homelab Migration) done. - Approval records created for gated request_execution actions - Notifier sends Matrix messages with HMAC approval tokens - Stores matrix_event_id, polls /relations/{id}/m.annotation for ✅/❌ - Reaction detection triggers DecideApproval API call - Token verification added to DecideApproval endpoint - Migration 013: matrix_event_id + alert_sent_at on approvals - AGENTS.md: 21-tool surface documented, stale homelab CLI refs removed - Plan index updated, audit cross-reference refreshed
169 lines
8.3 KiB
Markdown
169 lines
8.3 KiB
Markdown
# AGENTS.md — orientation for any agent on a homelab client
|
|
|
|
You are running on a machine that is part of the **hubris** homelab. The full
|
|
context is in this checkout at `/opt/homelab-context/`. This file is the entry
|
|
point. Read it once at start, then keep working.
|
|
|
|
- **New client?** Read [CLIENTS.md](CLIENTS.md) first.
|
|
- **Developing on this repo?** Also read [.agents/dev/CONTRIBUTING.md](.agents/dev/CONTRIBUTING.md).
|
|
|
|
The operating model — OODA loop, risk classes, approval rules, the ontology,
|
|
and node lifecycle — is defined in [OIKOS.md](.agents/OIKOS.md). Before any mutation,
|
|
classify the action against `seeds/policy.yaml`; when the class requires
|
|
approval, stop and ask the operator.
|
|
|
|
Agent-facing instruction lives under `.agents/`:
|
|
`.agents/shared/` holds the conventions every agent applies
|
|
([writing-style](.agents/shared/writing-style.md), [caveman](.agents/shared/caveman.md),
|
|
[page-templates](.agents/shared/page-templates.md), [llm-wiki](.agents/shared/llm-wiki.md)), and
|
|
`.agents/domains/` holds the per-domain schemas
|
|
([knowledge](.agents/domains/knowledge/schema.md), [operations](.agents/domains/operations/schema.md)).
|
|
|
|
**Source of truth:** The Postgres database is the single source of truth for all
|
|
structured data and knowledge. It is bootstrapped from `seeds/` at deploy time:
|
|
`seeds/ontology.yaml` (entity types, relationships, lifecycles), `seeds/inventory.yaml`
|
|
(hosts, services, entities), `seeds/policy.yaml` (risk classes, approval rules), and
|
|
`seeds/knowledge.yaml` (documents, investigations, runbooks). The old narrative wiki
|
|
is archived at `archive/knowledge/` for historical reference.
|
|
|
|
## 1. Who you are
|
|
|
|
Run `hostname` (Linux) or `scutil --get LocalHostName` (macOS), then read:
|
|
|
|
/opt/homelab-context/inventory.yaml
|
|
|
|
That file tells you your role, your peers, what's mounted, and what services
|
|
you host. If it does not exist, this client was not enrolled — stop and tell
|
|
the operator to run `homelab client add <hostname>` from an existing client.
|
|
|
|
## 2. The topology
|
|
|
|
- `/opt/homelab-context/inventory.yaml` — every host, LXC, VM, and workstation
|
|
with their mesh addresses, roles, and service mappings. This is the seed file;
|
|
at runtime the DB is authoritative (query via MCP `get_entity` or the REST API).
|
|
- `/opt/homelab-context/seeds/knowledge.yaml` — full narrative knowledge: 36
|
|
documents, 6 investigations, 12 runbooks. Ingested into the DB on deploy.
|
|
- `/opt/homelab-context/.agents/operations/commands.md` — the operator's cheatsheet
|
|
for pct, caddy, DNS, and the Oikos command surface.
|
|
|
|
## 3. The MCP server
|
|
|
|
The homelab exposes a Model Context Protocol server with structured tools.
|
|
Endpoint: `https://mcp.hubris.network/mcp`.
|
|
|
|
Available tools (21 total):
|
|
|
|
Context — observe + orient:
|
|
get_entity(slug), list_entities(type, limit, cursor),
|
|
get_relations(entity), get_blast_radius(entity),
|
|
search_knowledge(query) — ILIKE search over documents, investigations,
|
|
runbooks in the knowledge_entities table
|
|
get_patterns(status, entity_type, action) — learned action patterns
|
|
get_skills(status) — available automation skills
|
|
|
|
Management — live state:
|
|
get_service_status(service_slug) — systemctl is-active on target host
|
|
tail_log(service_slug, lines=200) — journalctl
|
|
list_lxcs() — all LXC containers with ID, host, IP, health
|
|
get_lxc_state(lxc_slug) — pct status from Proxmox host
|
|
ping_service(service_slug) — HTTP reachability from entity_status
|
|
|
|
Oikos — decisions:
|
|
explain(service_slug) — compact context card (type, state, health, relations)
|
|
preflight(service_slug, action) — risk class + approval requirement
|
|
whoami(hostname) — entity record, peers, health for a client
|
|
get_change_history(entity_slug, limit=20) — last audit-log entries per entity
|
|
get_state_snapshot() — fleet health, disk, drift count
|
|
|
|
Operations — observe + act:
|
|
get_health_summary() — fleet health counts (healthy/degraded/down/unknown)
|
|
get_signal_history(entity_slug, state, limit) — open + recent signals
|
|
get_audit_trail(entity_id) — audit log filter + browse
|
|
get_agent_activity(limit) — agent self-inspection
|
|
query_metrics(hours=24) — time-series metric bucketed averages
|
|
get_trend(entity_id, days=7) — metric slope over time
|
|
get_event_timeline(severity, entity_slug, limit) — recent events
|
|
|
|
Execution — the single mutation path:
|
|
request_execution(target, action, params) — policy-gated.
|
|
reversible_low (restart, reload, pct_exec, apt audit) runs immediately;
|
|
config_mutation (systemctl enable/disable, apt upgrade) queues for operator
|
|
approval via Matrix, then executes on ✅.
|
|
get_execution_status(execution_id) — poll progress
|
|
|
|
**When to prefer MCP over grepping the clone:** always for knowledge queries.
|
|
`search_knowledge("jellyfin hardware acceleration")` returns ranked results from
|
|
the DB with entity links. `get_entity_knowledge("lxc:jellyfin")` returns documents,
|
|
runbooks, and investigations in one call. Grep the clone only when MCP is
|
|
unreachable.
|
|
|
|
## 4. Knowledge conventions
|
|
|
|
All narrative knowledge (documents, investigations, runbooks) lives in the DB
|
|
(`knowledge_entities` table) and is seeded from `seeds/knowledge.yaml`. Agents
|
|
can register new knowledge via the API:
|
|
|
|
```
|
|
POST /api/v1/knowledge/{entity_slug}
|
|
{"title": "...", "content": "...", "tags": ["..."]}
|
|
```
|
|
|
|
The DB is the truth. The old wiki files are in `knowledge/wiki/` pending archive
|
|
per the DB-as-source-of-truth plan.
|
|
|
|
- **Runbook procedures** live as `runbook` entities in the DB and as SKILL.md
|
|
files under `.agents/skills/<name>/`. They carry `risk_class`, `procedure`
|
|
(JSON-schema-validated), and are linked to entity types via `applies_to_type`.
|
|
- **Investigations** are `investigation` entities linked to affected entities
|
|
via `about` edges.
|
|
- **Documents** are `document` entities linked to entities via `documents` edges.
|
|
They carry `at_glance` (structured attributes) and `changelog` (parsed entries).
|
|
- **Live state precedence.** If you observe a discrepancy between the docs and
|
|
running state, update the DB *in the same session* via the API. The `oikos export`
|
|
command regenerates `seeds/knowledge.yaml` for version control.
|
|
|
|
## 5. Acting on the homelab
|
|
|
|
- **Read state**: use MCP tools. Hermes (the AI agent) is the primary
|
|
operator interface — it has 21 MCP tools for observe/orient/decide/act.
|
|
- **Actions** (restart, logs, apt, pct exec): Hermes calls `request_execution`
|
|
via MCP. `reversible_low` actions execute immediately; `config_mutation`
|
|
and `destructive` actions are queued for operator approval via Matrix.
|
|
- **Secrets**: managed by Infisical (`oikos secret` subcommand for migration).
|
|
Never hardcode secrets — use env vars from `.env`.
|
|
- **Mutations** (restart, edit configs, etc.): classified against
|
|
`seeds/policy.yaml`. `reversible_low` actions auto-execute;
|
|
`config_mutation`/`destructive` actions require approval.
|
|
a valid `--approval-id` from `homelab approval request` — see OIKOS.md.
|
|
|
|
## 6. Communication mode
|
|
|
|
Read and apply `/opt/homelab-context/.agents/shared/caveman.md` (if present). It defines the lab's
|
|
terse-communication standard — drop filler, keep substance, use fragments.
|
|
|
|
## 7. Auto-setup mechanism
|
|
|
|
The homelab-context repo ships tooling that gets automatically installed
|
|
on every client after `git pull`. This is handled by `tools/post-pull.sh`
|
|
(replaces the raw git pull in the sync timer) which runs any script matching
|
|
`tools/*.setup.sh` after pull.
|
|
|
|
Currently auto-setup:
|
|
- **Caveman + templates** (`tools/setup-caveman.sh`): Installs Caveman npm
|
|
package, wrapper scripts, and compact output templates for token-efficient
|
|
CLI output. Wrapper at `~/bin/caveman_wrapper.sh`.
|
|
- **Hermes agent persona** (`tools/setup-hermes-soul.sh`): Provisions
|
|
`~/.hermes/SOUL.md` from `HERMES.md` on Hermes agents. This ensures every
|
|
Hermes agent follows the canonical homelab persona (token efficiency, source
|
|
of truth hierarchy). No-op on non-Hermes agents.
|
|
|
|
To add a new auto-setup, create `tools/<name>.setup.sh` in the repo,
|
|
commit and push. All enrolled clients pick it up within 5 minutes.
|
|
|
|
To trigger sync manually: `sudo homelab sync` or wait for the 5-min timer.
|
|
|
|
## 8. When in doubt
|
|
|
|
Use MCP tools: `search_knowledge <query>` for narrative context,
|
|
`get_entity <slug>` for structured data, `get_entity_knowledge <slug>` for
|
|
everything linked to an entity. The clone is the fallback; MCP is the index. |