To manually add Dynamic Variables to a workflow, you can use our Expression Language syntax. This involves wrapping the variable in double curly brackets . This syntax specifies the variable type and its reference path within the workflow, enabling dynamic data usage across different workflow components.
YAML
using the syntax shown below.{{ }}
.
The syntax specifies the variable type and its reference path within the workflow. Understanding this format allows you to insert variables manually when necessary or desired.
null
, which can cause issues when displaying values in the variable picker or workflow inputs.Here is a useful tip to replace null
with a default value:{{event.payload.case.vendors != null ? event.payload.case.vendors : "N/a"}}
str({{steps.s2.output}})
category
defines the dynamic variables type (e.g., inputs, steps, event, metadata).
identifier
specifies the exact reference within the category.
param_name
represents the name you assigned to the input parameter.S
in steps.S1.output
represents a step in the workflow, and the number
following it (1
in this case) indicates the specific step being referenced.
Each step in a workflow is assigned a unique identifier (S1
, S2
, etc.),
allowing you to retrieve outputs from a particular step.last
instead of a step ID
to reference the most recent step output:
context
variable to access dynamic variables. This means that all the expressions mentioned above can be accessed in Python using the following syntax:
Extract the Domain or Username from an Email Address
@
).{{split(steps.1.output.payload.headers[0].value, '@')[1]}}
Breakdown:steps.1.output.payload.headers[0].value
: References the email address value returned in step 1 (S1
), specifically from the first object in the headers array.split(..., '@')
: Splits the email string into two parts at the @ symbol.[1]
: Returns the second element of the array, which corresponds to the domain.@
symbol.{{split(steps.1.output.payload.headers[0].value, '@')[0]}}
Breakdown:Identical to the previous expression, but [0]
retrieves the first element from the split array, representing the username.Extract the Domain from a URL
{{split(split(steps.3.output.files[0].webViewLink, 'https://')[1], '.')[0]}}
Breakdown:steps.3.output.files[0].webViewLink
: Retrieves a URL (e.g., https://drive.google.com/…) from the first file object in step S3.split(..., 'https://')[1]
: Removes the https:// prefix and keeps the remaining part of the URL.split(..., '.')[0]
: Splits the remaining string at the first period and returns the first element — the subdomain or main domain prefix.https://drive.google.com/...
. This is done by targeting the subdomain or first segment of the domain name following the https://
prefix.Create a New URL Using Part of Another URL
{{split(steps.1.output.data.links.item, '/api/v3')[0] + split(steps.1.output.data.links.item, '/api/v3')[1]}}
Breakdown:steps.1.output.data.links.item
: Retrieves the original URL from the output of step S1.split(..., '/api/v3')
: Splits the URL at the /api/v3 segment.[0]
: Returns the portion of the URL before /api/v3.+
: Concatenates both parts together, effectively removing /api/v3.[1]
: Returns the portion of the URL after /api/v3.Fallback if a Field is Null
{{steps.1.output.username!= null ? steps.1.output.username: 'User Not found'}}
blinkopstester123
. Since the user does not exist, the API response does not return a username
field—resulting in a null
value. The expression checks for this and instead displays the fallback message "User Not found"
to avoid showing a blank or null
output.str({{steps.s1.output}})
Switch-Case Style Value Mapping
{{event.payload.severity == "MEDIUM" ? "medium" : event.payload.severity == "Low"? "Low" : "Not Found"}}
event.payload.severity
: Retrieves the severity value from the event payload.== "MEDIUM"
: Checks if the value is “MEDIUM” and maps it to “medium” (lowercase).== "Low"
: If the first condition fails, it checks for “Low” and maps it as-is."Not Found"
: If none of the conditions match, the expression returns a default fallback value of “Not Found”.Check if a Value is in a List
{{event.payload.severity in ["High", "Low"] ? steps.2.output.severity : "Not Found"}}
event.payload.severity
: Retrieves the severity value from the incoming event payload.in ["High", "Low"]
: Checks whether the severity is included in the specified list of allowed values.? steps.2.output.severity
: If the value is in the list, return the severity output from step S2.: "Not Found
: If the value is not in the list, return “Not Found” as the default response.Switch Based On Successful Action
{{steps.2.status == "OK" ? steps.2.output : steps.3.output}}
steps.2.status
:S2
).== "OK"
: Evaluates whether step S2 executed successfully.? steps.2.output
: If step S2 was successful, return its output.: steps.3.output
: If step S2 was not successful, fall back to the output from step S3.if-else
structure.Use a Variable Within a Variable
{{steps.2.output.keymap[ steps.1.output.selected_key]}}
selected_key
.steps.2.output.keymap
: refers to the output of step 2, specifically the keymap JSON object.[steps.1.output.selected_key ]: uses the value of selected_key from step 1’s(
S1`) output as the dynamic key to access a value inside keymap.{{steps.2.output.keymap[ steps.1.output.selected_key ][ steps.1.output.selected_key2 ]}}
steps.2.output.keymap
: A nested JSON object.
[steps.1.output.selected_key]
: First-level dynamic key from step 1 output.
[ steps.1.output.selected_key2]
: Second-level dynamic key from step 1 output.
{{steps.2.output.keymap[ steps.1.output.selected_key[ steps.1.output.selected_key2 ]]}}
steps.1.output.selected_key
: A JSON object[steps.1.output.selected_key2]
: dynamically accesses a key inside selected_key.The result of steps.1.output.selected_key[ steps.1.output.selected_key2]
is used as a key to index into steps.2.output.keymap
Dynamic Loop Limiter
{{len(variables.data_to_loop) < variables.loop_max ? len(variables.data_to_loop)-1 : variables.loop_max}}
len(variables.data_to_loop)
: Returns the number of items in the list stored in the variable data_to_loop.< variables.loop_max
: Compares the list length to the maximum allowed number of iterations, loop_max.? ... : ...
: This ternary operator returns one of two values depending on the comparison:len(variables.data_to_loop) - 1
(the last valid index of the list).variables.loop_max
.len(variables.data_to_loop) - 1
: Because loops are zero-indexed, this sets the loop limit to the last valid item index if the list is shorter than the max limit.variables.loop_max
: The maximum number of iterations allowed if the list is longer or equal in length.loop_max
variables.data_to_loop = ["item1", "item2", "item3"]
variables.loop_max = 5
len(data_to_loop) = 3
3 < 5
→ True3 - 1 = 2
2
(allowing indices 0, 1, 2).
loop_max
variables.data_to_loop = ["item1", "item2", "item3"]
variables.loop_max = 2
len(data_to_loop) = 3
3 < 2
→ Falsevariables.loop_max = 2
2
.
String Building
{{steps.2.output.payload.headers[0].value + " ( " + steps.2.output.payload.headers[1].name + steps.2.output.payload.headers[1].value + " ) "}}
inputs.Name
: This retrieves the Delivered-To email address from the email header.+
: String concatenation which combines multiple substrings into one final string." ( " + ... + " ) "
: Literal characters that wrap the date value(steps.2.output.payload.headers[1].value
) in parentheses.steps.2.output.payload.headers[1].name
: Retrieves the name of the second header, which in this case is Received
.steps.2.output.payload.headers[1].value
: Represents metadata about the message transmission (e.g., SMTP server info, timestamp, etc.).