You can use both inside the same step (different fields), but you cannot mix them in the same expression — see Condition step for the constraint.
JSONata Expressions
JSONata is a query language for JSON. The minimum you need:
See JSONata cookbook for more.
Some extra functions are available beyond standard JSONata:
Limits
One expression may run for 10 seconds and nest 1,000 levels deep (a recursive function uses about three levels per call). An expression that passes either limit — usually a recursive function that never reaches its base case — fails its step rather than evaluating to"". The limits cover everything the expression runs, including expressions run with $eval, which have every function above except $credential and $secret. That includes regular expressions: a pattern that can backtrack without end (one that repeats something able to match the same text in more than one way, such as (a|aa)+$ on a long run of as) is stopped at the deadline inside $match, $contains, $replace or $split, and fails its step, without holding up other runs. One exception keeps results identical: on text holding characters the timed matcher reads differently (accents typed as separate combining marks, the control characters \x1c–\x1f, the Turkish İ and ı with the i flag, or characters newer than the platform’s Unicode tables), such a pattern runs untimed, as it always has.
A function or a regular expression is not a value a step can record: an expression whose whole result is one — {{ $uuid }} instead of {{ $uuid() }} — fails its step.
AI Expressions
${...} sends the contents (with {{...}} interpolations resolved first) to an LLM and replaces the expression with the response.
Generating expressions with AI
Writing JSONata by hand is optional. In a smart value field, open the Generate tab, describe the value you want in plain English (e.g. “the customer’s email from the previous step” or “full name from first and last”), and Anyreach writes a JSONata expression from your workflow’s available variables. This happens once, at design time — it produces a normal{{ ... }} expression you can review and edit. It is different from the AI tab, which stores a ${ ... } prompt that runs an LLM call every time the workflow executes:
Use Generate to speed up authoring deterministic expressions; use AI when the value genuinely requires reasoning at call time.
Pure vs interpolated
A field whose entire value is one expression is pure:Why this matters
Pure expressions preserve types — ifn3.body.id is an integer, customer_id is an integer. Interpolated expressions always produce strings.
This affects HTTP request bodies (where APIs may require integer IDs, not strings) and Output schemas (where validation enforces types).
Evaluation order
When a step is about to run, the platform evaluates expressions in its config:- JSONata is resolved first, top to bottom, against the current
ctx - AI is resolved next, with
{{...}}interpolations already replaced
{{...}} is replaced with the actual transcript before the LLM sees the prompt.
Where expressions are evaluated
Most fields in most step types support expressions. A few notable places:
Code steps don’t use expressions inside the source code — your Python reads
ctx natively.
