diff --git a/src/strands/multiagent/graph.py b/src/strands/multiagent/graph.py index 04d158108..29a51a0bb 100644 --- a/src/strands/multiagent/graph.py +++ b/src/strands/multiagent/graph.py @@ -189,7 +189,7 @@ def reset_executor_state(self) -> None: if hasattr(self.executor, "messages"): self.executor.messages = copy.deepcopy(self._initial_messages) - if hasattr(self.executor, "state"): + if hasattr(self.executor, "state") and hasattr(self.executor.state, "get"): self.executor.state = AgentState(self._initial_state.get()) # Reset execution status diff --git a/tests/strands/multiagent/test_graph.py b/tests/strands/multiagent/test_graph.py index e978701cd..5ef825b39 100644 --- a/tests/strands/multiagent/test_graph.py +++ b/tests/strands/multiagent/test_graph.py @@ -2476,3 +2476,35 @@ def test_find_newly_ready_nodes_only_evaluates_outbound_edges(): ready = graph._find_newly_ready_nodes([node_d]) ready_ids = {n.node_id for n in ready} assert ready_ids == {"E"}, f"Expected only E, got {ready_ids}" + + +@pytest.mark.asyncio +async def test_reset_executor_state_preserves_graph_state_for_nested_graph(): + """Verify reset_executor_state does not corrupt MultiAgentBase state. + + When a GraphNode wraps a MultiAgentBase executor (e.g. a nested Graph), + reset_executor_state() must not overwrite GraphState with AgentState. + Regression test for #1775. + """ + inner_agent = create_mock_agent("inner", "inner response") + inner_builder = GraphBuilder() + inner_builder.add_node(inner_agent, "inner_node") + inner_builder.set_entry_point("inner_node") + inner_graph = inner_builder.build() + + # inner_graph.state is a GraphState, not AgentState + assert isinstance(inner_graph.state, GraphState) + + node = GraphNode(node_id="nested", executor=inner_graph) + + # Simulate a completed execution + node.execution_status = Status.COMPLETED + node.result = NodeResult(result=MagicMock(), status=Status.COMPLETED) + + # Reset should NOT corrupt the nested graph's state + node.reset_executor_state() + + # After reset, the executor's state must still be GraphState + assert isinstance(inner_graph.state, GraphState), "reset_executor_state overwrote GraphState with AgentState" + assert node.execution_status == Status.PENDING + assert node.result is None