Template Syntax#
Parent document: YAML Reference Epic: DOC-002 (YAML Reference Modularization)
Overview#
Templates use Jinja2 (TEA-YAML-001), providing familiar syntax used in Flask, Ansible, and dbt. This allows variable interpolation, conditionals, loops, and filters within YAML configurations.
Table of Contents#
Basic Substitution#
Syntax |
Description |
Example |
|---|---|---|
|
State value |
|
|
Global variable |
|
|
Secret value |
|
|
Checkpoint directory |
|
|
Last checkpoint path |
|
|
GitLab CI style |
|
Jinja2 Filters#
All standard Jinja2 filters are available, plus custom filters:
Filter |
Description |
Example |
|---|---|---|
|
JSON serialize |
|
|
Alias for tojson |
|
|
Parse JSON string |
|
|
Uppercase |
|
|
Lowercase |
|
|
Get length |
|
|
Default for undefined |
|
|
Truncate string |
|
|
Join list items |
|
|
First item |
|
|
Last item |
|
|
Compute SHA256 hash |
|
Jinja2 Constructs#
Conditionals#
- name: format_message
uses: template.render
with:
template: |
{% if state.priority == 'high' %}
URGENT: {{ state.message }}
{% elif state.priority == 'medium' %}
{{ state.message }}
{% else %}
{{ state.message }}
{% endif %}
Loops#
- name: format_report
uses: template.render
with:
template: |
Report Items:
{% for item in state.items %}
- {{ item.name }}: {{ item.value | tojson }}
{% endfor %}
Total: {{ state.items | length }} items
GitHub Actions to Jinja2 Equivalents#
GitHub Actions Style |
Jinja2 Native Equivalent |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object Passthrough#
When a template is a single expression (e.g., "{{ state.data }}"), it returns the actual Python object, not a string representation. This enables passing complex objects between actions:
- name: get_data
uses: http.get
with:
url: "{{ variables.api_url }}"
output: response
- name: process
uses: json.transform
with:
# data receives the actual dict, not a string
data: "{{ state.response }}"
expression: "items[*].name"
This is particularly useful when:
Passing dictionaries or lists between actions
Chaining action results without serialization overhead
Working with structured data from API responses
Undefined Variable Handling#
Templates use StrictUndefined mode. Undefined variables:
Single-level access (
{{ state.missing }}) returnsNoneNested access (
{{ state.missing.deep }}) raisesValueErrorUse
| default("fallback")filter for graceful fallbacks:
url: "{{ state.custom_url | default(variables.default_url) }}"
Security Note#
Template processing uses Jinja2’s sandboxed environment. Unlike the old eval() approach:
__import__and dangerous builtins are blocked in templatesThis improves security for template expressions
run:blocks still useexec()with full Python access (by design)
Template in Different Contexts#
variables:
base_url: https://api.example.com
nodes:
- name: example
uses: http.post
with:
# Template in URL
url: "{{ variables.base_url }}/users/{{ state.user_id }}"
# Template in headers
headers:
Authorization: "Bearer {{ secrets.token }}"
X-Request-ID: "{{ state.request_id }}"
# Template in JSON body
json:
name: "{{ state.name | upper }}"
data: "{{ state.payload | json }}"
Nested Access#
# Access nested state values
{{ state.user.profile.name }}
# Access nested variables
{{ variables.config.timeout }}
# Combine with filters
{{ state.response.data.items | length }}
See Also#
Node Specification - Using templates in node configuration
Navigation & Flow - Templates in conditions
Actions Overview - Action parameters with templates