ConditionalEdge¶
The ConditionalEdge
class represents a directional, optionally guarded transition between two graph nodes. It encapsulates navigation rules that determine when execution can flow from a source node to a target node based on runtime conditions.
Overview¶
A conditional edge acts as a gatekeeper in your graph workflow, allowing you to create dynamic execution paths that respond to the current state. The edge evaluates a predicate function against either KernelArguments
or GraphState
to determine if traversal is allowed.
Key Concepts¶
Conditional Routing: Edges that only allow traversal when specific conditions are met, enabling dynamic workflow branching.
Predicate Evaluation: Functions that examine the current execution context and return true/false to determine routing decisions.
State-Based Decisions: Conditions that can access both simple arguments and rich graph state information.
Merge Configuration: Settings that control how state is combined when multiple parallel branches converge.
Core Properties¶
Edge Identity¶
EdgeId
: Unique, immutable identifier generated at construction timeName
: Human-readable name for diagnostics and visualizationSourceNode
: The origin node from which traversal startsTargetNode
: The destination node reached when condition is true
Condition Evaluation¶
Condition
: Predicate function that evaluates againstKernelArguments
StateCondition
: Optional predicate function that evaluates againstGraphState
CreatedAt
: UTC timestamp when the edge was created
Execution Metadata¶
TraversalCount
: Number of times this edge has been traversedLastTraversedAt
: UTC timestamp of the last traversalHasBeenTraversed
: Boolean indicating if the edge has been used
Configuration¶
Metadata
: Mutable collection for storing routing weights, visualization hints, or provenance informationMergeConfiguration
: Settings for state joining during parallel branch convergence
Constructors¶
Basic Conditional Edge¶
public ConditionalEdge(
IGraphNode sourceNode,
IGraphNode targetNode,
Func<KernelArguments, bool> condition,
string? name = null)
Creates an edge with a predicate that evaluates over KernelArguments
.
Parameters:
* sourceNode
: The origin node
* targetNode
: The destination node
* condition
: Side-effect free predicate function
* name
: Optional human-readable name (defaults to "Source -> Target")
Example:
var edge = new ConditionalEdge(
sourceNode: startNode,
targetNode: successNode,
condition: args => args.ContainsKey("success") && (bool)args["success"],
name: "Success Path"
);
State-Based Conditional Edge¶
public ConditionalEdge(
IGraphNode sourceNode,
IGraphNode targetNode,
Func<GraphState, bool> stateCondition,
string? name = null)
Creates an edge with a predicate that evaluates over GraphState
.
Parameters:
* sourceNode
: The origin node
* targetNode
: The destination node
* stateCondition
: Side-effect free predicate function for graph state
* name
: Optional human-readable name
Example:
var edge = new ConditionalEdge(
sourceNode: decisionNode,
targetNode: highPriorityNode,
stateCondition: state => state.GetValue<int>("priority") > 7,
name: "High Priority Route"
);
Factory Methods¶
CreateUnconditional¶
public static ConditionalEdge CreateUnconditional(
IGraphNode sourceNode,
IGraphNode targetNode,
string? name = null)
Creates an edge that is always traversable (condition always returns true).
Example:
var alwaysEdge = ConditionalEdge.CreateUnconditional(
sourceNode: startNode,
targetNode: nextNode,
name: "Default Path"
);
CreateParameterEquals¶
public static ConditionalEdge CreateParameterEquals(
IGraphNode sourceNode,
IGraphNode targetNode,
string parameterName,
object expectedValue,
string? name = null)
Creates an edge that is traversable only when a specific argument equals an expected value.
Example:
var modeEdge = ConditionalEdge.CreateParameterEquals(
sourceNode: inputNode,
targetNode: advancedNode,
parameterName: "mode",
expectedValue: "advanced",
name: "Advanced Mode Route"
);
CreateParameterExists¶
public static ConditionalEdge CreateParameterExists(
IGraphNode sourceNode,
IGraphNode targetNode,
string parameterName,
string? name = null)
Creates an edge that is traversable only when a specific argument exists.
Example:
var authEdge = ConditionalEdge.CreateParameterExists(
sourceNode: loginNode,
targetNode: protectedNode,
parameterName: "authToken",
name: "Authenticated Route"
);
Condition Evaluation¶
EvaluateCondition (KernelArguments)¶
Evaluates the condition against the provided arguments.
Parameters:
* arguments
: The argument bag to evaluate
Returns: true
if the condition is met, false
otherwise
Exceptions:
* ArgumentNullException
: When arguments is null
* InvalidOperationException
: When the underlying predicate throws
Example:
var args = new KernelArguments { ["status"] = "approved" };
if (edge.EvaluateCondition(args))
{
// Traverse to target node
}
EvaluateCondition (GraphState)¶
Evaluates the condition using GraphState
when available, otherwise falls back to the KernelArguments
predicate.
Parameters:
* graphState
: The graph state to evaluate
Returns: true
if the condition is met, false
otherwise
Example:
var state = new GraphState(new KernelArguments { ["score"] = 85 });
if (edge.EvaluateCondition(state))
{
// Traverse to target node
}
Merge Configuration¶
WithMergePolicy¶
Configures the edge to use a specific merge policy for all parameters.
Example:
var edge = ConditionalEdge.CreateUnconditional(source, target)
.WithMergePolicy(StateMergeConflictPolicy.PreferFirst);
WithMergeConfiguration¶
Configures the edge with detailed merge settings for parallel branch joins.
Example:
var config = new StateMergeConfiguration
{
DefaultPolicy = StateMergeConflictPolicy.Reduce
};
var edge = ConditionalEdge.CreateUnconditional(source, target)
.WithMergeConfiguration(config);
WithKeyMergePolicy¶
Configures a merge policy for a specific parameter key.
Example:
var edge = ConditionalEdge.CreateUnconditional(source, target)
.WithKeyMergePolicy("userData", StateMergeConflictPolicy.PreferSecond);
WithTypeMergePolicy¶
Configures a merge policy for a specific .NET type.
Example:
var edge = ConditionalEdge.CreateUnconditional(source, target)
.WithTypeMergePolicy(typeof(List<string>), StateMergeConflictPolicy.Reduce);
WithCustomKeyMerger¶
Configures a custom merge function for a specific parameter key.
Example:
var edge = ConditionalEdge.CreateUnconditional(source, target)
.WithCustomKeyMerger("counters", (baseVal, overlayVal) =>
{
var baseCount = baseVal as int? ?? 0;
var overlayCount = overlayVal as int? ?? 0;
return baseCount + overlayCount;
});
WithReduceSemantics¶
Configures the edge to use reduce semantics with default reducers for common types.
Example:
Validation and Integrity¶
ValidateIntegrity¶
Validates the edge for potential issues like self-loops and invalid condition functions.
Returns: A ValidationResult
containing warnings and errors
Example:
var validation = edge.ValidateIntegrity();
if (validation.HasErrors)
{
foreach (var error in validation.Errors)
{
Console.WriteLine($"Edge validation error: {error}");
}
}
Usage Patterns¶
Basic Conditional Routing¶
// Create nodes
var startNode = new FunctionGraphNode(startFunction, "start");
var successNode = new FunctionGraphNode(successFunction, "success");
var failureNode = new FunctionGraphNode(failureFunction, "failure");
// Create conditional edges
var successEdge = new ConditionalEdge(
startNode,
successNode,
args => args.ContainsKey("result") && (bool)args["result"]
);
var failureEdge = new ConditionalEdge(
startNode,
failureNode,
args => !args.ContainsKey("result") || !(bool)args["result"]
);
// Add to graph
graph.AddEdge(successEdge);
graph.AddEdge(failureEdge);
Complex State-Based Conditions¶
var decisionEdge = new ConditionalEdge(
decisionNode,
actionNode,
state =>
{
var priority = state.GetValue<int>("priority", 0);
var isUrgent = state.GetValue<bool>("isUrgent", false);
var hasPermission = state.GetValue<string>("userRole") == "admin";
return priority > 7 || (isUrgent && hasPermission);
},
name: "High Priority or Urgent Admin Route"
);
Using Factory Methods¶
// Simple parameter check
var authEdge = ConditionalEdge.CreateParameterExists(
loginNode,
dashboardNode,
"authToken"
);
// Value comparison
var premiumEdge = ConditionalEdge.CreateParameterEquals(
userNode,
premiumNode,
"subscription",
"premium"
);
// Always traversable
var defaultEdge = ConditionalEdge.CreateUnconditional(
fallbackNode,
endNode
);
Merge Configuration for Parallel Branches¶
var mergeEdge = ConditionalEdge.CreateUnconditional(source, target)
.WithMergePolicy(StateMergeConflictPolicy.Reduce)
.WithKeyMergePolicy("counters", StateMergeConflictPolicy.Reduce)
.WithTypeMergePolicy(typeof(List<string>), StateMergeConflictPolicy.Reduce)
.WithCustomKeyMerger("userData", (baseVal, overlayVal) =>
{
// Custom merge logic for user data
if (baseVal is Dictionary<string, object> baseDict &&
overlayVal is Dictionary<string, object> overlayDict)
{
var merged = new Dictionary<string, object>(baseDict);
foreach (var kvp in overlayDict)
{
merged[kvp.Key] = kvp.Value;
}
return merged;
}
return overlayVal;
});
Integration with Graph Executor¶
Direct Edge Addition¶
Using ConnectWhen Extension¶
graph.ConnectWhen("sourceNode", "targetNode",
args => args.ContainsKey("condition") && (bool)args["condition"],
"Conditional Route");
Template-Based Routing¶
graph.ConnectWithTemplate("sourceNode", "targetNode",
"{{priority}} > 7 && {{isUrgent}} == true",
templateEngine,
"High Priority Urgent Route");
Performance Considerations¶
- Condition Functions: Keep predicates fast and side-effect free
- State Access: Use
GraphState
methods likeGetValue<T>()
for type-safe access - Caching: Consider caching expensive condition evaluations
- Validation: Use
ValidateIntegrity()
during development to catch issues early
Thread Safety¶
- Instances are safe for concurrent reads
- The
Metadata
bag and traversal counters are not synchronized - External synchronization required when multiple threads may mutate concurrently
- Use
RecordTraversal()
for atomic updates when exact counts are important
Error Handling¶
- Conditions that throw are wrapped in
InvalidOperationException
- Use try-catch blocks around condition evaluation in production code
- Validate edge integrity before adding to graphs
- Monitor traversal metrics for unexpected behavior