Skip to main content
Intermediate

Defensive Prompt Templates for Production

Copy-paste prompt templates with built-in error handling, validation, and safety measures

Tools Required

OpenAI Anthropic LangChain

Tags

LLM Prompts Production

Defensive Prompt Templates for Production

Copy-paste these battle-tested templates. They handle edge cases so you don’t have to discover them in production.

Template 1: Structured Data Extraction

Use case: Extract structured data from unstructured text

You are a data extraction specialist. Extract information from the text below and respond with ONLY valid JSON.

OUTPUT FORMAT (required):
{
  "field1": "<type>",
  "field2": "<type>",
  "confidence": <number 0-100>
}

EXTRACTION RULES:
1. If a field is not found, use null (not empty string)
2. confidence represents how certain you are (0-100)
3. If confidence < 50, explain why in "notes" field
4. Dates must be in ISO 8601 format (YYYY-MM-DD)
5. Numbers must be numeric, not strings

EXAMPLES:

Input: "John Doe, CEO at TechCorp, john@techcorp.com, joined 2020"
Output:
{
  "name": "John Doe",
  "title": "CEO",
  "company": "TechCorp",
  "email": "john@techcorp.com",
  "join_date": "2020-01-01",
  "confidence": 80,
  "notes": "Exact join date unknown, using Jan 1"
}

Input: "Contact: unknown"
Output:
{
  "name": null,
  "title": null,
  "company": null,
  "email": null,
  "join_date": null,
  "confidence": 0,
  "notes": "No contact information found"
}

Now extract from this text:
{input_text}

Remember: ONLY return valid JSON. No explanations before or after.

Template 2: Classification with Confidence

Use case: Classify text into categories

You are a content classifier. Classify the input and return ONLY valid JSON.

CATEGORIES (choose exactly one):
- category_a: <definition>
- category_b: <definition>
- category_c: <definition>
- uncertain: Use this if you can't confidently classify

OUTPUT FORMAT:
{
  "category": "<one of the categories above>",
  "confidence": <number 0-100>,
  "reasoning": "<brief explanation max 100 chars>",
  "keywords": ["<relevant>", "<keywords>"]
}

CLASSIFICATION RULES:
1. confidence >= 80: High certainty
2. confidence 50-79: Medium certainty
3. confidence < 50: Use "uncertain" category
4. reasoning must explain your decision
5. keywords should be 2-5 terms that influenced decision

EXAMPLES:

Input: "This is a clear example of category A with obvious signals"
Output:
{
  "category": "category_a",
  "confidence": 95,
  "reasoning": "Contains all key indicators",
  "keywords": ["signal1", "signal2", "signal3"]
}

Input: "Could be A or B, unclear"
Output:
{
  "category": "uncertain",
  "confidence": 40,
  "reasoning": "Ambiguous signals, needs human review",
  "keywords": ["ambiguous"]
}

Now classify:
{input_text}

Output:

Template 3: Content Generation with Guardrails

Use case: Generate content with safety constraints

You are a professional {type} writer.

TASK: Write {content_type} about {topic}

REQUIREMENTS:
1. Length: {min}-{max} words
2. Tone: {tone_description}
3. Target audience: {audience}
4. Format: {format_requirements}

MUST INCLUDE:
- {required_element_1}
- {required_element_2}

MUST NOT INCLUDE:
- Pricing or financial commitments
- Legal or medical advice
- Personal opinions presented as facts
- Clickbait or sensational language
- Emojis or excessive punctuation

QUALITY CHECKS (before responding):
✓ Fact-check: Is everything verifiable?
✓ Tone-check: Appropriate for audience?
✓ Length-check: Within word count?
✓ Safety-check: No prohibited content?

EXAMPLE OUTPUT:
{example_output}

CONTEXT:
{additional_context}

Now write the {content_type}:

Template 4: Q&A with Source Attribution

Use case: Answer questions using provided context

You are a helpful assistant. Answer the question using ONLY information from the context below.

CONTEXT:
{context}

QUESTION:
{question}

ANSWER RULES:
1. ONLY use information from the context
2. If the answer isn't in the context, say "I don't have enough information to answer this question."
3. Include citations: [Source: <source_name>]
4. If you're uncertain, explicitly state your confidence level
5. Keep answers concise (50-150 words)

OUTPUT FORMAT:
Answer: <your answer with citations>
Confidence: <Low|Medium|High>
Sources: [<list of sources used>]

EXAMPLES:

Context: "Our return policy allows returns within 30 days. [Source: Policy Doc]"
Question: "What is the return window?"
Answer: Returns are accepted within 30 days. [Source: Policy Doc]
Confidence: High
Sources: [Policy Doc]

Context: "Product X costs $50."
Question: "What is the warranty period?"
Answer: I don't have enough information to answer this question. The context only mentions pricing, not warranty.
Confidence: N/A
Sources: []

Now answer the question based on the context above.

Template 5: Multi-Step Reasoning

Use case: Complex tasks requiring logical steps

You are a problem-solving assistant. Think through this step-by-step.

TASK:
{task_description}

APPROACH:
1. Analyze the problem
2. Break it into subtasks
3. Solve each subtask
4. Combine results
5. Validate solution

OUTPUT FORMAT:
{
  "analysis": "<problem breakdown>",
  "steps": [
    {"step": 1, "description": "...", "result": "..."},
    {"step": 2, "description": "...", "result": "..."}
  ],
  "final_answer": "<combined result>",
  "confidence": <0-100>,
  "assumptions": ["<list any assumptions made>"]
}

ERROR HANDLING:
- If you can't complete a step, mark it as "uncertain"
- If you make assumptions, list them explicitly
- If the task is impossible, explain why

Now solve:
{problem}

Think step by step and output JSON only.

Validation Function

Always validate LLM outputs:

import json
from typing import Optional, Dict, Any

def validate_llm_output(
    response: str,
    required_fields: list,
    field_types: dict
) -> tuple[Optional[Dict[Any, Any]], Optional[str]]:
    """
    Validate structured LLM output
    
    Returns: (parsed_data, error_message)
    """
    try:
        data = json.loads(response)
    except json.JSONDecodeError as e:
        return None, f"Invalid JSON: {str(e)}"
    
    # Check required fields
    for field in required_fields:
        if field not in data:
            return None, f"Missing required field: {field}"
    
    # Check types
    for field, expected_type in field_types.items():
        if field in data and not isinstance(data[field], expected_type):
            return None, f"Field '{field}' should be {expected_type.__name__}"
    
    return data, None

# Usage
response = call_llm(prompt)
data, error = validate_llm_output(
    response,
    required_fields=["category", "confidence"],
    field_types={"confidence": int, "category": str}
)

if error:
    # Retry or use fallback
    logger.error(f"Validation failed: {error}")
else:
    # Process valid data
    process(data)

Key Takeaways

  1. Be explicit - Don’t assume the model knows what you want
  2. Show examples - Especially for edge cases
  3. Constrain outputs - Use structured formats (JSON, XML)
  4. Handle errors - Include fallback behavior in prompts
  5. Validate always - Never trust LLM output blindly

Copy these templates, customize for your use case, and save yourself weeks of debugging.