Conditional Output Ports
How nodes use custom portKey values to branch execution, and how the edge router evaluates edge conditions to determine which downstream paths activate.
Two Mechanisms for Branching
Flow Studio provides two complementary mechanisms for branching from a single node:
| Mechanism | Who decides | How |
|---|---|---|
| Port-based routing | The executor (C#) | Return different portKey values from Success() |
| Edge conditions | The designer (expressions) | Condition expression on edge evaluated by the router |
Port-Based Routing in C#
The executor examines its input/business logic and returns a named port key. All edges connected to that port on the canvas are followed:
public class CreditCheckExecutor : BaseNodeExecutor
{
public override async Task<NodeExecutionResult> ExecuteAsync(NodeExecutionContext ctx)
{
var applicantId = ctx.GetInput<string>("applicantId");
var score = await _creditService.GetScoreAsync(applicantId);
if (score >= 750)
return NodeExecutionResult.Success(new { score, tier = "premium" }, portKey: "approved");
if (score >= 600)
return NodeExecutionResult.Success(new { score, tier = "standard" }, portKey: "review");
return NodeExecutionResult.Success(new { score, tier = "declined" }, portKey: "rejected");
}
}
Edge Conditions (Expression-Based)
Even on the main port, an edge can have a condition expression. Only edges whose condition evaluates to true are followed. This allows multiple downstream branches from the same port with different routing logic:
// WorkflowEdge type — condition field
interface WorkflowEdge {
id: string;
sourceNodeId: string;
targetNodeId: string;
sourcePortKey: string; // which port this edge originates from
condition?: string; // optional expression — must evaluate to boolean
}
// Example edge conditions (set in the Flow Studio edge inspector)
$output.checkNode.amount > 10000 // high-value path
$output.checkNode.status === "active" // active-only path
$output.checkNode.roles.includes("admin") // role-gated path
Evaluation Order
- Node executor returns
NodeExecutionResult.Success(data, portKey: "approved") - Edge router finds all edges where
sourceNodeId == thisNode && sourcePortKey == "approved" - For each such edge, the router evaluates
edge.condition(if set) - Edges where condition is absent or evaluates to
trueare followed - All followed edges trigger their target nodes in parallel
Decision Pattern Without a Gateway Node
Because port keys encode the decision, you often don't need a separate gateway node. The CreditCheck node above directly routes to three different branches via its return value. This keeps the canvas clean and co-locates the decision logic with the data that drives it.
┌──────────────────┐
│ CreditCheckNode │
└──────────────────┘
│ │ │
"approved" "review" "rejected"
│ │ │
┌────▼──┐ ┌──▼───┐ ┌──▼────┐
│Premium│ │Manual│ │Decline│
│ Offer │ │Review│ │ Node │
└───────┘ └──────┘ └───────┘