9.6 KiB
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/keymitAuthorization: Bearer <KEY>→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_usdmit 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:
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:
mesh-cost-break.pyliest letzte Usage-Zeile (Tages-Delta), vergleicht mitbudget.yaml-Deckeln.- Bei Deckel-Überschreitung (je Agent ODER Gesamt) schreibt es
kill_switches.jsonmitPAUSED-Status + Grund. - Jeder Sub-Agent hat im
mesh-agent-poller.sheinen Guard am Anfang (vor Task-pull), der per SSH prüft: "bin ich PAUSED?" → wenn ja:exit 0(keine Task-Übernahme, keine weiteren Kosten).
# 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('<MEINE_ID>',{})
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.blockiertin budget.yaml als Konfig/Log; harter Blocker (Modell gar nicht erst laden) ist offen.
Abfrage-Snippets
Master (lokal)
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)
u=$(sshpass -p 'Bp3lskt0' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=12 mehlzoerwer@<IP> '
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:
# 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.
hermes config set model.providers.openrouter.blocked_models '["deepseek/deepseek-v4-pro"]'
- Achtung Singular: Schlüssel ist
model.providers.…NICHTmodels.(sonst nur notiert, nicht gelesen). - Verifikation: Modell taucht in
hermes models listnicht mehr auf; Fallback greift aufs nächste. - Allowlist (
allowed_modelsnur 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.pynochmal 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.yamlentsprechend:tageslimit_agent_usd: 1.0,tageslimit_gesamt_usd: 4.0(4 Agents × 1$), keinegesamt_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