From dfaf14e25c8e4d3fd95f7a00122fb185d2000d89 Mon Sep 17 00:00:00 2001 From: Manohar Paturi <186662190+ManoharPaturi@users.noreply.github.com> Date: Sun, 18 Oct 2026 20:03:20 +0530 Subject: [PATCH 1/2] Python: coerce Magentic max round count below one up to one Signed-off-by: Manohar Paturi <186662190+ManoharPaturi@users.noreply.github.com> --- .../_magentic.py | 5 +++- .../orchestrations/tests/test_magentic.py | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) 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..b3264cb98a4 100644 --- a/python/packages/orchestrations/tests/test_magentic.py +++ b/python/packages/orchestrations/tests/test_magentic.py @@ -303,6 +303,32 @@ 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.""" + manager = FakeManager(max_round_count=0) + ledger_calls = 0 + original_create_ledger = manager.create_progress_ledger + + async def counting_create_ledger(magentic_context: MagenticContext) -> MagenticProgressLedger: + nonlocal ledger_calls + ledger_calls += 1 + return await original_create_ledger(magentic_context) + + manager.create_progress_ledger = counting_create_ledger # type: ignore[method-assign] + + 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 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") From 90648c66827ce4014cd33534c71a9df49eaa0f17 Mon Sep 17 00:00:00 2001 From: Manohar Paturi <186662190+ManoharPaturi@users.noreply.github.com> Date: Thu, 22 Oct 2026 15:35:07 +0000 Subject: [PATCH 2/2] Python: subclass FakeManager in Magentic round coercion test so ty accepts it Signed-off-by: Manohar Paturi <186662190+ManoharPaturi@users.noreply.github.com> --- .../orchestrations/tests/test_magentic.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/python/packages/orchestrations/tests/test_magentic.py b/python/packages/orchestrations/tests/test_magentic.py index b3264cb98a4..ba6a09b189d 100644 --- a/python/packages/orchestrations/tests/test_magentic.py +++ b/python/packages/orchestrations/tests/test_magentic.py @@ -306,16 +306,18 @@ async def test_magentic_limit_termination_yields_update_in_streaming() -> None: 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.""" - manager = FakeManager(max_round_count=0) - ledger_calls = 0 - original_create_ledger = manager.create_progress_ledger - async def counting_create_ledger(magentic_context: MagenticContext) -> MagenticProgressLedger: - nonlocal ledger_calls - ledger_calls += 1 - return await original_create_ledger(magentic_context) + 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 - manager.create_progress_ledger = counting_create_ledger # type: ignore[method-assign] + @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)], @@ -325,7 +327,7 @@ async def counting_create_ledger(magentic_context: MagenticContext) -> MagenticP 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 ledger_calls == 1 + assert manager.ledger_calls == 1 assert outputs