Skip to content
GuideAPIANT.aiv2

Subroutines and calling automations

View .md

How APIANT automations call subroutines and other automations, the difference between synchronous and asynchronous calls, passing inputs, reading results, calling by name, and nesting limits.

A subroutine is an automation with no trigger that other automations call, pass inputs to, and read results from. Use one for logic several automations share, such as "find or create a contact". An automation can also call an ordinary automation, or launch it in the background.

Two ways to call another automation

MethodTargetsUse it for
Call automation stepOne automation or subroutine by its ID, in the same accountReusable logic, sequential pipelines, background launches
Execute automation by mapped name (Automations app)An automation by name, in this account or linked accountsLaunching by name, reaching linked accounts, or passing a query string or webhook body

Prefer the call automation step when the target is fixed. A name is looked up when the run reaches the step, so renaming the target breaks a call by name.

Building a subroutine

Ask for one directly: "build a subroutine that takes a customer email, finds the contact in HubSpot, and creates it if it does not exist". A subroutine:

  • Has no trigger and never runs on its own. It is created off and runs only when called.
  • Reads the values the caller passes as trigger.input.<name>, for example {{ trigger.input.customer_email }}.
  • Returns the output of all of its steps, keyed by step ID.

A subroutine can declare its inputs and outputs, each with a name, datatype, help text and, for inputs, whether it is required. A call that leaves a required input missing or empty fails with an error naming the input. Declared outputs describe the result; the caller receives every step's output either way.

Calling a subroutine

A call automation step names the target and passes inputs:

json
{
  "step_id": "find_or_create_contact",
  "type": "call_automation",
  "automation_uuid": "<subroutine id>",
  "inputs": {
    "customer_email": "{{ trigger.body.email }}",
    "source": "webshop"
  }
}

Input values can be expressions, fixed text, numbers, or nested objects and lists. Input names are case-sensitive and must match what the subroutine reads.

Reading the result

A later step in the caller reads the subroutine's step outputs under outputs:

text
{{ steps.find_or_create_contact.output.outputs.lookup_contact.id }}

Here lookup_contact is a step ID inside the subroutine. When that inner step is a script, its value is one level deeper, under result:

text
{{ steps.find_or_create_contact.output.outputs.build_name.result }}

Synchronous and asynchronous calls

A call automation step waits for the target by default. Setting launch_async launches it in the background instead:

Synchronous (default)Asynchronous (launch_async: true)
CallerWaits until the target finishesContinues immediately
Resultoutputs holds the target's step outputsoutputs is empty
Target's errorsFail the call step, so the caller's error handling appliesNot reported to the caller
RequiresThe target's IDThe target's ID and a latch group name

Every call step reports the same fields: automation_uuid, executed_automation_uuid, launched, latch_group and outputs. Check launched to tell the two modes apart: it is false for a synchronous call and true for a background launch.

To launch several automations in the background and then wait for all of them, see Fan-out and fan-in.

Subroutine or ordinary automation as the target

What a synchronous call does depends on how the target was built:

TargetRunsCan pauseTasks count against
SubroutineInside the caller's runYesThe caller's run
Ordinary automationAs its own child runNo. Snooze, form waits and latch waits fail inside it.The target automation

If the called logic needs to wait, build it as a subroutine, or launch it asynchronously.

Calling by name

The Automations app's Execute automation by mapped name actions find the target by name when the step runs. The match ignores case but must otherwise be exact, and a name that matches no automation or more than one fails the step. The target's on/off state is not checked.

InputPurpose
nameThe target automation's name
query_stringParameters such as order=10482&rush=true. The target reads them as {{ trigger.params.order }}, or the whole string as {{ trigger.query_string }}.
webhook_payloadA JSON or XML body delivered to the target as its trigger body
waittrue to wait for the target and receive its result

The target account's monthly task allowance is checked before the launch.

Calling automations in linked accounts

Plan: Enterprise

Three variants reach beyond the running account:

ActionRuns the named automation in
Execute automation by mapped name (includes linked parent)This account or its linked parent
Execute automation by mapped name in all linked accountsThe parent and every linked child account, always in the background
Execute automation by mapped name in specified accountOne linked account you identify

The all-linked-accounts variant launches in every account that has an automation with that name and reports the accounts it could not resolve or launch. The step fails only when no account could be launched at all. See Linked and associated accounts.

Limits

  • Calls can nest 16 levels deep. A deeper call fails.
  • A call automation step or error handler cannot create a loop back to the same automation, directly or through other automations. Saving such a change is refused. A loop made through Execute automation by mapped name is not caught when saving and stops at the 16-level limit when it runs.

Finding and reusing subroutines

While you view an automation diagram, the navigation bar shows Subroutines. It opens a read-only catalog with a Mine tab for your own subroutines, a Community tab for public ones, and a search box.

The Subroutines page lists subroutines in folders, with Mine and Community tabs above the list.

Before building a new subroutine, ask Claude whether a matching one exists; building never warns about an existing subroutine with the same name.

To see which automations use a subroutine, open its gear menu and choose Manage > Referenced by…. The list includes automations that call it and automations that use it as an error handler.

From Claude Code, Claude can test a subroutine on its own with sample inputs. The assistant tests a subroutine by running an automation that calls it. See Testing an automation.

Next steps

Related docs

Last updated September 15, 2026