Templating Style
When you write @article in a prompt, Pipelex inserts the content of the article input — wrapped in a tag so the model can tell where your data starts and stops. Templating style is what decides the shape of that wrapper.
It is an authoring decision, not a property of the model you happen to run on. You declare it on the pipe; the model never changes it.
[pipe.summarize_article]
type = "PipeLLM"
description = "Summarize an article"
inputs = { article = "Text" }
output = "Text"
templating_style = "xml"
prompt = """
Summarize the article below.
@article
Keep it to one sentence.
"""
renders as:
Summarize the article below.
<article>
Bees pollinate a third of the food we eat.
</article>
Keep it to one sentence.
Two levels, and that's all
A prompt renders under exactly one style, resolved in two steps:
- What the pipe declares — the
templating_stylefield on the pipe. - The runtime default — when the pipe declares nothing.
There is no third level. The style is never derived from the model, the provider, or the backend: a method that renders XML on one model renders XML on all of them.
The shipped default is xml with plain text, set in pipelex.toml:
[inference.templating]
default_templating_style = { tag_style = "xml" }
Override it in your project's .pipelex/pipelex.toml to change the house style for every pipe that doesn't declare one.
Two ways to write it
Bare string — the common case. The string is the tag style; the text format stays plain.
templating_style = "square_brackets"
Inline table — when you also want to set the text format.
templating_style = { tag_style = "xml", text_format = "markdown" }
| Field | Type | Description | Required |
|---|---|---|---|
tag_style |
string | How @variable insertions are wrapped: xml, ticks, square_brackets, no_tag |
Yes |
text_format |
string | How values are rendered inside the prompt: plain (default), markdown, html, json |
No |
The tag styles
Each style below shows what @article produces for an input named article.
xml
The default, and the best-supported shape across current models.
<article>
Bees pollinate a third of the food we eat.
</article>
ticks
A fenced code block, prefixed with the variable name.
article: ```
Bees pollinate a third of the food we eat.
```
square_brackets
BBCode-flavored delimiters.
[article]
Bees pollinate a third of the food we eat.
[/article]
no_tag
The value, bare. Nothing is added — use it when your prompt already provides its own framing, or when a wrapper would confuse the task.
Bees pollinate a third of the food we eat.
Tag names come from the variable
@article tags with article. A value with no name of its own — anything piped through with_images, for instance — falls back to data under xml and square_brackets. Under ticks it renders as a bare fence with no prefix, and no_tag adds nothing either way.
What the two sigils do
The two insertion sigils are governed by different halves of the style:
@variableon its own line inserts the whole input, wrapped pertag_style.$variableinline inserts the value formatted pertext_format, with no wrapper.
So a pipe with templating_style = "no_tag" and one with $article instead of @article produce similar-looking output for different reasons — the first chose not to wrap, the second never asked for a wrapper.
Beyond PipeLLM
PipeComposetakestemplating_styleon its[pipe.name.template]section, for templates that use thetagorformatfilters directly. A compose pipe that declares nothing renders under the same runtime default.PipeImgGenandPipeSearchhave no authored style of their own — their prompts render under the runtime default. Image and search prompts rarely benefit from tagging, but they do render under a real style rather than an invisible fallback.- Construct-mode template fields and the built-in structuring prompts likewise resolve a real style, so a template of yours that uses
| tagbehaves the same everywhere.
A style is always required, and never invented
The Jinja2 tag and format filters have no fallback of their own. Every prompt-rendering entry point resolves a real style before rendering, so a template using | tag always renders in a shape somebody chose. If you build prompts through the kernel API directly and omit the style, you get a loud error rather than a silent default.
Choosing a style
- Stay on
xmlunless you have a reason. It is unambiguous, it nests, and every major model family handles it well. - Reach for
no_tagwhen the input is the prompt — a single block of text that your instructions already introduce. - Set
text_format = "markdown"when the model's output quality depends on seeing structured values (tables, nested objects) rather than flattened text. - Declare the style on the pipe when a specific pipe needs a shape the rest of your method doesn't; change the config default when your whole project wants a different house style.
Related Documentation
- PipeLLM - The
templating_styleparameter in context - PipeCompose - Templating style on composed templates
- LLM Integration - High-level LLM capability overview
- Optimize Cost & Quality - Model choice and presets