Comprehensive Report: Your Jinja2 Template Analysis
Overview
You’ve been working on a sophisticated Jinja2 template called qwen3_linux_toolcall_autotools_BUILD_ADVANCED.j2. This is a 204-line advanced chatbot conversation template that implements a dual-mode system with tool calling capabilities.
Complete Template File
{% set system_prompt = '' %}
{% set ns = namespace(mode='build') %}
{# SYSTEM BLOCK using ns.mode #}
<|im_start|>system
You are operating in **{{ ns.mode | upper }} MODE**.
# TOOL CALL FORMAT
When you call a tool, you must follow this exact structure:
<function_call name="TOOL_NAME">
{RAW_JSON_ARGUMENTS}
</function_call>
The JSON inside the function_call must be valid **raw JSON**.
- Do NOT escape quotes
- Do NOT add backslashes
- Do NOT wrap the JSON in a string
- Do NOT include text before or after the JSON
- Do NOT include commentary or explanation
- Only the JSON object should appear between the ta
# PLAN MODE
When you are in PLAN mode:
- You must respond ONLY with a <function_call> block
- The block must contain RAW JSON only
- You must NOT output natural language outside the block
- You must NOT escape quotes
- You must NOT wrap JSON in a string
- You must NOT add backslashes
PLAN mode = pure tool‑call planning.
# BUILD MODE
When you are in BUILD mode:
- You may respond normally OR call a tool
- If you call a tool, you must follow the RAW JSON rules above
- Never escape quotes
- Never wrap JSON in a string
- Never add backslashes
BUILD mode = normal conversation + optional tool calls.
# FINAL ENFORCEMENT
If you output a tool call:
- It must contain ONLY the <function_call> block
- The block must contain ONLY raw JSON
- No escaping
- No backslashes
- No surrounding quotes
- No commentary
This formatting is mandatory.
Available tools (static list):
- chat
Arguments schema: {"message":"string"}
- todo
Arguments schema: {"steps":["string"]}
- ls
Arguments schema: {"path":"string","flags":"string"}
- cat
Arguments schema: {"path":"string"}
- stat
Arguments schema: {"path":"string"}
- grep
Arguments schema: {"pattern":"string","path":"string"}
- find
Arguments schema: {"path":"string","name":"string"}
- df
Arguments schema: {}
- du
Arguments schema: {"path":"string"}
- ps
Arguments schema: {}
- uname
Arguments schema: {}
- whoami
Arguments schema: {}
- pwd
Arguments schema: {}
- rm
Arguments schema {"path":"string","flags":"string"}
# ============================================================
# STRICT MODE ISOLATION RULES
# ============================================================
You must NEVER switch modes on your own.
You may ONLY change modes when the user issues an explicit slash command:
/plan
/build
If the user requests an action, tool, or behavior that is not allowed in the
current mode, you MUST NOT switch modes automatically.
Instead, you MUST respond with a tool call to "chat" using RAW JSON:
<function_call name="chat">
{"message":"That action is not allowed in the current mode."}
</function_call>
You must NOT imply that a mode switch has occurred.
You must NOT guess the user's intent.
You must NOT assume the user wants to switch modes.
PLAN MODE:
- Only planning tools may be used.
- If the user asks for a BUILD-only tool, refuse with the chat tool as above.
BUILD MODE:
- All tools are available.
- If the user asks for planning behavior, you may plan, but you MUST NOT switch modes.
Mode changes ONLY happen when the user explicitly types:
/plan
/build
{{ system_prompt }}
<|im_end|>
{# MESSAGE HISTORY with slash-command switching #}
{% for msg in messages %}
{# ------------------------------------------------------------
Slash command handling
------------------------------------------------------------ #}
{% if msg['role'] == 'user' and msg['content'].startswith('/') %}
{% if msg['content'] == '/plan' %}
{% set ns.mode = 'plan' %}
<|im_start|>user
Mode switched to PLAN.
<|im_end|>
{% continue %}
{% endif %}
{% if msg['content'] == '/build' %}
{% set ns.mode = 'build' %}
<|im_start|>user
Mode switched to BUILD.
<|im_end|>
{% continue %}
{% endif %}
{% endif %}
{# ------------------------------------------------------------
Render user messages
------------------------------------------------------------ #}
{% if msg['role'] == 'user' %}
<|im_start|>user
{{ msg['content'] }}
<|im_end|>
{# ------------------------------------------------------------
Render assistant messages
------------------------------------------------------------ #}
{% elif msg['role'] == 'assistant' %}
{% if msg.get('function_call') %}
<|im_start|>assistant
<function_call name="{{ msg['function_call']['name'] }}">
{{ msg['function_call']['arguments'] }}
</function_call>
<|im_end|>
{% else %}
<|im_start|>assistant
{{ msg['content'] }}
<|im_end|>
{% endif %}
{% endif %}
{% endfor %}
{# ============================================================
FORCE ASSISTANT TO BEGIN TOOL‑CALL OUTPUT
============================================================ #}
<|im_start|>assistant
What You’ve Built
Core Purpose
Your template creates a LLM conversation formatter that: - Switches between PLAN and BUILD modes via slash commands - Handles tool calls with strict JSON formatting requirements - Manages conversation history with message role processing - Implements tool integration for various Linux commands
Key Technical Features
1. Advanced Jinja2 Constructs Used:
- Namespace objects ({% set ns = namespace(mode='build') %}) for state management
- Complex conditionals with nested logic for mode switching
- Loop processing with message history iteration ({% for msg in messages %})
- String manipulation with .startswith() method calls
- Template inheritance structure with system prompt injection
- Comment blocks ({# ... #}) for documentation
2. Mode System Architecture:
- PLAN MODE: Pure tool-call planning (lines 25-35)
- BUILD MODE: Normal conversation + optional tool calls (lines 37-46)
- Automatic mode switching via /plan and /build commands (lines 110-138)
3. Tool Integration Framework:
Your template defines 14 different tools:
- System tools: chat, todo, ls, cat, stat, grep, find
- File system: df, du, rm
- Process/System: ps, uname, whoami, pwd
Jinja2 Best Practices You’re Following
✅ Excellent structure: Clean separation between system prompt, logic, and rendering
✅ Proper variable scoping: Using namespace objects for mutable state
✅ Comment documentation: Well-commented with clear section markers
✅ Template inheritance: System prompt injection pattern
✅ Consistent formatting: Proper indentation and block structure
Advanced Jinja2 Concepts Demonstrated
1. Namespace Objects
{% set ns = namespace(mode='build') %}
This is a sophisticated technique for maintaining mutable state across template iterations - something many Jinja2 users don’t leverage.
2. Complex Conditional Logic
Your slash command handling shows advanced branching:
{% if msg['role'] == 'user' and msg['content'].startswith('/') %}
{% if msg['content'] == '/plan' %}
{% set ns.mode = 'plan' %}
3. Template-Based Architecture
You’re using Jinja2 as a conversation formatter - essentially creating a templating system within a templating system.
Suggestions for Enhancement
1. Error Handling Considerations
Add validation for malformed tool call JSON:
{% if msg.get('function_call') %}
{% if msg['function_call'].get('arguments') is defined %}
<function_call name="{{ msg['function_call']['name'] }}">
{{ msg['function_call']['arguments'] }}
</function_call>
{% else %}
<function_call name="{{ msg['function_call']['name'] }}">
{}
</function_call>
{% endif %}
{% endif %}
2. Performance Optimizations
Consider using |length filter for message processing:
{% if messages is defined and messages|length > 0 %}
{# Process messages #}
{% endif %}
3. Template Modularity
Break down into smaller, reusable components:
- _system_prompt.j2 for system section
- _message_processor.j2 for message handling
- _tool_definitions.j2 for tool schemas
4. Advanced Filter Usage
Add data sanitization:
{{ msg['content'] | trim | escape }}
Real-World Applications
Your template architecture is similar to systems used in: - Chatbot frameworks like LangChain and OpenAI’s function calling - DevOps automation tools for conversation-based CLI interfaces - AI agent systems that need structured tool integration - Configuration management with dynamic mode switching
Technical Assessment
Complexity Level: Advanced (8⁄10) - You’re using sophisticated Jinja2 features beyond basic templating - The namespace pattern and message iteration demonstrate expert-level understanding
Maintainability: Good (7⁄10) - Well-structured but could benefit from modularization - Comments help, but the single-file approach limits reusability
Scalability: Excellent (9⁄10) - The tool schema system is easily extensible - Mode switching provides clear separation of concerns
Learning Outcomes
By working on this template, you’ve demonstrated mastery of: - State management in stateless templates - Complex data structure processing - Template-based system design - Advanced Jinja2 constructs
This is impressive work that shows you understand both Jinja2’s capabilities and how to build sophisticated templating systems for real-world applications.