Formula reference
Formulas work out a value from data the workflow already has. They’re used in a Calculation step, in any value set to Calc, inside {{ }} in text and JSON, and in branch rules.
Formulas use CEL, with a few changes that make them forgiving:
- A field that doesn’t exist reads as empty instead of failing.
- Empty text,
0, empty lists and empty values count as false. - Every number is a decimal, so
3and2.5mix freely.
Type {{ or press Ctrl+Space in a formula to choose an input, variable or earlier result. In a Calc value the reference goes in without braces, like input.quantity.
Sample data
Section titled “Sample data”Every example on this page runs against this data. The build checks each one against the real formula engine, so the results are exactly what a workflow gets.
{ "input": { "name": "Ada Lovelace", "email": " Ada@Example.com ", "quantity": 3, "price": 2.5, "tags": [ "vip", "beta" ], "company": "" }, "nodes": { "lookup": { "output": { "found": true, "row": { "Status": "Active", "Plan": "Pro" } } } }, "total": 10}input holds the workflow’s inputs. nodes.<step>.output holds an earlier step’s results, and workflow variables are read by name, like total.
Operators
Section titled “Operators”| Operator | Meaning | Example | Result |
|---|---|---|---|
+ |
Add two numbers, or join two pieces of text | input.quantity + 1 |
4 |
- |
Subtract, or make a number negative | total - input.quantity |
7 |
* |
Multiply | input.quantity * input.price |
7.5 |
/ |
Divide. The result can be a decimal | 10 / 4 |
2.5 |
== |
Equal to | input.name == "Ada Lovelace" |
true |
!= |
Not equal to | input.quantity != 3 |
false |
< |
Less than | input.price < 3 |
true |
<= |
Less than or equal to | input.price <= 2.5 |
true |
> |
Greater than | input.quantity > 2 |
true |
>= |
Greater than or equal to | input.quantity >= 5 |
false |
&& |
Both sides are true | input.quantity > 2 && input.price < 3 |
true |
|| |
Either side is true | input.quantity > 5 || nodes.lookup.output.found |
true |
! |
Not. Empty text, zero and empty values count as false | !input.company |
true |
? : |
If the first part is true, the second, otherwise the third | input.company ? input.company : "No company" |
"No company" |
in |
The list contains the value | "vip" in input.tags |
true |
. |
A field inside a value | nodes.lookup.output.row.Status |
"Active" |
[ ] |
An item in a list, counting from 0 | input.tags[0] |
"vip" |
Use brackets to group parts: (input.quantity + 1) * input.price.
Functions
Section titled “Functions”| Function | What it gives | Example | Result |
|---|---|---|---|
has() |
Whether a field exists. Takes one field path | has(input.email) |
true |
size() |
Characters in text, items in a list, or fields in an object | size(input.tags) |
2 |
string() |
Turn a value into text | string(input.quantity) + " items" |
"3 items" |
double() |
Turn text into a number | double("2.5") * 2 |
5 |
Methods
Section titled “Methods”Call a method on a value with a dot.
| Method | What it gives | Example | Result |
|---|---|---|---|
.size() |
Characters in text, or items in a list | input.name.size() |
12 |
.contains() |
Whether text contains other text. Case-sensitive | input.name.contains("Love") |
true |
.startsWith() |
Whether text starts with other text. Case-sensitive | input.name.startsWith("Ada") |
true |
.endsWith() |
Whether text ends with other text. Case-sensitive | input.name.endsWith("lace") |
true |
.lowerAscii() |
Text in lower case. Changes A to Z only | input.email.trim().lowerAscii() |
"ada@example.com" |
.upperAscii() |
Text in upper case. Changes a to z only | input.name.upperAscii() |
"ADA LOVELACE" |
.trim() |
Text without spaces at the start and end | input.email.trim() |
"Ada@Example.com" |
.join() |
A list of text joined into one piece of text, with an optional separator | input.tags.join(", ") |
"vip, beta" |
Methods can be chained: input.email.trim().lowerAscii().
Missing fields
Section titled “Missing fields”input.missing gives null.
Check for a field with has(), or supply a fallback with ? :.
Errors
Section titled “Errors”A formula that can’t run fails its step. The step’s error names one of these codes.
| Error code | What happened | Example that fails |
|---|---|---|
runtime-workflow.expression.invalid |
The formula isn’t valid: a typo, an unsupported operator or function, or it’s too long | input.quantity % 2 |
runtime-workflow.expression.division_by_zero |
Something was divided by zero | total / 0 |
runtime-workflow.expression.type_mismatch |
An operator got values it can’t use, like text times a number. Use string() or double() to convert first | input.name + 1 |
runtime-workflow.expression.number_out_of_range |
A number got too large to store | 1e308 * 10 |
Text and numbers never convert by themselves. Use string() to turn a number into text, and double() to turn text into a number.
Limits
Section titled “Limits”A formula can be up to 1,024 characters long.
There are no loops, regular expressions or date functions.