# What is a prompt template, and how should you version and test prompts in production?

A prompt kept as a file with placeholders filled in at run time, so it can be versioned, reviewed and tested like the rest of your code.

- Page: https://tecyfy.com/concepts/prompt-template
- Subject: How AI works (https://tecyfy.com/concepts)
- Level: beginner
- Also called: Prompt Versioning, Versioned Prompt

A prompt template is a prompt with gaps. The fixed part, the instructions and examples, is written once; the gaps, such as `$email` or `{question}`, are filled in for each request. Every real LLM app works this way, because the same instructions go with thousands of different inputs.

## Keep prompts in files, not in strings

A prompt buried in a Python string is easy to change by accident and hard to review. Kept as its own file, it is a first-class part of the code:

- **Versioned.** Each meaningful change is a new version, `triage-v2.md` beside `triage-v1.md`, or a new commit, so you can say which prompt produced an answer and roll back a bad change.
- **Logged.** Record the prompt's name, version and a hash of its text with every call. When an answer goes wrong a month later, you know exactly what the model was told.
- **Reviewed.** A change to a prompt is a change to behaviour, and deserves the same review as a change to code.
- **Tested.** A small set of cases with known right answers runs against every version before it ships, and grows into an [eval set](https://tecyfy.com/concepts/eval-set).

## How to fill the gaps safely

- **Fail on a missing value.** A template library that silently leaves `$email` blank produces a call that looks fine and answers nothing. Python's `string.Template.substitute` raises an error instead.
- **Mark where outside text goes.** Put the filled-in value inside tags, such as `<email>` and `</email>`, so the model can tell your instructions from a customer's words. It helps the model read the prompt correctly; it does not by itself stop [prompt injection](https://tecyfy.com/concepts/prompt-injection), so keep the limits on what the model can do in code.
- **Choose a placeholder style that will not clash.** Curly braces collide with JSON examples in the prompt; `$name` placeholders, or a library like Jinja, avoid that.

## Put the fixed part first

The fixed part of a template should come before the variable part, ideally in the [system prompt](https://tecyfy.com/concepts/system-prompt) with the user's input last. That order is what [prompt caching](https://tecyfy.com/concepts/prompt-caching) needs: the cache covers the prompt from the start up to a marked point, so a stable beginning can be reused across requests, while a timestamp or customer name near the top would make every request look new. On current Claude models a prefix needs at least 512 tokens to be cached at all.

## Related

- [Prompt Engineering](https://tecyfy.com/concepts/prompt-engineering): Writing and testing the instructions, context and examples you give a model so it does a job reliably, and measuring each change instead of guessing.
- [System Prompt](https://tecyfy.com/concepts/system-prompt): Instructions the builder of an AI app gives the model before you type anything. It sets the role, the tone and the rules, and it outranks what users say.
- [Few-shot Learning](https://tecyfy.com/concepts/few-shot-learning): Putting a few worked examples of the task in the prompt, so the model copies their format, labels and tone without any training.
- [Eval Set](https://tecyfy.com/concepts/eval-set): The list of test cases an LLM app is graded on after every change. Each case is an input and what a good answer must do, so a score going up or down shows whether the change helped.
- [Prompt Caching](https://tecyfy.com/concepts/prompt-caching): Letting the API keep the processed start of a prompt for a few minutes, so later requests that begin the same way are cheaper and quicker.
- [Prompt Injection](https://tecyfy.com/concepts/prompt-injection): An attack that hides instructions in text a model reads, such as a web page, an email or a file, so the model follows the attacker instead of you.

## Sources

- [Prompting best practices](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices)
- [Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)
- [Prompt engineering overview](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/overview)
