Skip to content

Python: fix(orchestrations): coerce Magentic max_round_count below 1 up to 1 - #9527

Closed
Yufeng He (he-yufeng) wants to merge 3 commits into
microsoft:mainfrom
he-yufeng:fix/magentic-zero-round-coercion
Closed

Yufeng He (he-yufeng) wants to merge 3 commits into
microsoft:mainfrom
he-yufeng:fix/magentic-zero-round-coercion

Conversation

@he-yufeng

Copy link
Copy Markdown
Contributor

Fixes #9500

Root cause

MagenticOrchestrator.__init__ calls super().__init__, whose contract documents that a max_rounds below 1 "will be coerced to 1" (max(1, max_rounds) in _base_group_chat_orchestrator.py) — but then overwrites self._max_rounds with the manager's raw max_round_count. With max_round_count=0 the coercion is lost and the first limits check (self._round_index >= self._max_rounds, i.e. 0 >= 0) fires before any coordination round: the run emits "Workflow terminated due to reaching maximum round count." and no participant is ever invoked.

Fix

Apply the same clamp when adopting the manager's value:

self._max_rounds = max(1, manager.max_round_count) if manager.max_round_count is not None else None

One line, matching the base contract and GroupChatOrchestrator's treatment of the same input. None (unlimited) still passes through.

Test plan

New regression test test_magentic_zero_max_round_count_is_coerced_to_one (next to the existing round-limit tests) builds a workflow with FakeManager(max_round_count=0) and asserts the run reaches the manager's final answer — the exact expectation the existing max_round_count=1 test uses, so the test pins "0 behaves as 1". On the unpatched code it fails with the issue's verbatim symptom (Workflow terminated due to reaching maximum round count.).

Verified locally (orchestrations + core from this branch on the repo venv):

python -m pytest packages/orchestrations/tests/          # 298 passed, 6 skipped
python -m pyright packages/orchestrations/.../_magentic.py  # no diagnostics in the changed hunk
ruff check / ruff format --check                            # clean

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused fix matches the documented contract, and the regression test covers the original premature termination.

No open issues 🎉

What changed in this PR

Fixes #9500 by aligning Magentic’s round-limit handling with the base orchestrator contract.

Changes:

  • Clamps max_round_count below 1 to 1 while preserving None as unlimited.
  • Adds a regression test confirming a zero limit reaches the manager’s final answer.
File Description
python/​packages/​orchestrations/​tests/​test_magentic.py Tests zero-limit coercion.
python/​packages/​orchestrations/​agent_framework_orchestrations/​_magentic.py Clamps the manager’s round limit.

Review effort: Balanced

… of failing every turn

MemoryFileStore.read_state parsed state.json without a guard, so a
corrupt state file (interrupted editor, partial external write) raised
out of the per-turn memory bookkeeping path forever. Move the unreadable
file aside (the session store's corrupt-snapshot convention) and restart
from a clean state; the next write recreates the file.
RedisContextProvider built its own AsyncSearchIndex from redis_url when
none was injected, but its __aexit__ was empty and it had no aclose, so
the index's connection pool was never released and providers created per
session leaked sockets.

Track ownership the same way RedisHistoryProvider does for its client
(_owns_client + aclose): the provider now closes the index (redisvl
disconnect) on aclose/__aexit__ only when it built the index itself; an
injected index stays under the caller's control.

Fixes microsoft#9509
…up to 1

MagenticOrchestrator overrode the base class's coerced round limit with
the manager's raw max_round_count, so max_round_count=0 skipped the
documented "coerced to 1" behavior and the first limits check
(round_index 0 >= 0) terminated the workflow before any participant ran.

Clamp the manager value exactly like the base contract describes. Adds a
regression test that a zero-limit run now reaches the manager's final
answer after one round, matching the max_round_count=1 behavior.

Fixes microsoft#9500
@he-yufeng
Yufeng He (he-yufeng) force-pushed the fix/magentic-zero-round-coercion branch from cd896ff to 385c3ad Compare October 21, 2026 02:55

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Magentic change itself is focused and matches the documented base-orchestrator contract, but this PR currently also includes the unrelated memory-state quarantine commit (68bc218) and Redis context-provider cleanup commit (a4f739b). Please rebase onto current main and retain only the Magentic fix (385c3ad, plus any conflict-only adjustments) so the PR returns to the intended two-file scope, then rerun CI.

@eavanvalkenburg

Copy link
Copy Markdown
Member

Closing in favor of #9502, which predates this PR, links the same issue, and contains the same focused round-limit fix on a clean branch. Thanks for the alternative regression coverage.

This branch was successfully deployed

1 active deployment
github-app-auth — 385c3ad3 Deployed Oct 21, 2026 by he-yufeng via add_label #25837
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: Magentic max_round_count below 1 terminates the workflow before any round instead of being coerced to 1

3 participants