|Ben @ Grepture

Prompt-Management: Versionskontrolle für deine LLM-Prompts

Speichere, versioniere und liefere Prompts über Grepture aus — mit Variablen, konditionaler Logik, sofortigem Rollback und voller Traffic-Sichtbarkeit.

Prompts sind ein neues Primitiv

Prompts sind keine Config. Sie sind kein Copy. Sie sind eine neue Art von Artefakt, die es vor LLMs nicht gab, und sie brauchen eigenes Tooling. Ein Prompt steuert, wie sich deine AI verhält — Ton, Reasoning, Guardrails. Ändere einen Prompt und du änderst das Produkt. Das macht Prompts eher zu Code als zu Content, aber sie passen trotzdem nicht nahtlos in deinen bestehenden Entwicklungs-Workflow.

Wir haben Prompt-Management in Grepture eingebaut, weil wir glauben, dass Prompts dasselbe verdienen, was Code bereits hat: Versionierung, Rollback, Sichtbarkeit darüber, was in Produktion läuft, und eine Möglichkeit für dein ganzes Team, daran zu kollaborieren — ohne jedes Mal einen Deploy-Zyklus durchlaufen zu müssen.

So funktioniert Greptures Prompt-Management

Greptures Prompt-Management behandelt Prompts als verwaltete Ressource — versioniert, über den Proxy ausgeliefert und vollständig in das Traffic-Logging integriert. So sieht der Lifecycle aus:

  1. Erstellen — einen Prompt im Dashboard mit einem Slug anlegen (z.B. standard-support-replies)
  2. Bearbeiten — den Draft schreiben, Variablen definieren, mit dem Preview-Panel testen
  3. Publizieren — den Draft als unveränderliche nummerierte Version einfrieren (v1, v2, v3...)
  4. Aktivieren — festlegen, welche Version der Proxy ausliefert
  5. Auflösen — zur Request-Zeit injiziert der Proxy die richtigen Messages, bevor er an das LLM weiterleitet

Kein Redeployment. Keine Code-Änderung. Dein Anwendungscode referenziert einen Slug, und der Proxy erledigt den Rest.

Drafts und Versionierung

Das Versionierungsmodell ist bewusst einfach gehalten — es spiegelt wider, wie du mit allem arbeiten möchtest, das in Produktion geht.

Drafts

Jeder Prompt hat genau einen Draft. Er ist deine Arbeitskopie. Bearbeite ihn so oft du willst, teste ihn mit Variablen im Preview, teile ihn mit Teammates zur Review. Ein Draft wird nie in Produktion ausgeliefert, es sei denn, du forderst ihn explizit an (nützlich zum Testen — dazu gleich mehr).

Publizieren

Wenn du mit einem Draft zufrieden bist, publiziere ihn. Das erstellt einen Snapshot des aktuellen Drafts als unveränderliche nummerierte Version — v1, v2, v3 und so weiter. Publizierte Versionen können nicht bearbeitet werden. Das ist beabsichtigt: Du musst darauf vertrauen können, dass das, was du publiziert hast, auch das ist, was ausgeliefert wird.

Beim ersten Publizieren eines Prompts wird die Version automatisch aktiviert. Das ist eine Komfortfunktion — du willst nicht v1 publizieren und dich dann wundern, warum sich nichts geändert hat, weil du vergessen hast zu aktivieren.

Aktivieren und Rollback

Die aktive Version ist das, was der Proxy standardmäßig ausliefert. Du kannst jederzeit jede publizierte Version aktivieren. Das bedeutet: Rollback ist sofort. Wenn v5 Probleme macht, aktiviere v4. Kein Deploy, kein Revert-Commit, kein Warten. Dein nächster Request bekommt die vorherige Version.

Das ist das zentrale Wertversprechen von verwalteten Prompts. Wenn du Prompt-Inhalte vom Anwendungscode trennst, wird das Ändern oder Zurücksetzen eines Prompts eine Dashboard-Aktion statt eines Deployments.

Variablen und Template-Logik

Statische Prompts sind nützlich, aber die meisten Prompts in der Praxis brauchen Laufzeitdaten. Grepture verwendet Handlebars-Templates, die drei Muster unterstützen.

Variablen-Interpolation

Der einfachste Fall — einen Wert zur Request-Zeit injizieren:

You are a customer support agent for {{company_name}}.
The customer's name is {{customer_name}}.
Their issue: {{issue}}

Variablen werden beim Verwenden des Prompts übergeben (via SDK oder Headers), und der Proxy ersetzt sie, bevor er den Request weiterleitet.

Bedingte Blöcke

Nutze {{#if}}, um Abschnitte basierend auf dem Vorhandensein einer Variable ein- oder auszuschließen:

{{#if premium}}
This customer is on a premium plan. Prioritize their request
and offer proactive solutions.
{{else}}
This customer is on the free tier. Be helpful but direct
them to documentation for complex issues.
{{/if}}

Listen-Iteration

Nutze {{#each}}, um über Array-Variablen zu iterieren:

The customer has the following open tickets:
{{#each open_tickets}}
- {{this}}
{{/each}}

Variablen-Schema

Jeder Prompt kann ein Variablen-Schema definieren — Name, Typ und Standardwert für jede Variable. Das dient als Dokumentation für jeden, der den Prompt nutzt, und treibt das Test-Panel im Editor an. Du kannst genau sehen, wie dein Prompt mit verschiedenen Variablen-Kombinationen aufgelöst wird, bevor du publizierst.

SDK-Integration

Das Grepture SDK bietet drei Muster für die Nutzung verwalteter Prompts, jeweils mit unterschiedlichem Kontrollgrad.

Server-seitige Auflösung mit prompt.use()

Das ist der einfachste Ansatz und was wir für die meisten Anwendungsfälle empfehlen. Du referenzierst den Prompt per Slug, das SDK setzt die richtigen Headers, und der Proxy löst das Template auf und injiziert die Messages, bevor er an das LLM weiterleitet.

import Grepture from "@grepture/sdk";
import OpenAI from "openai";

const grepture = new Grepture({
  apiKey: process.env.GREPTURE_API_KEY,
  proxyUrl: "https://proxy.grepture.com",
});

const openai = new OpenAI({
  ...grepture.clientOptions({
    apiKey: process.env.OPENAI_API_KEY,
    baseURL: "https://api.openai.com/v1",
  }),
});

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: grepture.prompt.use("standard-support-replies", {
    variables: {
      customer_name: ticket.customerName,
      issue: ticket.description,
      tone: "friendly",
    },
  }),
});

Unter der Haube gibt prompt.use() ein spezielles Marker-Array zurück. Wenn der Wrapped Fetch des SDKs diesen Marker erkennt, setzt er X-Grepture-Prompt- und X-Grepture-Vars-Headers auf den ausgehenden Request. Der Proxy liest diese Headers, holt das Prompt-Template, löst Variablen auf und ersetzt das Messages-Array im Request-Body mit dem aufgelösten Inhalt. Dein LLM-Provider empfängt einen normalen Chat-Completion-Request — er hat keine Ahnung, dass ein Prompt-Management-System beteiligt ist.

Client-seitige Auflösung mit prompt.assemble()

Manchmal möchtest du die aufgelösten Messages inspizieren oder modifizieren, bevor du sie an das LLM sendest. prompt.assemble() holt den Prompt vom Proxy, löst Variablen auf und gibt dir das fertige Messages-Array zurück, das du beliebig verwenden kannst.

const { messages, metadata } = await grepture.prompt.assemble(
  "standard-support-replies",
  {
    variables: {
      customer_name: "Sarah",
      issue: "billing question",
      tone: "formal",
    },
  },
);

// Zusätzlichen Kontext anhängen vor dem Senden
messages.push({
  role: "user",
  content: additionalContext,
});

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages,
});

Das ist nützlich, wenn du zusätzliche Messages hinzufügen musst (z.B. abgerufenen Kontext aus einer RAG-Pipeline), Prompts aus verschiedenen Quellen zusammenführen oder die exakten Messages loggen willst, die gesendet werden.

Abrufen und Wiederverwenden mit prompt.get() und prompt.resolve()

Für Batch-Verarbeitung oder High-Throughput-Szenarien kannst du das rohe Template einmal abrufen und es mehrfach mit verschiedenen Variablen-Sets auflösen — ohne einen Netzwerk-Call pro Auflösung.

// Template einmal abrufen
const template = await grepture.prompt.get("standard-support-replies");

// Für jedes Ticket im Batch auflösen
const results = await Promise.all(
  tickets.map(async (ticket) => {
    const messages = grepture.prompt.resolve(template.messages, {
      customer_name: ticket.customerName,
      issue: ticket.description,
      tone: ticket.priority === "high" ? "empathetic" : "friendly",
    });

    return openai.chat.completions.create({
      model: "gpt-4o",
      messages,
    });
  }),
);

prompt.get() gibt die Messages mit {{handlebars}}-Platzhaltern zurück, plus das Variablen-Schema. prompt.resolve() ist eine reine Funktion — keine Netzwerk-Calls, keine Seiteneffekte. Diese Kombination ist ideal, wenn du Hunderte von Items verarbeitest und den Overhead eines Proxy-Roundtrips pro Auflösung vermeiden willst.

Version pinnen

Alle drei Methoden akzeptieren einen optionalen version-Parameter. Standardmäßig liefert der Proxy die aktive Version. Du kannst aber auch eine bestimmte Version pinnen oder den Draft anfordern:

// Auf Version 3 pinnen
grepture.prompt.use("standard-support-replies", { version: 3 });

// Draft verwenden (zum Testen)
grepture.prompt.use("standard-support-replies", { version: "draft" });

Das ist nützlich, um eine neue Version zu testen, bevor du sie aktivierst, oder um einen bestimmten Workflow auf einer bewährten Version zu halten, während du an der aktiven iterierst.

Wie der Proxy Prompts auflöst

Falls du dich für die Mechanik interessierst: So läuft es ab, wenn ein Request mit einem verwalteten Prompt den Proxy erreicht.

Der Proxy liest zwei Headers:

  • X-Grepture-Prompt — der Prompt-Slug, optional mit Versions-Referenz (z.B. standard-support-replies oder standard-support-replies@3 oder standard-support-replies@draft)
  • X-Grepture-Vars — ein JSON-String mit den zu injizierenden Variablen

Der Proxy holt das Prompt-Template (aus dem Redis-Cache oder der Datenbank), löst das Handlebars-Template mit den übergebenen Variablen auf und ersetzt das messages-Array im Request-Body. Der aufgelöste Request wird dann an den Ziel-LLM-Provider weitergeleitet.

Caching

Publizierte Prompt-Versionen werden in Redis mit einer TTL von 60 Sekunden gecacht. Da publizierte Versionen unveränderlich sind, ist der Cache immer konsistent — der einzige Preis ist eine kurze Verzögerung, wenn du eine neue Version aktivierst. Draft-Requests umgehen den Cache komplett und holen immer direkt aus der Datenbank, damit du Änderungen sofort siehst, wenn du testest.

Rules überspringen

Verwaltete Prompts können optional skip_rules setzen, um die Security-Pipeline (PII-Redaktion, Prompt-Injection-Erkennung usw.) für ihren Inhalt zu umgehen. Die Begründung: Wenn du den Prompt geschrieben hast und seinen Inhalt kontrollierst, ist es unnötiger Overhead, ihn durch die Injection-Erkennung zu schicken. Vom Nutzer bereitgestellte Variablen durchlaufen weiterhin die normale Pipeline. Das ist Opt-in und standardmäßig deaktiviert.

Traffic-Sichtbarkeit

Jeder Request, der einen verwalteten Prompt nutzt, speichert prompt_id und prompt_version im Traffic Log. Das gibt dir volle Nachverfolgbarkeit — für jeden geloggten Request kannst du genau sehen, welche Prompt-Version diese Antwort erzeugt hat.

Im Dashboard zeigt sich das an mehreren Stellen:

  • Traffic-Tabelle — eine Prompt-Spalte zeigt den Prompt-Namen für Requests, die verwaltete Prompts genutzt haben. Du kannst das Traffic Log nach Prompt filtern, um alle Requests für einen bestimmten Prompt zu sehen.
  • Traffic-Detail — die Detailansicht eines Requests zeigt Prompt-Name und -Version, mit einem direkten Link zu dieser Version im Prompt-Editor.
  • Prompt-Liste — die Prompts-Übersichtsseite zeigt Nutzungszahlen, damit du auf einen Blick siehst, wie viel Traffic jeder Prompt verarbeitet.
  • Prompt-Editor — ein „Traffic anzeigen"-Link führt dich zum Traffic Log, gefiltert auf diesen Prompt, damit du direkt vom Bearbeiten eines Prompts zu seiner Performance in Produktion springen kannst.

Das schließt die Lücke, die entsteht, wenn Prompts im Code leben. Du kannst eine verschlechterte Antwort auf eine bestimmte Prompt-Version zurückverfolgen, die Antwortqualität über Versionen hinweg vergleichen und fundierte Entscheidungen treffen, ob du rollbacken oder weiter iterieren solltest.

Erste Schritte

Prompt-Management einzurichten dauert ein paar Minuten.

1. Prompt erstellen — gehe zur Prompts-Seite im Grepture Dashboard, erstelle einen neuen Prompt mit Slug, schreibe deine Messages und publiziere.

2. SDK installieren und deine LLM-Calls durch den Proxy leiten:

npm install @grepture/sdk
import Grepture from "@grepture/sdk";

const grepture = new Grepture({
  apiKey: process.env.GREPTURE_API_KEY,
  proxyUrl: "https://proxy.grepture.com",
});

// Mit jedem OpenAI-kompatiblen Client verwenden
const openai = new OpenAI({
  ...grepture.clientOptions({
    apiKey: process.env.OPENAI_API_KEY,
    baseURL: "https://api.openai.com/v1",
  }),
});

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  messages: grepture.prompt.use("your-prompt-slug", {
    variables: { name: "World" },
  }),
});

3. Traffic Log prüfen — dein Request erscheint mit Prompt-Name und -Version, damit du verifizieren kannst, dass alles korrekt verdrahtet ist.

Wenn du Grepture bereits für PII-Redaktion oder Traffic-Logging nutzt, funktioniert Prompt-Management mit deinem bestehenden Setup — derselbe Proxy, dasselbe SDK, dasselbe Dashboard. Und wenn du neu bei Grepture bist, bringt dich der Quickstart-Guide in etwa fünf Minuten von Null zu einem funktionierenden Proxy.

Prompts sind zu wichtig, um als Strings in deiner Codebase zu leben. Gib ihnen dieselbe Versionierung, Sichtbarkeit und Kontrolle, die du dem Rest deiner Produktionsinfrastruktur gibst. Probier Grepture aus und sieh den Unterschied.