{{ ... }} templates for workflow strings and prompts.
Template context
Workflow and prompt templates can reference:| Expression | Resolves to |
|---|---|
{{ goal }} | The workflow goal |
{{ inputs.name }} | A value from [run.inputs] |
{{ env.NAME }} only in config strings and HTTP hook headers.
Run config inputs
Define typed inputs in[run.inputs]:
run.toml
{{ inputs.* }}:
check.fabro
goal
Agent and prompt nodes also receive the workflow goal at runtime:
example.fabro
Create a plan for: Implement the login feature.
Expansion timing
Fabro expands templates in multiple passes:- Before DOT parsing,
{{ inputs.* }}can parameterize structural parts of the graph, including imported.fabrofiles. - After parsing, all string graph, node, and edge attributes are rendered again with the real
{ goal, inputs }context. - Agent and prompt handlers do a final runtime render pass as a safety net.
{{ goal }} is preserved through the pre-parse step so it can be resolved later. That means goal-dependent MiniJinja control flow such as {% if goal %} is not useful in structural pre-parse templates.
Undefined variables
Fabro uses strict undefined-variable handling. If a workflow template references an unknown value such as{{ inputs.langauge }}, validation fails instead of passing the literal text through to the model.
Escaping
To emit literal template syntax, use MiniJinja escaping:{{ '{{' }} when needed.
Input merging
[run.inputs] intentionally replaces the inherited map wholesale rather than merging by key. Whichever layer has the highest precedence and sets [run.inputs] wins its entire map.
| Source | Priority |
|---|---|
CLI flags (-V key=value, repeated) | Highest |
workflow.toml [run.inputs] | |
.fabro/project.toml [run.inputs] | |
~/.fabro/settings.toml [run.inputs] | Lowest |