--- name: mesh-master-control description: "Use when: Master steuert Modell/Budget/Notfall im Mesh." version: 1.0.0 platforms: [linux] related_skills: [model-allocation, multi-agent-mesh, openrouter-cost-budgeting] --- # Mesh-Master-Control — SSH + Modell-Scout + Kill-Switch ## Prinzip Der Master (VPSHermes, 172.24.196.119) bestimmt im Mesh **alles** was Modell, Budget und Notfall-Steuerung angeht. Der Nutzer soll nicht 24/7 aufpassen müssen — der Master handelt autonom bei Kosten-Explosion, Modell-Ausfall oder Budget-Knappheit. **Kernregel (Nutzervorgabe, August 2026, hart):** SSH-Kanal vom Master zu allen Sub-Agenten MUSS funktionieren. NFS-Tasks sind zu langsam für Notfälle. WENN SSH fehlt → SOFORT fixen (Key generieren + an Sub-Agenten pushen), NICHT stillschweigend mit NFS weiterwursteln. ## 1. SSH-Control-Kanal ### SSH-Key auf Master generieren ```bash ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N "" -C "mesh-master@172.24.196.119" ``` ### Public-Key an Sub-Agenten verteilen (AcceptMasterKey-Task) Datei in `/srv/work/tasks/offen/YYYYMMDD.C.D.AcceptMasterKey.json`: ```json { "task_id": "YYYYMMDD.C.D.AcceptMasterKey", "ziel_agent": "", "aufgabentyp": "config", "prioritaet": "high", "beschreibung": "AcceptMasterKey", "aufgabe_details": { "master_pubkey": "", "schritte": [ "mkdir -p ~/.ssh && chmod 700 ~/.ssh", "echo '' >> ~/.ssh/authorized_keys", "chmod 600 ~/.ssh/authorized_keys" ] } } ``` **Dateiname-Schema:** `YYYYMMDD.C.D.AcceptMasterKey.json` (C.D = letzte 2 ZT-IP-Oktette) ## 2. Model Scout (alle 3 Tage) **Script:** `/usr/local/bin/mesh-model-scout.py` (Python, 26 KB, vollstaendig autonom) **Cron:** `0 6 */3 * * /usr/local/bin/mesh-model-scout.py >> /var/log/mesh-model-scout.log 2>&1` **Bekannte Modelle (Hardcoded in Script):** 25+ Modelle aus DeepSeek, Llama, Gemini, Qwen, Mistral, Nvidia, MiniMax, Cohere — mit Bewertungen in 5 Dimensionen. **Cache:** OpenRouter-API-Cache unter `/tmp/openrouter_models.json` (1h-Gueltigkeit) ### Ablauf 1. **OpenRouter-API live abrufen** (GET /api/v1/models, 300+ Modelle) oder aus Cache 2. **Filtern** auf ≥64k Kontext + gültige Preise + bekanntes Modell 3. **Bewerten** in 5 Dimensionen (1–5): Coding, Reasoning, Linux/Ops, Docs/Text, Tool-Use 4. **Agenten-Matching** nach Rollenprofil 5. **Budget-Simulation** (Token × Preis = Tageskosten × 30 = Monat) 6. **Aenderungserkennung** (Vergleich mit `model_scout_last.json`) 7. **Ausgabe:** JSON + HTML-Doku + Tasks an Sub-Agenten 8. **Telegram-Benachrichtigung** mit Zusammenfassung ### Rollen-Profile (Stand 31.08.2026 — Nutzer-Bestaetigung: je Agent eigenes Modell, Master das teuerste bis $2/M) | Agent | Modell | Input $/M | Begruendung | Kosten/Monat | |-------|--------|-----------|-------------|------------| | Master | `deepseek/deepseek-v4-flash` | $0.089 | Coding 5/5, Linux 4/5, Tool-Use 4/5 — beste Passung fuer Master-Aufgaben | ~$1.33 | | UnraidHermes | `deepseek/deepseek-v4-flash-0731` | $0.065 | Coding 5/5, Reasoning 4/4 — guenstiger als Maverick bei besserer Leistung. Nutzer fand $3.89 zu teuer → DeepSeek V4 Flash, $1.12/Monat | ~$1.12 | | SwitchHermes | `qwen/qwen3.7-flash` | $0.030 | 1M Kontext, sehr guenstig, solides Allround-Modell fuer ARM64 | ~$0.66 | | LaptopHermes | `mistralai/mistral-nemo` | $0.019 | Solides Allround, 131k Kontext, flexibel fuer Text + leichte System-Aufgaben | ~$0.26 | **Regel (Nutzer 31.08.2026):** Jeder Sub-Agent bekommt ein ANDERES Modell. Der Master bekommt das teuerste (bis $2/M Input). Subs bleiben unter $1/M Input. Gesamtkosten unter $25/Monat. **Gesamtkosten:** ~$3.37/Monat (von $25 Limit → ~7 Monate Reserve) ### Ausgabe-Orte - JSON: `/srv/work/tasks/model_scout_last.json` - HTML: `/var/www/dokumentationen.perfekt-ohne-en.de/model-scout-.html` - Live: https://dokumentationen.perfekt-ohne-en.de/model-scout-latest.html - Tasks: `/srv/work/tasks/offen/YYYYMMDD.C.D.ModelAssignment.json` ### Bekannte Bugs im Script (Stand August 2026) - `distribute_via_tasks()` erwartet `/srv/work/tasks/offen/` — wenn nicht vorhanden, schlaegt silent fehl. Fix: `os.makedirs(task_dir, exist_ok=True)` vor Schreibzugriff. (Gefixt in Version 1.1 via Patch 22.08.2026.) ## 3. Budget-Kill-Switch (3 Stufen, alle 30 Min) **Script:** `/usr/local/bin/mesh-budget-watch.sh` (Cron-gesteuert) **Cron:** `*/30 * * * * /usr/local/bin/mesh-budget-watch.sh` **State:** `/var/lib/mesh-budget-state` (entprellt Telegram-Benachrichtigungen) **Aktuelles Guthaben (28.08.2026):** $25.69 USD (nach Aufladung +$25) **Letzter Log:** `/var/log/mesh-budget-watch.log` ### Budget-Keyword-Report (per Chat/Telegram) **Script:** `/usr/local/bin/mesh-budget-report.sh` Wenn der Nutzer "Budget" sagt (als Wort, nicht als Frage), führt Master dieses Script aus. Es holt: - **OpenRouter-Guthaben** live via API (`/api/v1/credits`) - **Modelle aller 4 Agents** live via SSH (`hermes config get model.default`) **Telegram-Format (Bullet-Liste, KEIN Code-Block):** ``` ​​​​ Budget (29.08 13:35) Guthaben: $24.09 • Master — gemini-2.5-flash • Unraid — gemini-2.5-flash • Switch — nemotron-3 • Laptop — gemini-2.5-flash ``` **Regel (Nutzer 29.08.2026):** Bullet-Liste statt Code-Block. Kein Doppel-Output (Script schreibt nur an Telegram, gibt nichts auf stdout). Modellnamen auf <20 Zeichen kuerzen (family + version only). ### Schwellen (verbindlich, Nutzer-Bestaetigung 28.08.2026) | Stufe | Guthaben | Aktion | |-------|----------|--------| | OK | > $1.00 | Normalbetrieb | | WARN | < $1.00 | Telegram-Warnung (einmalig) | | SWITCH | < $0.50 | Alle Agents → Ollama via `mesh-kill-all.sh` | | STOP | < $0.10 | Komplett-Stopp (alle kostenpflichtigen Calls) | ## 4. Notfall-Tools ### mesh-kill-all.sh ```bash /usr/local/bin/mesh-kill-all.sh ``` Setzt **alle Agents** auf Ollama: 1. Telegram: "🚨 MESH-KILL-SWITCH ausgelöst" 2. SSH an 3 Sub-Agenten → `hermes config set model.default ollama` 3. Master selbst → ebenfalls Ollama ### mesh-model-broadcast.sh ```bash mesh-model-broadcast.sh [provider] # provider default: openrouter mesh-model-broadcast.sh google/gemini-2.5-flash:free openrouter mesh-model-broadcast.sh ollama ollama ``` Setzt Modell + Provider auf **Master + allen 3 Sub-Agenten** gleichzeitig. ## 5. Status-Monitor (Antworten tracken) **Script:** `/usr/local/bin/mesh-status-monitor.sh` **Cron:** `*/30 * * * * /usr/local/bin/mesh-status-monitor.sh` - Prüft: offene Tasks, erledigte Tasks, SSH-Status pro Agent - Telegram-Meldung NUR bei Status-Änderung (entprellt) - Finalmeldung: "✅ ALLE 3 SSH FUNKTIONIEREN" wenn komplett ## 6. Sub-Agenten im Mesh | Sub-Agent | ZT-IP | Suffix (C.D) | |-----------|-------|--------------| | UnraidHermes | 172.24.34.142 | 34.142 | | SwitchHermes | 172.24.20.26 | 20.26 | | LaptopHermes | 172.24.178.202 | 178.202 | ## 7. Gateway-Auto-Restart (Reboot-Festigkeit) Der hermes-gateway.service startet nicht automatisch nach Reboot, wenn UFW/ZeroTier noch nicht bereit sind. **Fix (29.08.2026):** ```bash # 1. Service-File bereinigen (doppelte Restart-Einträge entfernen) # 2. ZeroTier-Abhängigkeit hinzufügen (After=zerotier-one.service) # 3. StartLimitBurst erhöhen (Default 5 → nie aufhören zu retryen) # 4. RestartSec auf 15s setzen (Netzwerk-Zeit geben) systemctl enable hermes-gateway.service # damit nach Reboot startet ``` **Service-File (final, getestet 29.08.2026):** ``` [Unit] Description=Hermes Agent Gateway - Messaging Platform Integration After=network-online.target zerotier-one.service Wants=network-online.target zerotier-one.service StartLimitIntervalSec=0 StartLimitBurst=999 [Service] Type=simple User=root Group=root Restart=always RestartSec=15 ... ``` **Wichtig:** OHNE `After=zerotier-one.service` startet der Gateway bevor ZeroTier verbunden ist → Telegram-Verbindung scheitert → exit code 1 → systemd gibt auf (nach 5 Versuchen default). Der Fix ist NICHT nur `enable`, sondern auch die Abhängigkeit und das Burst-Limit. **Prüfung nach Reboot:** ```bash systemctl is-active hermes-gateway.service # sollte 'active' sein systemctl show hermes-gateway.service -p Restart -p RestartSec -p StartLimitBurst # Restart=always, StartLimitBurst=999 ``` **Detail (Fehleranalyse 29.08.2026):** - `journalctl -u hermes-gateway.service --no-pager | tail -30` zeigte `Connection error` + `exit code 1` - ZeroTier war nicht bereit, UFW blockte SSH (siehe SSH/UW-Fix) - Der Fix kombiniert: Service enable + ZeroTier-After + StartLimitBurst + UFW-Regeln ## 8. Sub-Agent-Task-Format (hart, Pitfall August 2026) **Sub-Agenten führen lange Tasks nicht aus — sie analysieren sie.** Ein Task mit 5+ Sätzen Kontext, Erklärungen oder mehreren Optionen führt dazu, dass der Sub-Agent einen Essay über die Aufgabe schreibt statt sie auszuführen. **Regel (verbindlich):** - Tasks MÜSSEN ein `befehl`-Feld enthalten — ein einzelner, kurzer Shell-Befehl - Max 2 Sätze Kontext pro Task - KEINE Erklärung, KEINE Optionen, KEINE Theorie - Sub-Agent antwortet mit Ausführung oder Fehler, nicht mit Analyse **Richtiges Format (funktioniert):** ```json { "task_id": "YYYYMMDD.C.D.Key", "ziel_agent": "AgentName", "prioritaet": "high", "befehl": "mkdir -p ~/.ssh && echo '' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" } ``` **Falsches Format (Sub-Agent analysiert statt auszuführen):** ```json { "task_id": "...", "kontext": "Master hat neuen SSH-Key generiert...", "aufgabe_details": { "schritte": ["1. Prüfe...", "2. Überlege...", "3. Analysiere..."] } } ``` **Erkenntnis aus 28.08.2026 (3 vergebliche AcceptMasterKey-Versuche):** Sub-Agenten verstehen `ausfuehren`/`befehl` als direkten Terminal-Befehl. Ohne dieses Feld denken sie über die Aufgabe nach statt sie zu terminieren. ## 9. Budget-Report-Format (Nutzer-Vorgabe, 29.08.2026) Wenn der Nutzer "Budget" sagt (ein Wort, kein Fragezeichen): 1. Führe `/usr/local/bin/mesh-budget-report.sh` aus (stumm, >/dev/null) 2. Das Script sendet direkt an Telegram 3. **Kein Doppel-Output** ins Chat-Fenster **Telegram-Format:** ``` ​​​​ Budget (DD.MM HH:MM) Guthaben: $XX.XX • Master — model-shortname • Unraid — model-shortname • Switch — model-shortname • Laptop — model-shortname ``` **Format-Regeln:** - Bullet-Liste (KEIN Code-Block) - Modellnamen auf <20 Zeichen kürzen (nur family+version, z.B. `gemini-2.5-flash` statt `google/gemini-2.5-flash:free`) - Zeile `Agent Modell` + Trennlinie entfernt (führt auf Handy) - Kein vorheriges Echo der Ausgabe (Script stdout >/dev/null) ## 10. Deploy-Check-Pflicht (3-Check-Liste, aus Impressum-Fehlern gelernt) **Vor JEDEM systemctl reload/restart oder nginx-Config-Change:** ```bash bash /usr/local/bin/mesh-deploy-check.sh [python-app.py] ``` ### Die 3 Checks | # | Check | Befehl | Verhindert | |---|-------|--------|------------| | 1 | nginx -t | `nginx -t` | Config-Fehler, die nginx killen | | 2 | HTTP 200 | `curl -s -o /dev/null -w '%{http_code}' https:///` | Domain offline nach Deploy | | 3 | Python-Syntax | `python3 -m py_compile app.py` | SyntaxError nach systemd-Restart | 4. **Nach dem Deploy: Team-Review auf der LIVE-Seite, bevor dem Nutzer "fertig" gemeldet wird** → Technischer Deploy-Check (nginx-t + HTTP 200 + py_compile) reicht nicht: **Kontrast-Fehler vom 01.09.2026:** Seite war technisch 200, Inhalt komplett, aber Text auf Hintergrund hatte nur 4.2:1-Kontrast (WCAG-AA fordert 4.5:1) → schwarze Schrift auf schwarzem Hintergrund. SwitchHermes hat es im Review sofort gefunden. → **Fix:** Nach bestandenem 3-Check: Task an SwitchHermes ODER LaptopHermes mit vollem Seiteninhalt + Aufforderung zur visuellen Prüfung (Kontrast, Lesbarkeit, Layout). → **Regel:** "Fertig" bedeutet: technische Checks PASS + Team-Review PASS + Nutzer-Korrektur-Runde PASS. 5. **Sub-Agent-Review: Seite NICHT per URL prüfbar → Inhalt einbetten** → Sub-Agenten (besonders schwächere = SwitchHermes) laden oft keine externen URLs oder stoßen an Tool-Limits. `curl -s "https://seite.de/"` liefert leeres Resultat. → **Fix:** Seiteninhalt DIREKT in die Task-Beschreibung einbetten (HTML, relevante Text-Auszüge). Nie: "Siehe https://.../ -> prüfe das." Sondern: "Hier der Seiten-Inhalt: <...>. Prüfe Kontrast/Layout." 6. **Cleanup-Cron für alte Tasks** ```bash openssl x509 -in /etc/letsencrypt/live//fullchain.pem -noout -text | grep DNS: ``` → certbot --expand überschreibt Configs und kann falsche Zertifikate zuweisen (Fehler #5: veganbedeutetleben.de war offline, weil evolution-Zertifikat verwendet wurde). 2. **Kein nginx reload ohne nginx -t vorher** → Ein fehlerhafter Vhost killt ALLE Domains, nicht nur die eine. 3. **Kein systemd restart ohne py_compile vorher** → IndentationError nach Patch killt den Service (Fehler #3). 4. **Sub-Agent-Tasks immer mit konkretem Material, nicht mit Verweisen** → `curl -s https:///` als Beispiel ODER Inhalt direkt im `kontext`-Feld. → Nie "URL siehe Master-Datei" — Sub-Agent hat keinen Zugriff auf Master-Files. 5. **Cleanup-Cron für alte Tasks** → `find /srv/work/tasks/in_arbeit/ -mtime +7 -exec mv {} /srv/work/tasks/archiv/ \;` → Läuft wöchentlich Mo 06:00 (seit 01.09.2026 aktiv). ### mesh-deploy-check.sh (Tool) ```bash # Nutzung bash /usr/local/bin/mesh-deploy-check.sh evolution.perfekt-ohne-en.de bash /usr/local/bin/mesh-deploy-check.sh evolution.perfekt-ohne-en.de /opt/impressum/app.py # Ausgabe bei Erfolg [1/3] nginx -t ... ✅ [2/3] curl https://.../ ... ✅ HTTP 200 [3/3] python3 -m py_compile ... ✅ ✅ ALLE CHECKS BESTANDEN — Deploy freigegeben! ``` ## 11. Pitfalls - **Detaillierte SSH-Key-Verteilung mit Fehlerverlauf:** `references/ssh-key-verteilung-2026-08-28.md` - **Ersteinrichtung (Modell, Budget, Tools):** `references/ersteinrichtung-2026-08-22.md` - **Ohne SSH keine Master-Kontrolle.** Vor Scout/Kill-Switch prüfen: `ssh mehlzoerwer@ "echo OK"`. Bei Fehler: AcceptMasterKey ablegen + warten ODER Nutzer manuell auf Sub-Agenten einloggen lassen. - **Sub-Agent antwortet 2h nicht?** Sofort nutzer ansprechen — kein Ghosting, kein NFS-Workaround. - **<$0.50 triggert automatisch.** Nutzer informieren. - **Scout schreibt NFS-Tasks, kein SSH-Broadcast.** Bei kritischen Änderungen IMMER `mesh-model-broadcast.sh` nutzen. - **Ollama-Port vor Kill-Switch prüfen:** `curl http://172.24.196.119:11434/api/tags` - **Ergebnisse von Sub-Agenten IMMER gegen echten Systemstand verifizieren** (curl, ls, ss). Keine Agenten-Behauptung blind glauben. - **ed25519-Key, kein rsa.** Name: `id_ed25519`. - **Sub-Agent-Tasks muessen kurz und befehlsorientiert sein.** Lange Text-Tasks (5+ Saetze, Kontext) → Sub-Agent analysiert statt auszufuehren. Kurzer `befehl`-Eintrag → Ausfuehrung. Pitfall im August 2026: AcceptMasterKey und SetModel-Tasks scheiterten, weil Sub-Agenten analysierten statt den Befehl zu terminieren. Loesung: Task-Format `{"aufgabentyp": "terminal", "befehl": ""}` - **Modelle auf Sub-Agenten immer mit absolutem Hermes-Pfad setzen.** `hermes config set ...` scheitert, wenn `$PATH` den `hermes`-Pfad nicht enthaelt. IMMER: `/home/mehlzoerwer/.local/bin/hermes config set model.default ` - **Henne-Ei: SSH-Key-Verteilung per NFS-Task.** Master braucht SSH, kann aber Keys nicht per SSH verteilen → NFS-Task. Sub-Agenten fuehren Shell-Befehle (`echo pubkey >> authorized_keys`) nicht in ihrer Sandbox (nur `execute_code`/Python) aus. Loesung (Stand 28.08.2026): Nutzer loggte sich manuell auf allen 3 Sub-Agenten per SSH ein und fuehrte die 2 Befehle aus (Key akzeptieren + Modell setzen). Danach funktioniert SSH vom Master zu ALLEN Sub-Agenten. - **SSH-Status aus 28.08.2026 (FINAL):** ✅ SSH funktioniert zu ALLEN 3 Sub-Agenten (UnraidHermes, SwitchHermes, LaptopHermes). Kill-Switch und Model-Broadcast sind operationsbereit. - **Sub-Agenten haben `hermes` nicht immer in $PATH.** Bei SSH-Befehlen IMMER absoluten Pfad nutzen: `/home/mehlzoerwer/.local/bin/hermes config ...`. Auf SwitchHermes z.B. war `hermes` in $PATH nicht auffindbar, nur via absolutem Pfad. - **Jeder Sub-Agent bekommt ein eigenes Modell** (Nutzer-Vorgabe 31.08.2026). Keine zwei Subs teilen sich dasselbe Modell. Der Grund: Diversitaet der Modell-Familien als Fehlertoleranz und Kostenoptimierung. - **LaptopHermes hatte unpinned Cron-Job** (`Monatsanfang-Budget-Erinnerung`) nach Modell-Wechsel → `hermes cron edit --provider openrouter --model google/gemini-2.5-flash:free`. Erkannt via Drift-Fehler beim ersten SSH-Zugriff. - **Official HTML-Dokumentation** von Scout-Ergebnissen unter `/var/www/dokumentationen.perfekt-ohne-en.de/` — Nginx-Vhost `dokumentationen` leitet dorthin. - **OpenRouter-Guthaben-Prüfung** via API: `curl -sk https://openrouter.ai/api/v1/credits -H "Authorization: Bearer "`