Skip to main content
Endprompt uses Liquid templating to create dynamic prompts. This lets you inject request data, apply transformations, and add conditional logic to your prompts.

Basic Syntax

Variable Output

Use double curly braces to output values:
{{ inputs.name }}
{{ inputs.text }}
{{ inputs.count }}

Filters

Apply filters to transform values:
{{ inputs.name | upcase }}
{{ inputs.text | truncate: 100 }}
{{ inputs.items | size }}

Tags

Use tags for logic and control flow:
{% if inputs.include_examples %}
Here are some examples:
{% endif %}

Accessing Input Values

All input fields are available under inputs:
Customer name: {{ inputs.customer_name }}
Order ID: {{ inputs.order_id }}
Items: {{ inputs.items | join: ", " }}

Default Values

Use the default filter for optional fields:
Language: {{ inputs.language | default: "English" }}
Max length: {{ inputs.max_length | default: 100 }}
Always provide defaults for optional fields to ensure your prompt works even when values aren’t provided.

Common Filters

String Filters

FilterDescriptionExample
upcaseConvert to uppercase{{ "hello" | upcase }}HELLO
downcaseConvert to lowercase{{ "HELLO" | downcase }}hello
capitalizeCapitalize first letter{{ "hello" | capitalize }}Hello
truncateShorten with ellipsis{{ "hello world" | truncate: 8 }}hello...
stripRemove whitespace{{ " hello " | strip }}hello
replaceReplace text{{ "hello" | replace: "e", "a" }}hallo
splitSplit into array{{ "a,b,c" | split: "," }} → array

Number Filters

FilterDescriptionExample
plusAdd numbers{{ 5 | plus: 3 }}8
minusSubtract{{ 5 | minus: 3 }}2
timesMultiply{{ 5 | times: 3 }}15
divided_byDivide{{ 10 | divided_by: 2 }}5
roundRound number{{ 4.6 | round }}5

Array Filters

FilterDescriptionExample
sizeArray length{{ inputs.items | size }}
firstFirst element{{ inputs.items | first }}
lastLast element{{ inputs.items | last }}
joinJoin with separator{{ inputs.items | join: ", " }}
sortSort array{{ inputs.items | sort }}
reverseReverse order{{ inputs.items | reverse }}
uniqRemove duplicates{{ inputs.items | uniq }}

Control Flow

If / Else

{% if inputs.tone == "formal" %}
Please respond in a formal, professional manner.
{% elsif inputs.tone == "casual" %}
Keep the response casual and friendly.
{% else %}
Use a neutral, balanced tone.
{% endif %}

Unless

{% unless inputs.skip_examples %}
Here are some examples to guide you:
- Example 1
- Example 2
{% endunless %}

Case / When

{% case inputs.format %}
  {% when "json" %}
    Return your response as valid JSON.
  {% when "markdown" %}
    Format your response using Markdown.
  {% when "plain" %}
    Return plain text without formatting.
  {% else %}
    Use your best judgment for formatting.
{% endcase %}

Loops

For Loop

Process the following items:
{% for item in inputs.items %}
- {{ forloop.index }}. {{ item }}
{% endfor %}

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

Loop Example with Conditions

{% for category in inputs.categories %}
{% if forloop.first %}Categories to analyze:{% endif %}
  - {{ category | capitalize }}
{% if forloop.last %}
Please evaluate the content against all listed categories.
{% endif %}
{% endfor %}

Working with Objects

Access nested properties with dot notation:
Customer: {{ inputs.customer.name }}
Address: {{ inputs.customer.address.city }}, {{ inputs.customer.address.country }}

Iterate Over Object Properties

{% for item in inputs.metadata %}
  {{ item[0] }}: {{ item[1] }}
{% endfor %}

Including Snippets

Reuse common template fragments with includes:
{% include 'json-output-instructions' %}
{% include 'tone-guidelines' %}
Snippets are defined in the Prompt Snippets section. See Working with Snippets for details.

Real-World Examples

Email Generator

Write a {{ inputs.tone | default: "professional" }} email for the following situation:

Subject: {{ inputs.subject }}
Recipient: {{ inputs.recipient_name }}
Context: {{ inputs.context }}

{% if inputs.key_points %}
Key points to include:
{% for point in inputs.key_points %}
- {{ point }}
{% endfor %}
{% endif %}

{% if inputs.max_length %}
Keep the email under {{ inputs.max_length }} words.
{% endif %}

Return the email with a clear subject line and body.

Content Classifier

Classify the following {{ inputs.content_type | default: "text" }} into one of these categories:
{% for category in inputs.categories %}
- {{ category }}
{% endfor %}

Content to classify:
{{ inputs.content | truncate: 5000 }}

{% include 'json-output-instructions' %}

Return:
{
  "category": "selected category",
  "confidence": 0.0 to 1.0,
  "reasoning": "brief explanation"
}

Multi-Language Support

{% case inputs.language %}
  {% when "es" %}
    Responde en español.
  {% when "fr" %}
    Répondez en français.
  {% when "de" %}
    Antworten Sie auf Deutsch.
  {% else %}
    Respond in English.
{% endcase %}

{{ inputs.instruction }}

Content: {{ inputs.content }}

Best Practices

Optional fields should have sensible defaults to prevent empty values in prompts.
Use truncate to prevent extremely long inputs from exceeding token limits.
Common instructions (JSON formatting, tone guidelines) should be snippets.
Test with empty arrays, missing optional fields, and unusual values.
Complex logic is hard to debug. Keep conditionals straightforward.

Debugging Templates

If your template isn’t working:
  1. Check the rendered preview in the prompt editor
  2. Verify input field names match exactly
  3. Test with simple values first
  4. Check for typos in filter names
  5. Ensure conditionals have proper endif / endfor tags

Next Steps