Skip to content

Prompt Templates & Variables

A prompt hardcoded with data is a script. A prompt with variables is a function. Templates separate the prompt logic from the data, making prompts reusable, testable, and version-controlled. This lesson covers Jinja2-style templating, variable management, and treating prompts as code.

Gnome mascot

What you'll learn

  • Templates separate prompt structure from data, same prompt, different inputs, consistent output format
  • Jinja2 or Python's string.Template are the standard tools, avoid string concatenation
  • Version control the template, not the rendered output. The template is the source of truth

Build it

Step 1: Python string.Template

Python's string templates allow you to define a static prompt structure and inject variables at runtime.

python
from string import Template

SUPPORT_TEMPLATE = Template("""You are a customer support agent for $company.

## User Info
Name: $customer_name
Plan: $plan_type

## Recent Orders
$recent_orders

## Message
$user_message

Respond in 2-3 sentences. Be helpful and concise.""")

prompt = SUPPORT_TEMPLATE.substitute(
    company="Acme Corp",
    customer_name="Alice",
    plan_type="Premium",
    recent_orders="Order #12345: Shipped\nOrder #12346: Processing",
    user_message="Where is my order?",
)

Step 2: Jinja2 for complex logic

Jinja2 provides advanced templating features like loops and conditionals for building complex, dynamic prompts.

python
from jinja2 import Template

template = Template("""You are a code reviewer. Focus on: {% for area in focus_areas %}{{ area }}{% if not loop.last %}, {% endif %}{% endfor %}.

Review:
```python
{{ code }}

{% if include_tests %} Also check that tests cover the new code. {% endif %}""")

prompt = template.render( focus_areas=["security", "performance", "style"], code="def foo(): pass", include_tests=True, )


### Step 3: Store templates as files

Storing templates as YAML files separates prompt configuration from your application code, enabling version control and schema validation.

```yaml
# prompts/support/response.yaml
name: customer-support-response
version: 2.0.0
template: |
  You are a customer support agent for {{ company }}.

  ## User Info
  Name: {{ customer_name }}
  Plan: {{ plan_type }}

  ## Message
  {{ user_message }}

  Respond in 2-3 sentences.
variables:
  company:
    type: string
    required: true
  customer_name:
    type: string
    required: true
  plan_type:
    type: string
    default: "Basic"
  user_message:
    type: string
    required: true

What goes wrong

MistakeHow you notice itThe fix
Variable not escapedSpecial characters in user input break the prompt formatUse template engines that auto-escape. Never use str.replace() for variable substitution
Missing variableTemplate.render() raises KeyErrorValidate all required variables before rendering. Provide defaults for optional ones
Template too complexConditionals and loops make the template hard to readIf the template has more than 3 conditionals, split it into multiple templates
Template and data drift apartTemplate expects customer_name but code passes nameUse a schema to validate variables. Pydantic models or JSON Schema catch mismatches

Confirm it worked

Ensure your templates render correctly by validating variable substitution before sending the prompt to the model.

python
from string import Template
t = Template("Hello, $name. Your order $order_id is $status.")
result = t.substitute(name="Alice", order_id="12345", status="shipped")
assert "Alice" in result and "12345" in result and "shipped" in result

Next: Day 3, Context & Optimization