Skip to main content
The Falcon engine uses the @stackone/expressions library to evaluate dynamic values throughout connector YAML files. Three expression formats are available, each suited to different use cases.
Quick rule of thumb:
  • JSONPath ($.path) — Direct value access
  • String Interpolation (${...}) — Building strings/URLs
  • JEXL ('{{...}}') — Logic, conditions, and transformations

JSONPath Expressions

When an expression starts with $, it is treated as a JSONPath expression. Use this for direct data access without transformation.

Syntax

OperatorDescriptionExample
$Root object$.user.name
.Child operator$.user.name
@Current object (in filters)@.age
*Wildcard — all elements/properties$.users[*]
..Recursive descent$..name
[]Subscript$.users[0]
[,]Union$.users[0,2]
[start:end:step]Array slice$.users[0:2]
[?(expression)]Filter expression$.users[?(@.age > 30)]
()Script expressionCustom expressions

Available Contexts

ContextDescriptionExample
$.credentialsAuthentication credentials$.credentials.apiKey
$.inputsAction input parameters$.inputs.userId
$.configConnector configuration$.config.region
$.steps.{stepId}.outputPrevious step output$.steps.fetch_users.output.data
$.responseCurrent response (in response handling)$.response.pagination.cursor
$.iteratorCurrent foreach iteration context$.iterator.item

Examples

# Simple value access
token: $.credentials.apiKey
value: $.inputs.employee_id

# Step output
dataSource: $.steps.fetch_users.output.data

# Nested access
expression: $.user.address.city

# Bracket notation (for keys with special characters)
value: $["info/email"]

# Array access
value: $.steps.get_all_employees.output.data.employees[0].id

# Wildcard
iterator: $.steps.get_all_employees.output.data.employees[*].id
For more details on JSONPath syntax, refer to the JSONPath specification.

String Interpolation

Use ${...} syntax to embed values within strings. This is the preferred method for building URLs, composing strings, and simple variable substitution.

Syntax

${variable.path}
The content inside ${...} supports the same dot-notation paths as JSONPath but without the $ root prefix.

Examples

# URL path parameters
url: /users/${inputs.id}
url: /users/${inputs.userId}/posts/${inputs.postId}

# Dynamic base URLs
baseUrl: https://${credentials.subdomain}.api.provider.com
baseUrl: https://api.${credentials.region}.provider.com/v2

# OAuth callback URLs
redirect_uri: ${apiHostUri}/connect/oauth2/${connector}/callback

# Composing strings
value: Bearer ${credentials.accessToken}
String interpolation only substitutes values — it does not support operators, conditionals, or function calls. Use JEXL expressions for logic.

JEXL Expressions

JEXL (JavaScript Expression Language) expressions are enclosed in double curly brackets {{expression}} and support variables, operators, functions, and conditional logic. In YAML, these must be wrapped in single quotes: '{{...}}'.

Operators

Arithmetic

OperatorDescriptionExampleResult
+Addition / string concatenation{{x + y}}15
-Subtraction{{x - y}}5
*Multiplication{{x * 2}}20
/Division{{x / y}}2
//Floor division{{7 // 2}}3
%Modulus{{x % 3}}1
^Exponentiation{{2 ^ 3}}8

Comparison

OperatorDescriptionExampleResult
==Equal{{x == 10}}true
!=Not equal{{x != y}}true
>Greater than{{x > y}}true
>=Greater than or equal{{x >= 10}}true
<Less than{{x < 100}}true
<=Less than or equal{{x <= 10}}true
inElement of string or array{{x in [1, 2, 3]}}false

Logical

OperatorDescriptionExample
!Logical NOT{{!active}}
&&Logical AND{{x > 5 && y < 10}}
||Logical OR{{x < 5 || y > 10}}

Special

OperatorDescriptionExample
? :Ternary operator{{x > 10 ? "big" : "small"}}
??Nullish coalescing{{x ?? "default"}}

Identifiers and Context Access

Access variables from the evaluation context using dot notation:
# Given context: { name: { first: "John" }, jobs: ["Developer", "Designer"] }
'{{name.first}}'    # "John"
'{{jobs[1]}}'        # "Designer"

Collection Filtering

Filter arrays using bracket expressions:
# Given context: { users: [{ name: "John", age: 30 }, { name: "Jane", age: 25 }] }
'{{users[.name == "John"].age}}'   # 30
'{{users[.age > 25].name}}'        # ["John"]

Common Patterns in Connector YAML

# Conditional argument inclusion
condition: '{{present(inputs.filter)}}'

# Default values
value: '{{inputs.limit || 100}}'
value: '{{$.inputs.status ?? "active"}}'

# Ternary logic
value: '{{$.count > 0 ? $.count : 0}}'

# String concatenation
expression: '{{$.first_name + " " + $.last_name}}'

# Null checking with fallback
value: '{{present(inputs.cursor) ? inputs.cursor : null}}'

# Complex conditionals
condition: '{{present(inputs.start_date) && present(inputs.end_date)}}'

Built-in Functions

The expression engine includes a set of built-in functions available in JEXL expressions.

Presence & Type Checking

present(value)

Returns true if the value is not null or undefined. This is the most commonly used function in connector YAML for conditional argument inclusion.
# Include query param only if provided
condition: '{{present(inputs.filter)}}'
condition: '{{present(inputs.cursor)}}'

# Check step output exists
condition: '{{present(steps.fetch_data.output.data)}}'
InputResult
present("hello")true
present(0)true
present([])true
present({})true
present(null)false
present(undefined)false

missing(value)

Returns true if the value is null or undefined. The inverse of present().
condition: '{{missing(inputs.optional_field)}}'

String Functions

capitalize(value, mode?)

Capitalizes characters in a string. By default capitalizes the first character; use 'each' mode to capitalize each word.
value: '{{capitalize(inputs.name)}}'            # "john" → "John"
value: '{{capitalize(inputs.name, "each")}}'    # "john doe" → "John Doe"

truncate(value, maxLength, suffix?)

Truncates a string to a maximum length, appending a suffix (default "...").
value: '{{truncate(inputs.description, 100)}}'         # Truncate to 100 chars with "..."
value: '{{truncate(inputs.title, 50, "…")}}'           # Custom suffix
value: '{{truncate(inputs.note, 80, "")}}'              # No suffix

padStart(value, targetLength, padString?)

Pads the start of a string to reach a target length. Numbers are converted to strings automatically.
value: '{{padStart(inputs.id, 8, "0")}}'    # "42" → "00000042"
value: '{{padStart(5, 3, "0")}}'             # 5 → "005"

encodeBase64(value)

Encodes a string to Base64.
value: '{{encodeBase64(credentials.apiKey + ":" + credentials.secret)}}'

decodeBase64(value)

Decodes a Base64 string.
value: '{{decodeBase64(inputs.encoded_data)}}'

regexMatch(value, pattern, groupIndex?)

Extracts a value from a string using a regular expression. Returns the specified capture group (default: 1) or null if no match.
# Extract cursor from Link header
value: '{{regexMatch(steps.request.output.headers.link, "after=([^&>]+)", 1)}}'

# Extract numeric ID
value: '{{regexMatch(inputs.reference, "user_id=(\\d+)", 1)}}'

# Full match (group 0)
value: '{{regexMatch(inputs.text, "World", 0)}}'

extractMatch(value, pattern)

Similar to regexMatch but simplified for common extraction patterns.
value: '{{extractMatch(inputs.url, "id=(\\w+)")}}'

Array Functions

includes(array, value)

Checks if an array includes a value. If value is an array, checks that ALL values are included.
condition: '{{includes(inputs.roles, "admin")}}'
condition: '{{includes(inputs.scopes, ["read", "write"])}}'   # All must match

includesSome(array, value)

Checks if an array includes AT LEAST ONE of the given values.
condition: '{{includesSome(inputs.tags, ["urgent", "critical"])}}'

dedupe(array)

Removes duplicate entries from an array, preserving order. Works with primitives and objects (compared by content with sorted keys).
value: '{{dedupe(steps.merge_data.output.data.ids)}}'
InputResult
dedupe([1, 2, 2, 3, 1])[1, 2, 3]
dedupe(["a", "b", "a"])["a", "b"]
dedupe([{id: 1}, {id: 2}, {id: 1}])[{id: 1}, {id: 2}]

join(array, separator?)

Joins array elements into a string with a separator (default: ","). Filters out null/undefined values.
value: '{{join(inputs.fields, ",")}}'
value: '{{join(inputs.tags, " - ")}}'
value: '{{join(["first", "last"], " ")}}'
InputResult
join(["a", "b", "c"])"a,b,c"
join(["a", "b"], " - ")"a - b"
join(["a", null, "b"])"a,b"
join(["a", "b", "c"], "")"abc"

Object Functions

keys(object)

Returns the keys of an object as an array. Returns empty array for non-objects.
value: '{{keys(steps.fetch_data.output.data.metadata)}}'

values(object)

Returns the values of an object as an array. Returns empty array for non-objects.
value: '{{values(steps.fetch_data.output.data.attributes)}}'

Date Functions

now()

Returns the current date/time in ISO 8601 format.
value: '{{now()}}'   # "2025-04-10T12:00:00.000Z"

yearsElapsed(startDate, format, endDate?)

Calculates the number of complete years between two dates. If endDate is omitted, uses today.
value: '{{yearsElapsed(inputs.hire_date, "yyyy-MM-dd")}}'
value: '{{yearsElapsed("2015-01-01", "yyyy-MM-dd", "2025-01-01")}}'   # 10

hasPassed(date, format, yearsToAdd?)

Checks whether a date (optionally with years added) has already passed.
condition: '{{hasPassed(inputs.expiry_date, "yyyy-MM-dd")}}'
condition: '{{hasPassed(inputs.start_date, "yyyy-MM-dd", 5)}}'   # Has start + 5 years passed?

nextAnniversary(initialDate, format)

Calculates the next anniversary of a date.
value: '{{nextAnniversary(inputs.hire_date, "dd/MM/yyyy")}}'

deltaFromNowMs(dateInput, format?)

Calculates milliseconds between a date and now. Supports ISO strings (default), Unix timestamps ('timestamp'), and seconds ('seconds').
value: '{{deltaFromNowMs(inputs.expires_at)}}'
value: '{{deltaFromNowMs(inputs.timestamp, "timestamp")}}'

Expression Selection Guide

Choosing the right expression format depends on the context:
ScenarioFormatExample
Access a credential valueJSONPath$.credentials.apiKey
Access an input parameterJSONPath$.inputs.userId
Reference step outputJSONPath$.steps.fetch.output.data
Build a URL with parametersString Interpolation/users/${inputs.id}
Dynamic base URLString Interpolationhttps://${credentials.subdomain}.api.com
Provide a default valueJEXL'{{inputs.limit ?? 100}}'
Conditional argumentJEXL'{{present(inputs.filter)}}'
Ternary logicJEXL'{{x > 0 ? x : 0}}'
String concatenation with logicJEXL'{{inputs.first + " " + inputs.last}}'
Enum matchingJEXL'{{$.status == "ACTIVE"}}'
Do not mix expression formats within a single value. Use one format per field:
  • Correct: value: '{{$.inputs.limit ?? 25}}'
  • Incorrect: value: '$.inputs.limit ?? 25'

Validation and Error Handling

isValidExpression(expression)

The expression engine validates syntax before evaluation. Invalid expressions return errors that help identify issues.

Incremental JSONPath Errors

When using the expression engine with incrementalJsonPath: true, detailed error messages are provided for JSON Path evaluation failures:
Key 'age' not found at '$.user.details'. Available keys: name
This is used internally by the AI Builder for self-repair during connector development.

Safe Evaluation

The safeEvaluate function returns null instead of throwing errors, which is useful for optional expressions and fallback patterns.