Skip to content

Jinja2 Templates

Rules, category descriptions, prologues, epilogues, and the default category description support Jinja2 templates for dynamic content based on configuration and scope metadata.

Available Template Variables

Templates can access:

  • Configuration: All DAIMYO_* environment variables and settings from config/settings.toml
  • Scope metadata: scope.name, scope.description, scope.tags, scope.sources
  • Category info: category.key, category.when (in rule text only)
  • Daimyo version: daimyo_version — the running version of daimyo (e.g., 1.15.0)

Basic Example

Configuration (config/settings.toml):

TEAM_NAME = "Backend Team"
SLACK_CHANNEL = "#backend"

Rules with templates (commandments.yml):

python.monitoring:
  when: "When monitoring {{ scope.name }} in {{ scope.tags.env | default('dev') }}"
  ruleset:
    - "Alert {{ TEAM_NAME }} via {{ SLACK_CHANNEL }}"
    - "Log level: {{ LOG_LEVEL }}"

Rendered output (assuming scope.tags.env = "production"):

## python.monitoring
*When monitoring my-service in production*
- **MUST**: Alert Backend Team via #backend
- **MUST**: Log level: INFO

Best Practices

Always use the default filter for optional variables:

- "Use {{ MY_VAR | default('fallback_value') }} for configuration"

Conditionals:

- "{% if scope.tags.env == 'prod' %}Use strict security{% else %}Use standard security{% endif %}"

Multiple variables:

- "Team {{ scope.tags.team }} deploys to {{ scope.tags.region }}"

Error Handling

Daimyo handles template errors gracefully. When templates fail to render (missing context variables, unavailable filters/tests), the system:

  • Removes the failed element from the main response body
  • Collects failure information
  • Reports failures in a separate section (minimal format for LLMs)

JSON/YAML responses include a template_failures field:

{
  "metadata": { ... },
  "commandments": { ... },
  "suggestions": { ... },
  "template_failures": [
    {
      "element_type": "rule",
      "element_identifier": "python.web rule #2",
      "template_text": "Use {{ UNDEFINED_VAR }} ...",
      "error_message": "'UNDEFINED_VAR' is undefined",
      "variable_name": "UNDEFINED_VAR"
    }
  ]
}

Markdown responses include a compact failures section wrapped in <ignore-failed-template> tags:

<ignore-failed-template>
## Template Failures

**python.web rule #2**: `UNDEFINED_VAR` undefined
```
Use {{ UNDEFINED_VAR }} for configuration
```

**python.testing rule #5**: `TEST_FRAMEWORK` undefined
```
Use {{ TEST_FRAMEWORK }} for all tests
```

</ignore-failed-template>

Failed elements are removed from the main response body and only appear in this diagnostic section. The <ignore-failed-template> tags provide a clear signal to LLMs to completely ignore this information. The format is concise while still showing the original template content for debugging.

Use Cases

Environment-aware rules:

python.deployment:
  when: "When deploying to {{ scope.tags.region }}"
  ruleset:
    - "Deploy to {{ scope.tags.region }} region"
    - "{% if scope.tags.env == 'production' %}Require manual approval{% endif %}"
    - "Notification: {{ SLACK_DEPLOY_CHANNEL | default('#deployments') }}"

Team-specific rules:

code-review:
  when: "When reviewing code for {{ TEAM_NAME }}"
  ruleset:
    - "Review in {{ CODE_REVIEW_TOOL | default('SonarQube') }}"
    - "Require approval from {{ scope.tags.team }} lead"

Version-aware rules:

general:
  ruleset:
    - "These rules require daimyo {{ daimyo_version }} or later"
    - "{% if daimyo_version >= '1.15' %}Use the MCP server interface{% endif %}"

Templated prologues and epilogues:

rules_markdown_prologue = '''
# Rules for {{ scope.name }}
*{{ scope.description }}*

These rules are {{ "critical" if scope.tags.env == "production" else "recommended" }}.
'''

rules_markdown_epilogue = "Questions? Contact {{ TEAM_NAME | default('the team') }} via {{ SLACK_CHANNEL | default('#general') }}"

default_category_description = "Rules for {{ category.key }} - applies in {{ scope.name }}"