Control Flow Nodes

Nodes for managing workflow execution paths — branching, looping, merging, and more

Control Flow Nodes

Control flow nodes are the directors of your workflow. They make decisions, loop through data, pause execution, and combine multiple execution paths. Let's look at each one.


Start Node

When to use: Every workflow needs a Start Node. It's your entry point and defines how the workflow gets triggered.

The Start Node is where your workflow begins. It can be triggered manually by a user, on a schedule, or by an incoming webhook. You can also define what input data your workflow expects.

Configuration

Configuration:
  trigger_type: manual | scheduled | webhook
  input_schema: JSON Schema for validation

Example: Order Processing Workflow

Start Node Configuration:
  trigger_type: webhook
  input_schema:
    type: object
    required:
      - order_id
      - customer_email
      - items
    properties:
      order_id:
        type: string
      customer_email:
        type: string
      items:
        type: array

When someone places an order, the webhook sends this data through to the next nodes, which might check inventory, charge the card, and send a confirmation email.

Note: The Start Node doesn't do any processing—it just captures incoming data and validates it against your schema. If validation fails, the workflow won't run.

Common Patterns

  • Manual trigger: User clicks a button in your UI
  • Scheduled trigger: Workflow runs every morning at 9 AM
  • Webhook trigger: External service (Stripe, GitHub, Shopify) sends data

If Node

When to use: Any time you need to split your workflow into two paths based on a condition.

The If Node checks a condition and routes execution down one of two paths: true or false. Use it for simple yes/no decisions.

Configuration

Configuration:
  condition: "{{ input.value }} > 100"
  # Or structured mode:
  field: "status"
  operator: equals | not_equals | greater | less | contains | matches
  value: "active"

Example 1: Approval Threshold

If Node Configuration:
  condition: "{{ input.amount }} > 1000"

Flow:

  • If amount > $1000 → true path (send for manager approval)
  • If amount ≤ $1000 → false path (auto-approve)

Example 2: Order Status Check

If Node Configuration:
  field: "order_status"
  operator: equals
  value: "paid"

Flow:

  • If status is "paid" → true path (proceed to shipping)
  • If status is not "paid" → false path (send payment reminder email)

When to Use If vs. Switch

Use If Node for simple binary decisions. Use Switch Node (below) if you have 3+ paths.

Tip: You can nest If nodes for complex logic, but it gets messy fast. Consider using Switch or Code nodes for complex conditions.


Switch Node

When to use: When you have 3 or more different paths based on the same value.

The Switch Node routes execution based on matching values, patterns, or ranges. It's cleaner than chaining If nodes when you have multiple cases.

Configuration

Configuration:
  mode: value | pattern | range | type | expression
  field: "status"
  cases:
    - value: "pending"
      port: "pending"
    - value: "approved"
      port: "approved"
    - value: "rejected"
      port: "rejected"
  default: "other"

Example 1: Order Status Router

Switch Node Configuration:
  mode: value
  field: "order_status"
  cases:
    - value: "pending"
      port: "pending"
    - value: "processing"
      port: "processing"
    - value: "shipped"
      port: "shipped"
    - value: "delivered"
      port: "delivered"
  default: "unknown"

Flow:

  • pending → send confirmation email
  • processing → update inventory
  • shipped → notify customer with tracking
  • delivered → send satisfaction survey
  • anything else → log error

Example 2: Priority-Based Routing

Switch Node Configuration:
  mode: value
  field: "priority"
  cases:
    - value: "critical"
      port: "critical"
    - value: "high"
      port: "high"
    - value: "normal"
      port: "normal"
  default: "low"

Note: Each case creates a separate output port. You can connect different nodes to each port.


Loop Node

When to use: When you need to repeat an action for each item in an array or over a range of numbers.

The Loop Node iterates over arrays, ranges, or objects. For each iteration, it outputs loop with the current item. When done, it outputs done.

Configuration

Configuration:
  mode: array | range | object | batch | page
  field_to_loop_on: "items"
  batch_size: 10  # For batch mode

Example 1: Process Orders (Array)

Incoming data:

{
  "orders": [
    { "id": "ORD-001", "amount": 50 },
    { "id": "ORD-002", "amount": 120 },
    { "id": "ORD-003", "amount": 75 }
  ]
}

Loop Node Configuration:

mode: array
field_to_loop_on: "orders"

Outputs:

  1. loop output: { "id": "ORD-001", "amount": 50 }
  2. loop output: { "id": "ORD-002", "amount": 120 }
  3. loop output: { "id": "ORD-003", "amount": 75 }
  4. done output: (once all items processed)

Connect your processing nodes to the loop port. Each will execute once for each order.

Example 2: Batch Processing (Batch Mode)

Loop Node Configuration:
  mode: batch
  field_to_loop_on: "email_addresses"
  batch_size: 100

Perfect for sending emails to 10,000 users—processes them 100 at a time.

Example 3: Range Loop (Generate Numbers)

Loop Node Configuration:
  mode: range
  from: 1
  to: 12  # Loop 12 times

Useful for generating 12 months of reports, paginating through results, etc.

Warning: Be careful with large arrays—a 1 million item loop will create 1 million executions. Consider using batch mode for large datasets.

Common Patterns

  • Email list: Loop through recipients and send personalized emails
  • Data import: Loop through CSV rows and insert into database
  • API pagination: Loop through page numbers and fetch all results

Merge Node

When to use: When multiple execution branches need to come back together before continuing.

The Merge Node waits for input from multiple paths, then combines them and passes the result forward. This is essential for parallel workflows.

Configuration

Configuration:
  strategy: wait_all | first | append | merge_objects
  timeout: 30000  # milliseconds

Example: Parallel Data Collection

Workflow:

  1. Start → split into 3 paths:
    • Path A: Fetch user data from database
    • Path B: Fetch user analytics from API
    • Path C: Fetch preferences from cache
  2. All 3 paths → Merge Node (wait_all strategy)
  3. Merge → Log the combined result

Merge Configuration:

strategy: wait_all
timeout: 30000

The Merge waits for all 3 paths to finish (up to 30 seconds), then outputs:

{
  "user_data": { ... },
  "analytics": { ... },
  "preferences": { ... }
}

Merge Strategies

Strategy Behavior Use When
wait_all Waits for all inputs, combines them You need all results before proceeding
first Uses the first input to arrive You only care about the fastest result
append Combines arrays into one Merging array results
merge_objects Deep merges objects Combining multiple data objects

Tip: Always set a timeout. If one branch hangs, the workflow won't wait forever.


Delay Node

When to use: When you need to pause execution for a certain amount of time.

The Delay Node pauses execution, then passes the input through to the output unchanged. Useful for rate limiting, spreading out notifications, or waiting for external systems.

Configuration

Configuration:
  delay_ms: 5000  # Delay in milliseconds
  # Or dynamic:
  delay_expression: "{{ input.wait_time }}"

Example 1: Fixed Delay (Rate Limiting)

Delay Node Configuration:
  delay_ms: 1000  # 1 second between API calls

Workflow:

  1. Start with list of API endpoints
  2. Loop through each endpoint
  3. Delay 1 second (rate limiting)
  4. HTTP Request to that endpoint

This prevents overwhelming the API with requests.

Example 2: Dynamic Delay (Retry with Backoff)

Delay Node Configuration:
  delay_expression: "{{ input.retry_delay }}"

Incoming data:

{
  "retry_count": 2,
  "retry_delay": 4000  // 4 seconds
}

The workflow pauses for 4 seconds before retrying.

Common Patterns

  • Rate limiting: Delay between API calls
  • Exponential backoff: Retry failed requests with increasing delays
  • Staggered notifications: Send emails over time instead of all at once

Note: The Delay Node doesn't block other workflows—only this execution is paused.


Chain Node

When to use: When you want to execute another workflow from within your current workflow, or link workflows together.

The Chain Node lets you reuse workflows. You can call another workflow, wait for it to complete, and use its output as input for the next step.

Configuration

Configuration:
  workflow_id: "wf_abc123"
  operation: execute | create | update
  wait_for_completion: true

Example: Multi-Step Order Processing

Main Workflow:

Start (order data)
  ↓
Log: "Processing order"
  ↓
Chain Node: Call "Validate Order" workflow
  ↓
Chain Node: Call "Process Payment" workflow
  ↓
Chain Node: Call "Send Confirmation Email" workflow
  ↓
End

Each Chain node waits for the called workflow to complete before moving to the next step.

Configuration:

Chain Node 1:
  workflow_id: "wf_validate_order"
  operation: execute
  wait_for_completion: true

Chain Node 2:
  workflow_id: "wf_process_payment"
  operation: execute
  wait_for_completion: true

Tip: Break complex workflows into smaller, reusable pieces and chain them together. Makes debugging and testing easier!

Common Patterns

  • Sub-workflows: Complex logic in separate workflows
  • Reusable processes: "Send Email" workflow used by multiple workflows
  • Parallel workflows: Multiple workflows executing simultaneously

Terminal Node

When to use: When you need to execute shell commands (in a sandboxed environment).

The Terminal Node runs shell commands in a secure sandbox. It's useful for running scripts, system commands, or tools not available through other nodes.

Configuration

Configuration:
  command: "echo 'Hello World'"
  timeout: 30000  # milliseconds
  working_directory: "/tmp"

Example 1: Convert Image Format

Terminal Node Configuration:
  command: "convert input.jpg output.png"
  working_directory: "/tmp/images"
  timeout: 10000

Example 2: Generate Report

Terminal Node Configuration:
  command: "python /scripts/generate_report.py --date {{ input.date }} --output report.pdf"
  timeout: 30000

Example 3: Compress File

Terminal Node Configuration:
  command: "gzip -9 file.txt"
  working_directory: "/data"
  timeout: 5000

Warning: Terminal Node commands run in a sandbox. You can't access system files outside the working directory. Use File Operations Node for file system access in your workflows.


Common Control Flow Patterns

Pattern 1: Decision Tree

Start
  ↓
Check: Is order > $1000?
  ├─ YES → Send for approval
  │        ↓
  │        Approval Node
  │        ├─ Approved → Charge card
  │        └─ Rejected → Send cancellation email
  │
  └─ NO → Charge card directly
           ↓
           Send confirmation email
           ↓
           End

Pattern 2: Batch Processing

Start (with array of items)
  ↓
Loop (for each item)
  ├─ Process item
  ├─ Store result
  └─ Move to next item (when loop → done)
     ↓
     Log summaryEnd

Pattern 3: Parallel Execution with Merge

Start
  ├─ Path A: Fetch data from DB
  ├─ Path B: Fetch data from API
  └─ Path C: Fetch from cache
     ↓ (all paths merge here)
     Merge Node
     ↓
     Combine results
     ↓
     End

Workflow Execution Example

Let's trace through a complete order workflow:

1. Start Node
   Receives: { order_id: "ORD-123", customer: "Alice", amount: 250, items: [...] }

2. If Node
   Condition: amount > 100
   Result: TRUE (250 > 100)
   Routes to: approval path

3. Approval Node (in true path)
   Waits for manager approval
   Result: Approved

4. HTTP Request (in approval path)
   Calls payment processor

5. Log Node
   Logs: "Order ORD-123 approved and charged"

6. Loop Node (for each item)
   Iterates through items array
   For each iteration  Update inventory

7. Merge Node (collects loop results)
   Waits for all Loop iterations to complete

8. Email Node
   Sends confirmation email to Alice

9. End
   Workflow complete

Next Steps