Buni.aiDocs
NewAutomation

Loop

Repeats the nodes on its body handle once for each item in a list, with optional pacing, then continues with the collected results.

Loop runs part of an automation once per item in a list. The nodes connected to its each item handle run for the first item, then the second, and so on, one at a time. When every item is done, the flow continues from the done handle with all the results collected.

When to use it

  • Send a WhatsApp message to every contact in a list.
  • Create one record per row returned by an API or a Data Store query.
  • Call a rate-limited API for many items without tripping its limit, using pacing.
  • To run a few different steps at the same time rather than the same steps many times, use Parallel.
  • To drop repeated items before looping, put Remove Duplicates in front.

Automation projects only

Loop appears only in the palette of automation projects.

Loop settings with Items expression set to state.contacts, Even pacing at 20 per second, and Carry on, then report selected

Settings

Prop

Type

When you choose a pacing mode, the panel estimates how long the pacing alone takes at Max iterations: One run if it fits in one, or how many runs the list will be spread over (see Long lists).

If an item fails

OptionWhat happens
Stop the whole runThe remaining items are never attempted and the run is marked failed.
Skip the item and carry onThe failure is recorded in the results and the run finishes as a success.
Carry on, then reportEvery item is attempted. The run finishes, and a summary of which items failed is written to {{state.loopResultsSummary}} and shown in the run's activity. Best for sending to a list.

Outputs

HandleWhat runs
each itemOnce per item. Every node on this branch can read input.item (the current item), input.index (its position, from 0) and input.loop.
doneOnce, after the last item. Its input is the loop's input plus the results under the output variable's name.

Written to state:

  • {{state.loopResults}}: an array with one entry per item, the value the body's last node returned. A skipped item is recorded as { loopIterationError, index }.
  • {{state.loopResultsSummary}}, with Carry on, then report, or whenever the loop stops before the end of its list: { total, attempted, succeeded, failed, notAttempted, failures }, where each failure has index, label, message and the node that failed. A loop that stopped early also has stoppedEarly, with the reason, and a list spread over more than one run has runs. Results from earlier runs are kept up to about 1 MB; past that they are left out of {{state.loopResults}}, and resultsOmitted says how many.

The names follow Output variable: set it to sent and you get state.sent and state.sentSummary.

Long lists

A run carries on for about 3 minutes. A loop that is still going after that does not stop: it hands the rest of its list to a fresh run, which picks up at the next item about 15 seconds later. This repeats until the list is done. The done branch runs once, in the run that finishes the list, with every item's result.

  • Each of those runs counts as an automation run, with the minutes it lasts. See Billing and usage.
  • In the Activity tab, the run shows as Waiting between handovers, with the time it picks up again in Resumes At.
  • If the loop cannot hand over, it carries on in the same run and stops shortly before the run's 15-minute limit. The done branch still runs, and the run shows as partial with how many items were not attempted.
  • A run started by calling its URL directly may have a caller waiting for the answer. It keeps the list in one run while the rest can finish within the 15 minutes, and hands over only when it cannot.
  • Each handover is checked against your plan. If your automation runs or credits are used up, the loop stops there and the run shows how many items were done.
  • The list is worked out again in each run, from the same data. If it has changed in between, the loop stops instead of skipping or repeating items, and says so.

A loop that stops at Max iterations is also shown as partial, with the items it did not reach.

Example

A scheduled automation reminds everyone with a booking tomorrow:

  1. Schedule trigger runs daily at 17:00.
  2. Data Store, GET bookings for tomorrow, output variable bookings.
  3. Loop, Items expression state.bookings, Even pacing at 20 per second, Carry on, then report.
  4. On each item: Messaging sends a WhatsApp template to ${input.item.phone}.
  5. On done: Messaging sends the operations lead "Reminders sent: ${state.loopResultsSummary.succeeded}".

Tips and limits

  • A long list is spread over several runs (see Long lists). To keep a list in one run, raise the pacing rate or lower Max iterations.
  • Iterations run one after another, never at the same time.
  • Not allowed in the body: Wait, Approval, Collect Payment, Respond Webhook, Parallel, or another Loop. The body must not connect back to the loop or into the done branch. Publishing fails with an error naming the node if it does.
  • The Items expression is JavaScript, not a template: write state.contacts, not {{state.contacts}}.
  • input.item stays readable after a node in the body replaces the flowing data (an API response, for example), so later body nodes can still reach the current item.
Last reviewed 2 October 2026

On this page