> ## 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.

# Prompt Management

> Create and manage dynamic prompts using Jinja templates with YAML frontmatter

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:

| Layout            | Path                                                   | When to use                                                                                                            |
| ----------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Shared prompts    | `app/launchpad/prompts/<name>.j2`                      | Templates reused across many workflows. This is the default; no `prompts_dir` argument needed.                         |
| Colocated prompts | `app/launchpad/workflows/<workflow>/prompts/<name>.j2` | Templates 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`:

```jinja theme={null}
---
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

```python theme={null}
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:

```python theme={null}
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": {...},
# }
```

<Info>
  `StrictUndefined` is enabled. Any variable referenced in the template but not passed to `get_prompt` raises `UndefinedError` — prefer Jinja `default(...)` filters for optional fields.
</Info>

## Further reading

* [Jinja2 documentation](https://jinja.palletsprojects.com/) — filters, macros, inheritance.
* [`python-frontmatter`](https://python-frontmatter.readthedocs.io/) — YAML frontmatter parsing used under the hood.
