Skip to content

Prompt Asset Pattern

This content was migrated from Documentation/prompt_asset_management_pattern.md and verified against the current codebase. Review for accuracy.

What This Pattern Is

The Prompt Asset Management (PAM) pattern separates prompt content (what we ask the LLM) from prompt logic (how we format and deliver it). Every LLM-powered node in the Global Supervisor pipeline follows this pattern.

Structure

{node}_helpers/
├── prompts/              # Content Layer (Markdown files)
│   └── {use_case}.md     # Human-readable prompt templates
└── prompt_builder.py     # Logic Layer (Python)
                          # Loads templates, injects variables

Where It's Used

The pattern is used in 10 helper modules across the supervisor pipeline (verified from codebase):

Helper Module Prompt Files Builder
intent_classification_helpers/ intent_classification.md Static/dynamic split with [SYSTEM]/[DEVELOPER]/[USER] markers
entity_resolution_helpers/ context_resolution.md, entity_resolution.md Context-aware candidate resolution
disambiguation_blocking_helpers/ disambiguation_blocking.md Ask-only HITL question generation
disambiguation_helpers/ disambiguation_simple.md, disambiguation_complex.md, disambiguation_voice.md Answer + "by the way" flows
disambiguation_resolution_helpers/ disambiguation_matching.md, ask_entity_details.md Response matching, entity detail questions
create_new_entity_helpers/ extract_entity_details.md New entity detail extraction
fact_extraction_helpers/ fact_extraction.md Fact extraction from messages
planner_helpers/ (planner prompts) Complex query planning
summarization_helpers/ (summarization prompts) Conversation summarization
ui_helpers/ greeting.md, greeting_simple.md, greeting_voice.md, simple_btw.md, + more UI response generation with variants

How It Works

1. Prompt templates use {{PLACEHOLDER}} variables

# File: prompts/intent_classification.md

# [SYSTEM]
You classify user messages for routing...

# [DEVELOPER]
## Decision Rules
...

# [USER]
**Previous conversation:**
{{CONVERSATION_CONTEXT}}

**Current message to classify:**
{{USER_MESSAGE}}

2. Builder loads template and injects values

# File: prompt_builder.py

def build_dynamic_user_content(user_message, conversation_context, ...):
    template = _load_prompt_template("intent_classification.md")
    _, dynamic_template = _split_static_dynamic(template)
    content = dynamic_template.replace("{{USER_MESSAGE}}", user_message)
    content = content.replace("{{CONVERSATION_CONTEXT}}", context_str)
    return content

3. Some builders use static/dynamic split for LLM cache efficiency

The intent classification builder splits the prompt at the [USER] marker. The static portion ([SYSTEM] + [DEVELOPER]) is identical across all requests and cached in memory. Only the dynamic portion ([USER] section with message-specific content) changes per request. This enables LLM provider-side prompt caching.

Why This Matters

Benefit Before (embedded strings) After (PAM pattern)
Reviewability Prompts hidden in 500-line Python files Prompts in readable .md files with clear git diffs
Non-dev contribution Product owner must edit Python code Product owner edits .md directly — no Python needed
Testability Can't test prompt content separately Test loading, test variable injection, test content independently
A/B testing Requires code change Swap template file or select variant at runtime
Variant management Multiple f-strings in same file Separate files: greeting.md, greeting_simple.md, greeting_voice.md

Conventions

Do:

  • Use semantic filenames (intent_classification.md, not prompt1.md)
  • One prompt per .md file
  • Use {{PLACEHOLDER}} for variables (mustache-style, double braces)
  • Use [SYSTEM], [DEVELOPER], [USER] section markers for prompts that need static/dynamic split
  • Version-control prompts like code — review changes in PRs

Don't:

  • Embed multi-line prompts in Python string literals
  • Mix multiple prompts in one .md file
  • Put business logic in .md files (content only — logic goes in the builder)
  • Hard-code the same prompt text in multiple places