Template features
Prompting Press uses MiniJinja as its template engine — a strict, sandboxed subset of the Jinja2 syntax. The feature set is deliberately narrow to preserve the sound agreement check.
Supported features
Section titled “Supported features”These features are fully supported in prompt templates:
Interpolation
Section titled “Interpolation”Variable substitution uses {{ }} delimiters:
You are a support assistant for {{ company }}. Keep your replies under {{ max_words }} words.Variables referenced in the template must be declared in the prompt’s variables map — the
agreement check catches any undeclared reference at construction time, not at render time.
Conditionals
Section titled “Conditionals”{% if %} / {% elif %} / {% else %} / {% endif %}:
{% if count == 1 %}You have 1 message.{% elif count > 1 %}You have {{ count }} messages.{% else %}You have no messages.{% endif %}{% for item in items %} / {% endfor %}:
Your items:{% for item in items %}- {{ item }}{% endfor %}Loop variables (the iteration variable, e.g. item above) are loop-local — the agreement
check correctly excludes them from the “undeclared variable” analysis.
Filters and tests
Section titled “Filters and tests”Standard Jinja2 filters (| upper, | lower, | join(", "), etc.) and tests (is defined,
is none, etc.) are supported. Filter names are part of the engine’s built-in globals and are
excluded from the agreement-check’s “required roots” set.
Whitespace control
Section titled “Whitespace control”{%- ... -%} strips surrounding whitespace, as in standard Jinja2.
Excluded features
Section titled “Excluded features”The following features are explicitly disabled and are rejected at construction with a
ConsumerError::Kernel / PromptRenderError carrying code: "excluded_feature":
| Feature | Tag(s) | Reason |
|---|---|---|
| Template inclusion | {% include "…" %} | Requires a cross-template graph walk for the agreement check, which would force the unstable AST API. |
| Template inheritance | {% extends "…" %} | Same: block resolution requires full cross-template analysis. |
| Import | {% import "…" as … %}, {% from "…" import … %} | Cross-template dependency. |
| Macros | {% macro … %} / {% call … %} | Macro calls introduce their own variable scope, breaking the single-template agreement analysis. |
| Block | {% block … %} | Only meaningful with extends; disabled alongside it. |
The enforcement is structural: the Rust engine is compiled with MiniJinja’s macros and
multi_template features disabled. The excluded tags are therefore unrecognised at parse
time — they cannot be accidentally enabled by configuration.
Strict-undefined behaviour
Section titled “Strict-undefined behaviour”The engine runs with UndefinedBehavior::Strict. A template that references a variable that was
not supplied in vars at render time produces a loud KernelError::UndefinedVariable (code
"undefined_variable"), never a silent empty string. This is independent of the agreement check:
the agreement check catches undeclared variables at construction; strict-undefined catches any
gap that slips through at render time.
The agreement check
Section titled “The agreement check”The agreement check is the construction-time enforcement of the subset invariant:
template references ⊆ declared variables (in the prompt's variables map)If a template references a variable name that is not declared in variables, construction fails
immediately — Prompt::new, from_yaml, from_json, from_toml all return an error (or raise
in Python / throw in TypeScript). A constructed Prompt is always agreement-sound.
prompt.check() is a pure advisory lint for the remaining live finding:
an untrusted (trusted: false) variable without a declared guard. See
Lint prompts in CI.
docs current as of 0.2.0