Expand description
system_prompt template rendering for the Operator path.
Lets the agent.md body (AgentDef.profile.system_prompt) carry
Jinja2-compatible syntax ({{ directive }} / {% if intent %} /
{{ x | upper }} and so on). The caller passes
TaskSpec.initial_directive as JSON and its fields expand into the
template slots.
§Engine choice
minijinja (maintained by Armin Ronacher, the Jinja2 author — a light dependency). Two defaults are forced up front to avoid classic traps:
auto_escape = None. HTML auto-escape is off; for LLM prompts, turning</>into</>corrupts the prompt.UndefinedBehavior::Strict. A typo’d variable would otherwise silently render as an empty string; in a production prompt template we want that to fail loud.
§Syntax available inside the agent.md body (Jinja2-compatible, per
minijinja v2)
Variables: {{ directive }} / {{ slot.nested }} / {{ items[0] }}
Filters: {{ name | upper }} / {{ x | default("fallback") }} / {{ s | length }}
Branch: {% if intent %}...{% elif other %}...{% else %}...{% endif %}
Loop: {% for x in items %}{{ x }},{% endfor %}
Comment: {# note #}
Raw: {% raw %}{{ literal }}{% endraw %}Macros, include, and inheritance are not available here — this
layer performs a flat render over one string handed in by the caller,
and does not support multi-template composition. If we ever need
that, adding a source loader to Environment is a carry.
§Slot names (the variables the caller can reference in the
template)
slots_from_prompt(prompt: &str) builds the slot map:
- When
promptis a JSON object, the object’s top-level keys become the slot names — for exampler#"{"directive":"X","intent":"fix"}"#exposes{{ directive }}and{{ intent }}. - When
promptis anything else (a plain string, a number, an array, an already-stringified JSON), it is wrapped as{"directive": <the prompt itself>}; only{{ directive }}is available.
To expose additional slots, the caller (whoever assembles
TaskSpec.initial_directive) passes a JSON object. Conventions:
directive(effectively required) — the main task instruction; the plain-prompt fallback also lives here.intent— task kind / classification hint (optional; used inifbranches).context— additional context (optional).- Beyond those, agent.md authors are free to add whatever slots the template needs.
§Errors
- Undefined variable →
RenderError::Template(strict mode). - Syntax error →
RenderError::Template. - On the
OperatorSpawnerpath this is wrapped inSpawnError::Internal("render system_prompt: ...")and propagated — no silent fallback, fail loud.
Enums§
- Render
Error - Render errors. Anything from minijinja is wrapped as
Template.
Functions§
- render_
system - Render a
system_prompttemplate in strict mode with auto-escape disabled. - slots_
from_ prompt - If
promptparses as a JSON object, treat it as the slot map; otherwise wrap it as{"directive": prompt}. Corresponds to theinitial_directiveintake convention on the caller side (OperatorSpawner).