Docs/Core concepts
Docs/Core concepts

Rule node

The Rule node is where a flow decides whether something is correct. It evaluates a condition and branches the flow into two paths.

The Rule node is where a flow decides whether something is correct. It evaluates a condition against the data available to it (the output of Fetch nodes and the triggering event's parameters) and produces a result of true or false. That result branches the flow into two paths, which is what lets a flow respond differently depending on the outcome (for example, sending an alert only when a check fails).

A rule is defined by:

Name
a name for the rule (required).
Description
an optional description.
Expression
the condition to evaluate, written in Vaurd's expression language.

The expression language

Rules are written using an expression builder, a dedicated expression language for comparing and evaluating values. It operates on the data available to the rule: the output of Fetch nodes and the parameters of the triggering event. An expression evaluates to a single value; when used as a rule, that value is a true/false result that determines the flow's branch.

Functions

The expression builder includes built-in functions, grouped into categories. Each function is written as a call with named parameters, for example, abs(numeric_value). Some functions accept more than one form (for example, with or without an optional argument); each form is listed separately below.

Math functions

FunctionDescriptionExample
abs(numeric_value)Absolute (positive) value of a number.abs(-5) → 5
ceil(numeric_value)Round a number up to the nearest whole number.ceil(3.14) → 4.0
floor(numeric_value)Round a number down to the nearest whole number.floor(3.14) → 3.0
round(numeric_value)Round a number to the nearest whole number.round(3.5) → 4.0
sqrt(numeric_value)Square root of a number.sqrt(16) → 4.0
min(a, b)The smaller of two numbers.min(5, 3) → 3
max(a, b)The larger of two numbers.max(5, 3) → 5
pow(base, exponent)A number raised to a power.pow(2, 3) → 8.0

String functions

FunctionDescriptionExample
contains(string_value, substring)True if the string contains the substring.contains("hello world", "world") → true
startsWith(string_value, prefix)True if the string begins with the prefix.startsWith("hello", "hel") → true
endsWith(string_value, suffix)True if the string ends with the suffix.endsWith("hello", "lo") → true
indexOf(string_value, substring)Position of the first occurrence, or -1 if not found.indexOf("hello world", "world") → 6
indexOf(string_value, substring, start_position)Same, searching from a given position.indexOf("hello world hello", "hello", 5) → 12
lastIndexOf(string_value, substring)Position of the last occurrence.lastIndexOf("hello world hello", "hello") → 12
lastIndexOf(string_value, substring, start_position)Same, searching backward from a given position.lastIndexOf("hello world hello", "hello", 10) → 0
replace(string_value, old, new)Replace all occurrences of old with new.replace("hello world", "world", "CEL") → "hello CEL"
replace(string_value, old, new, count)Replace up to count occurrences.replace("ha ha ha", "ha", "ho", 2) → "ho ho ha"
split(string_value, delimiter)Split the string into a list on the delimiter.split("a,b,c", ",") → ["a", "b", "c"]
split(string_value, delimiter, limit)Split into at most limit parts.split("a,b,c,d", ",", 2) → ["a", "b,c,d"]
substring(string_value, start)The substring from start to the end.substring("hello", 2) → "llo"
substring(string_value, start, end)The substring between start and end.substring("hello", 1, 4) → "ell"
trim(string_value)Remove leading and trailing whitespace.trim(" hello ") → "hello"
upper(string_value)Convert to uppercase.upper("hello") → "HELLO"
lower(string_value)Convert to lowercase.lower("HELLO") → "hello"
reverse(string_value)Reverse the characters in the string.reverse("hello") → "olleh"
charAt(string_value, index)The character at a given position.charAt("hello", 1) → "e"
join(list)Join a list of strings into one string.join(["a", "b", "c"]) → "abc"
join(list, delimiter)Join a list of strings, separated by the delimiter.join(["a", "b", "c"], ",") → "a,b,c"
trimPrefix(string_value, prefix)Remove the prefix if the string starts with it.trimPrefix("hello world", "hello ") → "world"
trimSuffix(string_value, suffix)Remove the suffix if the string ends with it.trimSuffix("hello world", " world") → "hello"
trimLeft(string_value)Remove leading whitespace only.trimLeft(" hello") → "hello"
trimRight(string_value)Remove trailing whitespace only.trimRight("hello ") → "hello"

Date & time functions

FunctionDescriptionExample
now()The current timestamp.now() → 2025-11-23T10:30:45Z
timestamp(iso8601_string)Parse an ISO 8601 string into a timestamp (UTC).timestamp('2024-01-15T10:30:00Z')
timestamp(iso8601_string, timezone)Parse an ISO 8601 string in a specified timezone.timestamp('2024-01-15T10:30:00', 'America/New_York')
getDatePart(timestamp_value, part)Extract a component of a timestamp. part: year, month (0-based), day, hours, minutes, seconds, milliseconds.getDatePart(ts, 'day') → 15
addDate(timestamp_value, amount, unit)Add time to a timestamp; negative subtracts. unit: year, month, day, hours, minutes, seconds, milliseconds.addDate(ts, 2, 'year')
toUTC(timestamp_value)Convert a timestamp to UTC.toUTC(ts) → 2024-01-15T19:30:00Z
toTimezone(timestamp_value, timezone)Convert a timestamp to a specified timezone.toTimezone(ts, 'America/New_York')
getDayOfWeek(timestamp_value)Day of the week: 0 = Sunday, 6 = Saturday.getDayOfWeek(ts) → 1
getDayOfWeek(timestamp_value, timezone)Day of the week in a specified timezone.getDayOfWeek(ts, 'America/New_York') → 1
getDayOfYear(timestamp_value)Day of the year: 0-based, January 1 = 0.getDayOfYear(ts) → 14
getDayOfYear(timestamp_value, timezone)Day of the year in a specified timezone.getDayOfYear(ts, 'America/New_York') → 14

JSON functions

FunctionDescriptionExample
toJSON(string_value)Parse a JSON object string into a map. Returns null if the input is not a JSON object.toJSON('{"name":"John"}') → {name: "John"}
hasKey(map, key)True if the map contains the given key.hasKey({"name":"John"}, "name") → true
getKeys(map)A list of all keys in the map.getKeys({"name":"John","age":30}) → ["name","age"]
getValues(map)A list of all values in the map.getValues({"name":"John","age":30}) → ["John",30]
getKeysByValue(map, value)Keys whose value equals the given value. Supports subset matching when the value is a map.getKeysByValue({'a':1,'b':2,'c':1}, 1) → ['a','c']

List functions

FunctionDescriptionExample
indexOf(list, item)Position of the first occurrence of item, or -1 if not found.indexOf([1,2,3], 2) → 1
concat(list_a, list_b)Combine two lists into one.concat([1,2], [3,4]) → [1,2,3,4]
slice(list, start, end)A sublist from start (inclusive) to end (exclusive).slice([1,2,3,4,5], 1, 4) → [2,3,4]

Variable & output functions

FunctionDescriptionExample
output(node_name)The output of another node, by name, for example a Fetch node's result.output("fetch_orders")
params(param_name)The value of an event parameter, by name.params("orderId")
config(node_name)The configuration of another node, by name, as a map. The available keys depend on the node type (see below).config("fetch_orders")["source"] == "dev_mysql"
retry(node_name)How many retries a Rule node has driven so far in this run. Returns null for nodes that are not Rule nodes.retry("retry_gate") >= 2

These are how a rule references fetched data and event parameters when building a condition: comparing a value returned by a Fetch node against a threshold, or against a value carried on the triggering event.

config() and retry() let a rule read how the flow itself is configured. The keys config() returns for each node type are:

Node typeConfig keys
Eventdelay, delayParam
Fetchsource
Ruleretry, retryBranch, noRetries, retryDelay
Actiontype
How delay and retry() behave

delay is the wait the current execution actually ran with, which on a retry is the rule's retryDelay rather than the original event delay. retry(node_name) is shorthand for that Rule node's retry key, and returns null instead of failing when pointed at another node type. Because it counts a single rule's retries, retry("retry_gate") < config("retry_gate")["noRetries"] is true while the rule still has retries left.

What happens next

A rule's true/false result determines what happens next in the flow. Each branch can lead to a different Action node, for example, taking no action when a rule holds, and sending an alert when it does not. See the Action node.