Docs / Strand / advanced/nested-workflows

Nested Workflows

Call workflows from other workflows to create modular, reusable designs.

Flow Call Node#

The Flow Call node allows you to execute another workflow as a step in your current workflow.

Configuration#

Example#

  1. Create a workflow called "process-user" and copy its ID from the editor URL
  2. In your main workflow, add a Flow Call node
  3. Set flow_id to that ID (workflow names are not accepted)
  4. Optionally pass custom data:
json

{
  "user_id": "{{ payload.id }}",
  "context": {
    "source": "main_workflow"
  }
}
Direct Connection

If the Flow Call node is directly connected to the previous node, use payload instead of steps.node_id.output_payload.

Passing Data#

Default Behavior#

If you don't specify data, the current event's payload and metadata are automatically passed to the called workflow.

Custom Data#

You can pass a custom data object that supports templating:

Direct connection:

json

{
  "user_id": "{{ payload.id }}",
  "timestamp": "{{ meta.received_at }}",
  "nested_data": {{ payload | tojson }}
}

Non-direct access:

json

{
  "user_id": "{{ steps.user_lookup.output_payload.id }}",
  "timestamp": "{{ meta.received_at }}",
  "nested_data": {{ steps.process.output_payload | tojson }}
}

Accessing Output#

The output from a nested workflow is available through the Flow Call node:

jinja

{{ steps.flow_call_node.output_payload }}
{{ steps.flow_call_node.output_payload.result }}

Infinite Loop Prevention#

Strand automatically prevents infinite loops by tracking the call chain. If a workflow tries to call itself (directly or indirectly), an error is raised:

code

Infinite loop detected: workflow 'workflow-id' is already in the call chain.
Call chain: workflow-a -> workflow-b -> workflow-a

Best Practices#

1

Use descriptive workflow names

Makes it clear what each workflow does

2

Keep workflows focused

Each workflow should have a single responsibility

3

Document dependencies

Note which workflows call which others

4

Test incrementally

Test nested workflows individually before combining

Use Cases#

Modular Processing#

Break complex workflows into smaller, reusable pieces:

Conditional Execution#

Call different workflows based on conditions:

jinja

{% if payload.type == 'user' %}
  {{ 'process-user-workflow' }}
{% else %}
  {{ 'process-admin-workflow' }}
{% endif %}

Reusable Components#

Create reusable workflow components: