Skip to main content

Documentation Index

Fetch the complete documentation index at: https://launchpad.datalumina.com/llms.txt

Use this file to discover all available pages before exploring further.

Jinja2 lets you keep large, dynamic prompts out of Python strings. The Launchpad ships a small PromptManager service (app/launchpad/services/prompt_loader.py) that loads .j2 templates, parses their YAML frontmatter, and renders them with runtime variables using StrictUndefined so missing variables fail loudly.

Why templates

  • Readable structure — sections like “Role”, “Context”, “Examples” stay visible in the template instead of buried in string concatenation.
  • Reuse — Jinja includes, blocks, and macros let you share common snippets across prompts.
  • Conditional content — show a section only when relevant data is available, or swap tone per user tier.
  • Variable injection — interpolate runtime data without manual string formatting.
  • Frontmatter metadata — each template can declare its own description, author, and any custom fields via YAML frontmatter at the top of the file.

Template locations

PromptManager supports two layouts — use whichever fits the workflow:
LayoutPathWhen to use
Shared promptsapp/launchpad/prompts/<name>.j2Templates reused across many workflows. This is the default; no prompts_dir argument needed.
Colocated promptsapp/launchpad/workflows/<workflow>/prompts/<name>.j2Templates that belong to a single workflow. Pass prompts_dir= so the loader resolves them next to the workflow code.
The quickstart workflow uses the colocated layout — see app/launchpad/workflows/examples/quickstart/prompts/ticket_analysis.j2.

Example template

app/launchpad/workflows/examples/quickstart/prompts/ticket_analysis.j2:
---
description: A template for analyzing incoming {{ pipeline | default('customer support') }} tickets
author: TechGear AI Team
---

You're an AI assistant named {{ name | default('Emma') }}, working for {{ company | default('TechGear') }}.
Your goal is to analyze incoming {{ pipeline | default('support') }} tickets and classify their intent.

# CONTEXT
You will be provided with the following information from a {{ pipeline | default('support') }} ticket:
- Sender: The name or identifier of the person who sent the ticket
- Subject: The subject line of the ticket
- Body: The main content of the ticket

# TASK
Your task is to analyze the ticket and determine its primary intent. You should also provide a confidence score for your classification and explain your reasoning.
The lines between --- markers are YAML frontmatter. They are stripped before the template is rendered and are available via PromptManager.get_template_info.

Using a template from a node

from pathlib import Path

from launchpad.core.nodes.agent import AgentNode, AgentConfig, ModelProvider
from launchpad.services.prompt_loader import PromptManager

PROMPTS_DIR = Path(__file__).parent.parent / "prompts"


class DetermineTicketIntentNode(AgentNode):
    def get_agent_config(self) -> AgentConfig:
        return AgentConfig(
            instructions=PromptManager.get_prompt(
                "ticket_analysis",
                prompts_dir=PROMPTS_DIR,
                name="Emma",
                company="TechGear",
            ),
            output_type=self.OutputType,
            model_provider=ModelProvider.OPENAI,
            model_name="gpt-5.4-mini",
        )
Drop prompts_dir=PROMPTS_DIR for shared templates in app/launchpad/prompts/.

Inspecting metadata and variables

PromptManager.get_template_info(name) returns the template’s metadata plus the set of variables referenced in the body — useful when wiring templates into a registry or generating documentation:
info = PromptManager.get_template_info("ticket_analysis")
# {
#   "name": "ticket_analysis",
#   "description": "A template for analyzing incoming customer support tickets",
#   "author": "TechGear AI Team",
#   "variables": ["pipeline", "name", "company"],
#   "frontmatter": {...},
# }
StrictUndefined is enabled. Any variable referenced in the template but not passed to get_prompt raises UndefinedError — prefer Jinja default(...) filters for optional fields.

Further reading