> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runtype.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runtype.com/_mcp/server.

# Flow variables and templates

A template variable is a `{{name}}` placeholder in a step's configuration that Runtype replaces with a value when the step runs. Use template variables to pass Flow inputs, step outputs, and built-in values between steps.

## Basic syntax

Use double curly braces to reference a variable:

```plaintext
{{variableName}}
```

Use template variables in prompts, URLs, request bodies, and conditions.

## Flow input

To pass values into a Flow through the Runtype API, include them in the `inputs` field. Reference each value by its key:

```plaintext
Name: {{customerName}}
Email: {{email}}
Order ID: {{orderId}}
```

Input keys can't start with `_`, because that prefix is reserved for system variables. Runtype rejects a run request or Schedule whose inputs include such a key.

To reference a Flow input explicitly, use the `flow:` prefix. `{{flow:customerName}}` is the same as `{{customerName}}`.

For a record-based execution, use `_record.metadata` to read record metadata:

```plaintext
Customer: {{_record.metadata.customer_name}}
Status: {{_record.metadata.status}}
```

Read a Record's or conversation's `ownerId` from `{{_record.ownerId}}`. It isn't part of
`_record.metadata`, so `{{_record.metadata.ownerId}}` stays unresolved. For a Record that has
no owner, `{{_record.ownerId}}` also stays unresolved. For what an unresolved reference
produces, see [Missing values](#missing-values).

## Message variables

When you pass a `messages` array to a Flow execution, Runtype creates these convenience variables:

| Variable           | Description                                                                                                          |
| ------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `{{messages}}`     | The conversation's messages as an array. If any message contains an image, each message keeps only its text content. |
| `{{userMessage}}`  | The content of the latest user message.                                                                              |
| `{{lastMessage}}`  | The content of the last message, regardless of role.                                                                 |
| `{{messageCount}}` | The number of messages in the conversation.                                                                          |

Use the camelCase names. The editor highlights the snake_case forms `{{user_message}}`, `{{last_message}}`, and `{{message_count}}`, and the flow validator doesn't warn about them, but a run doesn't resolve them. They stay in the output as literal text.

Use these variables to pass conversation history or the latest message to a step:

```plaintext
Conversation: {{messages}}
Latest request: {{userMessage}}
```

## Step outputs

Reference an earlier step's output by its `outputVariable` name:

```plaintext
Summary: {{generate_summary}}
```

## Setting variables

Use a **Set Variable** step to store a value under a variable name that later steps can reference. The value can be static text, a JSON object, or a template.

When the value is exactly one `{{...}}` expression, the variable keeps the original type of the resolved value, such as an object, number, or boolean. When the value mixes text and templates, the variable is a string. For example, a Set Variable step that sets `customer` to `{{lookup_result.customer}}` stores the customer object, so a later step can read `{{customer.tier}}`.

## Nested fields and arrays

Use dot notation to read nested fields of an object:

```plaintext
{{analyze_sentiment.label}}
{{customer_data.metadata.tier}}
{{_record.metadata.address.city}}
```

Use bracket notation and a zero-based index to read array items:

```plaintext
{{search_results[0].metadata.title}}
{{api_response.data[1].name}}
```

Use bracket notation with a quoted key to read a key that contains spaces:

```plaintext
{{form_data['first name']}}
```

## How values render

When Runtype inserts a value into text, it renders the value as follows:

* Strings render as they are.
* Numbers and booleans render as text, for example `42` or `true`.
* Objects and arrays render as JSON text. For example, `{{analyze_sentiment}}` inserts the whole object as JSON.

## System variables

Use these built-in variables in Flow templates. The `_now` date and time fields render in UTC, or in the schedule's timezone when a Schedule starts the run.

| Variable                                          | Description                                           | Example                           |
| ------------------------------------------------- | ----------------------------------------------------- | --------------------------------- |
| `{{_now.iso}}`                                    | ISO 8601 timestamp in UTC                             | `2026-05-20T17:42:13.123Z`        |
| `{{_now.date}}`                                   | Date in the run's timezone                            | `2026-05-20`                      |
| `{{_now.time}}`                                   | 24-hour time in the run's timezone                    | `10:42:13`                        |
| `{{_now.weekday}}`                                | Day of the week in the run's timezone                 | `Wednesday`                       |
| `{{_now.year}}`, `{{_now.month}}`, `{{_now.day}}` | Numeric date parts                                    | `2026`, `5`, `20`                 |
| `{{_now.timezone}}`                               | Timezone used to render the date and time fields      | `America/Los_Angeles`             |
| `{{_now.unix}}`                                   | Unix timestamp in seconds                             | `1779298933`                      |
| `{{_execution.id}}`                               | ID for the Flow execution                             | `exec_01ks3wvfwhexxvrjngdnds7rbg` |
| `{{_execution.timestamp}}`                        | Execution start time                                  | `2026-05-20T17:42:13.123Z`        |
| `{{_execution.type}}`                             | Execution type                                        | `standalone`, `record`, `batch`   |
| `{{_user.id}}`                                    | ID of the user who triggered the Flow                 | `user_01ks3wvfwhexxvrjngdnds7rbg` |
| `{{_user.organizationId}}`                        | ID of the user's organization                         | `org_01ks3wvfwhexxvrjngdnds7rbg`  |
| `{{_flow.id}}`                                    | Flow ID                                               | `flow_01ks3wvfwhexxvrjngdnds7rbg` |
| `{{_flow.name}}`                                  | Flow name                                             | `Customer Support Flow`           |
| `{{_record.id}}`                                  | Record ID in a record-based execution                 | `rec_01ks3wvfwhexxvrjngdnds7rbg`  |
| `{{_record.name}}`                                | Record name in a record-based execution               | `Acme Corp`                       |
| `{{_record.type}}`                                | Record type in a record-based execution               | `customer`                        |
| `{{_record.ownerId}}`                             | Owner key you set on the Record or conversation       | `user_8f21`                       |
| `{{_record.metadata.customer_status}}`            | Record metadata property                              | `paid`                            |
| `{{_endUser.id}}`                                 | ID of the end user that you pass in the request       | `dana`                            |
| `{{_endUser.email}}`                              | End-user email address, when provided                 | `dana@example.com`                |
| `{{_endUser.plan}}`                               | Additional field from the `endUser` object            | `standard`                        |
| `{{_tenant.id}}`                                  | ID of the Product Tenant that you pass in the request | `tnt_staffingco`                  |
| `{{_tenant.plan}}`                                | Additional field from the `tenant` object             | `enterprise`                      |

An `_agent` variable is available only in an Agent's `memory.profileTemplate`, not in Flow step templates. It carries `{{_agent.id}}` and, when the request selected a version, `{{_agent.alias}}`, `{{_agent.versionId}}`, and `{{_agent.version}}` (the version's label). See [Memory namespaces and release pointers](/user-guide/agents/agent-versioning-and-publishing#memory-namespaces-and-release-pointers).

A prompt step that has tools attached can use `_tools` variables in its system prompt. `{{_tools.names}}` lists the tool names, `{{_tools.count}}` gives the number of tools, and `{{_tools.interfaces}}` describes each tool's parameters. Use `{{_tools.interfaces}}` to describe the attached tools to the model. Runtype resolves `_tools` references only in the system prompt.

The `_schedule` variable is available only in schedule-fired executions. It includes `id`, `name`, `cron`, `timezone`, `lastRunAt`, and `nextRunAt` fields.

An `_endUser` variable is present when you include an `endUser` object with an `id` in the dispatch request or the `agents/:id/execute` request. Use `{{_endUser.id}}` in an agent memory `profileTemplate` to keep long-term memory separate for each end user. `_endUser` identifies your customer's end user, not the Runtype account holder in `_user`. If you omit `endUser`, a Flow template reference to `_endUser` stays unresolved. Add a fallback, such as `{{_endUser.id ?? "anonymous"}}`, when a request might not include an end user.

A Product Tenant is your customer's account or workspace inside your product. It sits between the builder organization in `_user` and the individual end user in `_endUser`. An `_tenant` variable is present when you include a `tenant` object with an `id` in the same requests. Use `{{_tenant.id}}` for state shared by a tenant's end users and `{{_endUser.id}}` for state scoped to one end user. If you omit `tenant`, a Flow template reference to `_tenant` stays unresolved in the same way.

Reference only `id` and the fields you pass in `endUser` or `tenant`. `projectedId` is a reserved key on both objects: Runtype drops it from the request, so `{{_tenant.projectedId}}` and `{{_endUser.projectedId}}` never resolve. The flow validator reports [`RESERVED_IDENTITY_VARIABLE`](/user-guide/flows/flow-validation-warnings#template-references-a-reserved-identity-field) for these references.

## Secret references

Use `{{secret:NAME}}` to insert a stored secret at runtime, for example `{{secret:WEATHER_API_KEY}}`. `NAME` is the secret's name in upper snake case. Secret references resolve in request fields, such as the URL, headers, and body of **Fetch URL**, **Make API Call**, **Paginate API**, and **Wait Until** steps, external (HTTP API) tools, and MCP server authentication. They don't resolve in transform-data code. For details, see [Managing secrets](/user-guide/settings/managing-secrets).

## Missing values

If a referenced variable doesn't exist when the step runs, Runtype leaves the `{{name}}` text unchanged. For example, a reference to a step that hasn't run, or to a branch that didn't run, stays in the output as literal `{{name}}` text. In a prompt, the model receives that text. A variable whose value is `null` counts as missing.

## Default values

Add a fallback when a variable might be missing:

```plaintext
{{customerId || "unknown"}}
{{customerData.tier || "standard"}}
{{discount ?? 0}}
```

The `||` operator uses the first truthy value. The `??` operator falls back only when a value is `null` or missing, so an empty string or `0` is kept. A fallback can be a quoted string, a number, `true`, `false`, `null`, or another variable.

Use one operator per expression. Runtype doesn't render an expression that mixes `||` and `??`, and leaves its text unchanged.

Older templates can use the single-pipe form `{{customerId|unknown}}`. It still works, but `||` and `??` are preferred.

## String concatenation

Combine variables with surrounding text in a template:

```plaintext
Customer {{customerName}} placed order #{{orderId}} on {{_now.date}}
```

## Calculations and conditional logic

Use a transform-data step for calculations, ternary expressions, and other complex logic. Template syntax supports variable references and fallback chains, but it doesn't support arithmetic or comparison operators.

## Using variables in JSON

Insert variables into JSON request bodies and metadata as follows:

```json
{
  "customer": "{{customerId}}",
  "summary": "{{generate_summary}}",
  "amount": {{calculate_total}},
  "customer_profile": {{customer_data}},
  "timestamp": "{{_now.iso}}"
}
```

Quote string values. Leave numbers, booleans, objects, and arrays unquoted. An object or array renders as JSON, so `{{customer_data}}` inserts a valid JSON object.

## Debugging variables

To inspect variable values, add a transform-data step. In the script, reference Flow variables by their `outputVariable` names:

```javascript
return {
  debug: true,
  customer_data_value: customer_data,
  analysis_value: analysis,
}
```

Check the step output in the execution results to see the returned values.

### Reference warnings

The flow validator reports these warnings for variable references:

| Code                            | Cause                                                                        | Fix                                                                                        |
| ------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `UNDECLARED_VARIABLE_REFERENCE` | No earlier step's output variable and no Flow input has the referenced name. | Correct the name, set it as an earlier step's output variable, or pass it as a Flow input. |
| `MALFORMED_VARIABLE_REFERENCE`  | A reference uses single braces, such as `{customerName}`.                    | Use double braces: `{{customerName}}`.                                                     |
| `UNKNOWN_VARIABLE_NAMESPACE`    | A reference uses an unrecognized prefix, such as `{{flwo:topic}}`.           | Use `flow:`, `secret:`, or a plain variable name.                                          |

For other warnings, see [Flow validation warnings](/user-guide/flows/flow-validation-warnings).

## Variable scope

Variables exist within one Flow execution:

* A step can reference the output variables of earlier steps in the same Flow.
* A step can't reference variables from another Flow.
* A step after a conditional can reference variables set inside a branch. A variable set in a branch that didn't run stays unresolved, so add a fallback.

## Best practices

Use these practices when you design variable references:

* Give each step a descriptive output variable name so references are clear.
* Add fallbacks or conditionals when data might be missing.
* Keep property chains shallow to reduce errors.
* Test variables with representative data in each scenario.

## Next steps

Continue with these Flow guides:

* [Using prompt steps](/user-guide/flows/using-prompt-steps): generate responses with variables.
* [Using transform-data steps](/user-guide/flows/using-transform-data-steps): transform and calculate values.
* [Using conditional steps](/user-guide/flows/using-conditional-steps): branch based on variable values.
* [Debugging flows](/user-guide/flows/debugging-flows): inspect execution results.
* [Flow validation warnings](/user-guide/flows/flow-validation-warnings): fix the warnings the validator reports.
* [Using records in flows](/user-guide/records/using-records-in-flows): read Record data with `_record`.
* [What are Schedules?](/user-guide/schedules/what-are-schedules): run a Flow on a schedule and use `_schedule`.
* [Managing secrets](/user-guide/settings/managing-secrets): store the credentials that `{{secret:NAME}}` references.
* [End-user identity and credentials](/developer-guides/guides/end-user-identity): pass `endUser` and `tenant` in requests.