Skip to content
Learn Agentic AI
Learn Agentic AI11 min read2 views

Prompt Variables and Templating: Dynamic Content Injection with Jinja2 and f-strings

Master prompt templating techniques using Jinja2 and Python f-strings. Learn variable injection patterns, conditional blocks, loop constructs, custom filters, and safety practices for dynamic prompts.

Why Static Prompts Fall Short

Hardcoded prompts work for demos. Production agents need prompts that adapt — inserting the user's name, adjusting tone based on context, including relevant data, and conditionally enabling features. This is prompt templating: defining a prompt structure once and injecting dynamic values at runtime.

The two dominant approaches in Python are f-strings for simple cases and Jinja2 for complex logic. Understanding when to use each prevents both over-engineering and under-engineering your prompt layer.

f-string Templating: Simple and Direct

For prompts with straightforward variable substitution, Python f-strings are the fastest path.

flowchart TD
    START["Prompt Variables and Templating: Dynamic Content …"] --> A
    A["Why Static Prompts Fall Short"]
    A --> B
    B["f-string Templating: Simple and Direct"]
    B --> C
    C["Jinja2 Templating: Full Power"]
    C --> D
    D["Custom Filters for Prompt-Specific Needs"]
    D --> E
    E["Safety Practices"]
    E --> F
    F["FAQ"]
    F --> DONE["Key Takeaways"]
    style START fill:#4f46e5,stroke:#4338ca,color:#fff
    style DONE fill:#059669,stroke:#047857,color:#fff
def build_support_prompt(
    user_name: str,
    account_tier: str,
    issue_summary: str
) -> str:
    """Build a support agent prompt with user context."""
    return f"""You are a customer support agent for Acme Corp.

The customer's name is {user_name}.
Their account tier is {account_tier}.

Issue summary: {issue_summary}

Respond helpfully and professionally. If the customer
has a Premium or Enterprise tier, prioritize their request
and offer direct escalation options."""

This is readable and type-safe — your IDE catches missing variables. However, f-strings hit limits quickly. You cannot loop over lists of items, conditionally include sections, or reuse template fragments.

Jinja2 Templating: Full Power

Jinja2 gives you conditionals, loops, filters, template inheritance, and macros. It is the standard for complex prompt templating.

from jinja2 import Environment, FileSystemLoader, select_autoescape

class PromptTemplateEngine:
    """Render prompts using Jinja2 templates."""

    def __init__(self, templates_dir: str = "prompt_templates"):
        self.env = Environment(
            loader=FileSystemLoader(templates_dir),
            autoescape=select_autoescape(default=False),
            trim_blocks=True,
            lstrip_blocks=True,
        )

    def render(
        self, template_name: str, **variables
    ) -> str:
        """Render a named template with variables."""
        template = self.env.get_template(template_name)
        return template.render(**variables)

Store templates as separate files.

See AI Voice Agents Handle Real Calls

Book a free demo or calculate how much you can save with AI voice automation.

# prompt_templates/support_agent.md.j2
# ---
# Template: support_agent
# Variables: user_name, account_tier, conversation_history,
#            available_tools, escalation_allowed
# ---

You are a customer support agent for Acme Corp.
Customer: {{ user_name }} ({{ account_tier }} tier)

{% if conversation_history %}
## Previous Conversation
{% for msg in conversation_history %}
{{ msg.role | upper }}: {{ msg.content }}
{% endfor %}
{% endif %}

## Available Actions
{% for tool in available_tools %}
- {{ tool.name }}: {{ tool.description }}
{% endfor %}

{% if account_tier in ["premium", "enterprise"] %}
This is a high-priority customer. You may offer:
- Direct phone callback within 1 hour
- Escalation to a senior specialist
{% endif %}

{% if not escalation_allowed %}
Note: Do NOT offer escalation options in this session.
{% endif %}
# Usage
engine = PromptTemplateEngine()

prompt = engine.render(
    "support_agent.md.j2",
    user_name="Alice Chen",
    account_tier="premium",
    conversation_history=[
        {"role": "user", "content": "My invoice is wrong"},
        {"role": "assistant", "content": "Let me look into that."},
    ],
    available_tools=[
        {"name": "lookup_invoice", "description": "Fetch invoice details"},
        {"name": "create_ticket", "description": "Open a support ticket"},
    ],
    escalation_allowed=True,
)

Custom Filters for Prompt-Specific Needs

Jinja2 filters transform values inline. Add custom filters for common prompt operations.

def setup_prompt_filters(env: Environment):
    """Add prompt-specific Jinja2 filters."""

    def truncate_tokens(text: str, max_tokens: int = 500) -> str:
        """Rough truncation by word count as a token proxy."""
        words = text.split()
        if len(words) <= max_tokens:
            return text
        return " ".join(words[:max_tokens]) + "..."

    def format_list(items: list, style: str = "bullet") -> str:
        """Format a list for prompt readability."""
        if style == "numbered":
            return "\n".join(
                f"{i+1}. {item}" for i, item in enumerate(items)
            )
        return "\n".join(f"- {item}" for item in items)

    def mask_pii(text: str) -> str:
        """Mask email addresses and phone numbers."""
        import re
        text = re.sub(
            r'[\w.+-]+@[\w-]+\.[\w.]+', '[EMAIL]', text
        )
        text = re.sub(
            r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b', '[PHONE]', text
        )
        return text

    env.filters["truncate_tokens"] = truncate_tokens
    env.filters["format_list"] = format_list
    env.filters["mask_pii"] = mask_pii

Use them in templates: {{ user_message | mask_pii | truncate_tokens(200) }}.

Safety Practices

Dynamic prompts introduce injection risks. User-provided values could contain instructions that hijack the agent's behavior.

class SafePromptRenderer:
    """Render prompts with input sanitization."""

    def __init__(self, engine: PromptTemplateEngine):
        self.engine = engine

    def sanitize_input(self, value: str) -> str:
        """Remove patterns that could be prompt injections."""
        dangerous_patterns = [
            "ignore previous instructions",
            "ignore all instructions",
            "disregard the above",
            "new instructions:",
            "system:",
            "ADMIN OVERRIDE",
        ]
        sanitized = value
        for pattern in dangerous_patterns:
            sanitized = sanitized.replace(
                pattern, "[FILTERED]"
            )
        return sanitized

    def render_safe(
        self, template_name: str, **variables
    ) -> str:
        """Render with all string variables sanitized."""
        safe_vars = {}
        for key, value in variables.items():
            if isinstance(value, str):
                safe_vars[key] = self.sanitize_input(value)
            else:
                safe_vars[key] = value
        return self.engine.render(template_name, **safe_vars)

Always sanitize user-provided inputs before injecting them into prompts. Treat prompt templates like SQL queries — never insert raw user input without validation.

FAQ

When should I use f-strings versus Jinja2?

Use f-strings when your prompt has fewer than five variables and no conditional logic. Switch to Jinja2 when you need conditionals, loops, template inheritance, or when non-engineers need to edit the templates. The readability of Jinja2 templates makes them better for team collaboration.

How do I handle missing template variables?

Configure Jinja2 with undefined=StrictUndefined to raise errors on missing variables rather than silently inserting empty strings. This catches bugs during development. In production, you can use default filters: {{ user_name | default("Customer") }}.

Can prompt injection be fully prevented with sanitization?

No. Blocklist-based sanitization catches known patterns but misses creative bypasses. Layer multiple defenses: sanitize inputs, use structured system-vs-user message separation, validate outputs, and monitor for anomalous agent behavior. Sanitization is one layer in a defense-in-depth strategy.


#PromptTemplating #Jinja2 #Python #DynamicPrompts #PromptEngineering #AgenticAI #LearnAI #AIEngineering

Share
C

Written by

CallSphere Team

Expert insights on AI voice agents and customer communication automation.

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.

Related Articles You May Like

Technical Guides

How to Train an AI Voice Agent on Your Business: Prompts, RAG, and Fine-Tuning

A practical guide to training an AI voice agent on your specific business — system prompts, RAG over knowledge bases, and when to fine-tune.

AI Interview Prep

8 LLM & RAG Interview Questions That OpenAI, Anthropic & Google Actually Ask

Real LLM and RAG interview questions from top AI labs in 2026. Covers fine-tuning vs RAG decisions, production RAG pipelines, evaluation, PEFT methods, positional embeddings, and safety guardrails with expert answers.

AI Interview Prep

7 AI Coding Interview Questions From Anthropic, Meta & OpenAI (2026 Edition)

Real AI coding interview questions from Anthropic, Meta, and OpenAI in 2026. Includes implementing attention from scratch, Anthropic's progressive coding screens, Meta's AI-assisted round, and vector search — with solution approaches.

Learn Agentic AI

Prompt Engineering for AI Agents: System Prompts, Tool Descriptions, and Few-Shot Patterns

Agent-specific prompt engineering techniques: crafting effective system prompts, writing clear tool descriptions for function calling, and few-shot examples that improve complex task performance.

Learn Agentic AI

Building a Multi-Agent Data Pipeline: Ingestion, Transformation, and Analysis Agents

Build a three-agent data pipeline with ingestion, transformation, and analysis agents that process data from APIs, CSVs, and databases using Python.

Learn Agentic AI

Building a Research Agent with Web Search and Report Generation: Complete Tutorial

Build a research agent that searches the web, extracts and synthesizes data, and generates formatted reports using OpenAI Agents SDK and web search tools.