Skip to content

Sub-flows

A flow that tests a real user journey — sign up, verify email, log in, create a project, invite a teammate, tear it all down — quickly grows past what fits comfortably on one canvas. And most of those journeys share steps: nearly everything you test needs a login first. Copy-pasting the login nodes into every flow means fixing them in five places when the auth endpoint changes.

Sub-flow nodes solve both problems: build the login sequence once as its own flow, then call it from every other flow that needs it.

A Sub-flow node runs another saved flow as a nested step, the same way a function call runs a function:

  • Ports: one in-port, one out-port. If any node inside the called flow fails, the Sub-flow node fails and everything downstream of it is skipped — exactly like a request node failing.
  • Isolation: the child flow does not see the parent's node outputs. Nothing leaks in by accident. Anything the child needs has to be passed explicitly.

In the Sub-flow node's inspector, add input mappings: a name, and a value expression resolved in the parent's scope (so it can reference {{login.outputs.token}} or anything else the parent already has). Each mapping becomes a plain variable inside the child flow, as if it had been set in the child's own environment.

If a mapping's value expression doesn't resolve, the Sub-flow node fails immediately — the child never runs with a hole in its inputs.

The inspector offers one-tap suggested inputs, populated from the child flow's own required-inputs list (the same manifest sharing uses), so you don't have to go open the child flow to see what it needs.

A Checkout Journey flow: Start → a run_auth sub-flow node (targeting the 'auth' flow, 1 input) → an after_checkout request. The selected sub-flow node's inspector shows its target flow, a baseUrl input mapping, and a suggested 'token' input

The child's terminal node results land on the Sub-flow node's own result (expand it in the run report to see each child node's status individually). Any extraction the child published comes back as:

{{subflowNode.outputs.childNodeName.extractionName}}

So if your reusable "Login" child flow has a request node named login with a token extraction, and you call it from a Sub-flow node named auth, downstream in the parent you'd reference {{auth.outputs.login.token}}.

A flow can't call itself, directly or through a chain of other flows — Probe checks the whole call graph at save time and rejects a cyclic save. The flow picker in the Sub-flow node's inspector goes a step further: it hides any flow that would create a cycle (itself, and anything that (transitively) calls back to the flow you're editing), so you can't even select an invalid target. Diamond-shaped call graphs — two different Sub-flow nodes both calling the same shared child — are fine; only cycles are blocked.

Nesting is capped at 8 levels deep as an additional runaway guard.

Sub-flow nodes are legal inside a Loop body — a common combination is "for every item, run this reusable per-item sub-flow."

  1. Build a small flow, "Auth: Login", with just a Start node and one request node named login that posts credentials and extracts token from the response body.
  2. In any other flow, drag in a Sub-flow node, pick "Auth: Login" as the target, and (if your login endpoint needs credentials passed in rather than hard-coded) add an input mapping like username{{globalTestUser}}.
  3. Anywhere downstream, reference {{authNode.outputs.login.token}} exactly like you would from an inline login request node.

Now every flow that needs a token calls the same one place — fix the login sequence once, and every flow that depends on it picks up the fix.