fix: adjust executor listener value to avoid recursion (#4705)

* fix: adjust executor listener value to avoid recursion

* fix: clear call count to ensure zero state

* feat: expose max method call kwarg
This commit is contained in:
Greyson LaLonde
2026-03-04 13:47:22 -05:00
committed by GitHub
parent 3cc6516ae5
commit ea70976a5d
4 changed files with 75 additions and 7 deletions

View File

@@ -123,7 +123,7 @@ class TestAgentExecutor:
executor.state.iterations = 10
result = executor.check_max_iterations()
assert result == "force_final_answer"
assert result == "max_iterations_exceeded"
def test_route_by_answer_type_action(self, mock_dependencies):
"""Test routing for AgentAction."""

View File

@@ -1843,3 +1843,53 @@ def test_cyclic_flow_works_with_persist_and_id_input():
f"'{method}' should fire 3 times, "
f"got {len(events)}: {execution_order}"
)
@pytest.mark.timeout(5)
def test_self_listening_method_does_not_loop():
"""A method whose @listen label matches its own name must not loop forever.
Without the guard, 'process' re-triggers itself on every completion,
running indefinitely (timeout → FAIL). The fix caps method calls
and raises RecursionError (PASS).
"""
class SelfListenFlow(Flow):
@start()
def begin(self):
return "process"
@router(begin)
def route(self):
return "process"
@listen("process")
def process(self):
pass
flow = SelfListenFlow()
with pytest.raises(RecursionError, match="infinite loop"):
flow.kickoff()
def test_or_condition_self_listen_fires_once():
"""or_() with a self-referencing label only fires once due to or_() guard."""
call_count = 0
class OrSelfListenFlow(Flow):
@start()
def begin(self):
return "process"
@router(begin)
def route(self):
return "process"
@listen(or_("other_trigger", "process"))
def process(self):
nonlocal call_count
call_count += 1
flow = OrSelfListenFlow()
flow.kickoff()
assert call_count == 1