Checks
Strands Version
main (latest)
Python Version
3.10+
Operating System
All
Installation Method
pip
Steps to Reproduce
- Create a Graph with a nested
MultiAgentBase executor (e.g., a nested Graph)
- Either:
- Enable
reset_on_revisit and create a cycle that revisits the nested graph node, OR
- Use session persistence and deserialize a completed graph run (no
next_nodes_to_execute)
- The nested executor's
GraphState gets overwritten with an AgentState
Expected Behavior
reset_executor_state() should handle MultiAgentBase executors correctly — either by resetting their state to the appropriate type or by skipping the reset for executor types that don't use AgentState.
Actual Behavior
reset_executor_state() checks hasattr(self.executor, "state") without distinguishing executor type. Since Graph (a MultiAgentBase) has a .state attribute (GraphState), the method overwrites it with an AgentState instance:
def reset_executor_state(self) -> None:
if hasattr(self.executor, "messages"):
self.executor.messages = copy.deepcopy(self._initial_messages)
if hasattr(self.executor, "state"):
self.executor.state = AgentState(self._initial_state.get()) # Wrong type for MultiAgentBase
self.execution_status = Status.PENDING
self.result = None
Note: __post_init__ has a guard (hasattr(self.executor.state, "get")) that prevents capturing the initial state for MultiAgentBase, so _initial_state stays as an empty AgentState(). But reset_executor_state lacks this guard.
Two call sites are affected:
_execute_node: guarded by reset_on_revisit (off by default), so only triggers if user opts in with a nested graph in a cycle
deserialize_state: unguarded — iterates all nodes unconditionally when restoring a completed run
Possible Solution
Add type-aware handling in reset_executor_state(). For example, only reset AgentState-based executors, and for MultiAgentBase executors either call their own reset mechanism or skip the state reset.
Checks
Strands Version
main (latest)
Python Version
3.10+
Operating System
All
Installation Method
pip
Steps to Reproduce
MultiAgentBaseexecutor (e.g., a nestedGraph)reset_on_revisitand create a cycle that revisits the nested graph node, ORnext_nodes_to_execute)GraphStategets overwritten with anAgentStateExpected Behavior
reset_executor_state()should handleMultiAgentBaseexecutors correctly — either by resetting their state to the appropriate type or by skipping the reset for executor types that don't useAgentState.Actual Behavior
reset_executor_state()checkshasattr(self.executor, "state")without distinguishing executor type. SinceGraph(aMultiAgentBase) has a.stateattribute (GraphState), the method overwrites it with anAgentStateinstance:Note:
__post_init__has a guard (hasattr(self.executor.state, "get")) that prevents capturing the initial state forMultiAgentBase, so_initial_statestays as an emptyAgentState(). Butreset_executor_statelacks this guard.Two call sites are affected:
_execute_node: guarded byreset_on_revisit(off by default), so only triggers if user opts in with a nested graph in a cycledeserialize_state: unguarded — iterates all nodes unconditionally when restoring a completed runPossible Solution
Add type-aware handling in
reset_executor_state(). For example, only resetAgentState-based executors, and forMultiAgentBaseexecutors either call their own reset mechanism or skip the state reset.