{"record":{"id":"e8f058724d162705","repo":"microsoft/autogen","slug":"speaker-speaker-name-not-found-in-participant-na","errorCode":null,"errorMessage":"Speaker {speaker_name} not found in participant names.","messagePattern":"Speaker (.+?) not found in participant names\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_base_group_chat_manager.py","lineNumber":182,"sourceCode":"            await self._transition_to_next_speakers(ctx.cancellation_token)\n        except Exception as e:\n            # Handle the exception and signal termination with an error.\n            error = SerializableException.from_exception(e)\n            await self._signal_termination_with_error(error)\n            # Raise the exception to the runtime.\n            raise\n\n    async def _transition_to_next_speakers(self, cancellation_token: CancellationToken) -> None:\n        speaker_names_future = asyncio.ensure_future(self.select_speaker(self._message_thread))\n        # Link the select speaker future to the cancellation token.\n        cancellation_token.link_future(speaker_names_future)\n        speaker_names = await speaker_names_future\n        if isinstance(speaker_names, str):\n            # If only one speaker is selected, convert it to a list.\n            speaker_names = [speaker_names]\n        for speaker_name in speaker_names:\n            if speaker_name not in self._participant_name_to_topic_type:\n                raise RuntimeError(f\"Speaker {speaker_name} not found in participant names.\")\n        await self._log_speaker_selection(speaker_names)\n\n        # Send request to publish message to the next speakers\n        for speaker_name in speaker_names:\n            speaker_topic_type = self._participant_name_to_topic_type[speaker_name]\n            await self.publish_message(\n                GroupChatRequestPublish(),\n                topic_id=DefaultTopicId(type=speaker_topic_type),\n                cancellation_token=cancellation_token,\n            )\n            self._active_speakers.append(speaker_name)\n\n    async def _apply_termination_condition(\n        self, delta: Sequence[BaseAgentEvent | BaseChatMessage], increment_turn_count: bool = False\n    ) -> bool:\n        \"\"\"Apply the termination condition to the delta and return True if the conversation should be terminated.\n        It also resets the termination condition and turn count, and signals termination to the caller of the team.\"\"\"\n        if self._termination_condition is not None:","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_base_group_chat_manager.py#L164-L200","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["List the exact participant names in the selector prompt and instruct the model to answer with one of them verbatim.","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.","After changing the team roster, regenerate or update any saved selector prompt/examples and checkpoints."],"exampleFix":"// before\nselector = SelectorGroupChat(participants, model_client=client,\n    selector_prompt=\"Pick the best agent to speak next.\")  # names not constrained\n\n// after\nnames = ', '.join(a.name for a in participants)\nselector = SelectorGroupChat(participants, model_client=client,\n    selector_prompt=f'''Select the next speaker. Reply with EXACTLY one of: {names}. No other text.''')","handlingStrategy":"validation","validationCode":"valid_names = {a.name for a in participants}\ndef clamp_selection(names: str | list[str]) -> list[str]:\n    selected = [names] if isinstance(names, str) else list(names)\n    unknown = [n for n in selected if n not in valid_names]\n    if unknown:\n        raise ValueError(f\"Selector returned unknown speakers {unknown}; valid: {sorted(valid_names)}\")\n    return selected","typeGuard":"def is_valid_speaker(name: str, participants: Sequence[ChatAgent]) -> bool:\n    return name in {p.name for p in participants}","tryCatchPattern":"try:\n    async for _ in team.run_stream(task):\n        pass\nexcept RuntimeError as e:\n    if \"not found in participant names\" in str(e):\n        # fix selector prompt / selector_func, then retry with a fresh team\n        ...","preventionTips":["Embed the exact participant name list in the selector prompt and demand verbatim answers.","With selector_func, validate/clamp the returned name against participants before returning it.","Regenerate selector prompts after any roster change."],"tags":["group-chat","llm-output","speaker-selection","runtime"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}