# Subflows

> Run one workflow from inside another with the Subflow step: the caller waits, and the result comes back as ordinary step output.

The **Subflow** step runs another workflow from inside this one and waits for its answer. The calling run pauses, the called workflow runs start to finish, and its result comes back as this step's output like any other step's.

Reach for it when the same job appears in several workflows. Build "notify the on-call channel" or "create the ticket" once, then call it from everywhere it is needed.

**Any workflow in your workspace can be called.** There is nothing to publish or switch on first: you pick the workflow from a list, and it becomes a subflow because you called it.

```mermaid
flowchart LR
    A[Calling Workflow] --> B[Subflow Step]
    B -->|Runs & Waits| C[Child Workflow]
    C -->|Returns Data| B
    B --> D[Next Step]
```

## Why split a workflow

- **Reuse.** One copy of a routine, called from every workflow that needs it. Fix it once and every caller gets the fix.
- **Readability.** Five workflows of ten steps are easier to follow than one of fifty.
- **Isolation.** Sensitive work stays in its own workflow with its own connections.

## Setting it up

### Add the Subflow step

Open **Subflows** in the dock. It lists every workflow in your workspace, ready to drop onto the canvas.

### Pick the workflow to call

Click the one you want. No preparation is needed on the workflow you are calling: every workflow in the workspace can be called as a subflow.

A workflow that cannot be called is greyed out with the reason: it has no steps yet, or calling it would make a loop.

### Check what it does

The App drawer shows a small map of the workflow you picked, so you can see what it does without leaving the canvas.

### Pass the data it needs

Give the subflow the values it should work with, referencing the calling workflow's steps by number:

```
{{ 1.email }}
{{ 3.customer_id }}
```

Build these from the data picker rather than typing them. What sits after the step number is a path into whatever that step produced, so it changes with the step you read from.

### Use the result

The called workflow's output is available on this step like any other, referenced by this step's own number.

## The caller waits, and that is the point

This is the difference from calling a workflow over its webhook. A webhook call is posted and forgotten: the caller carries on immediately and never sees the outcome.

A Subflow step **suspends the calling run** until the called workflow finishes, then resumes it with the answer. A step after it can use the result, branch on it, or pass it further along.

## What it passes on

Two things:

```
{{ 5.output }}          what the child workflow declared as its output
{{ 5.steps.3.ret.id }}  any step inside the child run, by its number there
```

`output` is the child's declared result: the value its own output step returned. `steps` exposes the whole child run, so a field the child never declared can still be reached by naming the child step that produced it.

## Limits

- **Three levels deep.** A workflow can call a workflow that calls a workflow. Beyond that the step reports a configuration error rather than running.
- **A workflow cannot call itself**, and it cannot call anything that would loop back to it. Glow checks the whole chain before running and refuses a cycle, so a run cannot recurse forever.
- **The data passed in is capped at 64 KB.** Pass an identifier and let the subflow fetch what it needs, rather than passing a large record.
- **Same workspace only.** The list offers workflows on your own team.

> **A run's subflow steps appear in the parent's Execution log**, indented under
> the step that called them. One log tells the whole story, so you do not have
> to open the called workflow separately to see what it did.

## Calling over a webhook instead

Sending an [HTTP Request](/build/action-steps/http-request) to another workflow's [Webhook](/build/triggers/webhook) trigger still works, and it suits a genuinely independent job: something that should start and run on its own while the caller finishes.

Two differences decide which to use:

|                                 | Subflow step        | HTTP Request to a webhook |
| ------------------------------- | ------------------- | ------------------------- |
| Does the caller wait?           | Yes                 | No                        |
| Does the caller get the result? | Yes                 | No                        |
| Where does it show in the log?  | In the caller's log | In its own run            |

If a later step needs the answer, use Subflow.

## What's Next?

- Read what a run records in [Executions](/build/core-concepts/executions).
- Send data to an outside service with [HTTP Request](/build/action-steps/http-request).
