Skip to main content

What is Liquid Templating?

Liquid is a template language that lets you combine static text with dynamic data. In Slate workflows, you can use Liquid templating in:
  • Text blocks - Format and combine data from previous steps
  • LLM blocks - Build dynamic prompts with workflow data
Think of Liquid as a way to write templates with placeholders that get replaced with actual data when the workflow runs.

Where Can I Use Liquid?

Text Block

Use Liquid to format workflow data into readable text, reports, or structured output. Example:

LLM Block

Use Liquid in prompts to include dynamic data from previous workflow steps. Example:

Basic Syntax

Output Tags

Use {{...}} to output data. Basic output:
Access object properties:
Access array items:

Logic Tags

Use {%...%} for control flow and logic. Examples:

Filters

Filters modify output values. Use the pipe | symbol to chain filters.

String Filters

Uppercase:
Input: "hello world" → Output: "HELLO WORLD" Lowercase:
Input: "HELLO WORLD" → Output: "hello world" Capitalize:
Input: "hello world" → Output: "Hello world" Strip whitespace:
Input: " hello " → Output: "hello" Replace:
Input: "old text" → Output: "new text" Remove:
Input: "remove word here" → Output: "remove here" Truncate:
Input: "This is a long sentence" → Output: "This is a long se..." Split into array:
Input: "a,b,c" → Output: ["a", "b", "c"] Join array:
Input: ["a", "b", "c"] → Output: "a, b, c" Append:
Input: "text" → Output: "text - suffix" Prepend:
Input: "text" → Output: "prefix - text" Slice (substring):
Input: "hello world" → Output: "hello" Strip HTML:
Input: "<p>text</p>" → Output: "text" URL encode:
Input: "hello world" → Output: "hello%20world" Escape:
Input: "<html>" → Output: "&lt;html&gt;"

Number Filters

Plus:
Input: 5 → Output: 15 Minus:
Input: 10 → Output: 7 Times:
Input: 5 → Output: 10 Divided by:
Input: 10 → Output: 5 Modulo:
Input: 10 → Output: 1 Round:
Input: 3.14159 → Output: 3.14 Ceil:
Input: 3.2 → Output: 4 Floor:
Input: 3.9 → Output: 3

Array Filters

Size (length):
Input: ["a", "b", "c"] → Output: 3 First:
Input: ["a", "b", "c"] → Output: "a" Last:
Input: ["a", "b", "c"] → Output: "c" Join:
Input: ["a", "b", "c"] → Output: "a | b | c" Reverse:
Input: ["a", "b", "c"] → Output: ["c", "b", "a"] Sort:
Input: ["c", "a", "b"] → Output: ["a", "b", "c"] Uniq (unique):
Input: ["a", "b", "a", "c"] → Output: ["a", "b", "c"] Map (extract property):
Input: [{"keyword": "crm"}, {"keyword": "sales"}] → Output: ["crm", "sales"] Where (filter by property):
Input: [{"name": "a", "status": "active"}, {"name": "b", "status": "inactive"}] → Output: [{"name": "a", "status": "active"}]

Chaining Filters

You can chain multiple filters together:

Control Flow

If Statements

Basic if:
Input: step_1.output = "approved" Output:
Input: step_1.output = "rejected" Output: (empty)
If-else:
Input: step_1.output.volume = 15000 Output:
Input: step_1.output.volume = 5000 Output:

If-elsif-else:
Input: step_1.output.volume = 75000 Output:
Input: step_1.output.volume = 25000 Output:
Input: step_1.output.volume = 5000 Output:

Multiple conditions with and:
Input: step_1.output.volume = 5000 and step_1.output.difficulty = 30 Output:
Input: step_1.output.volume = 500 or step_1.output.difficulty = 60 Output: (empty)
Multiple conditions with or:
Input: step_1.output.status = "active" Output:
Input: step_1.output.status = "pending" Output:
Input: step_1.output.status = "inactive" Output: (empty)

For Loops

Basic loop:
Input: step_1.output = ["crm", "sales", "marketing"] Output:

Loop with index:
Input: step_1.output = ["crm", "sales", "marketing"] Output:

Access object properties in loop:
Input:
Output:

Loop with conditions:
Input:
Output:

Loop variables:
  • forloop.index - Current iteration (1-indexed)
  • forloop.index0 - Current iteration (0-indexed)
  • forloop.first - True if first iteration
  • forloop.last - True if last iteration
  • forloop.length - Total number of iterations
Example with loop variables:
Input:
Output:

Limit iterations:
Input: step_1.output = ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8"] Output:

Skip items (offset):
Input: step_1.output = ["item1", "item2", "item3", "item4", "item5"] Output:

Unless (Negative If)

Input: step_1.output.status = "success" Output:
Input: step_1.output.status = "error" Output: (empty)

Case/When (Switch Statement)

Input: step_1.output.status = "approved" Output:
Input: step_1.output.status = "pending" Output:
Input: step_1.output.status = "rejected" Output:
Input: step_1.output.status = "unknown" Output:

Variables

Assign

Create variables to reuse values:
Use case:

Capture

Capture multi-line content into a variable:

Comments

Single line comment:
Multi-line comment:

Whitespace Control

Remove whitespace before:
Remove whitespace after:
Example:
Without -: "a, b, c, " With -: "a,b,c,"

Common Patterns

Extract Keywords from Array

Format Numbers

Conditional Formatting

Build Lists

Combine Multiple Steps


Use Cases

Use Case 1: Dynamic LLM Prompts

In LLM block prompt:

Use Case 2: Format Data for Reports

In Text block:

Use Case 3: Build Structured Output

In Text block:

Best Practices

Template Design

  • Keep it readable: Use line breaks and indentation
  • Test incrementally: Build complex templates step by step
  • Comment complex logic: Use {% comment %} for clarity
  • Handle missing data: Use conditionals to check for data

Filter Usage

  • Chain wisely: Too many filters can be hard to debug
  • Convert types: Use | plus: 0 to convert strings to numbers
  • Extract early: Use map before join for cleaner code
  • Filter before loop: Process data before iteration when possible

Control Flow

  • Avoid deep nesting: Keep if/for logic simple
  • Use elsif: Better than multiple nested ifs
  • Check array length: Use {% if array.size > 0 %} before looping
  • Limit iterations: Use limit: for large arrays

Troubleshooting

Output is Blank

Problem: Template shows no output. Solution:
  • Check step references: {{step_X.output}}
  • Verify previous steps completed successfully
  • Test with simple output: {{step_1.output}}

Filter Not Working

Problem: Filter produces unexpected results. Solution:
  • Check filter syntax: {{value | filter: "param"}}
  • Ensure data type matches filter (string/number/array)
  • Chain filters one at a time to debug

Property Access Error

Problem: {{step_1.output.keyword}} shows blank. Solution:
  • Check exact property name (case-sensitive)
  • Verify object structure: {{step_1.output}}
  • Use array index if needed: {{step_1.output[0].keyword}}

Loop Not Working

Problem: For loop doesn’t produce output. Solution:
  • Verify input is an array
  • Check array isn’t empty: {{step_1.output | size}}
  • Ensure correct loop syntax: {% for item in step_1.output %}

Condition Not Working

Problem: If statement doesn’t behave as expected. Solution:
  • Check comparison operators: ==, >, <, >=, <=, !=
  • Convert strings to numbers: {% assign num = value | plus: 0 %}
  • Use and/or for multiple conditions

What’s Next

Now that you understand Liquid templating: