Insights / AI Operations · · 12 min read

Prompt versioning and evaluation for production AI

Prompts in production are code that changes behaviour for every user at once, so we register them, version them, test them against fixed evaluation sets and keep a one-step rollback. How a prompt registry works, what goes into a test set and how we decide a new version is ready to release.

A prompt looks like text, so teams treat it like text. Someone opens a file, rewrites a sentence to fix a complaint, deploys, and moves on. The complaint goes away. Two other behaviours change quietly, and nobody notices for a week.

In production, a prompt is closer to code than to copy. It changes what the product does for every user at once, and its effects are hard to predict by reading it. That is why prompt versioning and evaluation is one of the standing practices across Oryvelon's AI products: every important prompt lives in a registry, has numbered versions, is tested against a fixed evaluation set before release, and can be rolled back in minutes. This article describes how that works and why each part exists.

Why prompts drift when nobody is watching

Prompt problems rarely come from one bad edit. They come from many reasonable ones.

A support lead asks for a friendlier tone. An engineer adds a line to stop the model mentioning a discontinued feature. A product manager adds an example to fix one customer's case. Each change is sensible. Together they produce a prompt that is twice as long, contradicts itself in two places and behaves differently from the version everyone thinks is live.

Three things make this worse with AI than with ordinary code. First, the effect of a change is not local: adding a sentence about tone can change how the model formats numbers. Second, the model underneath may change too, so the same prompt can behave differently next month. Third, there is usually no test that fails. Ordinary code breaks loudly. A drifting prompt just gets slightly worse.

Versioning and evaluation exist to make those changes visible and deliberate.

What a prompt registry is

A prompt registry is a central record of every prompt a product uses in production. Our AI gateway holds one per product. Products never share a registry, and there is no group-wide system prompt that every company inherits.

Each registered prompt has:

  • An identifier. A stable name such as briefing.summary or rules.explain.
  • Versions. Numbered, immutable. Version 7 is always exactly version 7.
  • An owner. The person who approves changes.
  • A changelog entry per version. What changed and why, in a sentence or two.
  • A test status. Which evaluation set it was run against, when, and the result.
  • Its model binding. Which routing rule it is designed for, since a prompt tuned for one model tier may behave differently on another. See Model routing: matching tasks to the right AI model.
  • Its output contract. The schema the output must match, if any.

Applications do not contain prompt text. They ask the gateway for briefing.summary at a given version, or at whatever version is marked live for that feature. The registry is where the text lives.

This one change — moving prompts out of application code and referring to them by identifier — does most of the work. It makes every prompt change a visible event with a name, a number and an author.

Versions are immutable

The single most useful rule in our registry is that a published version is never edited. If version 7 needs a fix, the fix is version 8.

It sounds pedantic until the first time something goes wrong. If versions can be edited in place, "roll back to version 7" is meaningless, because version 7 is no longer what it was. Logs that record "prompt version 7" stop telling you what the model actually received. Evaluations run last month cannot be compared with evaluations run today.

With immutable versions, every log line, every evaluation result and every incident report points at an exact text. That is what makes the rest of the system trustworthy.

We apply the same rule to anything the prompt depends on at runtime. If a prompt includes a few fixed examples, those examples are part of the version. If it includes a list of allowed categories, that list is part of the version. Changing any of them creates a new version.

What goes into an evaluation set

A prompt without an evaluation set is a prompt you can only judge by reading. That is not enough.

An evaluation set is a fixed collection of inputs for a feature, with a description of what a good output looks like for each one. We build them from four sources:

  1. Typical cases. Real-shaped inputs that represent everyday use. For a store briefing, an ordinary day with a normal mix of orders and a couple of refunds.
  2. Edge cases. The inputs that are unusual but legitimate. A day with zero orders. A store with a single product. A briefing input in which every figure is flat.
  3. Known failures. Every time a prompt misbehaves in production, the input (with personal information removed) becomes a test case. The set grows from real incidents.
  4. Adversarial cases. Inputs designed to push the model out of bounds: instructions hidden in user text, requests for things the product does not do, inputs that invite the model to invent a reference.

Test inputs are synthetic or anonymised. We do not copy real customer records into evaluation sets, and for products involving children we do not use real student content at all. See Environments and test data and Data minimisation for children in edtech.

For many features, a few dozen well-chosen cases is a useful starting point. Quantity matters less than coverage. Fifty variations of the same ordinary day tell you less than fifteen cases that each test something different.

How outputs are scored

Scoring is where evaluation becomes useful or useless. A vague rubric like "is it good?" gives vague answers. We break quality into checks that are as mechanical as possible.

Automatic checks run on every case:

  • Does the output match the schema?
  • Does every reference in the output point to something that exists in the input? See Structured outputs: validating AI responses before users see them.
  • Are required points present? For a briefing, is the largest change in the input mentioned?
  • Are forbidden things absent? Invented numbers, promises the product cannot keep, advice outside the product's boundaries.
  • Is the length within limits?

Rubric checks need judgement: is the explanation clear, is the tone right for the product, does it read naturally. These can be scored by a person, or by a second model call with a strict rubric. When we use a model as a grader, we treat it as a tool that needs its own checks: we compare its scores with a person's on a sample before trusting it, and we never let the same prompt grade its own output.

The result is a small table for each version: pass rates per check, with the failures listed. That table is what gets attached to the version's test status in the registry.

The release gate

A new prompt version goes live only when it passes a simple gate:

  1. It has been run against the feature's full evaluation set.
  2. It is at least as good as the current live version on every check marked as critical — schema validity, reference integrity, forbidden content.
  3. It improves something the change was meant to improve, and the improvement is visible in the results.
  4. Any regression on non-critical checks is understood and accepted in writing by the owner.
  5. The changelog says what changed and why.

The second point is the one that prevents most incidents. A change that makes summaries more readable but occasionally lets an invented figure through is not an improvement. It is a regression with good prose.

After passing the gate, the new version is rolled out to a share of traffic first. The gateway records the prompt version on every request, so validation failure rates, fallback rates and user feedback can be compared between old and new versions directly. If the numbers hold, the new version becomes live for everyone.

Rollback in minutes, not days

Every release plan needs a way back. For prompts, ours is a single configuration change: mark the previous version as live.

Because versions are immutable and applications refer to prompts by identifier, rollback does not require a code deployment, a review cycle or a hunt for the old text. The owner changes one value, and within minutes every new request uses the previous version.

We decide the rollback triggers before release, not during an incident. Typical ones:

  • the validation failure rate for the feature rises above its normal band;
  • the fallback rate rises, meaning users are seeing the degraded experience more often;
  • a critical check fails on a production input that the evaluation set did not cover.

That third case always ends the same way: roll back, add the input to the evaluation set, fix, re-test, release again. The set gets stronger with every incident.

Prompts and model changes together

Prompts and models are coupled. A prompt tuned on one model can behave differently on another, even a newer and supposedly better one. So we never change both at once.

When a product evaluates a new model, it runs the current live prompt on the new model against the existing evaluation set. If the results are good, the routing rule changes and the prompt stays the same. If the results are close but not quite there, a new prompt version may be written for the new model, and that pair is evaluated together as a unit.

Changing one thing at a time is slower on paper. In practice it is faster, because when something goes wrong you know which change caused it.

A worked example: a rule change at KeşifAtlası

KeşifAtlası helps people understand visa and relocation eligibility, starting from Türkiye. The eligibility decision comes from a verified rules database, never from a model. The model's job is to explain, in plain language, which rules applied and why, citing rule identifiers. See Rules engines for eligibility.

Imagine a destination country changes the minimum income requirement for one of its visa categories. The rules team updates the rules database first, with the new threshold, an effective date and a source. That is a data change, not a prompt change.

Now suppose the explanation prompt, rules.explain, contains an example that mentions the old threshold as a sample figure. That example is part of the prompt version. Left alone, it could nudge the model toward repeating the outdated number in some explanations. So the owner creates a new version with a neutral example, and the evaluation set gains new cases: an applicant just above the new threshold, one just below it, and one who would have qualified under the old rule but no longer does.

The new version is scored. The critical checks: every figure in the explanation must come from the input, every rule cited must exist in the input's rule list, and no explanation may state or imply a decision different from the one the rules engine produced. The new version passes. It rolls out to a share of traffic, the numbers hold, and it goes live. The old version stays in the registry, unchanged, in case it is ever needed.

The lesson generalises. Keep facts out of prompts wherever possible. When a fact must appear, it belongs to the version, and changing it is a release.

What this looks like in a small team

None of this requires a large platform team. The registry can start as a structured file per product with versions and changelogs, and a script that runs the evaluation set and prints a table. That is roughly where ours started. We built more only when the number of prompts made the simple version painful, in keeping with the rule against architecture theatre described in What an AI gateway does.

What matters is the discipline, not the tooling:

  • prompts out of application code;
  • immutable versions with owners and changelogs;
  • an evaluation set per feature, growing from real failures;
  • a written release gate;
  • a rollback that is one configuration change.

A founder with one AI feature can adopt all five this week.

Ownership, review and the changelog

Every prompt in the registry has one owner. Not a team, not a channel: one person. Others can propose versions, but the owner approves what goes live and answers for how the feature behaves.

For low-risk features, the owner's own review is enough once the evaluation passes. For features where a wrong output could mislead someone about something that matters to them — an eligibility explanation at KeşifAtlası, a learning explanation for a student at EduRelia, anything that touches consent or contact details at CastLyra — a second person reviews the diff and the evaluation table before release. The reviewer is looking for two things the numbers can miss: instructions that quietly widen what the model is allowed to say, and examples that smuggle in facts.

The changelog is where that review leaves a trace. A good entry is short and specific:

Version 12. Removed the sample income figure from the second example; added three threshold cases to the evaluation set. Critical checks unchanged; clarity improved on edge cases. Reviewed by the product lead.

A poor entry says "tweaks" or "improved tone". Six months later, nobody can tell what changed or why, and the version history stops being useful.

We also keep a short note on each prompt describing what it must never do. For a briefing prompt: never state a figure that is not in the input. For an explanation prompt: never state or imply an eligibility outcome. These lines turn directly into critical checks in the evaluation set, so the boundary is tested every release rather than remembered.

Common mistakes

  • Editing live prompts in place. It destroys the history you need for rollback and debugging.
  • Evaluating by reading. A prompt that looks better can behave worse. Run the set.
  • Only testing the happy path. Most production incidents come from edge and adversarial cases.
  • Using real customer data in test sets. Anonymise or synthesise. Test data is still data, and it has to follow the same retention and deletion rules as everything else.
  • Letting a model grade itself. Graders need their own validation against human judgement.
  • Changing the prompt and the model together. You lose the ability to tell which one caused a change.
  • Shared prompts across products. It feels efficient and quietly couples products that should stand alone. Each Oryvelon company owns its prompts, consistent with shared infrastructure, separate data.

How it pays off

The benefits compound over time. Every incident adds a test case, so the same failure rarely happens twice. Every model release can be evaluated quickly, because the test sets already exist. Every change has an author and a reason, so a new team member can read the changelog and understand why a prompt looks the way it does. And the cost side improves too: a clean evaluation set is what lets a team prove a smaller, cheaper model is good enough, which is one of the most reliable levers in cost discipline for AI products.

It also changes the conversation inside a team. "I think the new prompt is better" becomes "version 9 matches version 8 on every critical check and improves clarity scores on the edge cases". Disagreements get shorter.

Summary

Prompt versioning and evaluation treat production prompts as what they are: code that changes behaviour for every user at once. At Oryvelon each product keeps its own prompt registry in the AI gateway, with immutable numbered versions, owners, changelogs and test status. Every feature has an evaluation set built from typical, edge, known-failure and adversarial cases, scored with mechanical checks wherever possible. New versions pass a written release gate, roll out to a share of traffic first, and can be rolled back with a single configuration change. The practice needs little tooling, grows stronger with every incident and turns prompt changes from opinion into evidence.

Questions and answers

What is a prompt registry?

A prompt registry is a central record of the prompts a product uses in production, where each prompt has an identifier, numbered versions, an owner, a changelog and a test status, and applications request prompts by identifier and version.

How do you evaluate a prompt before release?

Run the new version and the current version against the same fixed set of test inputs, score both with the feature's checks — schema validity, factual faithfulness, required points, tone limits — and only release if the new version is at least as good on every check that matters.

How large should a prompt evaluation set be?

Large enough to cover the real variety of inputs and the known failure cases; for many features a few dozen carefully chosen examples is a useful start, growing as production reveals new edge cases.

NextStructured outputs: validating AI responses before users see them →