Skip to main content

Module 10 — Reusable prompt library

Modules 1 to 9 turned the running case's naive extraction into a prompt that is framed, exampled, structured, styled, hardened against injection and measured on a test set. The last mile is turning this one prompt into an artifact a team can share, review and evolve. This module covers templating, versioning, documentation and the lightweight governance that keeps a prompt library from decaying into folklore.

From a working prompt to a template

The prompt you shipped is bespoke to one task. A template makes the same structure reusable across tasks with variables that get substituted at call time:

from string import Template

EXTRACT_TEMPLATE = Template("""You extract $fields from
$input_kind. Return a JSON object with those fields.

Rules:
- Use only information present in the $input_kind.
- If a field is not mentioned, write null.
- Do not add commentary.

$input_kind:
$input
""")

def build_prompt(fields: list[str], input_kind: str, input_text: str) -> str:
return EXTRACT_TEMPLATE.substitute(
fields=", ".join(fields),
input_kind=input_kind,
input=input_text,
)

The variables are the ones that legitimately vary between uses — the fields to extract, the type of input. Everything else — the "use only information present", the "do not add commentary" — stays constant, because that is what modules 1 to 6 measured and validated. Variables of style live in a separate template, imported the same way.

Version every prompt

A prompt is code. It ships behaviour to production. It has to be versioned like code:

PROMPT_ID = "extract.complaint-email"
PROMPT_VERSION = "1.4.0"

def prompt_v1_4_0(email: str) -> str:
return build_prompt(
fields=["reason", "product", "urgency", "requested_action"],
input_kind="customer complaint email",
input_text=email,
)

Semantic versioning is the right convention: 1.4.0 bumps to 1.5.0 on a behaviour-improving change validated on the test set, and to 2.0.0 on any change that alters the output contract (a renamed field, a new required value). Every call logs the version alongside the input and output, so a downstream problem three weeks later can be traced back to the exact prompt that produced it.

The change history lives in a plain markdown file next to the prompt:

## 1.4.0 — 2026-09-06
- Added "unknown" as an allowed urgency value.
- Per-field scores: urgency 0.72 → 0.84 (+0.12), others unchanged.
- Evaluated on eval_set/complaint-en-v3.jsonl (50 emails).

## 1.3.0 — 2026-08-22
- Added the sarcasm handling instruction.
- Per-field scores: reason 0.81 → 0.88, urgency unchanged.

Notice the numbers. A change note without scores is a marketing message; a change note with scores is engineering history.

Document the context of use

A prompt in isolation is a mystery. Document what it is for, what its inputs look like, what temperature to call it with, which model family it was validated on, and what happens if it fails:

# extract.complaint-email/README.yml
id: extract.complaint-email
version: 1.4.0
purpose: Extract structured fields from a customer complaint email in English.
inputs:
- email: raw customer email text, no HTML, one language, English only.
outputs:
- schema: ComplaintFields v2 (reason, product, urgency, requested_action).
recommended:
model: gpt-4o-mini or equivalent.
temperature: 0.
retries: 3 with exponential backoff.
validated_on:
- gpt-4o-mini (2026-09)
eval_set: eval_set/complaint-en-v3.jsonl

Every developer picking up the prompt should be able to answer, from the README alone, three questions: what does it do, what does it expect, and what should I know before changing it.

Review prompts like pull requests

The change to a prompt goes through the same review as a code change:

  • Diff of the prompt file and the change log.
  • A/B evaluation of the two versions on the shared test set, per-field, attached to the pull request.
  • One reviewer familiar with the domain, one with the pipeline.

Two lightweight but useful conventions:

  • No prompt change without an eval run. The build fails if the evaluation results are not attached. This alone prevents most regressions.
  • Every change ships with at least one new test-set example that exercises the change. Prompts have a natural tendency to grow; the test set has to grow with them.
A "small fix" to a prompt is a change to behaviour

"Rephrased for clarity" is a change to model output. "Added a comma" can change output. Treat every prompt edit as behavioural and run the eval. The rule that "trivial edits skip review" does not apply to prompts.

Governance in a team

Beyond a handful of prompts, informal ownership breaks down. Two questions worth answering explicitly:

  • Who owns each prompt? One team, one person for a given release. Otherwise a prompt drifts across quarters as three teams edit it in different directions.
  • What is the deprecation policy? A retired prompt needs a successor documented and a migration window announced. Silent removal is what causes 3 am incidents.

For an organisation with many prompts, a shared library — internal package, mono-repo folder, or dedicated service — is the right home. It centralises the templates, the eval sets, the version history and the review process, and it prevents the same prompt from being copy-pasted six times with six slow divergences.

Cost governance

Prompts have a cost surface: length of the system message, number of few-shot examples, output length, retries on failure. A monthly report on the library that lists the top ten prompts by cost — with the per-call price and the monthly volume — is often revealing. The usual finding: one or two prompts dominate the bill, and are the ones worth optimising with prompt caching, shorter examples, or distillation to a cheaper model.

\left( t_p^{\text{in}} \times p^{\text{in}} + t_p^{\text{out}} \times p^{\text{out}} \right)$$ where $n_p$ is the monthly call count for prompt $p$, $t_p^{\text{in}}$ and $t_p^{\text{out}}$ are its average input and output token counts, and $p^{\text{in}}$, $p^{\text{out}}$ are the provider's per-token prices. The formula is trivial; the discipline of computing it every month is what turns cost into a decision instead of a surprise. :::tip[A prompt library is a small product] Treat it as one. It has users (your engineers), releases, a change log, an eval suite, a cost report, and a deprecation policy. Every week spent on library discipline pays for itself the first time you switch models, revert a bad change or answer an auditor without panic. ::: ## In summary - Turn working prompts into **templates with named variables**, keep the validated invariants outside the variables, and share a common style template across the library. - **Version prompts** with semantic versioning, log the version with every call, and record each change with per-field scores in a change log — a note without numbers is marketing, not engineering. - **Document the context of use** — inputs, outputs, model family, temperature, eval set — so a new developer can answer what it does, what it expects, and what to know before changing it. - **Review prompts like pull requests**: no change ships without an eval run and one new test-set example; a "small fix" to a prompt is a change to behaviour, and governance is what keeps a library from decaying into folklore. Next: the recap and the exam that certify what you have learned across the ten modules of this course.