Expressions
Use expressions and template strings to wire dynamic data between nodes.
Most node configuration fields let you enter a value directly. However, you can
toggle any field into expression mode by clicking the {} button next to
it. In expression mode, the field accepts a dynamic value — typically the output
of a previous node — instead of a hard-coded constant.
Note
Some fields, like IDs, only accept expressions and don't have a constant mode.
These fields won't show the {} toggle — they are already in expression mode.
Expressions
An Expression is a small piece of code that gets evaluated when the node runs.
Constants
Expressions support standard JavaScript-like literals:
| Type | Examples |
|---|---|
| Number | 42, 3.14, -1 |
| String | 'hello', "world" |
| Boolean | true, false |
| Array | [1, 2, 3], ['a', 'b'] |
| Object | { key: 'value', count: 1 } |
Referencing previous nodes
The most common use of expressions is reading the output of an earlier node. Reference a node by its Node ID and access its output fields with dot notation:
getChatMessage.content;This reads the content field from the output of the node with ID
getChatMessage. You can chain property access as deep as needed:
getChat.participants.data;Use bracket notation for array indexing:
getChat.participants.data[0];Or keys with special characters:
$variables["my variable"];Operators
Expressions support common operators for math, comparison, and logic:
| Category | Operators |
|---|---|
| Arithmetic | +, -, *, /, % |
| Comparison | ==, ===, !=, !==, >, <, >=, <= |
| Logical | &&, ||, ! |
| Ternary | condition ? valueIfTrue : valueIfFalse |
The + operator also concatenates strings:
"Hello, " + getChatMessage.participant.name;Examples
Use a node output directly:
getChatMessage.content;Arithmetic with a variable:
$variables.processedCount + 1;Comparison — useful in an If node:
getChatMessage.content === "hello";Ternary expression:
getChat.participants.totalCount > 2 ? "group" : "direct";Build an object:
{ text: getChatMessage.content, chatId: myEvent.chatId }Boolean logic combining two conditions:
$variables.attempts < 3 && !$variables.done;Template Strings
A Template String is a text field that supports rendering expressions within
it. This is done by wrapping expressions in {{ }}. Use this when you want to
embed dynamic values inside longer text, like a prompt or a message.
User: {{getChatMessage.content}}Any valid expression can go inside the braces:
{{getChatMessage.senderName}} said: {{getChatMessage.content}}Note
If the expression evaluates to null or undefined, the placeholder is
replaced with an empty string. If it evaluates to an object or array, it is
converted to a JSON string.
Examples
Simple interpolation:
Hello, {{getChatMessage.participant.name}}!Using a variable:
Attempt {{$variables.attempts}} of 3Arithmetic operation inside a template:
{{getChat.participants.totalCount - 1}} other participantsMultiple placeholders:
[{{myEvent.chatId}}] {{getChatMessage.content}}Built-in objects
The following objects and special variables are always available in expressions and template strings.
$variables
An object containing all variables set during the current execution.
$requestMetadata
An object containing metadata about the user and request that triggered the behavior execution:
| Property | Type | Description | Example |
|---|---|---|---|
$requestMetadata.userId | string | The unique ID of the user who initiated the execution. | "01a008e5-0f95-7aab-aaeb-a6d2b5c57f18" |
$requestMetadata.timeZone | string | The user's IANA time zone identifier (used automatically by Date.format()). | "America/New_York", "Asia/Tokyo", "UTC" |
$requestMetadata.locale | string | The user's preferred language and regional locale tag. | "en-US", "ja-JP", "de-DE" |
Example
User {{$requestMetadata.userId}} triggered workflow from {{$requestMetadata.timeZone}}Math
Expressions have access to the standard JavaScript
Math
built-in object. All standard static methods and mathematical constants are
supported:
| Member | Description | Example |
|---|---|---|
Math.random() | Returns a pseudo-random floating-point number between 0 (inclusive) and 1 (exclusive). | Math.random() |
Math.floor(x) | Returns the largest integer less than or equal to x. | Math.floor(4.9) (returns 4) |
Math.ceil(x) | Returns the smallest integer greater than or equal to x. | Math.ceil(4.1) (returns 5) |
Math.round(x) | Returns the value of x rounded to the nearest integer. | Math.round(4.5) (returns 5) |
Math.min(...v) | Returns the lowest-valued number passed into it. | Math.min(10, 20, 5) (returns 5) |
Math.max(...v) | Returns the highest-valued number passed into it. | Math.max(10, 20, 5) (returns 20) |
Math.abs(x) | Returns the absolute value of x. | Math.abs(-42) (returns 42) |
Math.pow(x, y) | Returns base x to the exponent power y ($x^y$). | Math.pow(2, 3) (returns 8) |
Math.PI | Ratio of the circumference of a circle to its diameter (~3.14159). | Math.PI |
Math.E | Euler's constant and the base of natural logarithms (~2.718). | Math.E |
For a complete reference of all standard trigonometric, logarithmic, and rounding functions, see the official MDN Math documentation.
Date
OpenRP provides a secure, lightweight Date utility namespace in expressions
and template strings. It allows you to obtain current timestamps, parse date
strings, and format dates with automatic user timezone adjustment.
Date.now()
Returns the numeric timestamp in milliseconds corresponding to the current time in UTC epoch.
- Signature:
Date.now(): number - Reference: MDN Date.now() Documentation
- Example:
Date.now(); // e.g. 1786847847412
Date.parse(dateString)
Parses a date string (such as an ISO 8601 string from a node output) and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC.
- Signature:
Date.parse(dateString: string): number - Reference: MDN Date.parse() Documentation
- Example:
Date.parse("2026-08-15T12:00:00Z"); // returns 1786795200000 Date.parse(getChatMessage.createdAt);
Date.format(formatString?, timestamp?)
Formats a date and time string adjusted for the current user's timezone
($requestMetadata.timeZone).
- Signature:
Date.format(formatString?: string, timestamp?: number): string - Parameters:
formatString(optional, string): A formatting template composed of tokens (e.g.'yyyy-MM-dd','h:mm a','HH:mm'). Defaults to'yyyy-MM-dd HH:mm:ss'if omitted.- Supported tokens follow the
date-fns format specification:
yyyy: 4-digit year (e.g.2026)MM: 2-digit month (01-12)MMMM: Full month name (e.g.August)dd: 2-digit day of the month (01-31)HH: 24-hour hour (00-23)h: 12-hour hour (1-12)mm: 2-digit minute (00-59)ss: 2-digit second (00-59)a: AM/PM marker (e.g.AM,PM)EEEE: Full day of the week (e.g.Saturday)
- Supported tokens follow the
date-fns format specification:
timestamp(optional, number): A Unix epoch timestamp in milliseconds (such as returned byDate.now()orDate.parse(...)). If omitted, it defaults to the current time (Date.now()).
Examples
Format the current time in the user's timezone:
Current Time: {{Date.format("h:mm a")}}(Output: Current Time: 2:30 PM)
Format current date with full date and time:
Date.format(); // "2026-08-15 14:30:00"
Date.format("MMMM d, yyyy"); // "August 15, 2026"Format a date timestamp received from an earlier node:
Message sent on {{Date.format("yyyy-MM-dd", Date.parse(getChatMessage.createdAt))}}Format a timestamp with custom format tokens:
Date.format("yyyy-MM-dd'T'HH:mm:ss", 1786795200000);