agents/prompts/PROMPTS.md once with {{variable}} placeholders. At runtime, you fill them in from a patient context dictionary.
This guide walks through how the templating system works, which variables are standardized across all prompts, and how to wire the rendered prompts into your agent pipeline.
Templating only changes how prompts are assembled. The clinical instructions —
tone, methodology, output rules — stay hardcoded in
PROMPTS.md. You are
parameterizing the patient-specific content, not the clinical reasoning.When to use templates
Use a{{variable}} when the value changes between patients, domains, or visits:
| Use a template for | Example |
|---|---|
| Patient-specific fields | {{patient_first_name}}, {{patient_age}}, {{chief_complaint}} |
| Domain-specific fields | {{domain_name}}, {{domain_scores}} |
| Optional sections | {% if has_parent_rater %}...{% endif %} |
| Variable-length lists | {% for rec in recommendations %}...{% endfor %} |
| Hardcode instead | Example |
|---|---|
| Clinical instructions | ”Write in third-person past tense” |
| Methodology | ”Use a Chain of Density approach” |
| Output format rules | ”Return clean markdown only” |
| Fixed domain definitions | The canonical list of cognitive domains |
Three pieces of syntax
You only need three Jinja2 constructs to template every prompt in Luria.1. Variable substitution
{"patient_first_name": "Sarah", "patient_age": 14, "chief_complaint": "difficulty concentrating"}, this becomes:
2. Conditional blocks
Use{% if %} / {% else %} / {% endif %} for content that only applies to some patients:
3. Loops
Use{% for %} / {% endfor %} to render a list whose length you do not know in advance — recommendations, history items, validity concerns:
Standard variables
These variables are loaded fromconfig.patient.yml and available to every prompt. Use them consistently so a single context dictionary works across the whole pipeline.
| Variable | Type | Example |
|---|---|---|
patient_first_name | string | "Sarah" |
patient_last_name | string | "Chen" |
patient_full_name | string | "Sarah Chen" |
patient_age | integer | 14 |
patient_dob | string | "2010-05-15" |
patient_pronouns | string | "she/her" |
he_she | string | "she" |
his_her | string | "her" |
evaluation_date | string | "May 15, 2026" |
referral_source | string | "PCP Dr. Smith" |
chief_complaint | string | "difficulty concentrating" |
clinician_name | string | "Joey Trampush, Ph.D." |
clinic_name | string | "Brainworkup Neuropsychology, LLC" |
Domain-specific variables
These apply only to domain-level prompts such asDOMAIN_INTERPRETATION and SIRF_SYNTHESIS. Pass them per call, not from the global patient config.
| Variable | Type | Example |
|---|---|---|
domain_name | string | "Memory" |
domain_type | string | "neurocog" or "neurobehav" |
domain_scores | dict | {"test1": 65, "test2": 62} |
has_parent_rater | boolean | true |
has_teacher_rater | boolean | true |
validity_concerns | list | ["low effort", "response bias"] |
Templated example: NSE_COD_SUMMARY
This is what a real prompt section inPROMPTS.md looks like after templating. Note how the clinical role and methodology remain hardcoded while patient identifiers and history fields use placeholders.
Rendering a prompt from Python
Installjinja2 in your Luria environment (it is already a dependency of the agent pipeline). Then load PROMPTS.md as a template and render it against a context dictionary.
Rendering a single prompt section
If you only need one section — say,NSE_COD_SUMMARY — extract it first with a regex, then render the snippet directly with jinja2.Template:
A reusable helper for the agent pipeline
In practice, every agent in the pipeline ends up calling the same render step. Wrap it in a helper so each agent only needs to pass its context:Common mistakes
Forgetting to render the template
Forgetting to render the template
Printing a string that contains
{{patient_name}} does not substitute
anything. You must construct a Template (or load it through an
Environment) and call .render(context) for substitution to happen.Missing a variable in the context dict
Missing a variable in the context dict
Jinja2 silently renders missing variables as an empty string. The prompt
still runs, but you get sentences like
"Patient Sarah is years old".
Validate your context dictionary against the variables used in each prompt
before sending it to a model.Mixing snake_case and camelCase
Mixing snake_case and camelCase
A template that reads
{{patientName}} will not be filled by a context
with key patient_name. Pick snake_case and stick with it everywhere —
in config.patient.yml, in PROMPTS.md, and in your Python code.Workflow recommendation
- Add
{{variable}}placeholders toPROMPTS.mdinagents/prompts/, starting with patient identifiers and chief complaint. - Build a context dictionary from
config.patient.ymlonce per evaluation. - For each agent in the pipeline, pass that context (plus any domain-specific keys) into the render helper.
- Send the rendered prompt to the model. Patient data never lives in
PROMPTS.mditself, which keeps the prompt library reusable and PHI-free.
agents/prompts/PROMPTS_JINJA_INTEGRATION.md in the Luria source tree.