Files

9.6 KiB
Raw Permalink Blame History

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 <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_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:

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).
# 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.blockiert in 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.… 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