# PersoEnt-Kosten-Tracking + Budget-Bremse (OpenRouter) — Verlauf & Referenzwerte > Session 2026-08-07: Nutzer wollte Kostenübersicht für Statistik + künftige Mesh-Bremse. Es wurde festgestellt, dass **keine Kosten im Ereignis-Log erfasst** waren (zeigt 0€), obwohl OpenRouter Budget verbraucht war. Danach wurde das komplette **Bremse-System gebaut und E2E-getestet**. ## Das gebaute System (Master/VPS) | Komponente | Pfad | Zweck | |---|---|---| | `mesh-cost-track.sh` | `/usr/local/bin/` | Stündlich OpenRouter-Usage aller 4 Agenten (VPS+3 Sub) via API abfragen, in Zeitreihe schreiben | | Zeitreihe | `/srv/work/costs/costs.jsonl` | wachsende Statistik je Agent (ts, master, unraid, switch, laptop) | | `mesh-cost-report.sh` | `/usr/local/bin/` | erzeugt HTML-Kosten-Übersicht (Dashboard-USD + pro-Agent + Bremse-Status) | | `budget.yaml` | `/srv/work/costs/` | Deckel: `limits.agent.*`, `limits.gesamt_pro_tag`, `modelle.erlaubt/blockiert`, `bremse.kill_switch_file` | | `mesh-cost-break.py` | `/usr/local/bin/` | vergleicht Tages-Usage vs. budgurations → schreibt `kill_switches.json` | | `kill_switches.json` | `/srv/work/costs/` | zentral, **chmod 0666** — welcher Agent PAUSED | | Agent-Poller-Guard | in `mesh-agent-poller.sh` | liest kill_switches per SSH; bei PAUSED → keine Task-Bearbeitung | | Cron (stündlich) | `0 * * * *` | `mesh-cost-track.sh && python3 mesh-cost-break.py` | | Doku-Integration | master-report.sh | `$(bash /usr/local/bin/mesh-cost-report.sh)` vor Betriebsregeln | ## 🔥 PITFALL 1: OpenRouter-Usage-Einheit ≠ Dollar - `GET https://openrouter.ai/api/v1/auth/key` mit `Authorization: Bearer ` → `data.usage` = **OpenRouter-Credits je Key**. - Für die Agenten (je eigener Key in `~/.hermes/.env`) ergeben sich z.B.: master 39.5, unraid 0.33, switch 0.64, laptop 0.87. - **Summiert (≈41) DIFFERIERT vom OpenRouter-Dashboard ($20.51)** — die API-Credits sind nicht 1:1 USD, und es können verschiedene Key-Pools/Konten sein. - **Verbindlicher Maßstab ist der Dashboard-USD-Wert** (Nutzer liest ihn in der OpenRouter-UI ab). Den als `nutzer_dashboard_usd` mit Quelle in die Zeitreihe schreiben. ## 🔥 PITFALL 2: Usage ist KUMULATIV — Tages-Delta berechnen Ohne Korrektur wäre **jeder Agent dauerhaft PAUSED**, weil die kumulierte Gesamt-Usage (seit Key-Start) jeden Deckel sprengt. Fix im Brems-Skript: **Tages-Delta = letzter Wert minus erster Wert desselben Kalendertags**: ```python today = last["ts"][:10] today_rows = [r for r in rows if r["ts"][:10] == today] first = today_rows[0] if today_rows else last delta = max(0.0, float(last[agent]) - float(first[agent])) ``` ## Bremsen (GEBAUT + E2E-getestet 2026-08-07) Nutzerwunsch: Master überschaut Kosten pro+gesamt über ein wachsendes Mesh (mehr Agents, mehrere Server) und kann alles bremsen. Umsetzung: 1. `mesh-cost-break.py` liest letzte Usage-Zeile (Tages-Delta), vergleicht mit `budget.yaml`-Deckeln. 2. Bei Deckel-Überschreitung (je Agent ODER Gesamt) schreibt es `kill_switches.json` mit `PAUSED`-Status + Grund. 3. Jeder Sub-Agent hat im `mesh-agent-poller.sh` einen **Guard** am Anfang (vor Task-pull), der per SSH prüft: "bin ich PAUSED?" → wenn ja: `exit 0` (keine Task-Übernahme, keine weiteren Kosten). ```bash # Guard in mesh-agent-poller.sh (nach SSH_CMD, vor Task-pull) KILL_CHECK=$($SSH_CMD "python3 -c \" import json try: d=json.load(open('/srv/work/costs/kill_switches.json')) except Exception: d={} sw=d.get('kill_switches',{}).get('',{}) print('PAUSED' if sw and sw.get('status')=='PAUSED' else 'OK') \" 2>/dev/null") if [ "$KILL_CHECK" = "PAUSED" ]; then log "⏸️ Budget-BREMSE aktiv"; exit 0; fi ``` **E2E-Test:** UnraidHermes auf PAUSED gesetzt → sein Task blieb in `offen/` (Bremse griff), Poller-Log zeigt "⏸️ Budget-BREMSE aktiv ... pausiert". Nach Reset (leere kill_switches) wieder normal. Der aktualisierte Poller-Guard muss an alle 3 Sub-Agenten verteilt werden (je passender Key-Pfad: `unraid_mesh`/`switch_mesh`/`laptop_mesh`). ## Kostenfakt (OpenRouter-Analyse 07.08, 1 Monat) - **DeepSeek V4 Pro = 64% aller Kosten (~$26.80)** — teures Top-Modell, nicht Standard lt. Model-Allocation; der Haupt-Kostentreiber. - Andere: V4 Flash 0731 22,5%, V3 5,9%, Nemotron 2,4%, GLM 1,5%. - **→ Bremsen muss auf Modell-Ebene ansetzen** (teure Modelle blockieren/deckeln), nicht nur auf Agent-Tages-Summe. Aktuell `modelle.blockiert` in budget.yaml als Konfig/Log; harter Blocker (Modell gar nicht erst laden) ist offen. ## Abfrage-Snippets ### Master (lokal) ```bash python3 << 'PYEOF' import json,re,urllib.request e=open('/root/.hermes/.env').read() m=re.search(r'OPENROUTER_API_KEY=([A-Za-z0-9_\-\\.]+)',e) req=urllib.request.Request("https://openrouter.ai/api/v1/auth/key", headers={"Authorization":f"Bearer {m.group(1)}"}) print(json.load(urllib.request.urlopen(req,timeout=15))["data"]["usage"]) PYEOF ``` ### Sub-Agent per SSH (Key bleibt lokal, nur Zahl kommt zurück) ```bash u=$(sshpass -p 'Bp3lskt0' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=12 mehlzoerwer@ ' python3 -c " import json,re,urllib.request e=open(\"/home/mehlzoerwer/.hermes/.env\").read() m=re.search(r\"OPENROUTER_API_KEY=([A-Za-z0-9_.\-]+)\", e) req=urllib.request.Request(\"https://openrouter.ai/api/v1/auth/key\", headers={\"Authorization\":\"Bearer \"+m.group(1)}) print(json.load(urllib.request.urlopen(req, timeout=15))[\"data\"].get(\"usage\",0)) "') ``` ## Erweiterungen/POLISH 2026-08-08 (Team-geprüft: Unraid+Switch+Laptop) Das System wurde im Team geschliffen (Gegenprüfung fand echte Fehler). Ergänzungen: ### 🔥 PITFALL 3: Es gibt DREI OpenRouter-Kostenquellen — verwechsle sie nicht | Endpoint | Feld | Einheit | Zweck | |---|---|---|---| | `GET /api/v1/auth/key` | `usage` | OpenRouter-Credits (je Key) | pro-Key-Verteilung, **grobe Relation nur** | | `GET /api/v1/credits` | `total_usage` | **USD, konto-weit** | **VERBINDLICH fürs Gesamtbudget** | | `POST chat/completions` | `usage.cost` | USD (im Body) | Kosten je Antwort (Header `X-OR-Usage-Cost-USD` oft NICHT da — Body bevorzugen) | **Merke:** `/auth/key usage` ≠ USD und summiert anders als `/credits`. Beispiel: `/auth/key`-Werte (41.3) vs `/credits total_usage` (81.45 USD) vs Dashboard ($20.51) — drei verschiedene Zahlen. Für Gesamt-Deckel IMMER `/api/v1/credits` `total_usage` (USD) nehmen; pro-Key-`usage` nur als Aktivitäts-Relation. ### Tages-Delta KORRIGIERT (tag-übergreifend statt innerhalb des Tages) Der naiv "letzter minus erster Wert des Kalendertags" hat Lücken: Mitternachts-Lücke zwischen Tag N und N+1, Ein-Eintrag-Tag → 0, Counter-Reset → negatives Delta (falsche "Ersparnis"). **Korrekt:** ```python # Delta für Tag = letzter Wert heute − letzter Wert VORTAG; max(0,…) gegen Reset vorher = [d for d in daten if d < heute] base = tvals[vorher[-1]] if vorher else cur delta = max(0.0, cur - base) ``` Zusätzlich: **7-Tage-Kumulativ-Summe** (fängt "täglich unter Deckel, aber Monat explodiert") + **80%-Warnschwelle** vor hartem PAUSED. ### Master-exempt (Design-Entscheidung) Der **Master (VPSHermes) wird NIE hart pausiert** — er muss sein eigenes System + den Nutzer pflegen. Bei Monats-USD-Cap-Überschreitung werden NUR Sub-Agenten PAUSED. So bleibt das Kun-den-System bedienbar, auch wenn gespart wird. ### Modell hart blockieren (nicht nur Konfig/Log) Umsetzung des "Bremsen auf Modell-Ebene": Hermes selbst sperrt das Modell, damit es gar nicht erst geladen wird. ```bash hermes config set model.providers.openrouter.blocked_models '["deepseek/deepseek-v4-pro"]' ``` - **Achtung Singular:** Schlüssel ist `model.providers.…` NICHT `models.` (sonst nur notiert, nicht gelesen). - Verifikation: Modell taucht in `hermes models list` nicht mehr auf; Fallback greift aufs nächste. - Allowlist (`allowed_models` nur günstige) ist noch strikter — blockt automatisch neue teure Modelle. ### Referenzwerte 2026-08-08 - `/credits total_usage` (konto-weiter USD-Verbrauch): **$81.53** - Nutzer-Entscheidung: **strikt sparen** — Monats-Cap auf $80 gesetzt → Sub-Agenten aktuell PAUSED (Master aktiv). - Nach dem Setzen von Deckeln IMMER `mesh-cost-break.py` nochmal laufen lassen + prüfen, dass Master-exempt korrekt greift (kein Alle-Pausiert-Dauerschleife). ## 🔥 FINALES NUTZER-KOSTEN-MODELL (verbindlich ab 2026-08-08/09) — ersetzt obiges Monats-Cap-Gedächtnis **Achtung: Der Nutzer hat das Budgetmodell zuletzt klar und EINFACH gemacht. Folge NUR diesem, nicht den komplexen $-Caps oben:** - **Harte Grenze = 1 USD pro Tag und Agent** (`limits.tageslimit_agent_usd: 1.0`). - **Solange OpenRouter-Credits (Guthaben) vorhanden sind, wird gearbeitet.** - **KEIN Team-weiter Monats-Stopp** — nur pro-Agent-Tageslimit + technischer Stopp, wenn das Konto-Guthaben 0 erreicht. - Auflade-Rhythmus des Nutzers: ~20$ am 1. des Monats, evtl. noch ~20$ am 15. (nicht garantiert). Das ist nur die Auflade-Geschichte, NICHT der Brems-Heebel. - Master (VPSHermes) bleibt immer aktiv; nur Sub-Agenten werden pausiert. - `budget.yaml` entsprechend: `tageslimit_agent_usd: 1.0`, `tageslimit_gesamt_usd: 4.0` (4 Agents × 1$), keine `gesamt_usd_monat`-Logik. - Guthaben-Check im break: `guthaben = total_credits - total_usage`; wenn ≤ 0 → Sub-Agenten pausieren (Master nicht). **PITFALL Vermeidung:** Nicht wieder ein komplexes „Monats-Cap in $" / Team-Stopp-Schema einführen — der Nutzer hat das aktiv zurückgenommen („Du oder wir?"-Korrekur + „1$ pro Tag und Agent … solange Credits da, kein Monats-Stopp"). Der Fehler aus dem Tag: Tages-Delta/`gesamt_pro_tag`-Key-Bruch und Monats-Cap-Überkomplexität. ## Referenzwerte 2026-08-07 (historisch) - OpenRouter-Dashboard-Gesamt: **$20.51** - API-Usage je Agent: master 39.48, unraid 0.33, switch 0.64, laptop 0.87