Appearance
Rendering Variables
PromptContent.render(variables) substitutes {{variable}} placeholders with values you supply. It does the right thing per kind:
| Kind | render(vars) returns |
|---|---|
instruction | str — the prompt text (no substitution; instructions don't have variables) |
f_string | str — template with {{vars}} substituted |
chat | list[{role, content}] — messages with {{vars}} substituted in each body |
structured | dict — {base: <rendered>, response_schema: <dict>} |
Substitution rules
The substitution syntax is {{name}} — double curly braces around an identifier. Whitespace inside the braces is allowed and ignored:
txt
{{name}} ✓
{{ name }} ✓ (same as above)
{name} ✗ (not recognized)
{{name }} ✓The identifier matches [A-Za-z_]\w* — start with letter or underscore, then any word characters. No dots, no expressions, no method calls.
Missing variables
A {{name}} whose value isn't provided is replaced with an empty string. This is a deliberate choice — it makes templates forgiving but means you should validate inputs ahead of time if missing variables are bugs:
python
prompt = pm.get_active_prompt_version("greet")
# template: "Hi {{name}}, welcome to {{product}}."
prompt.render({"name": "Ada"})
# → "Hi Ada, welcome to ." ← product missing → empty stringTo enforce presence:
python
def render_strict(prompt, variables):
declared = {v["name"] for v in prompt.variables}
missing = declared - variables.keys()
if missing:
raise ValueError(f"Missing variables: {missing}")
return prompt.render(variables)Extra variables
Passing extra keys is harmless — they're ignored.
python
prompt.render({"name": "Ada", "extra": "ignored"})
# Works fine.Variable values are stringified
Values pass through str(). Numbers, booleans, even None become strings:
python
prompt.render({"count": 42, "ready": True, "missing": None})
# {{count}} → "42"
# {{ready}} → "True"
# {{missing}} → "None" ← surprising!If you want None to render as empty, normalize before calling:
python
clean = {k: (v if v is not None else "") for k, v in variables.items()}
prompt.render(clean)Repeated variables
Same placeholder used multiple times is substituted everywhere:
txt
"{{name}} likes {{food}}. {{name}} is hungry."python
prompt.render({"name": "Ada", "food": "tea"})
# → "Ada likes tea. Ada is hungry."Variables are NOT recursive
A value that itself contains {{...}} is not re-rendered. The substitution is one-pass.
python
prompt.render({"name": "{{evil}}"})
# Renders literally as "{{evil}}" in the output, not as a recursive expansion.This is intentional — it prevents template-injection issues.
Recipes per kind
Instruction — no variables
python
prompt = pm.get_active_prompt_version("system_intro") # kind: instruction
text = prompt.render() # variables arg ignoredF-string — full substitution
python
prompt = pm.get_active_prompt_version("translator") # kind: f_string
result = prompt.render({
"source_lang": "English",
"target_lang": "Spanish",
"text": "Hello, world!",
})
# → "Translate the following from English to Spanish:\n\nHello, world!"Chat — substitute inside every message body
python
prompt = pm.get_active_prompt_version("interview_bot") # kind: chat
messages = prompt.render({
"role_description": "senior backend engineer",
"topic": "system design",
})
# → [
# {"role": "system", "content": "You are interviewing a senior backend engineer about system design."},
# {"role": "user", "content": "Start with a question about system design."},
# ]Structured — recursive on the base
python
prompt = pm.get_active_prompt_version("entity_extractor") # kind: structured
# Variables come from the BASE prompt, not the structured wrapper:
print(prompt.base.variables)
# [{"name": "text", ...}]
result = prompt.render({"text": "Apple released..."})
# → {
# "base": "Extract entities from: Apple released...",
# "response_schema": { ... unchanged ... }
# }response_schema is never substituted — it's static metadata, not a template.
Driving a UI from prompt.variables
The variable spec attached to f-string and chat prompts is {name, type, description} per variable. Use it to render a form, validate inputs, or document API endpoints automatically:
python
prompt = pm.get_active_prompt_version("translator")
# Render an HTML form
for var in prompt.variables:
print(f'<label>{var["description"]}</label>')
print(f'<input name="{var["name"]}" type="text">')
# Or validate FastAPI request bodies dynamically:
from pydantic import create_model
Model = create_model(
"PromptInputs",
**{var["name"]: (str, ...) for var in prompt.variables}
)Defensive helper
A reusable wrapper that validates and renders in one call:
python
def render_with_validation(prompt, variables):
"""Render with required-variable enforcement."""
if prompt.kind in ("instruction",):
return prompt.render()
declared = {v["name"] for v in prompt.variables}
missing = declared - variables.keys()
if missing:
raise ValueError(
f"Prompt '{prompt.prompt_name}' requires {sorted(declared)}; "
f"missing: {sorted(missing)}"
)
return prompt.render(variables)