Skip to content

fix(agentchat): respect allow_repeated_speaker=False in selector fallback - #7568

Open
Darren Xu (extrasmall0) wants to merge 1 commit into
microsoft:mainfrom
extrasmall0:fix/selector-group-chat-livelock
Open

fix(agentchat): respect allow_repeated_speaker=False in selector fallback#7568
Darren Xu (extrasmall0) wants to merge 1 commit into
microsoft:mainfrom
extrasmall0:fix/selector-group-chat-livelock

Conversation

@extrasmall0

Copy link
Copy Markdown

Fixes #7471

Problem

When allow_repeated_speaker=False and the model exhausts max_selector_attempts without picking a valid (non-previous) speaker, the fallback in _select_speaker returns self._previous_speaker:

if self._previous_speaker is not None:
    trace_logger.warning(...)
    return self._previous_speaker  # ← returns the excluded speaker

This creates a livelock: agent A speaks → selector tries to pick someone else → exhausts attempts → falls back to A → A speaks again → repeat.

Root Cause

The _select_speaker method receives a participants list that already has the previous speaker filtered out (done by the caller when allow_repeated_speaker=False). The fallback logic ignores this filtered list and reads directly from self._previous_speaker.

Fix

Add an early-exit branch before the existing fallback: when allow_repeated_speaker=False and there is a previous speaker, use random.choice(participants) (the already-filtered list) instead of returning the excluded speaker.

if self._previous_speaker is not None and not self._allow_repeated_speaker:
    # participants already excludes the previous speaker
    return random.choice(participants)

The existing fallback for allow_repeated_speaker=True (return previous speaker) is unchanged.

…back

When the model fails to select a valid speaker within max_selector_attempts
and allow_repeated_speaker=False, the fallback unconditionally returned
self._previous_speaker — the exact speaker that should be excluded — causing
a livelock where the same agent kept being selected indefinitely.

The _select_speaker method already receives a participants list that has the
previous speaker filtered out (done by the caller at line 196-197), so the
fix is to use random.choice(participants) for the fallback when repeated
speakers are not allowed, instead of falling through to the
self._previous_speaker branch.
@extrasmall0

Darren Xu (extrasmall0) commented Apr 11, 2026

Copy link
Copy Markdown
Author

Quick follow-up: this is ready for review, and I wanted to add one concrete bit of context in case it helps triage. The regression happens in the selector fallback path when allow_repeated_speaker=False: after candidate filtering, the fallback can still pick a previously seen speaker instead of respecting the no-repeat setting. This patch keeps the existing selector flow intact and only fixes that fallback behavior. Happy to add a narrower regression test or trim the change further if that would make review easier.

@extrasmall0

Darren Xu (extrasmall0) commented Apr 18, 2026

Copy link
Copy Markdown
Author

Quick follow-up after another week in queue: this is still ready for review, and the scope remains intentionally narrow. The change only fixes the selector fallback path when allow_repeated_speaker=False, so repeated speakers cannot slip back in after candidate filtering. There are no functional changes outside that fallback path. If it helps triage, I can split out the regression test or trim the patch further.

@extrasmall0

Darren Xu (extrasmall0) commented Apr 23, 2026

Copy link
Copy Markdown
Author

Quick status refresh after rechecking against current main: this is still a small, isolated fix in the selector fallback path when allow_repeated_speaker=False. It only changes the exhausted-selector fallback so a previously filtered speaker cannot slip back in, and it does not affect the normal selection flow when valid candidates remain. Since the last update, the PR is still waiting on maintainer review rather than additional implementation work from my side. If a maintainer can take a pass, I am happy to adjust quickly if anything needs to change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] SelectorGroupChat livelock: fallback returns excluded previous speaker when allow_repeated_speaker=False

1 participant