Skip to Content
AgentsTemplate expressions

Template expressions

A template expression passes information from one step of a workflow to the next. You write it in double curly braces inside a step’s settings, and almyty fills in the value just before the step runs. For example, a prompt that reads Write a reply about order {{input.orderId}} goes to the model as “Write a reply about order NW-10428”.

An expression can read what the run started with, what an earlier step produced, or an agent variable. It is a lookup, not a programming language: a dotted path and nothing else. No function calls, no arithmetic, no array indexing, and no comparisons inside the braces.

Template expressions in node config

Syntax

{{source.path.to.value}}

The first segment identifies the data source. Subsequent segments navigate into the data structure using dot notation.

Data sources

SourceSyntaxDescription
Input{{input.property}}The agent’s invocation payload
Node output{{nodes.<id>.output}}Output of any upstream node
Variables{{variables.key}}An agent-level variable

There is no loop context. A Loop node outputs its whole array in one pass and does not re-run the nodes after it per item, so {{loop.item}} and {{loop.index}} name nothing and resolve to an empty string. See Loop.

Input data

{{input.message}} // Top-level property {{input.user.name}} // Nested property

Node outputs

{{nodes.llm_1.output}} // Full output of node llm_1 {{nodes.tool_1.output.data}} // Nested property {{nodes.transform_1.output}} // A transform node's rendered string

What a path may contain

Each segment is letters, digits, underscores and hyphens, and segments are separated by dots. Anything else is rejected and the node throws Template expression contains invalid characters. That rules out array indexing ({{input.items[0].title}} is an error, not an empty value), along with calls such as {{Date.now()}} and comparisons written inside the braces.

A segment that is exactly __proto__, constructor, prototype, process, require, import, global, window, Function or eval is rejected as well. A segment that merely contains one of those words is fine: {{nodes.processor.output}} and {{input.importItems}} both resolve.

Only own properties are read, so nothing reached through a prototype resolves. An expression may be at most 500 characters, and a whole template at most 10,000.

In the builder

Template expressions are used in node configuration fields throughout the builder:

  1. Click a node on the canvas to open its config panel
  2. Type the expression into any field that takes one: prompts, mappings, parameters
  3. A Model call node lists the expressions it found in your prompts, so you can check them at a glance
  4. Use the Test panel in the builder’s top bar to run the pipeline and see what each one resolved to

Examples

Simple string interpolation

In a Model call node’s user prompt template:

You asked: {{input.message}}

Resolves to: You asked: What is the weather?

Composing data from several steps

Based on the search results ({{nodes.tool_1.output.count}} found), here is a summary: {{nodes.llm_1.output}}

Composing a value in a Transform step

A Transform node renders its template and outputs the result:

Query "{{input.query}}" returned {{nodes.tool_1.output.count}} results.

The output is text. A template shaped like a JSON object produces a JSON string rather than an object, so a downstream {{nodes.transform_1.output.count}} resolves to an empty string instead of a number.

Type handling

Inside a template string every resolved value is rendered to text: numbers and booleans with String(), objects and arrays with JSON.stringify. A value of null or undefined renders as an empty string, which is also what a path that does not exist produces.

Two fields read a raw value instead and keep its type:

WhereField
Output nodesource, a bare dot path with no braces
Loop nodeiterableExpression, when it is a single {{...}} reference and nothing else

Everywhere else (prompts, transform templates, tool parameters, sub-agent input mappings, an output node’s mapping) the result is a string.

Error handling

ScenarioBehavior
Path does not existResolves to an empty string. A warning is logged; the run does not fail
Node id is misspelledThe same: an empty string, silently, in the prompt or parameter
Path contains invalid characters or a blocked segmentThe node throws and the run fails there
Upstream node failedEvery node downstream of it is skipped, so the expression is never resolved

The empty resolution is the one to watch for, because nothing reports it: a prompt with a mistyped path is sent with a hole in it and the model answers anyway. Run the pipeline from the Test panel and read what each expression resolved to before activating the agent.

Good practice

  1. Keep expressions to a path: there is nothing else available, so shape the data in the node that produces it: ask a Model call node for JSON, or pick a tool that returns the field you want
  2. Validate your schema: define an Input node schema to catch bad data early
  3. Use meaningful node IDs: search_api reads better than tool_1 in an expression, and a renamed node breaks every expression pointing at it
  4. Test incrementally: an expression that resolves to nothing does not fail the run, so check the Test panel rather than assuming