Skip to main content
Prompt files use Liquid.js for dynamic content. Instead of hardcoding values, you insert variables that get filled in when the prompt runs.
generate_summary@v1.prompt
---
provider: anthropic
model: claude-sonnet-4-20250514
temperature: 0.3
---

<system>
You summarize company information for sales teams.
</system>

<user>
Write a {{ max_paragraphs }}-paragraph summary of this company:

{{ company_data }}
</user>
When you call generateText({ prompt: 'generate_summary@v1', variables: { max_paragraphs: 2, company_data: '...' } }), Liquid replaces {{ max_paragraphs }} with 2 and {{ company_data }} with your content before the prompt is sent to the LLM. Templates render before YAML parsing, so you can template the frontmatter too — useful for dynamic model selection or configuration.

Variables

The double-brace syntax {{ variableName }} renders values from the variables object you pass to the generate function.
<user>
Write a company summary for {{ company_name }} in the {{ industry }} industry.
</user>
await generateText({
  prompt: 'generate_summary@v1',
  variables: {
    company_name: 'Acme Corp',
    industry: 'SaaS'
  }
});
For nested objects, use dot notation:
<user>
Write a summary for {{ company.name }} ({{ company.industry }}, {{ company.size }} employees).
</user>
variables: {
  company: { name: 'Acme Corp', industry: 'SaaS', size: 250 }
}
Undefined variables render as empty strings — no error is thrown, but your prompt may not make sense. Validate inputs in your step before calling the LLM.

Conditionals

Use {% if %} to include content only when a condition is true:
<system>
You are a sales research assistant.
{% if include_competitors %}
When relevant, mention how this company compares to competitors.
{% endif %}
</system>

<user>
Write a summary for {{ company_name }}.
</user>
With include_competitors: true, the competitor instruction is included. With false or undefined, it’s omitted entirely. Add {% else %} for alternate content:
<user>
{% if detailed %}
Provide a comprehensive analysis with industry context, competitive positioning, and growth trajectory.
{% else %}
Give a brief overview in 2-3 paragraphs.
{% endif %}
</user>
Use {% unless %} for the inverse — it renders when the condition is falsy:
{% unless skip_pain_points %}
Include potential pain points we could address in a sales call.
{% endunless %}

Loops

Iterate over arrays with {% for %}:
<user>
Evaluate this company summary against these criteria:

{% for criterion in criteria %}
{{ forloop.index }}. {{ criterion }}
{% endfor %}

Summary: {{ summary }}
</user>
forloop.index gives you the 1-based position (1, 2, 3…). Use forloop.index0 for 0-based indexing. For arrays of objects:
<user>
Compare these companies:

{% for company in companies %}
- {{ company.name }}: {{ company.industry }}, {{ company.size }} employees
{% endfor %}

Which is the strongest competitor?
</user>

Filters

Filters transform values using the pipe syntax {{ value | filter }}. Text transformations:
{{ company_name | upcase }}        # "ACME CORP"
{{ company_name | downcase }}      # "acme corp"
{{ company_name | capitalize }}    # "Acme corp"
Arrays:
{{ industries | join: ", " }}    # "SaaS, FinTech, Healthcare"
{{ companies | first }}          # First element
{{ companies | last }}           # Last element
{{ companies | size }}           # Array length
Default values:
{{ tone | default: "professional" }}
If tone is undefined or empty, it renders as “professional”. Chaining filters:
{{ company_name | downcase | replace: " ", "-" }}
# "Acme Corp" becomes "acme-corp"
For the full filter reference, see the Liquid.js documentation.

Templating Frontmatter

Variables work in the YAML frontmatter too. This lets you dynamically configure model settings:
---
provider: {{ provider }}
model: {{ model_name }}
temperature: {{ temperature | default: 0.7 }}
---

<user>
{{ prompt_text }}
</user>
await generateText({
  prompt: 'flexible@v1',
  variables: {
    provider: 'anthropic',
    model_name: 'claude-sonnet-4-20250514',
    temperature: 0.3,
    prompt_text: 'Summarize this company...'
  }
});
Use this pattern when you need to switch models based on task complexity or cost.

Common Patterns

Optional sections based on input:
<user>
Research {{ company_name }}.

{% if focus_areas %}
Focus specifically on:
{% for area in focus_areas %}
- {{ area }}
{% endfor %}
{% endif %}

{% if competitor_names %}
Compare against these competitors: {{ competitor_names | join: ", " }}
{% endif %}
</user>
Building structured instructions from an array of rules:
<system>
You are a {{ role }} assistant.

Your response must:
{% for rule in rules %}
{{ forloop.index }}. {{ rule }}
{% endfor %}
</system>
Conditional system behavior:
<system>
You help sales teams research companies.
{% if include_reasoning %}
Explain your reasoning before providing the final output.
{% endif %}
{% unless allow_creativity %}
Stick strictly to the facts provided. Do not add information.
{% endunless %}
</system>

Cheatsheet

Quick reference for the most common Liquid.js syntax.

Output

SyntaxDescriptionExample
{{ variable }}Output a variable{{ name }}Acme Corp
{{ obj.property }}Dot notation{{ company.industry }}SaaS
{{ array[0] }}Array index{{ items[0] }} → first item

Tags

SyntaxDescription
{% if condition %}...{% endif %}Conditional block
{% if condition %}...{% else %}...{% endif %}If/else
{% elsif condition %}Else if
{% unless condition %}...{% endunless %}Negative conditional
{% for item in array %}...{% endfor %}Loop over array
{% assign var = value %}Create a variable
{% capture var %}...{% endcapture %}Capture block into variable
{% comment %}...{% endcomment %}Comment (not rendered)

Operators

OperatorDescriptionExample
==Equals{% if status == "active" %}
!=Not equals{% if type != "draft" %}
>, <, >=, <=Comparison{% if count > 0 %}
andLogical and{% if a and b %}
orLogical or{% if a or b %}
containsString/array contains{% if tags contains "saas" %}

Loop Variables

VariableDescription
forloop.indexCurrent iteration (1-based)
forloop.index0Current iteration (0-based)
forloop.firstTrue if first iteration
forloop.lastTrue if last iteration
forloop.lengthTotal iterations

String Filters

FilterExampleResult
upcase{{ "hello" | upcase }}HELLO
downcase{{ "HELLO" | downcase }}hello
capitalize{{ "hello world" | capitalize }}Hello world
strip{{ " hi " | strip }}hi
truncate: n{{ "hello world" | truncate: 5 }}he...
truncatewords: n{{ "one two three" | truncatewords: 2 }}one two...
replace: a, b{{ "hello" | replace: "l", "x" }}hexxo
remove: str{{ "hello" | remove: "l" }}heo
append: str{{ "hello" | append: "!" }}hello!
prepend: str{{ "world" | prepend: "hello " }}hello world
split: delim{{ "a,b,c" | split: "," }}["a","b","c"]

Array Filters

FilterExampleResult
join: delim{{ arr | join: ", " }}a, b, c
first{{ arr | first }}First element
last{{ arr | last }}Last element
size{{ arr | size }}Array length
reverse{{ arr | reverse }}Reversed array
sort{{ arr | sort }}Sorted array
uniq{{ arr | uniq }}Unique elements
map: prop{{ users | map: "name" }}Array of names
where: prop, val{{ users | where: "active", true }}Filtered array

Other Filters

FilterExampleResult
default: val{{ x | default: "none" }}none if x is nil/empty
date: format{{ now | date: "%Y-%m-%d" }}2024-01-15
json{{ obj | json }}JSON string
escape{{ html | escape }}HTML-escaped string
newline_to_br{{ text | newline_to_br }}\n<br>

Number Filters

FilterExampleResult
plus: n{{ 5 | plus: 3 }}8
minus: n{{ 5 | minus: 3 }}2
times: n{{ 5 | times: 3 }}15
divided_by: n{{ 10 | divided_by: 3 }}3
modulo: n{{ 10 | modulo: 3 }}1
round{{ 4.6 | round }}5
ceil{{ 4.2 | ceil }}5
floor{{ 4.8 | floor }}4