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:
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.
