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¶
- Gateway Executes: The gateway processor evaluates its condition and returns
active_branches - Output Captured: The orchestrator captures
active_branchesfrom the output - Edge Evaluation: For each downstream edge, the orchestrator checks if the edge's
branchNamematchesactive_branches - 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:
- Reads the
branchesconfiguration fromnode.data.config.branches - Generates output handles for each branch
- 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:
- Output
confirmedas a boolean data value (for use in downstream data processing) - 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
confirmeddata 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¶
- Flexibility: Site builders can choose the visual representation that best fits their workflow
- Data + Flow Control: The same node provides both data outputs and execution flow control
- Backward Compatibility: Existing workflows using data outputs continue to work
Best Practices¶
-
Use Lowercase for Matching: While branch names can use any case for display (e.g., "True"), the
active_branchesvalue should match case-insensitively. -
Single Active Branch: For exclusive gateways, return only one branch name. For parallel gateways, return comma-separated names.
-
Default Branch: For switch gateways, always provide a default branch to handle unexpected values.
-
ReadOnly Parameter: Set
"readOnly": TRUEon the branches parameter schema to prevent users from modifying the default value while still allowing the parameter to be exposed as a port. -
Consistent Naming: Keep branch names simple and consistent (e.g., "True"/"False", "A"/"B", "Success"/"Failure").
-
Consider Hybrid: For nodes with boolean or enum outputs that affect flow, consider supporting both
defaultandgatewayvisual types.
Related Documentation¶
- Reserved Names - List of all reserved names including
branches - Execution Dependency Rules - How branching affects execution flow
- FlowDrop Node Processor - General node processor development
- Internal Parameters - System parameters like
__state__
See Also¶
modules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/BooleanGateway.phpmodules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/IfElse.phpmodules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/SwitchGateway.phpmodules/flowdrop_node_processor/src/Plugin/FlowDropNodeProcessor/AorB.phpmodules/flowdrop_pipeline/src/Service/JobGenerationService.php(branch matching logic)