Blog/LLMOps & Evals
Prompt-Versionierung in Produktion: Git, Registries, Labels und Rollbacks
Prompts in Produktion versionieren: was zu einer Version gehört, Git oder Prompt-Registry, Labels und Rollbacks, Eval-Gates in CI und Folgen für Caches.
Balázs Csorba··8 Min. Lesezeit
- Prompt management
- Versioning
- LLMOps
- Evals
- Langfuse

Das Wichtigste in Kürze
- Eine Prompt-Version ist das ganze Paket: Template, Modell, Parameter, Tools und Ausgabeschema. Gemeinsam versionieren, sonst lässt sich ein Ergebnis nicht reproduzieren.
- OpenAI stellt wiederverwendbare Prompt-Objekte ein, v1/prompts soll am 30. November 2026 abgeschaltet werden, und empfiehlt jetzt, Prompts im Anwendungscode zu halten.
- Registries wie Langfuse und MLflow bieten unveränderliche Versionen und verschiebbare Labels, ein Rollback wird so zur Label-Änderung statt zum Deployment.
- Jede Prompt-Änderung mit einem Eval-Lauf im Pull Request absichern und Produktions-Traces mit der erzeugenden Prompt-Version verknüpfen.
- Eine Änderung am System-Prompt oder an Tool-Definitionen invalidiert Prompt-Caches beim Anbieter, ein Prompt-Release ist also auch ein kurzes Kosten- und Latenzereignis.
Bei den meisten LLM-Features ändern sich die Prompts öfter als der Code. Ein Support-Assistent bekommt eine neue Eskalationsregel, ein Extraktionsschritt lernt ein neues Rechnungslayout, ein Klassifikator bekommt eine Kategorie mehr. Jede dieser Änderungen ist eine Verhaltensänderung in Produktion, und in vielen Codebasen die am wenigsten kontrollierte: ein im Dashboard bearbeiteter String, ein in eine Konfigurationsdatei kopiertes Template, kein Review und keine Aufzeichnung, welche Version einem bestimmten Kunden letzten Dienstag geantwortet hat.
Dieser Leitfaden zeigt, was eine Prompt-Version enthalten sollte, wann Git reicht und wann sich eine Prompt-Registry lohnt, wie Labels Rollbacks billig machen, wie man Prompt-Änderungen mit Evals in CI absichert, und eine Nebenwirkung, die Teams oft übersehen: ein Prompt-Release setzt den Prompt-Cache beim Anbieter zurück. Außerdem geht es um eine Änderung von 2026, die einen Teil der Debatte entscheidet: OpenAI stellt seine gespeicherten Prompt-Objekte ein.
Was zu einer Prompt-Version gehört
Ein Template-String allein bestimmt das Verhalten nicht. Derselbe Text liefert mit anderem Modell, anderer Temperatur, anderer Tool-Liste oder anderem Ausgabeschema eine andere Ausgabe. Wenn die Versionshistorie nur den Text festhält, lässt sich die Frage, die bei einem Vorfall zählt, nicht beantworten: was genau lief? Das Paket versionieren:
| Teil | Warum es zur Version gehört |
|---|---|
| System- und User-Templates | Die Anweisungen selbst |
| Modell-ID | Ein auf ein Modell abgestimmter Prompt ist auf einem anderen ein anderer Prompt |
| Parameter | Temperatur, Max-Tokens, Reasoning-Aufwand ändern die Ausgabe |
| Tool-Definitionen | Beschreibungen steuern die Tool-Wahl so stark wie der System-Prompt |
| Ausgabeschema | Nachgelagerter Code hängt davon ab |
| Few-Shot-Beispiele | Oft der größte und meistbearbeitete Teil |
Beide unten besprochenen Registries unterstützen das. Langfuse-Prompts haben neben dem Template ein Config-Feld, und MLflow erlaubt pro Version eine Commit-Message ähnlich wie bei Git. In Git erreicht man es, indem Template, Parameter und Schema im selben Modul liegen.
Git oder eine Prompt-Registry?
2026 kam das stärkste Argument für Git von einem Anbieter, der früher die Alternative verkaufte. OpenAI stellt wiederverwendbare Prompt-Objekte in seiner API ein: das Anlegen von Prompts wird ab 3. Juni 2026 zurückgestellt, und v1/prompts soll am 30. November 2026 abgeschaltet werden. Der Migrationsleitfaden rät, Prompt-Inhalte in den Anwendungscode zu ziehen, damit Prompt-Änderungen denselben Review- und Release-Prozess durchlaufen wie anderer Code, Prompt-Variablen durch typisierte Funktionsargumente zu ersetzen und Versionen mit Commits, Pull Requests und Evals in CI zu verwalten.
Registries lösen trotzdem echte Probleme. Langfuse und MLflow speichern unveränderliche Versionen mit verschiebbaren Labels, so kann eine Produktmanagerin eine Formulierung testen und ein Bereitschaftsingenieur in Sekunden ohne Deployment zurückrollen. Außerdem verknüpfen sie Produktionsmetriken mit Versionen. Die Frage ist nicht, welches Lager recht hat, sondern wer Prompts bearbeitet und wie schnell ein Rollback sein muss.
| Kriterium | Prompts in Git | Prompt-Registry |
|---|---|---|
| Wer bearbeitet | Entwickler | Entwickler und Fachleute |
| Review | Pull Request wie bei Code | Toolspezifisch, oft schwächer |
| Rollback | Revert und Deployment | Label verschieben, wirksam nach Cache-TTL |
| Laufzeitabhängigkeit | Keine | Registry-API, abgefedert durch Cache und Fallback |
| Metriken pro Version | Nur wenn man Traces selbst taggt | Eingebaut, wenn Traces verknüpft sind |
Unveränderliche Versionen, verschiebbare Labels
Das nützliche Denkmodell ist dasselbe wie bei Container-Registries: Versionen sind unveränderlich, Tags wandern. MLflow hält fest, dass Prompt-Versionen der Reproduzierbarkeit wegen unveränderlich sind und ein Alias wie production eine veränderliche Referenz ist, die man für A/B-Tests oder Rollbacks umhängen kann. Langfuse vergibt Versionsnummern automatisch, pflegt ein Label latest, das auf die neueste Version zeigt, und liefert die mit production gelabelte Version, wenn man ohne Label oder Version abfragt.
Zwei Details aus der Langfuse-Dokumentation sollte man im Design berücksichtigen. Wer ein Label anfragt, das keine Version trägt, bekommt einen 404; einen stillen Rückfall auf production oder latest gibt es nicht. Und geschützte Labels, verfügbar in den kostenpflichtigen und Enterprise-Editionen, verhindern, dass die Rollen viewer und member production verschieben, das Registry-Gegenstück zu einem geschützten Branch.
Prompts zur Laufzeit laden, ohne neue Fehlerquellen
Eine Registry setzt einen Netzwerkaufruf zwischen Feature und Anweisungen. Langfuse löst das mit einem clientseitigen Cache: die Standard-TTL beträgt 60 Sekunden, und nach Ablauf liefert das SDK weiter den alten Prompt aus, während es im Hintergrund neu lädt. Ist der Cache leer und die API nicht erreichbar, wird stattdessen ein mitgegebener Fallback-Prompt zurückgegeben. Für diesen letzten Fall muss man planen, denn er tritt beim Kaltstart genau in dem Vorfall auf, in dem die Registry ausfällt.
from langfuse import get_client
from prompts.support import SUPPORT_SYSTEM_FALLBACK # the same text, committed in git
langfuse = get_client()
def support_prompt():
# label, not version: promotion and rollback happen by moving "production"
return langfuse.get_prompt(
"support-assistant",
label="production",
cache_ttl_seconds=300, # default is 60; longer means slower rollbacks
fallback=SUPPORT_SYSTEM_FALLBACK,
)Die TTL ist ein Kompromiss, den man festhalten sollte: je länger, desto weniger Registry-Aufrufe und desto länger dauert es, bis ein Rollback jede Instanz erreicht. In Batch-Jobs und Evals eine explizite Version pinnen, dort zählt Reproduzierbarkeit mehr als das Folgen des Labels.
Wenn Prompts im Code leben: strukturieren
Der OpenAI-Leitfaden ist konkret: Prompts in ein kleines prompts/-Modul mit einem benannten Builder pro Prompt und leichten Eval-Fixtures, nicht inline über die Codebasis verstreut. Zwei Gewohnheiten kommen dazu. Erstens statische Inhalte nach vorn, dynamische nach hinten, was derselbe Leitfaden empfiehlt, weil Cache-Treffer von exakten Präfixen abhängen. Zweitens mit jedem Prompt eine Versionskennung exportieren, damit Traces auch ohne Registry festhalten, welcher lief.
// prompts/invoice-extract.ts
import { z } from 'zod'
export const INVOICE_EXTRACT = {
id: 'invoice-extract',
version: '2026-10-14.2', // bump on any change to text, model, params or schema
model: 'claude-sonnet-5-5',
params: { max_tokens: 2048 },
schema: z.object({ supplier: z.string(), total: z.number(), currency: z.string().length(3) }),
build: (input: { pdfText: string; locale: 'de' | 'en' | 'hu' }) => ({
system: SYSTEM_RULES, // static, long, cacheable: first
messages: [{ role: 'user' as const, content: `Locale: ${input.locale}\n\n${input.pdfText}` }],
}),
}Jede Prompt-Änderung mit einem Eval absichern
Versionierung sagt, was sich geändert hat; nur eine Evaluation sagt, ob es besser wurde. Das günstigste brauchbare Setup lässt bei jedem Pull Request, der Prompt-Dateien berührt, einen festen Testsatz gegen alten und neuen Prompt laufen. Die Promptfoo GitHub Action macht genau das: sie reagiert auf Änderungen unter den Prompt-Pfaden, vergleicht Prompts vor und nach der Änderung, postet das Ergebnis als PR-Kommentar mit Link zum Viewer und cacht Modellaufrufe zwischen Läufen, um Kosten zu sparen.
# .github/workflows/prompt-eval.yml (trimmed)
on:
pull_request:
paths: ['prompts/**']
jobs:
evaluate:
runs-on: ubuntu-latest
permissions: { pull-requests: write }
steps:
- uses: actions/checkout@v4
- uses: promptfoo/promptfoo-action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
prompts: 'prompts/**/*.json'
config: 'prompts/promptfooconfig.yaml'
cache-path: ~/.cache/promptfooWas in den Testsatz kommt, zählt mehr als das Tool. Bei echten Fehlern anfangen, wie in LLM-Evals für Produktfeatures beschrieben: jeder Bug-Report, den eine Prompt-Änderung behoben hat, wird ein Testfall, damit die nächste Änderung ihn nicht still zurückbringt. Ein Modell-Upgrade ist nur eine Prompt-Version mit neuer Modell-ID und bekommt dasselbe Gate, siehe Modellmigrationen ohne Regressionen.
Produktions-Traces mit Prompt-Versionen verknüpfen
Offline-Evals decken die Fälle ab, an die man gedacht hat. Die Produktion deckt den Rest ab, aber nur, wenn jede Generierung festhält, welche Prompt-Version sie erzeugt hat. Langfuse verknüpft einen Prompt über das SDK oder die Integrationen für OpenAI, LangChain und das AI SDK mit einer Generierung, und der Metrics-Tab vergleicht dann Versionen nach medianer Latenz, Input- und Output-Tokens, Kosten, Anzahl der Generierungen und medianem Score. Ein Vorbehalt aus der Dokumentation: wird der Fallback-Prompt verwendet, entsteht keine Verknüpfung, eine Häufung unverknüpfter Generierungen ist also selbst ein Signal, dass die Registry nicht erreichbar war.
Ohne Registry die Prompt-ID und -Version aus dem Code in die Span-Attribute schreiben. Das OpenTelemetry-Setup aus Observability für LLM-Agenten liefert denselben Vergleich mit einem Group-by.
Ein Prompt-Release ist auch ein Cache-Ereignis
Prompt-Caches beim Anbieter hängen an exakten Präfixen. Anthropic cacht tools, dann system, dann messages, und eine Änderung auf einer Ebene invalidiert diese und alle folgenden: wer eine Tool-Beschreibung ändert, verliert den ganzen Cache, wer den System-Prompt ändert, baut System und Nachrichten neu. Cache-Writes kosten mehr als normaler Input (das 1,25-Fache für den Fünf-Minuten-Cache), Reads nur einen Bruchteil, direkt nach einem Release zahlt man also Write-Preise und sieht längere Zeit bis zum ersten Token, bis das neue Präfix warm ist. Die Mechanik steht in Prompt-Caching und Modell-Routing.
Ein vernünftiger Standard für kleine Teams
In den Projekten, die ich baue, gilt: Git zuerst. Prompts liegen mit Modell, Parametern und Schema in einem prompts/-Modul; bei jeder Änderung wird ein Versionsstring erhöht; im Pull Request läuft ein promptfoo- oder vergleichbares Eval; und die Version landet in jedem Trace. Eine Registry kommt dazu, wenn jemand außerhalb des Entwicklerteams Prompts bearbeiten muss oder ein Rollback schneller sein muss als ein Deployment. Dann bleibt Git die Quelle der Wahrheit und CI veröffentlicht in die Registry, das Label wandert also erst, wenn das Eval-Gate bestanden ist.
- Produktionstext nie direkt bearbeiten. Version anlegen, evaluieren, Label verschieben.
- In Evals und Batch-Jobs Versionen pinnen, Labels nur in interaktiven Pfaden folgen.
- Für jeden Registry-Prompt einen Fallback-Prompt im Repository halten.
- Prompts im Review wie Code behandeln: der Diff eines Prompts verdient dieselbe Aufmerksamkeit wie der einer SQL-Abfrage.
Quellen
- OpenAI API Docs: Migrate from prompt objects
- OpenAI API Docs: Prompt engineering (reusable prompts deprecation note)
- Langfuse Docs: Prompt version control
- Langfuse Docs: Prompt caching in the SDKs
- Langfuse Docs: Link prompts to traces
- MLflow Docs: Prompt Registry
- Promptfoo Docs: GitHub Action
- Claude Platform Docs: Prompt caching
Häufige Fragen
Gehören Prompts in Git oder in ein Prompt-Management-Tool?
Standardmäßig in Git: Review, Historie und Tests gibt es gratis, und OpenAI empfiehlt inzwischen genau das. Eine Registry lohnt sich, wenn Nicht-Entwickler Prompts bearbeiten, wenn man ohne Deployment zurückrollen will oder Produktionsmetriken pro Version braucht. Viele Teams machen beides: Git als Quelle, eine Registry als Laufzeitspeicher.
Was ist der Unterschied zwischen Prompt-Version und Label?
Eine Version ist ein unveränderlicher Schnappschuss des Prompts; MLflow hält fest, dass Versionen nach dem Anlegen nicht bearbeitet werden können. Ein Label oder Alias wie production ist ein verschiebbarer Zeiger auf eine Version. Der Code fragt nach dem Label, und Freigabe oder Rollback heißt, den Zeiger zu verschieben.
Was passiert mit gespeicherten Prompts bei OpenAI?
OpenAI stellt wiederverwendbare Prompt-Objekte in der API ein. Das Anlegen von Prompts wird ab 3. Juni 2026 zurückgestellt, und der Endpunkt v1/prompts soll am 30. November 2026 abgeschaltet werden. Laut Migrationsleitfaden zieht man den Prompt-Text in den eigenen Code, ersetzt Variablen durch typisierte Funktionsargumente und übergibt das Ergebnis als input an die Responses API.
Kostet das Laden aus einer Registry Latenz?
Kaum, wenn das SDK cacht. Langfuse cacht Prompts clientseitig mit einer Standard-TTL von 60 Sekunden und aktualisiert sie im Hintergrund, währenddessen wird die alte Version ausgeliefert. Ist der Cache leer und die API nicht erreichbar, hält ein mitgegebener Fallback-Prompt die Anwendung am Laufen.
Wie teste ich eine Prompt-Änderung, bevor sie Nutzer erreicht?
Denselben Evaluationssatz bei jedem Pull Request, der Prompt-Dateien berührt, gegen alten und neuen Prompt laufen lassen. Die promptfoo GitHub Action macht das und postet den Vergleich als PR-Kommentar. Nach dem Release Scores, Latenz und Kosten pro Prompt-Version an verknüpften Traces vergleichen.