Versioning prompts
Treating the prompt as a deployable artifact: what a version is, why prompts belong in source control, and linking versions to eval scores and traces.
Here is the mistake that ends most AI-feature incidents in confusion: the prompt lives in a chat window, a Notion doc, or an un-versioned string, and nobody can say which prompt produced the bad output. You've kept version numbers by hand since Prompt Engineering; LLMOps makes prompt versioning real infrastructure, because in production the prompt is the code — and code you can't version, you can't operate.
What a 'version' is
A prompt version is not just the prompt text. It's the whole configuration that determines behavior — because changing any of it changes the output:
- The prompt template(s) — system and user.
- The examples (few-shot content).
- The model + settings (
claude-sonnet-5, max_tokens). - Retrieval/tool config, if any (k, which tools, thresholds).
- A version id and a change log entry: what changed, why, and its eval delta.
VERSION = "triage-v7"
MODEL = "claude-sonnet-5"
MAX_TOKENS = 500
SYSTEM = """...full system prompt..."""
EXAMPLES = [ ... ]
# CHANGELOG (newest first)
# v7: added forwarded-message boundary example.
# eval: golden-v3 pass 88% -> 93%; holdout 90%. Ships.
# v6: tightened urgency definitions. 84% -> 88%.Prompts in source control
- Prompts live in the repo, not the app UI. A change to a prompt is a pull request — diffable, reviewable, revertible. A changed gold answer or a reworded rule gets the same scrutiny as changed code, because it has the same blast radius.
- Every deployed output is stamped with its version. The trace's version field (Module 3) plus the versioned prompt means 'which prompt said that, on which model?' is a lookup, not an archaeology project.
- Version = eval score = traces. The three link into one record: this version scored 93% on golden-v3, and here are its production traces. That linkage is what makes the loop auditable — you can prove what shipped, what it scored, and how it behaved.
At scale, teams put prompts in a prompt registry — a store where versions are named, tagged (staging/production), and fetched at runtime by id, so deploying a new prompt doesn't require a code deploy and rolling back is a pointer change. You'll build the minimal version (a versioned module + a 'current' pointer) in the lab; the concept is identical to the model/index registries you met in RAG. One honest caveat: the lab's registry is file-based — prompts/<feature>/vN.py ships with the app, and a version file is code, so changing the pointer there is still a commit and a deploy. True fetch-at-runtime-without-a-deploy needs an external store (a database or a config service) the app reads at call time; that's the same pattern, one layer out, and out of scope here.