How to Build a Prompt Template Library
Create a reusable library of tested prompts for every business function.
Jay Banlasan
The AI Systems Guy
Building an ai prompt template library for business is how you stop writing prompts from scratch every time and start compounding on what already works. Every time you write a prompt that produces good output, that prompt has value. Without a library, that value disappears when you close the browser tab. With one, your team reuses proven prompts, you track which versions work best, and you stop paying to reinvent prompts you already figured out. I maintain a library for every client I work with and for my own systems.
The library also solves the team consistency problem. When three people write prompts for the same task independently, you get three inconsistent outputs. One shared template means one consistent output.
What You Need Before Starting
- Python 3.10+ with
anthropicandjinja2(pip install anthropic jinja2) - A clear set of recurring AI tasks in your business (start with 5-10)
- Existing prompts you already use that produce good results
Step 1: Design the Template Schema
A prompt template is more than a string. It has metadata that makes it searchable and maintainable.
from dataclasses import dataclass, field
from typing import Optional
from datetime import datetime
@dataclass
class PromptTemplate:
id: str # Unique ID: "email-follow-up-v2"
name: str # Human name: "B2B Follow-Up Email Generator"
category: str # "sales", "support", "ops", "content"
task_type: str # "generate", "classify", "extract", "summarize"
model_recommendation: str # "claude-haiku-4-5", "claude-sonnet-4-5"
system_prompt: str # The system prompt
user_prompt_template: str # Jinja2 template with {{variable}} placeholders
variables: list[str] # List of required variable names
example_inputs: list[dict] = field(default_factory=list)
notes: str = "" # Usage notes, known quirks
version: str = "1.0"
created_at: str = field(default_factory=lambda: datetime.utcnow().isoformat())
tags: list[str] = field(default_factory=list)
Step 2: Build a File-Based Template Store
Store templates as YAML files. One file per template, organized by category.
import yaml
import os
from pathlib import Path
TEMPLATES_DIR = Path("prompt_templates")
def save_template(template: PromptTemplate):
category_dir = TEMPLATES_DIR / template.category
category_dir.mkdir(parents=True, exist_ok=True)
filepath = category_dir / f"{template.id}.yaml"
template_dict = {
"id": template.id,
"name": template.name,
"category": template.category,
"task_type": template.task_type,
"model_recommendation": template.model_recommendation,
"system_prompt": template.system_prompt,
"user_prompt_template": template.user_prompt_template,
"variables": template.variables,
"example_inputs": template.example_inputs,
"notes": template.notes,
"version": template.version,
"created_at": template.created_at,
"tags": template.tags
}
with open(filepath, "w") as f:
yaml.dump(template_dict, f, default_flow_style=False, allow_unicode=True)
print(f"Saved: {filepath}")
def load_template(template_id: str) -> Optional[PromptTemplate]:
for yaml_file in TEMPLATES_DIR.rglob("*.yaml"):
with open(yaml_file) as f:
data = yaml.safe_load(f)
if data.get("id") == template_id:
return PromptTemplate(**data)
return None
def list_templates(category: str = None) -> list[PromptTemplate]:
templates = []
search_dir = TEMPLATES_DIR / category if category else TEMPLATES_DIR
for yaml_file in search_dir.rglob("*.yaml"):
with open(yaml_file) as f:
data = yaml.safe_load(f)
templates.append(PromptTemplate(**data))
return templates
Step 3: Add Template Rendering With Jinja2
Render templates with variable substitution.
from jinja2 import Template, UndefinedError
def render_template(template: PromptTemplate, variables: dict) -> tuple[str, str]:
# Check all required variables are provided
missing = [v for v in template.variables if v not in variables]
if missing:
raise ValueError(f"Missing required variables: {missing}")
try:
user_prompt = Template(template.user_prompt_template).render(**variables)
except UndefinedError as e:
raise ValueError(f"Template rendering failed: {e}")
return template.system_prompt, user_prompt
def run_template(
template_id: str,
variables: dict,
model_override: str = None
) -> str:
import anthropic
template = load_template(template_id)
if not template:
raise ValueError(f"Template not found: {template_id}")
system_prompt, user_prompt = render_template(template, variables)
model = model_override or template.model_recommendation
client = anthropic.Anthropic()
response = client.messages.create(
model=model,
max_tokens=500,
system=system_prompt,
messages=[{"role": "user", "content": user_prompt}]
)
return response.content[0].text
Step 4: Create Your First Templates
Here are three starter templates to populate the library.
# Template 1: Lead follow-up email
followup_template = PromptTemplate(
id="sales-followup-email-v1",
name="B2B Lead Follow-Up Email",
category="sales",
task_type="generate",
model_recommendation="claude-haiku-4-5",
system_prompt="""You write short B2B follow-up emails. Conversational. Under 80 words. End with one specific question.
No filler phrases. No em dashes. Write like a real person.""",
user_prompt_template="""Write a follow-up email for:
Name: {{ name }}
Company: {{ company }}
Context: {{ context }}
{% if previous_interaction %}Previous interaction: {{ previous_interaction }}{% endif %}""",
variables=["name", "company", "context"],
example_inputs=[
{"name": "Sarah Chen", "company": "TechCorp", "context": "Attended our AI automation webinar"},
{"name": "Marcus Williams", "company": "BuildCo", "context": "Downloaded pricing guide, no response in 3 days"}
],
tags=["sales", "email", "outreach"]
)
# Template 2: Support ticket classifier
ticket_classifier = PromptTemplate(
id="support-ticket-classify-v1",
name="Support Ticket Classifier",
category="support",
task_type="classify",
model_recommendation="claude-haiku-4-5",
system_prompt="Classify support tickets. Return JSON only. No explanation.",
user_prompt_template="""Classify this support ticket.
Subject: {{ subject }}
Body: {{ body }}
Return JSON: {"category": "billing|technical|account|feature_request|other", "priority": "urgent|high|normal|low", "summary": "one sentence"}""",
variables=["subject", "body"],
example_inputs=[
{"subject": "Payment failed", "body": "My card was declined three times this morning."},
{"subject": "API returning 500", "body": "Getting server errors on every endpoint since 2pm."}
],
tags=["support", "classification", "triage"]
)
# Template 3: Content summarizer
content_summarizer = PromptTemplate(
id="content-summarize-v1",
name="Business Content Summarizer",
category="ops",
task_type="summarize",
model_recommendation="claude-haiku-4-5",
system_prompt="Summarize business content. Extract key points. Be specific, not vague.",
user_prompt_template="""Summarize this {{ content_type }} in {{ format }}.
Content:
{{ content }}
Requirements: {{ requirements }}""",
variables=["content_type", "format", "content", "requirements"],
example_inputs=[
{
"content_type": "meeting transcript",
"format": "5 bullet points",
"content": "...",
"requirements": "Focus on decisions made and action items only"
}
],
tags=["summarization", "ops", "productivity"]
)
# Save them
TEMPLATES_DIR.mkdir(exist_ok=True)
save_template(followup_template)
save_template(ticket_classifier)
save_template(content_summarizer)
Step 5: Build a Template Registry With Search
def search_templates(
query: str = None,
category: str = None,
task_type: str = None,
tags: list = None
) -> list[PromptTemplate]:
all_templates = list_templates()
results = all_templates
if category:
results = [t for t in results if t.category == category]
if task_type:
results = [t for t in results if t.task_type == task_type]
if tags:
results = [t for t in results if any(tag in t.tags for tag in tags)]
if query:
query_lower = query.lower()
results = [
t for t in results
if query_lower in t.name.lower()
or query_lower in t.notes.lower()
or any(query_lower in tag for tag in t.tags)
]
return results
def print_template_catalog():
templates = list_templates()
print(f"\nPrompt Template Library ({len(templates)} templates)\n")
print(f"{'ID':<35} {'Name':<35} {'Category':<12} {'Model':<20}")
print("-" * 110)
for t in sorted(templates, key=lambda x: x.category):
print(f"{t.id:<35} {t.name:<35} {t.category:<12} {t.model_recommendation:<20}")
Step 6: Track Template Performance
Log every template run so you can see which templates produce the best results.
import json
import sqlite3
from datetime import datetime
def init_template_log(db_path: str = "template_log.db"):
conn = sqlite3.connect(db_path)
conn.execute("""
CREATE TABLE IF NOT EXISTS template_runs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
template_id TEXT,
model TEXT,
variables_json TEXT,
output TEXT,
rated_good INTEGER DEFAULT NULL,
run_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
conn.commit()
conn.close()
def log_template_run(
template_id: str,
model: str,
variables: dict,
output: str,
db_path: str = "template_log.db"
):
conn = sqlite3.connect(db_path)
conn.execute(
"INSERT INTO template_runs (template_id, model, variables_json, output) VALUES (?, ?, ?, ?)",
(template_id, model, json.dumps(variables), output)
)
conn.commit()
conn.close()
def get_template_stats(template_id: str, db_path: str = "template_log.db") -> dict:
conn = sqlite3.connect(db_path)
cur = conn.cursor()
cur.execute("""
SELECT COUNT(*), AVG(rated_good), MIN(run_at), MAX(run_at)
FROM template_runs
WHERE template_id = ?
""", (template_id,))
row = cur.fetchone()
conn.close()
return {
"total_runs": row[0],
"avg_rating": round(row[1], 2) if row[1] else None,
"first_run": row[2],
"last_run": row[3]
}
What to Build Next
- Build a web UI for browsing and testing templates without touching the code
- Add A/B testing support to compare template versions on the same input
- Create a template export function to share specific templates across projects
Related Reading
- Building a Review Response Template Library with AI - review response templates ai
- Building Prompt Libraries for Your Business - prompt library business guide
- How to Build an AI-Powered Email Template Library - ai email template library guide
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment