@@ -813,9 +813,8 @@ def __init__(
813813 self .type = type
814814 self .agent = agent
815815 self .metadata = metadata or {}
816- # Per-node retry policy. None means "use the workflow default",
817- # resolved at run time so a workflow-level policy can be set after
818- # the nodes were added.
816+ # None means "use the workflow default", resolved at run time so the
817+ # default can be set after the nodes were added.
819818 self .retry = retry
820819
821820 if not self .id :
@@ -917,9 +916,8 @@ def __init__(
917916 self .target = target
918917 self .metadata = metadata or {}
919918 self .condition = condition
920- # Resolved once, so fires() never has to probe by catching TypeError —
921- # a predicate that raises TypeError internally would otherwise be
922- # called a second time with a different signature.
919+ # Resolved once: probing by catching TypeError would call a predicate
920+ # that raises TypeError internally a second time.
923921 self ._condition_wants_context = _accepts_two_args (condition )
924922
925923 def fires (self , output : Any , outputs : Dict [str , Any ]) -> bool :
@@ -997,9 +995,8 @@ def from_nodes(
997995 tgt = target_node
998996
999997 # Put all kwargs into metadata dict
1000- # condition is a real constructor argument, not free-form metadata —
1001- # leaving it in kwargs would bury the predicate in the visualization
1002- # labels and silently drop the routing behaviour.
998+ # A real argument, not metadata: left in kwargs it lands in the
999+ # visualization labels and the routing is dropped.
10031000 condition = kwargs .pop ("condition" , None )
10041001 metadata = kwargs if kwargs else None
10051002 return cls (
@@ -1088,8 +1085,7 @@ def __init__(
10881085
10891086 # Checkpoint configuration
10901087 self .checkpoint_dir = checkpoint_dir
1091- # Default policy for nodes that don't carry their own. None means no
1092- # retrying, which is the historical behaviour.
1088+ # None means no retrying, the historical behaviour.
10931089 self .retry_policy = retry_policy
10941090 if on_node_failure not in (
10951091 "skip_downstream" ,
@@ -1101,8 +1097,7 @@ def __init__(
11011097 f"'propagate_error', got { on_node_failure !r} "
11021098 )
11031099 self .on_node_failure = on_node_failure
1104- # node_id -> error string, populated per run. Lets a caller inspect
1105- # failures without substring-matching every output for '[ERROR]'.
1100+ # node_id -> error, so callers need not grep outputs for '[ERROR]'.
11061101 self .failed_nodes : Dict [str , str ] = {}
11071102
11081103 # Private optimization attributes
@@ -1278,10 +1273,8 @@ def compile(self) -> None:
12781273 for node_id , parents in pred .items ()
12791274 }
12801275
1281- # Index inbound edges per target so the run loop can evaluate
1282- # routing without scanning self.edges once per node. _has_conditions
1283- # lets a graph with no conditions skip the gating pass entirely,
1284- # keeping the existing execution path free of added work.
1276+ # Indexed so the run loop does not scan self.edges per node;
1277+ # _has_conditions lets an unconditional graph skip gating entirely.
12851278 inbound : Dict [str , List ["Edge" ]] = {}
12861279 has_conditions = False
12871280 for edge in self .edges :
@@ -2188,9 +2181,8 @@ def _handle_node_failure(
21882181 if self .on_node_failure == "propagate_error" :
21892182 return f"[ERROR] Agent { agent_name } failed: { exc } "
21902183
2191- # skip_downstream: the node produced nothing, so dependents are
2192- # pruned rather than being handed an error string that reads like an
2193- # answer.
2184+ # skip_downstream: dependents are pruned rather than handed an error
2185+ # string that reads like an answer.
21942186 skipped .add (node_id )
21952187 logger .warning (
21962188 f"Node { node_id } failed; skipping its dependents "
@@ -2232,8 +2224,7 @@ def _node_is_eligible(
22322224 if edge .source in skipped :
22332225 continue
22342226 if edge .source not in prev_outputs :
2235- # Predecessor hasn't run yet (first layer of a later loop, or
2236- # a cycle edge). Don't let an unevaluated edge prune the node.
2227+ # Unevaluated edge (later loop, cycle): must not prune.
22372228 return True
22382229 if edge .fires (prev_outputs [edge .source ], prev_outputs ):
22392230 return True
@@ -2270,10 +2261,8 @@ def _build_prompt(
22702261
22712262 try :
22722263 preds = self ._get_predecessors (node_id )
2273- # Keep the id paired with its own output. Filtering the outputs
2274- # while zipping against the unfiltered predecessor tuple shifted
2275- # the labels, so a node with a skipped or missing predecessor
2276- # attributed each output to the wrong agent.
2264+ # Filtering outputs while zipping against the unfiltered
2265+ # predecessor tuple shifted every label by one.
22772266 pred_outputs = [
22782267 (pred , prev_outputs [pred ])
22792268 for pred in preds
@@ -2493,8 +2482,7 @@ def _get_executor() -> ContextThreadPoolExecutor:
24932482
24942483 execution_results = {}
24952484 prev_outputs = {}
2496- # Reset per loop: a node skipped on one iteration may well be
2497- # the one that runs on the next, once upstream output changes.
2485+ # Reset per loop: a skipped node may run on the next one.
24982486 skipped_nodes : Set [str ] = set ()
24992487 self .failed_nodes = {}
25002488
@@ -2573,10 +2561,8 @@ def _get_executor() -> ContextThreadPoolExecutor:
25732561 f"with { len (layer )} nodes: { [n [0 ] for n in layer ]} "
25742562 )
25752563
2576- # Conditional routing: drop nodes this layer whose inbound
2577- # edges all declined to fire. Entry points and nodes in
2578- # graphs without conditions are never gated, so an
2579- # unconditional graph takes the same path it always did.
2564+ # Drop nodes whose inbound edges all declined to fire.
2565+ # Entry points and unconditional graphs are never gated.
25802566 if self ._has_conditions or skipped_nodes :
25812567 eligible_layer = []
25822568 for entry in layer :
@@ -3631,11 +3617,8 @@ def node_to_dict(node: Node) -> Dict[str, Any]:
36313617 return node_data
36323618
36333619 def edge_to_dict (edge : Edge ) -> Dict [str , Any ]:
3634- # A predicate is a Python callable and cannot round-trip
3635- # through JSON. Flag it in the payload and warn, so a
3636- # deserialized graph is never silently missing its routing:
3637- # loading this JSON gives an unconditional graph, where every
3638- # branch fires.
3620+ # A callable cannot round-trip through JSON, so flag it:
3621+ # loading this back gives an unconditional graph.
36393622 d = {
36403623 "source" : edge .source ,
36413624 "target" : edge .target ,
0 commit comments