microsoft/autogen · error · RuntimeError

Speaker {speaker_name} not found in participant names.

Error message

Speaker {speaker_name} not found in participant names.

What it means

Raised at runtime by _transition_to_next_speakers when the group chat manager's speaker-selection step returned a name that is not among the team's participants. The selected name is looked up in the participant-name-to-topic map; a miss means the selector (often an LLM or a custom callback) produced a hallucinated, misspelled, or stale agent name, and routing cannot proceed.

Source

Thrown at python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_base_group_chat_manager.py:182

            await self._transition_to_next_speakers(ctx.cancellation_token)
        except Exception as e:
            # Handle the exception and signal termination with an error.
            error = SerializableException.from_exception(e)
            await self._signal_termination_with_error(error)
            # Raise the exception to the runtime.
            raise

    async def _transition_to_next_speakers(self, cancellation_token: CancellationToken) -> None:
        speaker_names_future = asyncio.ensure_future(self.select_speaker(self._message_thread))
        # Link the select speaker future to the cancellation token.
        cancellation_token.link_future(speaker_names_future)
        speaker_names = await speaker_names_future
        if isinstance(speaker_names, str):
            # If only one speaker is selected, convert it to a list.
            speaker_names = [speaker_names]
        for speaker_name in speaker_names:
            if speaker_name not in self._participant_name_to_topic_type:
                raise RuntimeError(f"Speaker {speaker_name} not found in participant names.")
        await self._log_speaker_selection(speaker_names)

        # Send request to publish message to the next speakers
        for speaker_name in speaker_names:
            speaker_topic_type = self._participant_name_to_topic_type[speaker_name]
            await self.publish_message(
                GroupChatRequestPublish(),
                topic_id=DefaultTopicId(type=speaker_topic_type),
                cancellation_token=cancellation_token,
            )
            self._active_speakers.append(speaker_name)

    async def _apply_termination_condition(
        self, delta: Sequence[BaseAgentEvent | BaseChatMessage], increment_turn_count: bool = False
    ) -> bool:
        """Apply the termination condition to the delta and return True if the conversation should be terminated.
        It also resets the termination condition and turn count, and signals termination to the caller of the team."""
        if self._termination_condition is not None:

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. List the exact participant names in the selector prompt and instruct the model to answer with one of them verbatim.
  2. If using selector_func, return only names from [a.name for a in participants]; clamp/normalize the LLM output to the closest valid name before returning.
  3. After changing the team roster, regenerate or update any saved selector prompt/examples and checkpoints.

Example fix

// before
selector = SelectorGroupChat(participants, model_client=client,
    selector_prompt="Pick the best agent to speak next.")  # names not constrained

// after
names = ', '.join(a.name for a in participants)
selector = SelectorGroupChat(participants, model_client=client,
    selector_prompt=f'''Select the next speaker. Reply with EXACTLY one of: {names}. No other text.''')
Defensive patterns

Strategy: validation

Validate before calling

valid_names = {a.name for a in participants}
def clamp_selection(names: str | list[str]) -> list[str]:
    selected = [names] if isinstance(names, str) else list(names)
    unknown = [n for n in selected if n not in valid_names]
    if unknown:
        raise ValueError(f"Selector returned unknown speakers {unknown}; valid: {sorted(valid_names)}")
    return selected

Type guard

def is_valid_speaker(name: str, participants: Sequence[ChatAgent]) -> bool:
    return name in {p.name for p in participants}

Try / catch

try:
    async for _ in team.run_stream(task):
        pass
except RuntimeError as e:
    if "not found in participant names" in str(e):
        # fix selector prompt / selector_func, then retry with a fresh team
        ...

Prevention

When it happens

Trigger: SelectorGroupChat where the LLM selector emits a name not in the participant list (paraphrased, cased differently, or invented); a custom selector_func returning a name of an agent that was removed or renamed; resuming from checkpointed state whose participant set differs from the current team.

Common situations: Selector prompts that describe agents loosely so the model returns e.g. 'CodeReviewer' instead of 'code_reviewer'; changing the agent roster between runs without updating the selector prompt; few-shot examples in the prompt referencing old agent names.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/e8f058724d162705. Report an issue: GitHub.