Zum Inhalt

Ollama Monitor

Autonomes Anomalie-Monitoring für Home Assistant mit dreistufiger Eskalationskette: Direkt-Fix → Ollama → Claude → User.

Komponenten

| Script | Trigger | Funktion | | /config/tools/ollama_monitor.py | alle 10 Min | Anomalie-Erkennung + 3-stufiger Fix | | /config/tools/ollama_reporter.py | So 18:00 | Wöchentlicher Home-Report via Telegram | | /config/tools/claude_queue_processor.py | alle 10 Min | Claude löst eskalierte Tasks | | /usr/anatol/claude/scripts/arr_webhook.py (NAS) | Webhook Port 8090 | Smarte Fehlermeldungen (Sonarr/Radarr/Lidarr/SABnzbd) | | /config/tools/telegram_watchdog.sh | alle 5 Min | Überwacht bun-Prozess, meldet per Telegram wenn tot |

Eskalationskette

Anomalie erkannt
Stufe 1: Direkt-Fix — bekannte Aktionen (turn_off) direkt via HA API
     │ nicht möglich
Stufe 2: Ollama-Fix — fragt Ollama nach passendem HA Service-Call
         Prompt: Problem + Snapshot → KANN_FIXEN: ja/nein + DOMAIN/SERVICE/ENTITY_ID
         Führt Service-Call aus + prüft VERIFY_STATE nach 3s
     │ nicht möglich
Stufe 3: Claude-Queue — JSON-Task in /config/tools/claude_queue/
         claude_queue_processor läuft alle 10 Min, ruft claude direkt auf (KEIN Wrapper!)
     │ Claude scheitert
Telegram-Meldung + 24h Cooldown für dieses Problem

Anomalie-Checks

| Check | Bedingung | Stufe | | NAS-Disks | ≥ 95% → hoch, ≥ 90% → mittel | Claude-Queue | | Licht + niemand zuhause | switch/light on + both not_home | Direkt turn_off | | 3D-Drucker | Plug on + Status unavailable | Claude-Queue | | Ollama Catch-All | Snapshot-Analyse durch Ollama (max 3 Anomalien) | Claude-Queue |

Deduplizierung: /config/tools/anomaly_state.json - Normaler Cooldown: 2h - Nach Claude-Eskalation (FAILED): 24h — Wert wird als failed: gespeichert

Konfiguration

Shell-Commands (configuration.yaml)

shell_command:
  ollama_monitor_run:      "nohup python3 /config/tools/ollama_monitor.py > /tmp/ollama_monitor.log 2>&1 &"
  ollama_reporter_run:     "nohup python3 /config/tools/ollama_reporter.py > /tmp/ollama_reporter.log 2>&1 &"
  claude_queue_process:    "nohup python3 /config/tools/claude_queue_processor.py > /tmp/claude_queue.log 2>&1 &"
  telegram_watchdog_run:   "sh /config/tools/telegram_watchdog.sh >> /tmp/telegram_watchdog.log 2>&1"

Wichtig: nohup ... & ist Pflicht — HA tötet shell_commands nach 60s.

HA Automations

| Entity-ID | Trigger | | automation.ollama_anomalie_monitor_alle_10_min | time_pattern minutes: /10 | | automation.claude_queue_processor_alle_10_min | time_pattern minutes: /10 | | automation.ollama_wochentlicher_home_report_so_18_00 | weekday: sun, time: 18:00 | | automation.telegram_watchdog | time_pattern minutes: /5 |

Claude-Queue

/config/tools/claude_queue/              — Offene Tasks (JSON-Dateien)
/config/tools/claude_queue/failed/       — Claude konnte nicht helfen (Telegram + 24h Cooldown)
/config/tools/claude_queue/resolved.log  — Protokoll erfolgreich gelöster Tasks

Task-Format (inkl. anomaly_key seit 2026-05-04):

{
  "id": "20260504_120000_ollama_monitor",
  "source": "ollama_monitor",
  "description": "NAS sdd1 zu 96% voll (kritisch!)",
  "context": "Schwere: hoch | Entity: keine",
  "ollama_attempt": "Ollama-Fix gescheitert: Ollama kann nicht helfen",
  "anomaly_key": "nas_disk_sdd1_95",
  "created": "2026-05-04T12:00:00"
}

anomaly_key wird vom Processor genutzt um bei FAILED den Cooldown auf 24h zu setzen.

Rate-Limit: out of extra usage → Task bleibt in Queue und wird beim nächsten Run erneut versucht.

Wichtig: Claude wird DIREKT aufgerufen (kein Wrapper)

claude_queue_processor.py ruft Claude nicht über /usr/local/bin/claude (Wrapper) auf, sondern direkt:

CLAUDE_BIN = "/usr/local/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe"
subprocess.run([CLAUDE_BIN, "--dangerously-skip-permissions",
                "--allow-dangerously-skip-permissions", "-p", prompt], ...)

Grund: Der Wrapper fügt --channels plugin:telegram hinzu. Im Subprocess-Kontext startet das einen zweiten Telegram-Bot → 409-Konflikt → erster Bot (MCP-Verbindung der Hauptsession) stirbt.

Der Wrapper selbst ist ebenfalls gepatcht: bei -p-Aufrufen wird --channels nicht hinzugefügt.

Telegram Watchdog

Script: /config/tools/telegram_watchdog.sh — läuft alle 5 Min via HA Automation.

Prüft: - Ist der bun-Prozess am Leben? (pgrep -f "bun.*telegram") - Antwortet der Bot korrekt? (getUpdates — Zombie-Detection)

Bei Problem: Nur Benachrichtigung via Telegram Bot API (kein automatischer Restart!).\ Grund: Auto-Restart würde den laufenden Konversations-Kontext von Claude Code zerstören.

Notify-Lock: /tmp/telegram_watchdog_notified — verhindert Spam. Wird gelöscht wenn Bot wieder OK.

Manueller Restart: HA → Add-ons → Claude Code (04e1c827-claude-terminal) → Neustart\ → Nur machen wenn keine wichtige Konversation läuft!

Ollama

| Modell | Größe | Verwendung | | qwen2.5:7b | 4.7 GB | Standard (Catch-All, Fix-Layer, Report, 600 Token/180s) | | qwen2.5:3b | 1.8 GB | Nur für schnelle State-Queries |

API: http://192.168.178.20:11434/api/generate\ GPU: AMD Radeon RENOIR via Vulkan (~5.5 t/s)

Logs & Diagnose

# Monitor-Ausführung
cat /tmp/ollama_monitor.log

# Claude-Queue-Prozessor
cat /tmp/claude_queue.log

# Wöchentlicher Report
cat /tmp/ollama_reporter.log

# Watchdog
cat /tmp/telegram_watchdog.log

# Offene Tasks
ls /config/tools/claude_queue/*.json 2>/dev/null

# Fehlgeschlagene Tasks
ls /config/tools/claude_queue/failed/

# Cooldown-Status (failed: = 24h, ISO = 2h)
cat /config/tools/anomaly_state.json

# Telegram Bot Status (ok+result=aktiv, result leer=Zombie)
curl -s "https://api.telegram.org/bot8685305507:.../getUpdates?limit=1"

Behobene Bugs

| Datum | Bug | Fix | | 2026-05-03 | shell_command 60s Timeout: save_known() nie aufgerufen → Cooldown versagte → Spam | nohup + & für alle shell_commands | | 2026-05-03 | ha_call() mit None entity_id → {"entity_id": null} → HA API Fehler | entity_id if entity_id else "" | | 2026-05-03 | Dead Code: check_nas_disks() definiert aber nie aufgerufen | Entfernt | | 2026-05-04 | --channels im Subprocess: Wrapper fügte Telegram zu claude -p hinzu → zweiter Bot → 409 → MCP-Disconnect | CLAUDE_BIN direkt + Wrapper überprüft -p Flag | | 2026-05-04 | Disk-Check Regex zu eng: nur sda1/sdb1/nvme explizit geprüft | Generischer Regex sd[a-z]\d+ | nvme\d+ | md\d+ | dm-\d+ | | 2026-05-04 | Endlosschleife bei unlösbaren Problemen: alle 2h neue Eskalation | 24h Cooldown via failed:-Prefix in anomaly_state |

Token-Spar-Tools für Claude (2026-05-04)

Drei Tools reduzieren Clauds Token-Verbrauch indem häufige Abfragen (Entity-Suche, Kontext-Sammlung, State-Abfrage) in lokale Dateien vorberechnet werden.

1. Erweiterter State-Snapshot

ha_state_snapshot.py (alle 2 Min via Automation) wurde um zwei neue Sektionen erweitert:

Neu: Fehlgeschlagene Integrationen

-- INTEGRATIONEN (fehlerhaft) --
  ✗ vidaa_tv: Wohnzimmer-TV (setup_retry)
  ✗ wled: WLED (setup_retry)

Neu: Kürzlich geänderte Entities (15 Min) Nur interessante Domains (person, device_tracker, light, switch, media_player, etc.) — keine Sensoren/Power-Readings.

-- KÜRZLICH GEÄNDERT (15min) --
  3min: media_player.plex_... = playing
  8min: light.bad_gruppe = off

Claude liest: cat /config/tools/state_snapshot.txt statt MCP-ha_get_state-Calls.

2. Entity-Alias-Map

Datei: /config/tools/entity_aliases.json

Mapping von Kurznamen → entity_id für alle häufig verwendeten Geräte:

{
  "tv":        "media_player.wohnzimmer_tv",
  "receiver":  "media_player.pioneer_vsx_s520d_e41051",
  "arnold":    "vacuum.arnold_schwarzensauger",
  "drucker":   "sensor.centauri_carbon_print_status",
  "pv":        "sensor.pv_eingang_power",
  ...
}

Claude liest: cat /config/tools/entity_aliases.json statt ha_search_entities MCP-Calls.

Pflege: Manuell aktualisieren wenn neue Geräte hinzukommen oder entity_ids sich ändern.

3. Problem-Kontext-Tool

Script: /config/tools/problem_context.py Output: /tmp/problem_context.txt

Sammelt automatisch alles Relevante zu einem Gerät/Problem: - Gefundene Entity-States (via Alias + Fuzzy-Search) - Integration-Status (setup_retry, failed, reason) - Logbook letzte 2h - Relevante Zeilen aus state_snapshot.txt

python3 /config/tools/problem_context.py vidaa_tv
cat /tmp/problem_context.txt

Beispiel-Output:

### Problem-Kontext: vidaa_tv — 2026-05-04 23:34
-- GEFUNDENE ENTITIES (2) --
  media_player.wohnzimmer_tv: unavailable  (Wohnzimmer-TV)
  update.vidaa_tv_update: off

-- INTEGRATION STATUS --
  vidaa_tv 'Wohnzimmer-TV': setup_retry | Reason: Failed to connect to TV at 192.168.178.54

-- LOGBOOK (letzte 2h) --
  ...

-- AKTUELLER SYSTEM-SNAPSHOT (relevant) --
  ✗ vidaa_tv: Wohnzimmer-TV (setup_retry)

Claude braucht damit nur 1 Read-Call statt 4-6 API-Calls zum Sammeln von Kontext.

Anwendungs-Workflow (CLAUDE.md)

# Gerätestatus prüfen:
cat /config/tools/state_snapshot.txt

# Entity-ID finden:
cat /config/tools/entity_aliases.json

# Problem debuggen:
python3 /config/tools/problem_context.py 
cat /tmp/problem_context.txt

Docker Auto-Updater (2026-05-05)

Täglich automatisches Update aller stale Docker-Container auf dem NAS.

Script: /usr/anatol/claude/scripts/docker_auto_updater.sh\ Cron: täglich 09:00 (nach watchtower-check um 08:05)\ Log: /tmp/docker_auto_updater.log

Ablauf

1. Watchtower (monitor-only) → erkennt stale Container
2. Filter: alles mit "postgres" im Namen/Image wird übersprungen
3. Watchtower (--run-once) → updated verbleibende Container
4. Telegram-Bericht: was wurde aktualisiert, was übersprungen

Ausnahmeliste

| Muster | Grund | | postgres | Datenbankupdates können Breaking Changes haben |

Beispiel Telegram-Meldung

✅ Docker Auto-Update abgeschlossen
Aktualisiert: sonarr radarr ollama tdarr dokuwiki plex sabnzbd

Manueller Aufruf

ssh omv '/usr/anatol/claude/scripts/docker_auto_updater.sh'

Monitoring: sensor.ollama_status

Hinzugefügt: 10.05.2026

Ein REST-Sensor überwacht Ollama direkt aus Home Assistant:

| Parameter | Wert | | Entity | sensor.ollama_status | | Package | /config/packages/docker_monitor.yaml | | Endpoint | http://192.168.178.20:11434/api/version | | Polling | alle 2 Minuten | | Wert (online) | Ollama-Versionsnummer (z.B. 0.23.2) | | Wert (offline) | unavailable → wird vom Sensor-Monitoring gezählt |

Wenn Ollama offline geht, erscheint sensor.ollama_status automatisch in der normalen Sensor-Monitoring-Benachrichtigung.

Bekanntes Problem: Runner-Crash (GPU)

Symptom: Ollama läuft (Container up), aber API-Requests schlagen mit HTTP 500 fehl. Logs zeigen:

signal arrived during cgo execution
msg="llama runner terminated" error="exit status 2"

Ursache: llama.cpp-Runner crasht während GPU-Inferenz auf AMD RENOIR iGPU (Vulkan). Tritt sporadisch auf, Ursache unklar (Vulkan-Bug oder Speicherproblem).

Fix:

docker restart ollama
# danach kurz warten (~10s), dann wieder verfügbar

Sensor sensor.ollama_status meldet den Ausfall automatisch — nach docker restart kehrt er in wenigen Minuten zu einem Versionswert zurück.