fix(agentchat): SelectorGroupChat fallback no longer returns excluded previous speaker#7610
Open
alvinttang wants to merge 1 commit intomicrosoft:mainfrom
Open
Conversation
… previous speaker When `allow_repeated_speaker=False`, exhausting `max_selector_attempts` caused `_select_speaker` to fall back to `self._previous_speaker` -- the exact participant that was supposed to be excluded. If the LLM kept picking the previous speaker, this produced a livelock where the same agent was chosen forever, silently violating `allow_repeated_speaker=False`. Fix: only fall back to the previous speaker when repeated speakers are explicitly allowed. Otherwise fall back to the first participant of the already-filtered candidate list (which upstream guarantees excludes the previous speaker). Added a regression test and updated the existing fallback test to opt into `allow_repeated_speaker=True`, which was its original intent. Fixes microsoft#7471
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a livelock in
SelectorGroupChatwhenallow_repeated_speaker=False: after the model exhaustsmax_selector_attempts,_select_speakerunconditionally returnedself._previous_speaker— the very speaker that is supposed to be excluded — so if the model kept picking that speaker, the group chat could loop forever on the same agent.Fixes #7471
Root cause
_select_speakerin_selector_group_chat.pyhas two fallback arms:max_selector_attemptsfail, reuse the previous speaker.Arm (1) ran regardless of
allow_repeated_speaker. When that flag isFalse, the caller has already filtered the previous speaker out ofparticipants, so reusing them breaks the user-visible contract and livelocks if the model keeps selecting them.Fix
allow_repeated_speaker=True, behaviour is unchanged.allow_repeated_speaker=False, pick the first candidate inparticipantsthat is notself._previous_speaker, withparticipants[0]as a defensive default.candidate_funcpath already pre-filtersparticipants; thecandidate_funcpath does not, so the same explicit skip protects both paths.max_selector_attemptsdocstring to reflect the new fallback behaviour.Tests
python/packages/autogen-agentchat/tests/test_group_chat.py:test_selector_group_chat_fall_back_excludes_previous_when_disallowed— defaultallow_repeated_speaker=Falsepath with three agents; verifies the fallback picksagent1oragent3, never the repeatedagent2.test_selector_group_chat_fall_back_excludes_previous_with_candidate_func— same scenario but driven viacandidate_func, which does NOT pre-filter. Placesagent2first in the candidate list to exercise the worst case.test_selector_group_chat_fall_back_to_previous_after_3_attempts— the existing test was adjusted to setallow_repeated_speaker=True, because it was previously codifying the buggy default behaviour.Locally on
darwin/arm64withuv:pytest tests/test_group_chat.py -k "fall_back_excludes_previous"→ 4 passed, 87 deselected.pytest tests/test_group_chat.py -k "selector"→ 32 passed.ruff checkclean,pyright0 errors.Risk notes
Behavioural change is observable only when the selector model exhausts
max_selector_attempts; users who relied on the prior "always fall back to previous speaker even when disallowed" behaviour need to opt into it withallow_repeated_speaker=True.