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"
  2. In your main workflow, add a Flow Call node
  3. Set flow_id to "process-user"
  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 calling itself (directly or indirectly).
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: