# Variables and data flow

> How data flows between nodes through node output and variables, with scoping rules for subflows and branches.

Nodes in a workflow do not share data automatically. When a node produces output, such as an HTTP response or a computed value, the nodes after it, called downstream nodes, read that output through expressions. An expression is a short piece of JavaScript that reads or computes a value. Data flow is how a workflow passes values between nodes and keeps them for the length of a run.

Data moves through a workflow in two ways:

- Node output: each node produces output that downstream nodes can reference.
- Variables: workflow-level values that you define to store and pass values between nodes.

[Expression syntax](expression-syntax.md) describes the full grammar, the operators, and how to write `$vars` references.

## How it works

### Node output

Every node that produces data makes it available through `$vars.<nodeName>.output`. The node name is assigned automatically from the node type. For example, the first HTTP Request node is named `httpRequest1`, and the second is named `httpRequest2`.

A node's variable name is its **ID**, shown on the **Advanced** tab of the properties panel when the node is selected. The pencil icon next to **ID** changes it.

```javascript
// Access HTTP Request response
$vars.httpRequest1.output.body
$vars.httpRequest1.output.code

// Access Script return value
$vars.script1.output

// Access a second HTTP Request
$vars.httpRequest2.output.body
```

![A Manual trigger, HTTP Request, Script, and Decision connected in order. Each of the first three nodes writes its output to $vars, and each later node reads the outputs that came before it.](https://dev-assets.cms.uipath.com/assets/images/maestro-automate/data-flow-node-output-automate-631ba8e9.webp)

The output structure depends on the node type. Each page of the [node reference](node-reference.md) lists the output of its node.

### Node errors

When a node fails and its error handle is connected, the details of the failure are on `$vars.<nodeName>.error`, next to the node's output. Read them in the nodes on the error path, for example in a Script node that logs the failure:

```javascript
// Read the error of a failed HTTP Request
$vars.httpRequest1.error.message   // what went wrong
$vars.httpRequest1.error.status    // the HTTP status, for example 404
```

The error object exists only on the error path. On the success path, `$vars.<nodeName>.error` is undefined. [The error object](error-handling.md#the-error-object) lists all its fields.

### Variables

Variables are workflow-level values that persist for the duration of a single run. You define them in the **Variables** panel, which opens from the **Variables** tab next to the **Properties** tab on the right. The panel lists the **Inputs**, **Outputs**, and **Variables** of the workflow, and the output of each node. A toggle switches between **All variables** and **Selected node**. The **Focus on node** icon on a node's row zooms the canvas to that node. With **Selected node** on, the panel is limited to the selected node, and its header shows the name of that scope, for example **Scope: Manual trigger**.

![The Variables panel with All variables selected, showing the Inputs section with the Manual trigger input, the Outputs section with a result output, the Variables section with an orderTotal variable, and the output of each node below.](https://dev-assets.cms.uipath.com/assets/images/maestro-automate/18-variables-panel-automate-fce0ac6d.webp)

The **+** next to **Variables** in the panel opens the **Add variable** dialog. Each variable has:

- Name: how you reference it in expressions, for example `$vars.orderTotal`.
- Data type: String, Number, Boolean, Object, or Array.
- Description: an optional note on what the value represents.
- Default value: an optional starting value.

Workflow-level variables are always bidirectional: any node can read or write them. There is no direction setting to configure. A read-only or write-only value comes from a trigger input or an output variable instead, described below.

The three kinds of data differ by where you define them:

| Kind | Defined in | Direction | Reference syntax |
|---|---|---|---|
| Variable | **Variables** panel, next to **Variables** | Bidirectional (read and write) | `$vars.<name>` |
| Trigger input | On the trigger node, or in the **Variables** panel next to the trigger | Read-only | `$vars.<triggerName>.output.<name>` |
| Output variable | On an End node, or in the **Variables** panel next to **Outputs** | Write-only | `$vars.<name>` |

When to use each:

- Node output fits data that passes from one node to the next. This is the most common pattern.
- Variables fit values that must be accessible across the entire workflow.
- Inputs and outputs fit values that define what the workflow itself receives or returns, as described in Trigger inputs and Output variables below.

Descriptive camelCase names, such as `customerEmail`, `invoiceTotal`, and `apiResponse`, remain readable in execution traces over time. Single-letter names and abbreviations lose meaning quickly.

### Trigger inputs

Input variables are not defined in the **Variables** section. They are added as input arguments in the trigger's properties panel, or with the **+** next to the trigger in the **Variables** panel, which opens the **Add input variable** dialog. Both ways make them read-only. When a trigger fires, its inputs are available as `$vars.<triggerName>.output.<inputName>`:

```javascript
// Access an input defined on a Manual Trigger named "manualTrigger1"
$vars.manualTrigger1.output.userId
```

This applies to all trigger types. If your workflow has multiple triggers, each trigger owns its own inputs, and downstream nodes reference the specific trigger that started the run.

### Output variables

Output variables represent the result of the workflow. They are added with **Add output variable** on the **Parameters** tab of an End node, or with the **+** next to **Outputs** in the **Variables** panel. They are write-only.

```javascript
// Access an output variable named "finalStatus"
$vars.finalStatus
```

Each output variable has:

- Name: how you reference it in expressions, for example `$vars.finalStatus`.
- Data type: String, Number, Boolean, Object, or Array.
- Description: an optional note on what the value represents.
- Default value: an optional fallback used when nothing sets the variable.

An output variable's value is set the same way as any other variable: from a node's **Update Variable** section, or as a Script node's return value.

## Variable definitions

Variable definitions live in the **Variables** panel. Each definition stores the variable name and type so the value can be referenced consistently during a run.

## Variable updates

Variables can be updated by node configuration or by Script node output.

### From any node

Every node has an **Update Variable** section on the **Advanced** tab of the properties panel, where **Add variable update** adds an assignment. The section stores a writable variable target, which is a workflow variable or an output variable, and the JavaScript expression assigned to it. The expression is evaluated after the node completes.

### From a Script node

A Script node's return value is accessible downstream as `$vars.<scriptName>.output`. The Script node also has the same Update Variable section as other nodes for direct variable writes:

```javascript
// The return value becomes $vars.script1.output
return {
  orderTotal: $vars.httpRequest1.output.body.price * $vars.httpRequest1.output.body.quantity
};
```

## Scoping rules

A node can access output from:

- Upstream nodes in the same scope: nodes at the same level that executed before it.
- Parent container nodes: if the node is inside a subflow or loop, it can access the parent's scope.

Scope means the part of a workflow where a name can be read. A node cannot access output from:

- Nodes in a different branch: if a Decision or Switch sent the run down a different path, those nodes' output is not available.
- Nodes that have not executed: output only exists after a node runs.

### Subflow scoping

Subflows create their own variable scope. Nodes inside a subflow can access:

- Other nodes within the same subflow
- The parent workflow's scope

Variables updated inside a subflow are namespaced, which means prefixed with the subflow name, to avoid collisions with the parent workflow. For example, a variable `counter` inside a subflow named `subflow1` is referenced as `$vars.subflow1.counter` from outside the subflow.

The subflow's return value is accessible to the parent workflow as `$vars.<subflowName>.output`.

### Parallel branches

Each parallel branch has its own variables. Mutating a variable inside one branch does not make that change visible in another branch. A Merge node consolidates outputs from parallel paths when the paths need to rejoin.

## Patterns

### Building dynamic strings

Template literals in a Script node combine variables and static text:

```javascript
return `Hello ${$vars.firstName}, your order #${$vars.orderId} has shipped.`;
```

### Accumulating values in a loop

An accumulator pattern uses an array initialized before the Loop node and appended to inside the loop body:

```javascript
// Script node inside the Loop body
results.push(item.processedValue);
return results;
```

### Keeping secret values out of logs

Secret variable values are masked in the UI but may appear in exported trace data. Logging them is a data exposure risk.

## Practical example

A workflow that fetches a user from an API and routes based on their role has three nodes:

1. HTTP Request (`httpRequest1`): sends a GET request to `https://api.example.com/users/42`.
2. Script (`script1`): extracts the user's role, with this code:

```javascript
const user = $vars.httpRequest1.output.body;
return {
  name: user.name,
  role: user.role,
  isAdmin: user.role === "admin"
};
```

3. Decision (`decision1`): branches on admin status, with this expression:

```javascript
$vars.script1.output.isAdmin === true
```

The **True** branch grants admin access, and the **False** branch grants standard access.

## Next steps
- [Expression syntax](expression-syntax.md): `$vars` grammar, operators, where expressions are written, and common errors.
- [Script node](node-script.md): writing JavaScript, return values, and `$vars` access.
- [Decision node](node-decision.md): branching on expressions.
- [The Flow canvas](flow-canvas.md): the properties panel and the Variables panel.
- [Community](community.md): ask questions and share workflows with other builders on the UiPath Forum.
