Invect

Loops

Iterate any node over an array of items.

Any node in a flow can be configured to run in a loop — executing once per item in an array and collecting the results. This is done through the node's Loop configuration panel in the editor, without adding a separate loop node.

How it works

When loop-over is enabled on a node:

  1. Invect resolves the loopOver expression against the upstream data to get an array
  2. The node executes once per item in that array
  3. Results are collected and packaged according to the outputMode
  4. The packaged output is passed to downstream nodes as a single value

The node behaves identically to a non-looping node from the perspective of downstream nodes — they just receive the collected output instead of a single execution's output.

Configuration

loopOver

A Nunjucks expression that resolves to the array to iterate. Evaluated against the node's incoming data.

{{ http_request.response.users }}
{{ fetch_issues.items }}
{{ manual_trigger.ids }}

itemAs and indexAs

Variable names that become available in the node's parameter templates during each iteration.

itemAs: "user"
indexAs: "i"

Inside the node's params you can then use:

{{ user.email }}
{{ user.name }}
{{ i }}            // 0-based index

The default item variable name is item if itemAs is not set.

Iteration context

Each iteration also exposes a _loop context object in templates:

VariableDescription
_loop.index0-based index
_loop.iteration1-based iteration number
_loop.firsttrue on the first iteration
_loop.lasttrue on the last iteration
_loop.totalTotal number of items
Processing {{ _loop.iteration }} of {{ _loop.total }}: {{ user.name }}

Output modes

Control how the results from all iterations are packaged:

ModeOutput
arrayArray of each iteration's output (default)
firstOnly the first iteration's output
lastOnly the last iteration's output
concatConcatenate string outputs into a single string
objectObject keyed by a field from each iteration's output

object mode

When using object output mode, set keyField to the field path that should become the key:

outputMode: "object"
keyField: "id"

If each iteration outputs { id: "abc", name: "Alice" }, the result is:

{
  "abc": { "id": "abc", "name": "Alice" },
  ...
}

Concurrency

By default, iterations run sequentially (concurrency: 1). Increase this to run multiple iterations in parallel:

concurrency: 5   // run up to 5 iterations simultaneously

Maximum concurrency is 50. Use parallel execution carefully with external APIs that have rate limits.

Empty array behaviour

Control what happens when loopOver resolves to an empty array or a non-array value:

SettingBehaviour
errorFail the node with an error (default)
skipSkip execution, output empty array
singleTreat a non-array value as a single-item array

Example

Send a Slack message for each item in a list returned by an upstream HTTP request:

  1. Add an http.request node that returns { users: [{ name: "Alice", channel: "C123" }, ...] }
  2. Add a slack.send_message node
  3. Enable loop on the Slack node with:
    • loopOver: {{ http_request.response.users }}
    • itemAs: user
    • outputMode: array
  4. In the Slack node's params, set message to {{ user.name }} has been notified and channel to {{ user.channel }}

The Slack node will execute once per user, and downstream nodes will receive an array of all send results.