Building reusable prompt templates
Published
A prompt template is a reusable prompt with placeholders for the parts that change, so a tested structure can be applied to many inputs. Name variables for what they mean, validate that none are left unreplaced, and version the template — a change that improves one input can quietly degrade another.
When should a prompt become a template?
As soon as you have run it twice with only small changes. At that point you are already maintaining a template — just informally, by copying and editing, which is the version with all of the cost and none of the benefits.
Formalising it buys three things: the structure gets tested once rather than re-improvised each time, improvements apply everywhere at once, and the prompt becomes something you can evaluate.
How should you name and structure variables?
Name them for what they mean, not where they appear. {{audience}} survives a restructure; {{paragraph_2}} does not.
<role>
You are a support engineer for {{product_name}}.
</role>
<context>
Customer tier: {{tier}}
Previous contacts: {{contact_history}}
Known issues: {{active_incidents}}
</context>
<task>
Reply to the message below.
</task>
<message>
{{customer_message}}
</message>- One variable per concept. A single
{{everything}}blob removes the structure the template exists to provide. - Decide what an empty variable means.
{{active_incidents}}with nothing to report should render as "None", not as an empty gap the model has to interpret. - Keep variables out of the middle of sentences. Substituting into
The customer is {{tier}} and...produces grammatical accidents.
What goes wrong with templates at scale?
| Failure | What it looks like | Guard |
|---|---|---|
| Unreplaced placeholder | {{customer_name}} reaches the model literally | Assert no {{ remains before sending |
| Empty variable | A gap where context should be; the model invents | Explicit default text per variable |
| Injection via variable | User content contains instructions | Delimit variable content; never interpolate into instructions |
| Length blowout | A large variable pushes past the context window | Cap and truncate each variable, visibly |
| Silent divergence | Three copies of the template drift apart | One definition, imported everywhere |
The injection row is the one to take seriously. If {{customer_message}} is interpolated somewhere the model reads as instructions, any customer can rewrite your prompt. Variables carrying user content belong inside delimiters, always.
How should templates be versioned?
Like code, because they behave like code: a small change can break a case you were not thinking about, and you will want to know exactly what was running when something went wrong.
- Keep templates in version control as files, not pasted into a database field.
- Record which template version produced any output you keep.
- Run the evaluation set before merging a change.
- Note *why* each constraint exists. Rules whose reason is forgotten are never removed and eventually contradict each other.
Should templates be built by concatenating fragments?
Sometimes, and carefully. Composing a prompt from shared fragments — a standard safety block, a standard output format — keeps common rules consistent. But the more dynamic the assembly, the harder it is to know what any given request actually sent.
A reasonable compromise: compose from a small fixed set of blocks whose order is deterministic, and log the fully-rendered prompt for anything you might need to debug. If you cannot reconstruct exactly what was sent, you cannot investigate what went wrong.
Common questions
- What is the difference between a prompt and a prompt template?
- A prompt is written for one specific request. A template is written once with placeholders for the parts that vary, so the same tested structure serves many inputs. The moment you copy and edit a prompt for the second time, you have a template.
- How do I stop user input breaking my template?
- Delimit every variable carrying user content and state that content inside the delimiters is data rather than instructions. Never interpolate user content into a sentence the model reads as an instruction.
- Where should prompt templates be stored?
- In version control, as files, alongside the code that uses them. They change behaviour like code does, and you will want history, review and the ability to identify exactly which version produced a given output.
- How do I handle optional sections in a template?
- Give every variable an explicit default that reads naturally — "None reported" rather than an empty string. A gap where context should be invites the model to fill it, which is exactly the behaviour you do not want.
- Should each model get its own template?
- The content should be shared and only the packaging should differ — XML for Claude, markdown for ChatGPT. Maintaining fully separate templates per model means they drift, and a fix applied to one silently misses the others.