Phase 3 — Gate + Skill-Scaffold
Ziel: Cost-Risiko sofort cappen, parallel das Skill-Repo anlegen damit die Notbremsen + alles Folgende als wiederverwendbare Capability dokumentiert ist.
Aufwand: ~2h
Vorbedingung: keine (laeuft parallel zu Phase 1/2 — Notbremsen brauchen keine Caller-Daten).
Nachbedingung: Budget+Action live, max_tokens in allen Callern, Skill bedrock-cost-optimize existiert mit Grundstruktur.
Teil A — Notbremsen auf av-production
3A.1 AWS Budget + Budget-Action (Hebel 2)
CloudFormation-Template fuer Budget mit Schwellen 50%/75%/100% von $80, Email-Alarm + Budget-Action bei 100% die eine IAM-Restrict-Policy auf bedrock:InvokeModel (Account-weit) haengt.
Template wandert in templates/budget-action.yaml im Skill-Repo (Teil B). Deploy:
aws cloudformation deploy \
--stack-name bedrock-cost-gate \
--template-file intern/capabilities/skills/bedrock-cost-optimize/templates/budget-action.yaml \
--parameter-overrides \
MonthlyBudgetUsd=80 \
AlertEmail=hello@marvinkuehlmann.com \
--capabilities CAPABILITY_NAMED_IAM \
--profile av-production --region us-east-1Region us-east-1 ist Pflicht fuer AWS Budgets (Global Service).
Test: trigger den 50%-Alert manuell ueber Console — Mail kommt? Wenn ja: ready.
3A.2 max_tokens-Caps + Stop-Sequences (Hebel 3)
Pro Caller den Default max_tokens setzen (siehe Hebel-Matrix in caller-inventar). Stop-Sequences wo strukturierter Output (JSON, Tool-Use).
Open-WebUI VF: LiteLLM-Sidecar-Config bzw Modelfile editieren — max_tokens: 2000 als Default pro Modell. ECS-Task neu starten.
mcp-whatsapp Brain: Brain-Lambda-Code (~/source/mcps/mcp-whatsapp/brain/) — max_tokens=300 im Bedrock-Aufruf hard-coded. CDK-Stack redeploy.
mcp-vf-hosted: Proxy-Layer durchreichen — der MCP selbst macht keine Bedrock-Calls, aber wenn doch (z.B. Routing-Logik), max_tokens=1000.
Lambda-Routinen in agents-platform: pro Lambda im Code-Pfad pruefen. Bei Cron-Routinen meist max_tokens=500 ausreichend.
icking-ai-rebuild: im FastAPI-Bedrock-Call-Helper hard-coded max_tokens=1500 als Default, overridable per Request.
3A.3 Bedrock Service-Quotas drosseln (Hebel 10)
Service Quotas Console (eu-central-1) — pro Modell die Requests per minute-Quota auf einen Wert setzen der Normal-Last + Pufferer abdeckt, aber Runaway-Loops cappt.
Beispiel: Sonnet 4.6 in eu-central-1, aktuell Default 50 RPM. Wenn Normal-Last bei 5 RPM liegt: drossle auf 15 RPM. Bei Runaway gibt’s 429-Errors statt $1000-Rechnung.
aws service-quotas list-service-quotas \
--service-code bedrock \
--profile av-production --region eu-central-1Quota-Codes finden, dann request-service-quota-decrease (Increase geht direkt, Decrease via Support-Ticket — bei uns ist Default eh hoch).
Wichtiger Hinweis: Cross-Region-Inference-Profiles (eu.anthropic.claude-sonnet-4-6-...) zaehlen auf alle Backing-Regionen, also Quota in eu-central-1 und eu-west-3 (Paris) und eu-north-1 (Stockholm) checken.
Teil B — Skill-Scaffold
3B.1 Skill-Verzeichnis anlegen
intern/capabilities/skills/bedrock-cost-optimize/
├── SKILL.md
├── playbook.md
├── audit-checklist.md
├── rollout-map.md
└── templates/
├── budget-action.yaml # CloudFormation, in 3A.1 verwendet
├── aip-cloudformation.yaml # leer, Phase 4 fuellt
├── tool-description-audit.py # Phase 2 hat manuelles Pattern, hier als Script
└── caller-config-snippets/ # max_tokens-Defaults pro Caller-Typ
├── open-webui-litellm.yaml
├── lambda-bedrock-helper.py
└── mcp-eigenbau-bedrock.py
3B.2 SKILL.md Frontmatter + Trigger
---
id: skill-bedrock-cost-optimize
type: skill
name: bedrock-cost-optimize
purpose: "Bedrock-Kosten auf av-production diagnostizieren, cappen, optimieren und das Wissen in Vault-Patterns zurueckspielen."
status: active
required_mcps:
- "[[../../mcps/aws-pricing]]"
- "[[../../mcps/aws-api]]"
required_tools:
- Bash
- Read
- Write
- Edit
inputs:
- "Bedrock-Caller-Slug (optional, ohne = Account-weit)"
outputs:
- "Aktualisiertes caller-inventar.md (im jeweiligen Projekt)"
- "AIPs + Tags live"
- "Notbremsen live"
runs_log_in: intern/runs/<jahr>-<monat>.md
last_used: 2026-05-17
---3B.3 Trigger-Phrasen in intern/capabilities/skills/_index.md ergaenzen
Neue Zeile in der Skills-Tabelle:
| `bedrock-cost-optimize` | „bedrock kosten audit", „warum kostet bedrock so viel", „AIP einrichten fuer X", „MCP token check", „cost-gate fuer Y", „spar bedrock" | Bedrock-Kosten diagnostizieren, Notbremsen einbauen, AIPs pro Caller anlegen, Tool-Descriptions auditieren, Compounding in Best-Practices | [[bedrock-cost-optimize/SKILL]] |3B.4 playbook.md — die 10 Hebel mit Code
Jeder Hebel als Sektion:
- Worum geht’s (1 Satz)
- Wann anwenden (Trigger-Bedingung)
- Wie tun (Commands / Code-Snippets)
- Wie verifizieren
- Links auf Templates
Quelle der 10 Hebel: dieses Projekt + die parallel-Session-Hebel (Caching, Routing) damit der Skill vollstaendig ist.
3B.5 audit-checklist.md — pro Caller-Typ
Was zu pruefen ist wenn ein neuer Caller dazukommt:
- ECS-Service (Open-WebUI-aehnlich): AIP-Tag im Task-Definition?
max_tokensim LiteLLM-Config? - Lambda-Routine:
max_tokensim Code? Bedrock-Call-Helper benutzt? - Eigenbau-MCP mit Bedrock-Brain: Tool-Description-Audit bestanden?
max_tokensgesetzt?
3B.6 rollout-map.md
Matrix die caller-inventar spiegelt aber generischer — fuer beliebige zukuenftige Caller. Sagt: „wenn dein Caller Typ X ist, brauchst du Hebel 1/3/4/5/6, NICHT 7/9”.
Definition of Done
- CloudFormation-Stack
bedrock-cost-gatedeployed, Test-Alert ausgeloest -
max_tokensin allen aktiven Callern (mind. Open-WebUI, mcp-whatsapp, daily-briefing) explizit gesetzt - Bedrock Service-Quotas in eu-central-1/west-3/north-1 fuer Sonnet auf Normal+Puffer eingestellt
- Skill-Verzeichnis existiert mit SKILL.md, playbook.md, audit-checklist.md, rollout-map.md, leeren Templates
- Eintrag in
intern/capabilities/skills/_index.mdergaenzt - Plugin reload getestet (Skill taucht in Skill-Tool-Liste auf)
Risiken
max_tokenszu eng kann Antworten abschneiden — vor Production-Deploy in Open-WebUI mit Test-Chats validieren- Budget-Action mit IAM-Restrict ist hart — falls Alarm faelschlich triggert, ist Bedrock fuer alle Caller down. Mitigation: Restrict-Policy hat einen Escape-Tag (
emergency-bypass=true) den ich manuell auf eine Role setzen kann. Implementierungs-Detail inbudget-action.yaml. - Service-Quota-Decrease via Support-Ticket dauert 1-3 Werktage. Increase-Direction geht sofort, also auf konservativen Wert starten und ggf hochziehen.
Deploy-Status (2026-05-17)
Was deployed wurde
AWS Budget bedrock-cost-monthly (us-east-1) — Email-Alarme an hello@marvinkuehlmann.com bei 50% / 80% / Forecast-100% von $80. CostFilters auf Service: Amazon Bedrock + alle Anthropic/Cohere-Sub-Services. Achtung Feasibility-Finding: Sub-Service-Strings koennen vom Budget-API anders interpretiert werden als von Cost-Explorer. Verifizieren beim ersten Trigger.
Open-WebUI ECS-Task-Def neue Revision (rev:15 → rev:16) auf default-Cluster, deployed 2026-05-17 21:30 UTC+2. Container alle HEALTHY, Deployment-Circuit-Breaker greift nicht. Aenderungen:
| Change | Vorher | Nachher |
|---|---|---|
LiteLLM model_list | nur claude-sonnet-4-6 | + claude-haiku-4-5 (Background-Tasks, NICHT in DEFAULT_MODELS) |
LiteLLM claude-sonnet-4-6.litellm_params.max_tokens | (Default 4096+) | 2000 (Hard-Cap) |
LiteLLM claude-haiku-4-5.litellm_params.max_tokens | (n/a) | 1000 |
Open-WebUI TASK_MODEL | claude-sonnet-4-6 | claude-haiku-4-5 |
Open-WebUI TASK_MODEL_EXTERNAL | claude-sonnet-4-6 | claude-haiku-4-5 |
Open-WebUI DEFAULT_MODEL_PARAMS.max_tokens | 8192 | 2000 |
Open-WebUI DEFAULT_MODEL_PARAMS.thinking | {type: enabled, budget_tokens: 4096} | {type: disabled} |
User-facing Default-Modell bleibt vf-sonnet (= claude-sonnet-4-6) — VF-Pilot-User merken nur Extended-Thinking aus + max_tokens-Cap, nicht den Modell-Wechsel im Background.
Rollback-Pfad: aws ecs update-service --cluster default --service open-webui-vf --task-definition OpenWebUiVfTaskDef2DC830C3:15 — 1-Min-Operation, alte Revision intakt.
Was nach Review NICHT mehr deployed wurde
- Budget-Action mit IAM-Restrict-Policy: Security-Lens-Risiko zu hoch (False-Positive-Trigger würde Friseur-Live-WhatsApp + VF-Pilot kappen). Nur Email-Alarm aktiv. Deferred bis Allow-List-Pattern + Emergency-Bypass mit Tag-Condition pre-deploy getestet ist.
max_tokens-Caps in Lambdas (receptionist-brain, daily-briefing, beleg-pipeline): Adversarial-Finding sagt Bauchgefuehl-Werte koennen Tool-Use-Loops abschneiden. Erst p95-Lookup ueber 7 Tage, dann setzen.- Service-Quota-Decrease: Adversarial-Finding sagt LiteLLM client-side RPM-Limit ist gleicher Effekt ohne Support-Ticket — alternative Variante. Aktuell nicht akut weil Open-WebUI-Fix den 1M-Context-Trigger praktisch eliminiert (Extended-Thinking war vermutlich der Ausloeser).
- AIPs anlegen (Phase 4) — defer bis 7 Tage Mess-Periode entschieden hat ob Plan-Reduktion oder Vollplan.
Verifizierung
- LiteLLM-Container-Logs zeigen
Set models: claude-sonnet-4-6 / claude-haiku-4-5, Liveness-Probes 200 - Alle 3 Container HEALTHY (litellm, open-webui, cloudflared)
- Smoke-Test User-Chat steht aus — Marvin sollte einmal kurz https://vf-chat.agenticventures.de testen
Definition of Done
- AWS Budget mit Email-Alarmen 50/80/100% live (us-east-1, Service-Filter)
-
max_tokensin Open-WebUI ECS-Task hard-coded auf 2000 (Sonnet) und 1000 (Haiku) ueber LiteLLM-Layer - TASK_MODEL + TASK_MODEL_EXTERNAL auf Haiku migriert
- Extended Thinking in Open-WebUI DEFAULT_MODEL_PARAMS deaktiviert
- Bedrock Service-Quotas drosseln — defer (LiteLLM client-side RPM-Limit als Alternative)
- Skill-Verzeichnis: ✅ angelegt (siehe
intern/capabilities/skills/bedrock-cost-optimize/) - Eintrag in
intern/capabilities/skills/_index.mdergaenzt - Plugin-Reload getestet — manueller Schritt durch Marvin
- Smoke-Test Open-WebUI durch Marvin — pending