Wzorzec mechaniczny: sekcje deploy/verify/install/testy wycinane do kb/runbooks/<serwis>-*.md, reszta zostaje dokumentem type: service. Wzajemne `links` w obie strony. Tresc sekcji nietknieta — przenoszone doslownie, dodany wylacznie naglowek H1 nowego runbooka. kb-query, paperless-worker, planner-agent, ha-diag-agent, ollama-piha, narty27, home-assistant, ha-mcp, job-gmail-header-backfill, job-mail-body-ingest. Weryfikacja: dla kazdego pliku multizbior niepustych linii (main + runbook) == oryginal z HEAD. Zero zgubionych, zero dodanych. Recon szacowal 13 splitow service+runbook; faktycznie 2-typowych jest 10, pozostale 5 (paperless, nextcloud, gokapi, fleet-prometheus, deploy-runner) sa 3-typowe i ida osobno jako splity wielotypowe. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4.4 KiB
| okf | type | visibility | status | updated | links | |
|---|---|---|---|---|---|---|
| 0.1 | service | private | active | 2026-05-27 |
|
planner-agent
Asynchroniczny agent diagnozujący zdarzenia zdrowotne w homelabowej infrastrukturze.
Nasłuchuje na kanałach Redis pub/sub, wysyła zdarzenie do LLM i zapisuje propozycję
akcji do actions/pending/ — gdzie musi ją zaakceptować operator.
Co robi
Redis pub/sub LLM (Ollama → Haiku → Sonnet)
health_events ──────────────► diagnoza zdarzenia
world_updates ──────────────► propozycja JSON
│
cooldown gate (5 min / svc_key)
│
actions/pending/<action_id>.json
│
events/<date>/<node>/evt-*.json
(typ: remediation_started)
HITL invariant: planner pisze wyłącznie do actions/pending/.
Executor wymaga pliku w actions/approved/ — planner nigdy tego katalogu nie dotyka.
Obsługiwane kanały
| Kanał | Źródło | Opis |
|---|---|---|
health_events |
node-agent, stability-agent | Zdarzenia zdrowotne kontenerów i systemu |
world_updates |
observer (control-plane) | Zmiany w world state |
Benign events (pomijane bez wywołania LLM)
service_healthy, service_recovered, node_online, deployment_completed,
deployment_started, remediation_started, remediation_completed
Fallback chain LLM
1. ollama/<OLLAMA_MODEL> timeout 8 s (lokalny GPU — SOLARIA)
2. claude-haiku-4-5-20251001 timeout 30 s (Anthropic cloud)
3. claude-sonnet-4-6 timeout 30 s (Anthropic cloud)
Model jest odrzucany, gdy:
- przekroczy timeout
- zwróci błąd sieci / API
- odpowie tekstem pasującym do wzorca odmowy (
"I cannot","nie wiem", …) - zwróci JSON niezgodny ze schematem propozycji
Metryki każdego wywołania są publikowane na kanał Redis llm_router_metrics.
Schemat propozycji (JSON Schema)
{
"action": "restart | redeploy | notify | ignore",
"service": "<nazwa serwisu>",
"node": "<nazwa noda>",
"reason": "<wyjaśnienie, min. 10 znaków>",
"confidence": <0.0–1.0>,
"requires_human": <true|false>
}
Mapowanie na typ executora:
| LLM action | Executor type | Risk level |
|---|---|---|
| restart | container_restart | low |
| redeploy | redeploy | guarded |
| notify | notify | low |
| ignore | (nie zapisuje) | — |
Zmienne środowiskowe
Wszystkie zmienne runtime żyją w /opt/homelab/config/planner-agent/.env na węźle.
Nie commituj tego pliku — nie jest w repo.
# Ollama — lokalny GPU węzła (np. SOLARIA)
# Użyj host-gateway zamiast localhost (kontener nie może sięgnąć hosta przez localhost)
OLLAMA_HOST=http://host-gateway:11434
OLLAMA_MODEL=qwen2.5-coder:14b # dowolny model dostępny w ollama list
# Redis na piha
REDIS_URL=redis://100.108.208.3:6379
# Tożsamość noda
NODE_NAME=solaria
# Cooldown między propozycjami dla tego samego serwisu
COOLDOWN_SECONDS=300
# Ścieżka do runtime state
RUNTIME_PATH=/opt/homelab
# Opcjonalnie — wymagane do cloud fallback (haiku/sonnet)
# ANTHROPIC_API_KEY=sk-ant-...
ANTHROPIC_API_KEY jest jedyną zmienną przekazywaną przez sekcję environment
w docker-compose.yml (nie jest w env_file — sekret injektowany przez operatora).
Healthcheck
Skrypt healthcheck.sh sprawdza czy plik heartbeat
/opt/homelab/state/planner-agent.heartbeat jest świeższy niż 300 s.
Heartbeat jest pisany na górze każdej iteracji pętli (≤5 s interwał).
# Ręczny test healthchecku
docker exec planner-agent /bin/sh /app/healthcheck.sh
Struktura plików
services/planner-agent/
├── src/
│ ├── planner.py # Główna pętla agenta
│ └── llm_router.py # Routing LLM z fallback chain
├── tests/
│ ├── test_planner.py # 49 testów
│ └── test_llm_router.py # 34 testy
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
├── service.yaml # Kontrakt operacyjny dla agentów
├── healthcheck.sh
└── README.md