RUNLOCALAIv38
->Will it run?Best GPUCompareTroubleshootStartLearnPulseModelsHardwareToolsBench
Run check
RUNLOCALAI

Independently operated catalog for local-AI hardware and software. Hand-written verdicts. Source-cited claims. Reproducible commands when we have them.

OP·Fredoline Eruo
DIR
  • Models
  • Hardware
  • Tools
  • Benchmarks
TOOLS
  • Will it run?
  • Compare hardware
  • Cost vs cloud
  • Choose my GPU
  • Prompting kits
  • Quick answers
REF
  • All buyer guides
  • Learn local AI
  • Methodology
  • Glossary
  • Errors KB
  • Trust
EDITOR
  • About
  • Author
  • How we make money
  • Editorial policy
  • Contact
LEGAL
  • Privacy
  • Terms
  • Sitemap
MAIL · MONTHLY DIGEST
Get monthly local AI changes
Monthly recap. No spam.
DISCLOSURE

Some links on this site are affiliate links (Amazon Associates and other first-class retailers). When you buy through them, we earn a small commission at no extra cost to you. Affiliate links do not influence our verdicts — there are cards we rate highly that we don't have affiliate relationships with, and cards that sell well that we refuse to recommend. Read more →

© 2026 runlocalai.coIndependently operated
RUNLOCALAI · v38
  1. >
  2. Home
  3. /Learn
  4. /Courses
  5. /Advanced Prompt Engineering
  6. /Ch. 6
Advanced Prompt Engineering

06. Dynamic Prompt Construction

Chapter 6 of 18 · 20 min
KEY INSIGHT

Dynamic prompt construction separates prompt architecture from prompt content, enabling component reuse and adaptive behavior without code changes.

Static prompts are strings written once, used repeatedly. Dynamic prompts are constructed at runtime from modular components selected based on context, user input, or system state. This enables adaptive behavior that static prompts cannot achieve.

The fundamental mechanism: template filling with conditional logic. A base template contains placeholders. Before rendering, logic selects which sub-templates to include, which examples to show, what constraints to add. The rendered prompt is specific to the current invocation.

Consider a support ticket classifier. A static prompt says "Classify this ticket into: billing, technical, feature_request, other." This works—but the definition of "billing" might differ between contexts. A SaaS product's billing is different from a hardware product's billing. Dynamic prompt construction allows injecting domain-specific definitions that the classifier uses for its categorization.

from string import Template
from typing import Optional

class DynamicPromptBuilder:
    def __init__(self):
        self.components = {
            'role': {},
            'context': {},
            'constraints': {},
            'examples': {},
            'format': {}
        }
    
    def register_component(self, category: str, name: str, template: str):
        """Register a reusable template component."""
        self.components[category][name] = template
    
    def build(
        self,
        role: Optional[str] = None,
        context_name: Optional[str] = None,
        constraint_names: list[str] = None,
        example_names: list[str] = None,
        format_name: Optional[str] = None,
        **template_vars
    ) -> str:
        """Construct a prompt from registered components."""
        parts = []
        
        # Select and apply role
        if role and role in self.components['role']:
            parts.append(self.components['role'][role])
        
        # Select and apply context
        if context_name and context_name in self.components['context']:
            parts.append(self.components['context'][context_name])
        
        # Select and apply constraints
        constraint_names = constraint_names or []
        for name in constraint_names:
            if name in self.components['constraints']:
                parts.append(self.components['constraints'][name])
        
        # Select and apply examples
        example_names = example_names or []
        for name in example_names:
            if name in self.components['examples']:
                parts.append(self.components['examples'][name])
        
        # Select and apply format
        if format_name and format_name in self.components['format']:
            parts.append(self.components['format'][format_name])
        
        # Combine parts
        prompt = "\n\n".join(parts)
        
        # Apply additional template variables
        try:
            prompt = Template(prompt).substitute(**template_vars)
        except KeyError as e:
            raise ValueError(f"Missing template variable: {e}")
        
        return prompt


# Register components for email classification domain
builder = DynamicPromptBuilder()

# Domain-specific role
builder.register_component('role', 'support_agent', """You are a technical support agent 
analyzing customer emails. Your job is to extract the core issue and categorize it accurately.""")

# Domain-specific context
builder.register_component('context', 'saas_platform', """This is a SaaS project management platform.
Available categories reflect common issues:
- billing: subscription, payment, invoice, charge disputes
- technical: bugs, errors, performance, integrations not working
- feature_request: suggestions for new capabilities
- account: login problems, access issues, permissions
- documentation: questions about how to use features""")

# Shared constraints
builder.register_component('constraints', 'strict_classification', """Respond ONLY with the 
category name. Do not explain your reasoning. Do not use quotes or punctuation.""")

builder.register_component('constraints', 'allow_uncertainty', """If the email touches multiple 
categories, choose the most prominent one. If truly uncertain, respond with 'mixed'.""")

# Domain-specific examples
builder.register_component('examples', 'billing_examples', """Examples:
Email: 'I was charged twice for my subscription this month'
Category: billing

Email: 'Can you send me an invoice for Q4?'
Category: billing

Email: 'The integration with Slack stopped working after your last update'
Category: technical""")

# Format directives
builder.register_component('format', 'json_output', """Return your response as JSON:
{"category": "value"}""")

# Construct a specific prompt
prompt = builder.build(
    role='support_agent',
    context_name='saas_platform',
    constraint_names=['strict_classification'],
    example_names=['billing_examples'],
    format_name='json_output'
)

print(prompt)

The component registration pattern enables separation of concerns: domain experts can define context and examples separate from engineers who build the execution logic. Updating the billing category definition requires changing only the context component, not hunting through all prompts that include that definition.

Failure modes of dynamic construction:

  1. Combinatorial explosion: With K categories and M constraint sets and N example sets, there are K×M×N possible prompts. Not all combinations are tested. Unknown bad interactions may appear in production.

  2. Inconsistent composition: When components are authored separately, combining them may produce logical inconsistencies. The billing definition assumes certain knowledge that the role definition doesn't establish.

  3. Empty composition: If a requested component name doesn't exist, the dynamic builder either fails or silently produces incomplete prompts. Silent failures are worse—production prompts missing critical context are hard to debug.

Dynamic construction is most valuable when the prompt must adapt to user characteristics (expert vs. novice), domain variations (legal text vs. marketing copy), or task variations (classify vs. summarize). Static prompts handle one variant well but require duplication to handle multiple.

EXERCISE

Identify a prompt that varies based on user type, content domain, or task subtype. Refactor it into a builder with 3-4 reusable components. Compare the resulting prompts before and after refactoring. Test at least 3 different component combinations to verify no unintended interactions.

← Chapter 5
Prompt Chaining Patterns
Chapter 7 →
DSPy Introduction