Skip to content

Gateway Nodes and Branching

This document describes the gateway node system in FlowDrop, including the reserved branches input parameter, the active_branches output, and how branch port names are dynamically generated.

Overview

Gateway nodes are special workflow nodes that control execution flow by routing execution to one or more conditional branches. They are analogous to BPMN gateways (exclusive, inclusive, or parallel).

Key Characteristics

Aspect Description
Visual Type gateway - renders as a diamond shape
Input Parameter branches - defines available output branches
Output active_branches - specifies which branch(es) to execute
Port Generation Branch names become dynamic output ports

Reserved Names

branches (Input Parameter)

The branches parameter is a reserved configuration key that defines the available conditional output paths for a gateway node.

Type: array of branch objects

Structure:

{
  "branches": [
    {
      "name": "True",
      "value": true
    },
    {
      "name": "False", 
      "value": false
    }
  ]
}

Fields:

Field Type Description
name string Display name for the branch (becomes the output port name)
value mixed The value to match against when determining which branch is active

Example configurations:

# Boolean Gateway (True/False)
branches:
  - name: 'True'
    value: true
  - name: 'False'
    value: false

# A/B Testing
branches:
  - name: 'A'
    value: 'a'
  - name: 'B'
    value: 'b'

# Switch Gateway (multiple options)
branches:
  - name: 'High'
    value: 'high'
  - name: 'Medium'
    value: 'medium'
  - name: 'Low'
    value: 'low'
  - name: 'Default'
    value: 'default'

active_branches (Output)

The active_branches output is a magic output name that gateway node processors must return to indicate which branch(es) should be activated.

Type: string (single branch) or comma-separated string (multiple branches)

Example return values:

// Single branch activation
return [
  "active_branches" => "true",   // Activates "True" branch
  // ... other outputs
];

// For A/B gateway
return [
  "active_branches" => "a",      // Activates "A" branch
  // ... other outputs
];

// Multiple branch activation (parallel gateway)
return [
  "active_branches" => "branch1,branch2",  // Activates both branches
  // ... other outputs
];

Matching Logic:

The orchestrator performs case-insensitive matching between active_branches and the branch name values:

// From JobGenerationService.php
$active_branch_list = explode(',', strtolower($active_branches));
$active_branch_list = array_map('trim', $active_branch_list);

if (in_array(strtolower($branch_name), $active_branch_list, TRUE)) {
  // Branch is activated
}

Dynamic Port Generation

When a node has visual_type: gateway, the frontend automatically generates output ports based on the branches configuration:

Port Naming Convention

Branch names become output port names:

Branch Name Output Port Handle Format
True {nodeId}-output-True
False {nodeId}-output-False
A {nodeId}-output-A
Default {nodeId}-output-Default

Edge Resolution

When an edge connects from a gateway's branch output, the branchName is extracted from the source handle and stored in WorkflowEdgeDTO:

// Edge: if_else.1-output-True → process_a.1-input-trigger
// branchName = "True"

This branch name is then used during execution to determine if the edge should be activated.

Creating a Gateway Node Processor

1. Define the Parameter Schema

Include the branches parameter with appropriate defaults:

public function getParameterSchema(): array {
  return [
    "type" => "object",
    "properties" => [
      // Your input parameters...
      "condition" => [
        "type" => "mixed",
        "title" => "Condition",
        "description" => "The condition to evaluate",
      ],
      // The branches parameter (reserved)
      "branches" => [
        "type" => "array",
        "description" => "The available branches",
        "readOnly" => TRUE,  // Value cannot be edited, but can be exposed
        "default" => [
          [
            "name" => "True",
            "value" => TRUE,
          ],
          [
            "name" => "False",
            "value" => FALSE,
          ],
        ],
        "items" => [
          "type" => "object",
          "properties" => [
            "name" => [
              "type" => "string",
              "description" => "The name of the branch",
            ],
            "value" => [
              "type" => "mixed",
              "description" => "The value of the branch",
            ],
          ],
        ],
      ],
    ],
  ];
}

2. Return active_branches in Process

public function process(ParameterBagInterface $params): array {
  $condition = $params->get("condition");

  // Evaluate your condition
  $result = $this->evaluateCondition($condition);

  // Determine which branch to activate
  $activeBranch = $result ? "true" : "false";

  // MUST return active_branches
  return [
    "active_branches" => $activeBranch,
    "execution_metadata" => [
      "timestamp" => time(),
      "gateway_type" => "branch",
      "flow_control" => TRUE,
    ],
  ];
}

3. Configure Node Type

id: my_gateway
label: 'My Gateway'
description: 'Custom gateway node'
category: logic
icon: 'mdi:source-branch'
plugin_version: 1.0.0
enabled: true
parameters:
  condition:
    configurable: false
    connectable: true
    required: true
  branches:
    configurable: true    # Allow users to modify branches
    connectable: false    # Branches are not runtime-connectable
    required: false
    default:
      - name: 'True'
        value: true
      - name: 'False'
        value: false
outputs: {}
tags: {}
executor_plugin: my_gateway
visual_type: gateway           # Renders as diamond with dynamic ports
supported_visual_types:
  - gateway

Built-in Gateway Nodes

Boolean Gateway

Simple true/false branching based on a boolean input.

Parameter Type Description
value boolean The value to evaluate
branches array Default: True/False

Branches: True, False

If/Else

Conditional branching based on text comparison.

Parameter Type Description
data mixed Input data to evaluate
matchText string Text to match against
operator string Comparison operator
caseSensitive boolean Case-sensitive comparison
branches array Default: True/False

Operators: equals, not_equals, contains, starts_with, ends_with, regex

Branches: True, False

A/B Gateway

Random A/B split for testing workflows.

Parameter Type Description
weight_a number Weight for A (default: 50)
weight_b number Weight for B (default: 50)
branches array Default: A/B

Branches: A, B

Switch Gateway

Multi-way branching based on expression matching.

Parameter Type Description
expression string The value to match
default_branch string Fallback branch name
branches array Configurable branch list

Branches: User-configurable (e.g., High, Medium, Low, Default)

Execution Flow

How Branch Activation Works

  1. Gateway Executes: The gateway processor evaluates its condition and returns active_branches
  2. Output Captured: The orchestrator captures active_branches from the output
  3. Edge Evaluation: For each downstream edge, the orchestrator checks if the edge's branchName matches active_branches
  4. Selective Execution: Only nodes connected to active branches are executed

Visual Representation

                    ┌──► [Process A] ── True branch
[Input] ──► [If/Else]
                    └──► [Process B] ── False branch

If active_branches = "true":
  ✓ Process A executes
  ✗ Process B is skipped

If active_branches = "false":
  ✗ Process A is skipped
  ✓ Process B executes

Trigger Edge Behavior

Edges from gateway branch ports are treated as trigger edges when they connect to another node's trigger input:

[If/Else]-output-True ──► [Process A]-input-trigger

This follows the OR logic for triggers: a node executes when any of its trigger sources is satisfied.

Frontend Integration

FlowDrop UI Library

The @d34dman/flowdrop library automatically:

  1. Reads the branches configuration from node.data.config.branches
  2. Generates output handles for each branch
  3. Highlights active branches based on node.data.executionInfo.output.active_branches

Handle Visibility

Branches can be conditionally hidden using the isBranchVisible() function in the frontend, which checks connected handles.

Hybrid Nodes (Gateway + Data Outputs)

Some nodes benefit from acting as both a regular data node and a gateway. For example, a "Confirmation" (Human-in-Loop) node might want to:

  1. Output confirmed as a boolean data value (for use in downstream data processing)
  2. Also provide True/False branches (for flow control)

Creating a Hybrid Node

A hybrid node simply outputs both regular data outputs and active_branches:

public function process(ParameterBagInterface $params): array {
  // Evaluate the condition
  $confirmed = $this->evaluateConfirmation($params);

  // Return BOTH data outputs AND active_branches
  return [
    // Regular data output
    "confirmed" => $confirmed,
    "response_time" => time(),
    "user_id" => $this->getCurrentUserId(),

    // Gateway output for flow control
    "active_branches" => $confirmed ? "true" : "false",
  ];
}

Node Type Configuration for Hybrid Nodes

Configure the node type to support both default and gateway visual types:

id: confirmation
label: 'Confirmation'
description: 'Pauses workflow for user confirmation (Yes/No)'
category: human_in_loop
enabled: true
parameters:
  message:
    configurable: true
    connectable: true
    required: true
  # Include branches for gateway mode
  branches:
    configurable: true
    connectable: false
    required: false
    default:
      - name: 'True'
        value: true
      - name: 'False'
        value: false
outputs:
  # Regular data outputs
  confirmed:
    exposed: true
  response_time:
    exposed: true
  user_id:
    exposed: true
executor_plugin: confirmation
# Default to standard node appearance
visual_type: default
# Support BOTH regular and gateway modes
supported_visual_types:
  - default
  - simple
  - gateway    # Enable gateway mode

Visual Mode Switching

When the user places a hybrid node in the workflow, they can switch between visual modes:

Visual Mode Behavior
default / simple Shows standard data outputs (confirmed, response_time, etc.)
gateway Shows diamond shape with branch outputs (True, False) based on branches config

In both modes, the processor outputs the same data - only the visual representation changes. This means:

  • Downstream nodes connected to the confirmed data port receive the boolean value
  • Downstream nodes connected to branch outputs (True/False) are triggered based on active_branches

Example: Hybrid Confirmation Workflow

                                    ┌──► [Send Email] ── True branch
[Request] ──► [Confirmation (gateway)]
                                    └──► [Log Rejection] ── False branch

                                              │
                                              ▼ (confirmed output)
                                    [Analytics Logger]

In this example: - When user confirms: Send Email executes (via True branch trigger) - When user cancels: Log Rejection executes (via False branch trigger) - Analytics Logger always receives the confirmed boolean value

Benefits of Hybrid Nodes

  1. Flexibility: Site builders can choose the visual representation that best fits their workflow
  2. Data + Flow Control: The same node provides both data outputs and execution flow control
  3. Backward Compatibility: Existing workflows using data outputs continue to work

Best Practices

  1. Use Lowercase for Matching: While branch names can use any case for display (e.g., "True"), the active_branches value should match case-insensitively.

  2. Single Active Branch: For exclusive gateways, return only one branch name. For parallel gateways, return comma-separated names.

  3. Default Branch: For switch gateways, always provide a default branch to handle unexpected values.

  4. ReadOnly Parameter: Set "readOnly": TRUE on the branches parameter schema to prevent users from modifying the default value while still allowing the parameter to be exposed as a port.

  5. Consistent Naming: Keep branch names simple and consistent (e.g., "True"/"False", "A"/"B", "Success"/"Failure").

  6. Consider Hybrid: For nodes with boolean or enum outputs that affect flow, consider supporting both default and gateway visual types.

See Also

  • modules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/BooleanGateway.php
  • modules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/IfElse.php
  • modules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/SwitchGateway.php
  • modules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/AorB.php
  • modules/flowdrop_pipeline/src/Service/JobGenerationService.php (branch matching logic)