Docs / Strand / nodes/flow-call

Flow Call Node

The Flow Call node executes another workflow as a step in the current workflow.

Overview

Flow Call nodes enable modular workflow design by allowing workflows to call other workflows.

Use Cases
  • Reusable workflow components
  • Modular design
  • Breaking complex workflows into smaller pieces
  • Shared business logic

Configuration

Field Type Required Description
flow_id string Yes ID of the workflow to call
data object No Custom data to pass (supports templating)

Basic Usage

Simple Call

Configuration:

json

{
  "flow_id": "process-user"
}

This passes the current event to the called workflow.

Custom Data

Configuration:

json

{
  "flow_id": "process-user",
  "data": {
    "user_id": "{{ steps.user_lookup.output_payload.id }}",
    "action": "update"
  }
}

Passing Data

Default Behavior

If you don't specify data, the current event is automatically passed:

json

{
  "payload": { /* current payload */ },
  "meta": { /* current meta */ }
}

Custom Data Object

Pass a custom object with full templating support:

Direct connection:

json

{
  "user_id": "{{ payload.id }}",
  "context": {
    "source_workflow": "{{ meta.workflow_id }}",
    "timestamp": "{{ meta.received_at }}"
  },
  "processed_data": {{ payload | tojson }}
}

Non-direct access:

json

{
  "user_id": "{{ steps.user_lookup.output_payload.id }}",
  "context": {
    "source_workflow": "{{ meta.workflow_id }}",
    "timestamp": "{{ meta.received_at }}"
  },
  "processed_data": {{ steps.process.output_payload | tojson }}
}

Accessing Output

The nested workflow's output 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.

Loop Detection

If a workflow tries to call itself (directly or indirectly), an error is raised:

code

Infinite loop detected: workflow 'workflow-id' is calling itself
Call chain: workflow-a -> workflow-b -> workflow-a

Examples

User Processing Workflow

Main Workflow:

code

[Event] -> [Flow Call: process-user] -> [Send Notification]

Flow Call Configuration:

json

{
  "flow_id": "process-user",
  "data": {
    "user_id": "{{ payload.user_id }}",
    "action": "{{ payload.action }}"
  }
}

Conditional Workflow Call

Flow Call with Dynamic ID:

json

{
  "flow_id": "{{ 'process-admin' if payload.role == 'admin' else 'process-user' }}"
}

Best Practices

Tips
  1. Use descriptive workflow names
  2. Keep workflows focused (single responsibility)
  3. Document workflow dependencies
  4. Test nested workflows individually
  5. Use custom data for clear interfaces
  6. Avoid deep nesting (keep call chains short)