Search
Ctrl+K
On this page
Documentation for workflows.
Workflows are the backbone of Shuffle. A workflow is a structured, event-driven automation pipeline that connects apps, data, and logic to execute tasks automatically. Instead of writing code to connect your tools, you build workflows visually using four building blocks: apps, triggers, conditions, and variables.
Every workflow follows a simple pattern: Input → Action → Output.
You need three parts:
1. Use Cases
Use Cases contains pre-made templates. Click "enable" on any use case and Shuffle spins up a ready-made workflow for you. This is the fastest way to get started.
2. AI generation
If you know what you want but aren't sure which nodes to use, type a plain English prompt. For example: "When a new ticket arrives, scan the IP address with VirusTotal." Shuffle generates the nodes and connections automatically. This feature is currently in Beta.
Read more about AI generation →
3. Manual setup
Build from scratch when you need custom logic. Go to workflows, click "Create workflow," give it a name, and start dragging apps onto the canvas.
Go to workflows to get started →
We recommend going through the Workflow Development Exercises before building. It covers the fundamentals so you can build anything, not just follow tutorials.
The checklist:
Before building from scratch, search public workflows. Someone may have already built something close to what you need. Use it as a starting point and modify it to fit your use case.
Below is a video walkthrough demonstrating the workflow creation process — from creating a new workflow to editing, saving, and executing it:
Go to the workflows dashboard and click "Create workflow." Give it a name and a short description. Both can be changed later.
All of your workflows live at /workflows, so you can always find them again.
After creating a workflow, the editor opens. The left panel lists four building blocks: apps, triggers, variables, and conditions. Apps and triggers can be dragged onto the canvas.
A new workflow starts with a default "change_me" node. You can edit it or delete it. Drag an app onto the canvas, click it, and select an action from the dropdown. The default action — "repeat back to me" from the Shuffle Tools app — simply returns its input. Swap it for whatever action you actually need.
The play button starts an execution at your starting node. A side panel shows the output for each node as it runs.
Click the save button next to the play button, or press Ctrl+S. A notification appears at the bottom of the screen when saving is in progress. You need to save before executing — saving makes your latest edits available to the execution engine.
With a saved workflow, click the Orange play button. Execution begins at your starting node, and a side panel opens showing results for each node as it completes.
To review past executions, go to /workflows, click the name of your workflow, and click Executions. It shows the status and output of every previous run.
Click the kebab menu (vertical three dots) on the workflow and select "Duplicate Workflow." A copy appears with a _copy suffix in the name. Use this to experiment without risking your original.
Click the kebab menu (vertical three dots) and select "Delete Workflow." Confirm the deletion when prompted.
Note: Workflows that reference this one as a subflow will break after deletion.
Export: Click the kebab menu (vertical three dots) on a workflow and select "Export Workflow." A JSON file downloads containing the full workflow definition — nodes, connections, variables, and authentication references. Use this to back up a workflow locally or move it between tenants.
Import: Go to /workflows and drag the exported JSON file onto the page, or use the import option in the workflow list. The workflow appears with its original name. You may need to reconfigure authentication for apps that require credentials in the new tenant.
You can also download workflows directly from Git repositories. See Workflow Backup for GitHub and Azure DevOps integration.
This section walks through building a simple workflow from scratch: two nodes, connected, with data passing between them.
Goal: Send a message via the HTTP app and print the response.
{"hello": "world"}.$change_me).You have built a working workflow. From here, you can swap the Testing app for a real service (like sending an email or querying an API), add conditions to branch the logic, or chain more nodes for additional steps.
Once you are comfortable with a two-node workflow:
Apps become nodes when you drag them onto the workflow canvas. Each node represents an app action — a specific call to an external tool or service.
To add a node, drag an app from the left panel onto the canvas. Click a node to configure it on the right side.
A well-structured workflow follows a clear pattern:
Below is a video showing the full structure of a complex workflow, including how to organize and read it:
The fewer nodes a workflow uses, the faster it runs and the easier it is to maintain. Before adding a new node, check whether an existing app action can handle the same step.
The starting node is the first action that runs when a workflow executes. It is marked with a turquoise circular border. It is not a trigger — it is the first app action that receives data from a trigger.
To change the starting node, hover over a different node until you see the flag control in the top-right corner and click it. The shape of the node changes from a square to a circle.
An app bundles one or more actions that connect to a specific service. Apps must be activated within your tenant before they can appear in the left panel.
Each app action requires authentication. Click the app on your workflow, go to Setup, and press the "+" button to add your credentials. Authenticated apps in one workflow are available across your tenant and can be distributed across your sub-tenants.
Shuffle includes a built-in HTTP app for making REST API calls to any endpoint. Use it when no dedicated app exists for a service, or when you need more control over the request than a dedicated app provides.
The HTTP app supports:
This is the same app you would use to call the Shuffle API itself from within a workflow. For example, you can use the HTTP app to trigger another workflow via its webhook URL, or to fetch data from an internal service that does not have a dedicated Shuffle app.
Compare this to dedicated apps (like the GitHub app or Outlook app), which wrap the same HTTP calls into pre-configured actions with built-in authentication. A dedicated app is easier to use; the HTTP app is more flexible.
Other built-in apps: Shuffle also includes several other pre-installed apps:
All other apps must be activated before they appear in the left panel. Once activated, they are available across your tenant.
The execution argument is the input that starts a workflow run. Every trigger provides one. You can also supply one manually when running a workflow by hand.
It can be anything: JSON, a string, a number, a list. It acts like a node — you can reference its value anywhere using:
$exec$trigger$webhook$schedule$userinput$email_triggerAll of these refer to the same value: the data that triggered the execution. Use $exec as the default.
Workflow variables are static values set before execution. They persist across runs and are shared with everyone who has access to the workflow. Common uses: API keys, base URLs, usernames.
Characteristics:
How to create a workflow variable:
$variable_name in any node or condition.Execution variables are temporary values set during a run. They exist only for that execution and are not saved. Use them to capture the result of an action for use later in the same run.
How to set a runtime variable:
$variable_name in any subsequent node.When you click into a field that accepts references, Shuffle shows an autocomplete dropdown listing all available nodes and variables. Click the plus button next to a field to open it.
The dropdown shows each node's output structure. You can navigate through JSON keys and select the exact value you need — without typing the $ syntax by hand. This is especially useful when working with deeply nested responses or when you are unsure of the exact key names.
If the output structure is not yet available (for example, the referenced node has not been executed), you can type the path manually. Use the $node.key and $node.key.subkey syntax described in Parsing JSON.
Passing data from one node to the next is the core of how workflows work. There are three ways:
$node_name or $variable syntax to reference data.You can reference:
$testing_1 — output from a node or variable called "testing_1"$exec — the execution argumentThis only works with nodes that precede the current one, connected via the directional arrows.
Shuffle uses $ to reference nodes and . to traverse JSON keys.
| Expression | Meaning |
|---|---|
$node_1 | Output of node called "node_1" |
$exec | The execution argument |
$exec.name | The name key inside the execution argument |
Given this execution argument:
{
"name": "this is some data",
"description": "Cool description",
"extra": {
"writer": "Fredrik"
}
}
name → $exec.namewriter → $exec.extra.writerIf a node doesn't exist or the key is missing, Shuffle writes the expression as-is.
Lists are identified with #. This is separate from $ (which references nodes).
| Syntax | Meaning |
|---|---|
| No loop — returns the raw value |
.# | Loop over the entire list |
.#0 | Only the first element |
.#1 | Only the second element |
.#0-1 | First and second elements |
.#.data | Loop over list, get data from each item |
.#0.data | First element, get data |
.#max.data | Last element, get data |
Example: Suppose you have a node called get_users that returns this data:
{
"users": [
{"name": "fredrik", "username": "@frikky", "id": "12345"},
{"name": "moomo", "username": "shuffle user 2", "id": "23456"}
]
}
To extract all IDs:
$get_users.users.#.id
Result: ["12345", "23456"]
To get only the first user's name:
$get_users.users.#0.name
Result: "fredrik"
To get the last user's name:
$get_users.users.#max.name
Result: "moomo"
You can use this pattern to reconstruct data in a subsequent node. Given a node called repeat_list with the same data:
{
"ids": "$repeat_list.users.#.id",
"names": "$repeat_list.users.#.name",
"usernames": "$repeat_list.users.#.username"
}
This produces:
{
"ids": ["12345", "23456"],
"names": ["fredrik", "moomo"],
"usernames": ["@frikky", "shuffle user 2"]
}
Important: For nested loops, pass each item to a subflow using the Shuffle Workflow trigger.
Since v0.9.25, Shuffle supports Liquid formatting for data transformation in action parameters. All action parameters are supported.
Example — strip whitespace:
{{ " So much room for activities " | strip }}!
More filters and syntax: Liquid Formatting Guide and the Shopify Liquid documentation.
Conditions control which nodes run and which are skipped. They sit on the lines (branches) between nodes, acting as gatekeepers: the next node only fires when the condition evaluates to true.
A condition requires at least two nodes connected by a line. By default, every branch is implicitly true — the next node always runs. You can override this by adding a condition to the branch.
To add a condition:
Both sides of the condition can reference anything a normal node can: previous node outputs, the execution argument ($exec), workflow variables — any value available in your workflow.
The condition uses the operator to compare the two sides. If the comparison is true, the next node runs. If false, it is skipped.
A node can have multiple outgoing branches, each with its own condition. These conditions are evaluated independently. When multiple branches from the same node are all true, those paths run in parallel.
Multiple conditions on a single branch are joined with implied AND logic. To create OR logic, use separate branches from the same node.
Note: Conditions cannot handle list loops ($variable.#). To filter a list by a condition, use the "Filter List" action described below.
Standard conditions work on individual values. To filter a list — keeping some items and discarding others — use the Filter List action in the Shuffle Tools app.
The Filter List action takes a list and returns two sub-lists: items that matched your criteria and items that did not.
When to use Filter List vs. subflows: If performance is not a concern, the preferred approach is to pass each list item to a subflow using the Shuffle Workflow trigger. Filter List is simpler but runs in-place, which can consume more memory on large datasets.
Example data:
[
{"ip": "1.2.3.4", "malicious": true},
{"ip": "4.3.2.1", "malicious": false},
{"ip": "1.2.3.5", "malicious": true}
]
The goal: extract only the items where malicious is true.
Steps:
$node_name (no # — pass the whole list, not individual items).malicious.true.{
"success": true,
"valid": [
{"ip": "1.2.3.4", "malicious": true},
{"ip": "1.2.3.5", "malicious": true}
],
"invalid": [
{"ip": "4.3.2.1", "malicious": false}
]
}
valid contains items that met the criteria. invalid contains everything else. Reference them as $filter_node_name.valid or $filter_node_name.invalid in subsequent nodes.
Most apps require authentication before you can use them — usually an API key, endpoint URL, or OAuth token.
When you select an app action that needs authentication, the Setup tab shows an Authentication section with a dropdown set to No selection and an orange + button. Until you add credentials, an orange warning box tells you "Authentication needed" and prompts you to click Add Authentication. The step will not work until authentication is configured.
Authentication follows a consistent pattern for apps built with the App Creator (using OpenAPI specs). Custom apps may vary depending on how the creator defined them.
Once you add authentication for an app, it becomes available across your tenant. You can also distribute authenticated apps to sub-tenants.
Tip: Use a workflow variable for credentials so they can be updated in one place.
Below is a screenshot showing the authentication prompt on a Wazuh node. The orange warning indicates that credentials are required before the node can execute.
Every execution generates a random authorization key. Execution data can only be accessed by the worker running it or a tenant admin. No action required on your part.
Triggers are the operators used to execute a workflow automatically. They connect to actions within workflows — often the starting node. Triggers take an execution argument that will be used to initialize the workflow run.
Triggers, alongside apps and variables, can be found on the left-hand panel under the "Triggers" tab.

Triggers are developed by Shuffle specifically to give users multiple ways to run a workflow. The triggers that are not available on-premises are due to access requirements — not hiding of features.
Execution options across environments:
ALL triggers are available everywhere if you have a Shuffle subscription. This allows routing executions through the cloud (without saving any data) to your open source / on-prem instance, eliminating the need to open inbound ports in your firewall.
Example: Say you want to get messages from a service like a SIEM, but it's in a different network or data center. How do you get that request all the way to your instance? This can be done by setting up cloud synchronization:
https://shuffler.io as a secure proxy.https://shuffler.io.https://shuffler.io — it will execute locally inside your on-prem instance.Read more about cloud synchronization in the tenant documentation.
When a trigger fires, you will not be notified by default — it runs behind the scenes. You can discover trigger executions and their data by opening the workflow and clicking the Executions button ("See all executions") at the bottom of the canvas, or by using the Workflow Run Debugger.
Webhooks are the real-time handler for Shuffle data. Webhooks were initially implemented to handle data from Office365 connectors and TheHive, but have turned into a generic trigger, taking any kind of HTTP data, as we saw the need for it.
HTTP Method(s):
PS: Data in the POST request will be the execution argument ($exec). If HTTP queries are present in the GET request, these will be converted to structured JSON.
You can secure your webhook by specifying required HTTP headers in the trigger configuration. Each header must be placed on its own line in the format:
Header-Name: Expected-Value
Any incoming request missing these headers or values will be rejected.

https://shuffler.io/api/v1/webhooks/webhook_<uuid>
Test from the command line:
API Call
curl -X POST 'https://uk.shuffle.security/api/v1/webhooks/webhook_336a7aa2-e785-47cc-85f4-31a4ab5b28b8' \ -d '{ "test": "testing" }'
Response
No response received.
Schedules run workflows on a recurring basis. Shuffle provides two scheduling engines depending on your deployment:

Subflow triggers allow you to execute another workflow from within your current workflow, establishing a parent/child execution relationship.
Key Use Cases:





.# notation:[{"ip": "1.2.3.4", "malicious": true}, {"ip": "4.3.2.1", "malicious": false}, {"ip": "1.2.3.5", "malicious": true}]
Using $Repeat_list.# triggers an independent subflow execution for each object.




The User Input trigger pauses workflow execution and waits for human review and approval/denial before continuing.
Common Scenarios:
frontend_continue, frontend_abort, API_continue, and API_abort).frontend_continue and frontend_abort display an interactive confirmation prompt:API_continue and API_abort immediately confirm the action:Pipelines provide high-throughput log ingestion and detection processing built on the Tenzir pipeline engine.
5162) to ingest incoming Syslog streams.0.0.0.0:5162. Point your syslog forwarders to this endpoint.If Shuffle cannot directly reach the log source, run detection on the host with Tenzir and forward matches to a Shuffle Webhook:
export | sigma /var/lib/tenzir/sigma_rules | to <webhook_url>
Direct email triggers have been superseded by Email Schedules. To trigger workflows from incoming emails, use scheduled polling workflows with dedicated apps:
Files in workflows are managed by reference (file ID). The system stores metadata alongside each file: md5/sha256 hash, filename, filesize, tenant, originating workflow, creation time, and status.
File_id field.File statuses:
| Status | Meaning |
|---|---|
| Created | Metadata prepared, no upload started yet |
| Uploading | Upload in progress — no other file can be added |
| Active | File exists and data is immutable |
| Deleted | File deleted through Shuffle, metadata retained |
Upload a file first in the Admin panel under the "files" tab. Copy the File ID from there.
Below is a screenshot of the Files management page in the Admin panel, showing the file list with metadata columns (name, workflow, MD5 hash, status, filesize, and actions).
Within a workflow, the Shuffle Tools app provides:
The Testing app can create files directly in a workflow.
To make an app action accept file uploads:
file).File_id field appears when used in a workflow.The Datastore is a persistent key-value store for sharing data across workflows and executions. Unlike workflow variables (which are scoped to a single workflow) or execution variables (which last only one run), Datastore entries persist until you delete them. Any workflow in your tenant can read or write to the Datastore.
Common uses: tracking processed items, sharing configuration between workflows, maintaining counters, caching API responses.
The Shuffle Tools app provides actions for Datastore operations:
Set a key:
POST /api/v1/orgs/{org_id}/set_cache
{
"key": "mykey",
"value": "myvalue",
"category": "optional"
}
Get a key:
POST /api/v1/orgs/{org_id}/get_cache
{
"key": "mykey"
}
List keys:
GET /api/v1/orgs/{org_id}/list_cache?top=50&category=optional
Delete a key:
POST /api/v1/orgs/{org_id}/delete_cache
{
"key": "mykey"
}
Bulk set (v2 API):
POST /api/v2/datastore?bulk=true
[
{"key": "k1", "value": "v1"},
{"key": "k2", "value": "v2"}
]
A common pattern: use the Datastore to track which items have already been processed, so the workflow skips duplicates.
This is a special case of Datastore usage. The key acts as a flag: its presence means "already handled."
Prevent the same item from being processed twice. Use the Datastore to track processed items (covered above). This is identical to the deduplication pattern but presented as a workflow-level concern: the workflow checks incoming data, looks up the unique identifier in the Datastore, and only proceeds if the item is new.
Use Liquid formatting to transform data between nodes. Common formatting tasks:
Example — convert a Unix timestamp to ISO format:
{{ "now" | date: "%s" | plus: 0 | date: "%Y-%m-%dT%H:%M:%S" }}
Use the HTTP App to make API calls to any service. Common patterns:
When a service has a dedicated Shuffle app (like GitHub or Jira), prefer that app over the HTTP app. The dedicated app handles authentication, pagination, and error handling for you. Use the HTTP app for services without a dedicated integration, or when you need full control over the request.
To loop over a list within a single workflow, connect a node back to a previous node and use the .# syntax to iterate. Each item in the list triggers one iteration.
Limitation: Standard loops run in a single worker container. Large lists or long-running iterations can consume significant memory and time.
For nested loops (a loop within a loop), or when processing large lists, pass each item to a subflow using the Shuffle Workflow trigger. The child workflow runs independently, and the parent workflow collects the results.
This approach:
When multiple branches from the same node all evaluate to true, those branches run in parallel. Shuffle spins up separate worker containers for each branch. No special configuration is needed — the workflow engine handles it automatically.
Use the Filter List action in the Shuffle Tools app (covered in Condition Loops) to split a list into matching and non-matching items without a subflow. This is simpler but runs in-place, so it is best suited for small to medium lists.
Click the Executions button at the bottom-left of the workflow editor to open the execution sidebar. It shows the history of workflow runs and lets you dig into individual results.
Each entry/run shows:
Click "Refresh Executions" to update the list — executions run in the background and are not always pushed to the UI in real time.
Click an execution to see detailed results:
The action list shows each step within the execution in order. For each action you can see: the app logo, the action name, the function name, and the result. Expand any action for more debug detail.
Tip: Clicking a JSON result value copies its path (e.g. #nodename.success). Clicking the Copy button copies the actual value.
The Workflow Run Debugger lets you search, filter, and manage large volumes of executions — up to 500 at once. Use it when you need to find past runs or view more than the 100 executions shown in the sidebar.
How to access:
https://shuffler.io/workflows/debug?workflow_id=<your-workflow-id>.Features:
Build a workflow once and distribute it to sub-tenants. Each tenant can add their own nodes and branches; the parent controls the shared structure.
Requirements:
Distributed workflows have a blue border.
Inside the workflow, you can switch between tenants.
Editing a child workflow is allowed, but the parent's version overrides shared nodes on the next save — except for nodes, branches, and authentication added by the child.
Every workflow is backed up at most once per 60 seconds. They are stored in a separate database index and can be reverted to at any time.
Access backups from the Revisions button in the bottom bar. Select a previous version to restore it. Your current state is also saved before reverting.
Run a single workflow against multiple sets of credentials. See Authentication Groups.
Multiple users can edit the same workflow simultaneously on Shuffle Cloud.
Every workflow can be accessed as a form at /forms/{workflow_id}. Configure form fields in the workflow's edit panel under "Sections."
See the Workflow API documentation.
Shuffle automatically backs up workflows connected to GitHub or Azure DevOps whenever you make changes and save or execute.
Required details:
https://github.com/<org>/<repo>.git).main or master.repo and workflow scopes.
Required details:
https://dev.azure.com/<org>/<project>/_git/<repo>).main or develop.Code (Read & Write) scope.Note: Azure DevOps support is available from version 2.1.1 and above.
Liquid is a templating language implemented in Shuffle that enables flexible data transformation, string formatting, mathematical operations, and list manipulation across your workflows.
Shuffle uses the Python library Liquidpy. If you find something that should work in Liquid, but doesn't work in Shuffle, please make an issue.
Liquid parsing is available in any field used for execution in Workflows, except directly inside the trigger Execution Argument definition.
Supported:
Not Supported:
The main use of Liquid within Shuffle is to format text. We recommend using the Repeat back to me action in our Shuffle Tools app to test, before moving it into the field of choice once you know your formatting works.
Generally in Liquid:
{{ variable }}{% if statement %}Shuffle also allows writing inline Python within Liquid. Any output printed to stdout with print() is returned as the result:
{% python %}
tags = ["tag1", "tag2", "tag3"]
print(",".join(tags))
{% endpython %}
By adding 86,400 seconds (1 day) to the Unix epoch of "now", we calculate tomorrow's timestamp:
Expression:
{{ "now" | date: "%s" | plus: 86400 | date: "%Y-%m-%dT%H:%M:%S" }}
Result:
2026-03-08T19:59:58
Convert "now" to seconds since January 1st, 1970:
Expression:
{{ "now" | date: "%s" }}
Result:
1773071998
Calculate a Time Range (e.g. 10 days ago):
TimeFrom={{ "now" | date: "%s" | minus: 864000 }}&TimeTo={{ "now" | date: "%s" }}
Return the element count of a list:
Expression:
{{ ["this", "is", "an", "array"] | size }}
Result:
4
Given an earlier node (e.g. shuffle_tools_5) returning:
[{"number": 1}, {"number": 2}, {"number": 3}]
Add 1 to each item when constructing a JSON payload:
{"new_number": {{ $shuffle_tools_5.#.number | plus: 1 }} }
When dealing with keys containing dots (e.g. Elasticsearch/Kibana alert fields like kibana.alert.rule.name), standard dot navigation may fail. You can use Python bracket notation to parse the dictionary safely:
{% python %}
import json
data = json.loads('''$nodename.body''')
print(data["_source"]["kibana.alert.rule.name"])
{% endpython %}
(Note: Dot notation for standard fields does not require Liquid and can be accessed directly as $node.field.)
Clean raw text containing quotes and newlines before injecting into JSON fields:
{
"fields": {
"project": {"key": "SEC"},
"summary": "Automated incident ticket",
"description": "{{ '$shuffle_tools_1' | newline_to_br | replace: '\"', '' | replace: '<br />', '\\\\n' }}",
"issuetype": {"name": "Task"}
}
}
Check whether the current time in EST falls between 4:30 PM and 8:00 AM:
{% python %}
import datetime
initial_timestamp = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(hours=5)
timedata = {
"now": initial_timestamp.strftime("%s"),
"comparison": "",
"run_alert": False,
}
midnight = datetime.datetime.combine(
datetime.date.today(),
datetime.time(0, 0)
)
if initial_timestamp.hour < 8 and initial_timestamp.hour >= 0:
tomorrowtime = (midnight + datetime.timedelta(hours=8)).strftime("%s")
timedata["comparison"] = tomorrowtime
if timedata["now"] < tomorrowtime:
timedata["run_alert"] = True
elif initial_timestamp.hour >= 16 and initial_timestamp.hour <= 23:
todaytime = (midnight + datetime.timedelta(hours=16, minutes=30)).strftime("%s")
timedata["comparison"] = todaytime
if timedata["now"] > todaytime:
timedata["run_alert"] = True
print(timedata["run_alert"])
{% endpython %}
Shuffle provides a comprehensive set of Liquid filters:
{{ -15 | abs }} → 15.{{ "item_" | append: "123" }} → "item_123".{{ 4 | at_least: 5 }} → 5.{{ 6 | at_most: 5 }} → 5.{{ "admin:password" | base64_encode }}.{{ "name,time\\nme,now" | csv_parse }}
{{ "now" | date: "%Y-%m-%d" }}.{{ missing_var | default: "fallback" }}.{{ 20 | divided_by: 4 }} → 5.to, from, subject, body, and attachments.
{{ raw_eml_content | eml_parse }}
{{ my_obj | get: "network.ip" }}.< becomes <).{{ "10.0.1.5" | in_cidr: "10.0.0.0/8" }}
{{ ["admin", "analyst", "auditor"] | join: ", " }}
{{ receive_event | jsonpath: "$.items[*].id" }}
{{ claim_set | jwt_sign: CREDENTIAL.private_key, "RS256" }}
{{ 10 | minus: 3 }} → 7.{{ 7 | modulo: 2 }} → 1.\\n) with HTML line breaks (<br>).{{ count | pluralize: 'alert', 'alerts' }}.{{ 5 | plus: 3 }} → 8.{{ "world" | prepend: "hello " }}.{{ "alert_102" | regex_replace: "[0-9]+", "XXX" }}
{{ "analyst@company.com" | split: "@" }}
{{ 5 | times: 4 }} → 20....).String, Array, Hash).{{ alerts | where: "severity", "critical" }}


strip in the action parameter:

When reversing an array directly returns an iterator object, chaining reverse | join: ',' formats the array correctly:
{{ $shuffle_tools_1 | reverse | join: ',' }}

You can use Liquid Python in app authentication fields to dynamically compute credentials on every run (e.g. generating signed JWT tokens):
{% python %}
import jwt
import time
def generate_token():
key = {
"customerName": "",
"accessID": "YOUR_ACCESS_ID",
"accessKey": "YOUR_PRIVATE_KEY",
"adminRestApiUrl": "https://api.example.com"
}
exp = time.time() + 3600
jwt_claims = {
"iat": time.time(),
"exp": exp,
"aud": key["adminRestApiUrl"],
"sub": key["accessID"],
}
return jwt.encode(jwt_claims, key["accessKey"], algorithm="RS256")
print(generate_token())
{% endpython %}