Runner — LLM-Agnostik-Schicht

Warum

Der Vault (wiki, pipelines, skills, runs) ist LLM-agnostisch. Nur der Runner spricht mit einem konkreten LLM. Indem wir diesen dünn und austauschbar halten, bleiben Vault und Prozesse unabhängig vom Anbieter.

Ziele:

  • Wechsel zwischen Claude (Anthropic), Mistral (EU) und Ollama (lokal) ohne Vault-Änderung
  • Routing nach Task-Typ: komplexes Reasoning → Claude, Routine → Ollama, EU-Compliance → Mistral
  • Kein Lock-in auf Claude Code als CLI

Stand (Phase 0)

Wir nutzen aktuell Claude Code als Runner. Dieses Dokument ist ein Konzept — wir planen die Abstraktion, bauen sie aber erst, wenn ein konkretes Bedürfnis auftritt (z.B. Kunde verlangt EU-only LLM, oder Ollama-Routing für Kostensenkung).

Bis dahin: jede Pipeline und jeder Skill MUSS so geschrieben sein, dass sie auch ohne Claude-Code-Spezifika laufen würden. Siehe ../../../_meta/conventions.md Abschnitt “Vendor-Neutralität”.

Geplanter Stack

Proxy-Schicht: LiteLLM

litellm vereinheitlicht die APIs:

Runner  ──►  LiteLLM Proxy  ──►  Anthropic | Mistral | Ollama | OpenAI | ...

Ein einziges Tool-Call-Format, ein Logging, ein Caching. Wechsel per ENV-Variable.

Runner-Optionen

OptionFuer wenKommentar
Claude CodeJetzt, Phase 0Ausgereift, Skills + MCPs out-of-the-box. Anbieter-gebunden.
aiderSehr Code-lastige PipelinesMulti-LLM, gut fuer Dev-Flows, weniger für Agentur-Prozesse
continue.devIDE-nahes ArbeitenEditor-Plugin, gut für Marvin beim Coden
Eigener Python-RunnerSpezifische PipelinesKlein halten: pydantic-ai oder DSPy + LiteLLM. ~200 Zeilen reichen für einen Pipeline-Executor, der Stage 01→05 durchgeht.

Empfehlung für ersten eigenen Runner

Wenn wir den Schritt gehen (nicht jetzt):

  • pydantic-ai für strukturierte Outputs (jede Stage liefert typisierte Daten)
  • LiteLLM als Modell-Abstraktion
  • Einfacher State-Machine-Loop der pipelines/<name>/ einliest, Stage für Stage durchgeht, Outputs in runs/<id>/ schreibt
  • MCPs optional einbinden via mcp-use (Python-MCP-Client)

Vendor-Neutralitaets-Checkliste fuer Skills und Pipelines

Damit ein spaeterer Runner-Wechsel ohne Umbau klappt:

  1. description in SKILL.md generisch halten — “Use when the user wants to X”, nicht “Claude laedt diese Skill, wenn…”
  2. Keine Claude-Idiomatik in Prompts — kein erzwungenes <thinking>, keine Anthropic-System-Prompt-Quirks
  3. MCPs als optional dokumentieren — jeder Stage-Contract: “Falls Tool Y verfuegbar, nutze es; sonst manuelle Eingabe”
  4. Tool-Call-Syntax dem LLM ueberlassen — wir schreiben Tool-Namen + Parameter in Prosa, nicht in Anthropic-spezifischem JSON
  5. Keine Claude-Plugins als harte Abhaengigkeit — alle Plugin-Funktionen koennten auch durch Skills + externe Scripts abgedeckt werden

Routing-Strategie (spaeter)

Grobe Heuristik:

  • Ollama lokal (mistral-nemo, qwen2.5, llama3.2): Tages-TODOs, Email-Scan-Preprocessing, Fahrtenbuch-Eintraege, Belege-Kategorisierung, einfache Formatierungs-Tasks
  • Mistral API (EU): Kunden-faehige Pipelines wenn EU-Daten-Anforderung, mittlere Komplexitaet
  • Claude Opus/Sonnet: Komplexes Reasoning, Pipeline-Orchestrierung, Strategie-Arbeit, lange Kontexte

Konfiguration via ENV:

# .env.local (nicht im Repo!)
LITELLM_DEFAULT=anthropic/claude-opus-4-6
LITELLM_ROUTINE=ollama/mistral-nemo
LITELLM_EU=mistral/mistral-large

Ordner-Struktur (wenn wir den Runner bauen)

Wenn die Abstraktion gebaut wird, kommt sie als eigenes Python-Projekt-Unterverzeichnis in den Vault. Vorschlag:

runner/
  litellm_config.yaml     ← Modelle + Routing
  executor.py             ← Pipeline-Executor
  adapters/               ← Tool-Call-Adapter pro Provider
  .env.example            ← ENV-Template ohne Secrets

Heute existiert runner/ noch nicht — wir legen ihn erst an, wenn wir den ersten eigenen Runner tatsächlich bauen.