# Merge

The **Merge** node joins the outputs of several incoming branches. It is a fan-in node: the workflow runner waits for the available upstream branches, then produces one value according to the selected mode.

## When to use it

- reunite parallel branches before continuing the workflow;
- concatenate lists returned by several nodes;
- build one object from complementary branch results;
- wait for several branches while forwarding only one of their outputs.

Connect every branch directly to the Merge node. It reads each source node's parsed output; if no parsed value exists, it tries to decode the raw output as JSON.

## Configuration

| Field | Required | Description |
| --- | --- | --- |
| **Label** | No | Display name shown in the editor. It does not affect execution. |
| **Mode** | Yes | Determines the shape of the merged result. The default is **Collect inputs**. |
| **Source node ID** | Pass-through only | Technical ID of the source whose value must be forwarded. This is the node ID, not its label. |

## Modes

### Collect inputs

Preserves the origin of every value. The result is a list of `node_id` / `value` objects.

Inputs from `customer` and `score`:

```json
{"id": 42, "email": "ada@example.com"}
85
```

Result:

```json
[
  {"node_id": "customer", "value": {"id": 42, "email": "ada@example.com"}},
  {"node_id": "score", "value": 85}
]
```

Use this mode when provenance matters or when branches return different data shapes.

### Append arrays

Creates one list by concatenating incoming arrays **one level deep**. Scalars and objects are appended as individual items; `null` values are ignored.

| Incoming values | Result |
| --- | --- |
| `[1, 2]`, `3`, `[4, 5]` | `[1, 2, 3, 4, 5]` |
| `[{"id": 1}]`, `{"id": 2}`, `null` | `[{"id": 1}, {"id": 2}]` |

Nested arrays are not recursively flattened. For example, `[[1, 2]]` remains `[[1, 2]]`.

### Combine objects

Performs a **shallow** combination of incoming objects. When several objects contain the same key, the value from the later incoming branch wins. Nested objects are replaced, not recursively merged.

```jsonc
// branch profile
{"id": 42, "name": "Ada", "preferences": {"theme": "dark"}}

// later branch enrichment
{"name": "Ada Lovelace", "preferences": {"language": "en"}}

// result
{"id": 42, "name": "Ada Lovelace", "preferences": {"language": "en"}}
```

If an incoming value is not an object, it is kept under its source node ID. For example, an object from `profile` and the number `85` from `score` produce:

```json
{"id": 42, "name": "Ada", "score": 85}
```

Use **Set fields** or a transformation node first if you need explicit key names or a deep merge.

### Pass through source

Waits at the join point but forwards one incoming value unchanged. Enter the exact technical node ID in **Source node ID**.

If the field is empty or does not match an incoming source, the last available incoming value is forwarded. Set the ID explicitly whenever the selected branch matters.

## Ordering and branch synchronization

The node processes inputs in the order of its incoming connections as stored by the workflow. This order affects:

- the item order in **Collect inputs** and **Append arrays**;
- which value wins on duplicate keys in **Combine objects**;
- the fallback value in **Pass through source**.

Do not use connection order as business logic when collisions matter. Rename or normalize keys before the merge, or select a source explicitly.

The runner delays a fan-in node until its reachable upstream parents have executed. A conditional branch that produces no output is absent from the merge; the node combines the outputs that are available and does not create a placeholder for the missing branch.

## Runtime output

The merged value becomes the node's standard output:

- `{outputs.<merge_node_id>.parsed}` — structured merged value, recommended for downstream nodes;
- `{outputs.<merge_node_id>.raw}` — text representation of the result;
- `{last_output_parsed}` — same structured value immediately after the Merge node;
- `{last_output}` — JSON text for objects/lists, text for scalars, or an empty string for `null`.

The runtime also records merge metadata in `merge`: `mode`, `source_count`, and the ordered `sources` list.

Example downstream references:

```text
{outputs.merge-customers.parsed}
{outputs.merge-customers.parsed.0}
{outputs.merge-profile.parsed.email}
```

## Choosing a mode

| Need | Mode |
| --- | --- |
| Keep each branch's identity | **Collect inputs** |
| Produce one flat list | **Append arrays** |
| Produce one shallow object | **Combine objects** |
| Synchronize branches but retain one value | **Pass through source** |

## Common pitfalls

- **Using a label as Source node ID:** copy the node's technical ID instead; labels are not used for matching.
- **Unexpected overwritten fields:** Combine objects is shallow and later branches win. Make keys unique before merging.
- **Unexpected list nesting:** Append arrays flattens only the incoming top-level arrays.
- **Missing branch in the result:** only sources that produced an output are included. Check the branch condition and its execution trace.
- **Losing provenance:** Append and Combine do not retain source metadata. Use Collect inputs when the downstream step must know the origin.

## Example workflow

Use the workflow card below to create a safe example in the editor. It starts two branches, collects their outputs, and then continues to the End node.

---

*Source: https://agentbuilder.systalink.sn/docs/node-merge — human documentation.*
*Other language: [/docs-md/fr/node-merge.md](/docs-md/fr/node-merge.md).*
*Machine-readable index: [/llms.txt](/llms.txt).*
