Skip to content
GuideAPIANT.aiv2

Fan-out and fan-in

View .md

How an APIANT automation launches child automations in parallel with a latch group and waits for all of them to finish, including latch scopes, timeouts and restrictions.

A parent automation can launch several child automations to run at the same time, then wait until every one of them has finished before continuing. The children share a named latch group: each launch adds one to the group's count, each finished child subtracts one, and the parent's wait step continues when the count reaches zero.

Ask for it in plain English: "start the contact, order and inventory syncs at the same time, and when all three are done, send me a Slack message".

How it is built

A fan-out and fan-in uses two kinds of step in the parent:

  1. Launch steps. One call automation step per child, each with launch_async: true and the same latch_group. Each launch returns immediately.
  2. One wait step. A wait_for_latch step with that latch_group. Steps after it run only once every child has finished.
json
{
  "name": "Nightly sync hub",
  "steps": [
    {
      "step_id": "launch_contacts",
      "type": "call_automation",
      "automation_uuid": "<contact sync id>",
      "launch_async": true,
      "latch_group": "nightly_sync",
      "inputs": { "batch_id": "{{ trigger.fired_at }}" }
    },
    {
      "step_id": "launch_orders",
      "type": "call_automation",
      "automation_uuid": "<order sync id>",
      "launch_async": true,
      "latch_group": "nightly_sync",
      "inputs": { "batch_id": "{{ trigger.fired_at }}" }
    },
    {
      "step_id": "wait_for_syncs",
      "type": "wait_for_latch",
      "name": "Wait for both syncs",
      "latch_group": "nightly_sync"
    },
    {
      "step_id": "notify_done",
      "type": "assembly",
      "assembly_uuid": "<send message action id>",
      "connection_uuid": "<chat app connection id>",
      "settings": { "Message": "Nightly sync finished for batch {{ trigger.fired_at }}" }
    }
  ]
}

The same wait is available as the Flow Control action Wait for latched automations, and the Automations app's Execute automation by mapped name actions can launch children into a latch group by name. See Subroutines and calling automations.

What the parent gets back

  • A launch step returns launched: true and the latch_group it joined. It does not return the child's result.
  • The wait step declares latch_group, latch_released and skipped. When it continues without waiting, latch_released is true and skipped is false. skipped is true only when the step has no group name. After a real wait, latch_released holds a value and the other two are empty; after a timeout, the output has timed_out: true.

The parent receives no output from the children. If the parent needs their results, have each child write them somewhere the parent can read after the wait, such as a lookup table or a Collector bucket. See Storing data between runs.

How the wait behaves

  • The parent's run is parked while it waits. It does not poll, and it holds no worker.
  • A child counts as finished when its run ends, whether it succeeded, failed or was halted. A child that is itself paused, for example snoozed or waiting on a form, keeps the parent waiting.
  • If every child already finished before the parent reaches the wait step, the parent continues without parking.
  • If the parent automation is turned off while it waits, it is not woken until it is turned back on.

Latch scopes

The scope decides which launches share one count. On call automation launch steps and the wait step, set the same scope:

ScopeThe count covers
This execution (default)Only the children this run launched. Two runs of the same automation at the same time each wait for their own children.
My accountEvery launch into that group name in your account, including launches from other runs
Linked accountsEvery launch into that group name across the linked parent account and its children. With no linked parent, it behaves like My account. Linked accounts are an Enterprise feature; see Linked and associated accounts.

A launch and a wait with different scopes count different things, so the wait can continue early with no error. Keep the default unless runs deliberately need to share one count.

The Execute automation by mapped name actions do not take these three scopes. Their count belongs to the launching run, like This execution, unless their shared latch group option is on, which keys the count to the linked parent account, like Linked accounts. Match the wait step's scope to that choice.

A child called synchronously, whether a subroutine or an ordinary automation, shares the caller's latch count. So a synchronous child can launch grandchildren and the caller can wait for them with the default scope. An asynchronous child has its own count: for the parent to wait on children that an asynchronous child launched, both sides need My account.

Timeouts

The wait_for_latch step takes an optional timeout_seconds. Leaving it out, or setting 0, waits indefinitely. When a timeout passes, the wait step does not fail: the run continues and the step's output shows it timed out.

The Flow Control action Wait for latched automations has settings for the group and scope only, so it always waits indefinitely.

Reusing a group name in a loop

The same group name can be reused safely inside a for-each loop:

  • Launch and wait inside the loop. Each pass waits for the children launched in that pass only.
  • Launch inside the loop, wait once after it. Every child from every pass joins one count, and the single wait covers all of them.

Restrictions

  • A wait step cannot run inside a parallel branch, or inside an ordinary automation called synchronously. It can run inside a subroutine, a condition or a loop.
  • A launch step with launch_async but no latch group is refused.
  • Match the group name exactly on every step. Letters, digits, hyphens, underscores and spaces are a safe choice.

Troubleshooting

SymptomLikely causeWhat to do
The parent continues before the children finishThe launch and wait steps use different group names or scopes, or a launch was synchronousAsk Claude to check that every launch has launch_async, the same group, and the same scope as the wait
The parent never continuesA child is still running or is paused, and the wait has no timeoutCheck the children's runs in Execution History, or add a timeout
The wait step fails immediatelyIt is inside a parallel branch or a synchronously called automationMove the wait to the top level or into a subroutine

Next steps

Related docs

Last updated September 15, 2026