Skip to content

Commit 6af5271

Browse files
DeanChensjcopybara-github
authored andcommitted
refactor: Forbid routed edges starting from START in graph validation
Modifies graph validation to forbid edges starting from the START node from having routes defined. Edges originating from START must be unconditional. Co-authored-by: Shangjie Chen <deanchen@google.com> PiperOrigin-RevId: 944703369
1 parent 0c517e7 commit 6af5271

2 files changed

Lines changed: 34 additions & 6 deletions

File tree

src/google/adk/workflow/utils/_graph_validation.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ def _validate_duplicate_edges(edges: list[Edge]) -> None:
129129
seen_edges.add(edge_tuple)
130130

131131

132+
def _validate_start_edges(edges: list[Edge]) -> None:
133+
"""Checks that edges from START do not have routes."""
134+
for edge in edges:
135+
if edge.from_node.name == START.name and edge.route is not None:
136+
raise ValueError(
137+
"Graph validation failed. Edges from START must not have routes"
138+
f" (edge to {edge.to_node.name} has route {edge.route})."
139+
)
140+
141+
132142
def _validate_default_routes(edges: list[Edge]) -> None:
133143
"""Checks constraints on DEFAULT_ROUTE."""
134144
default_route_edges: dict[str, str] = {}
@@ -202,6 +212,7 @@ def validate_graph(nodes: list[BaseNode], edges: list[Edge]) -> set[str]:
202212
"""Validates the workflow graph and returns terminal node names."""
203213
node_names = _validate_duplicate_node_names(nodes)
204214
_validate_start_node(node_names)
215+
_validate_start_edges(edges)
205216
_validate_connectivity(edges, node_names)
206217
_validate_duplicate_edges(edges)
207218
_validate_default_routes(edges)

tests/unittests/workflow/utils/test_graph_validation.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,30 +100,47 @@ def test_duplicate_edges_fail_validation(
100100
) -> None:
101101
"""Tests that duplicate edges fail validation, regardless of routes."""
102102
node_a = TestingNode(name='NodeA')
103+
node_b = TestingNode(name='NodeB')
103104
graph = Graph(
104105
edges=[
106+
Edge(from_node=START, to_node=node_a),
105107
Edge(
106-
from_node=START,
107-
to_node=node_a,
108+
from_node=node_a,
109+
to_node=node_b,
108110
route=routes[0],
109111
),
110112
Edge(
111-
from_node=START,
112-
to_node=node_a,
113+
from_node=node_a,
114+
to_node=node_b,
113115
route=routes[1],
114116
),
115117
],
116118
)
117119
with pytest.raises(
118120
ValueError,
119121
match=(
120-
r'Graph validation failed\. Duplicate edge found: from=__START__,'
121-
r' to=NodeA'
122+
r'Graph validation failed\. Duplicate edge found: from=NodeA,'
123+
r' to=NodeB'
122124
),
123125
):
124126
validate_graph(graph.nodes, graph.edges)
125127

126128

129+
def test_routed_start_edge_fails_validation() -> None:
130+
"""Tests that routed edges from START node fail validation."""
131+
node_a = TestingNode(name='NodeA')
132+
graph = Graph(
133+
edges=[
134+
Edge(from_node=START, to_node=node_a, route='route1'),
135+
],
136+
)
137+
with pytest.raises(
138+
ValueError,
139+
match=r'Graph validation failed\. Edges from START must not have routes',
140+
):
141+
validate_graph(graph.nodes, graph.edges)
142+
143+
127144
def test_start_node_with_incoming_edge() -> None:
128145
"""Tests graph with incoming edge to START node fails validation."""
129146
node_a = TestingNode(name='NodeA')

0 commit comments

Comments
 (0)