diff --git a/python/packages/orchestrations/agent_framework_orchestrations/_magentic.py b/python/packages/orchestrations/agent_framework_orchestrations/_magentic.py index 52e74d9eed6..149a566f092 100644 --- a/python/packages/orchestrations/agent_framework_orchestrations/_magentic.py +++ b/python/packages/orchestrations/agent_framework_orchestrations/_magentic.py @@ -942,7 +942,10 @@ def __init__( # Termination related state self._terminated: bool = False - self._max_rounds = manager.max_round_count + # The base group chat contract coerces a max round count below 1 up to 1; this + # value is assigned after super().__init__, so apply the same rule here instead + # of ending the workflow before any round can run. + self._max_rounds = max(1, manager.max_round_count) if manager.max_round_count is not None else None @override async def _handle_messages( diff --git a/python/packages/orchestrations/tests/test_magentic.py b/python/packages/orchestrations/tests/test_magentic.py index a93e8b51328..ba6a09b189d 100644 --- a/python/packages/orchestrations/tests/test_magentic.py +++ b/python/packages/orchestrations/tests/test_magentic.py @@ -303,6 +303,34 @@ async def test_magentic_limit_termination_yields_update_in_streaming() -> None: assert terminal.text +async def test_magentic_max_round_count_below_one_is_coerced_to_one() -> None: + """A max round count below 1 gets the base group chat contract: coerce to 1 + instead of terminating before any coordination round runs.""" + + class LedgerCountingManager(FakeManager): + def __init__(self, *, max_round_count: int | None = None) -> None: + super().__init__(max_round_count=max_round_count) + self.ledger_calls = 0 + + @override + async def create_progress_ledger(self, magentic_context: MagenticContext) -> MagenticProgressLedger: + self.ledger_calls += 1 + return await super().create_progress_ledger(magentic_context) + + manager = LedgerCountingManager(max_round_count=0) + + workflow = MagenticBuilder( + participants=[DummyExec(name=manager.next_speaker_name)], + manager=manager, + ).build() + + outputs = [event async for event in workflow.run("round coercion test", stream=True)] + + # One coordination round ran before the round limit ended the workflow. + assert manager.ledger_calls == 1 + assert outputs + + async def test_magentic_as_agent_does_not_accept_conversation() -> None: manager = FakeManager() writer = StubAgent(manager.next_speaker_name, "summary response")