AutoGen SelectorGroupChat speaker selection is the process by which the SelectorGroupChat class in Microsoft’s AutoGen framework uses a language model to decide which participant agent should take the next turn in a group conversation. Instead of a fixed rotation or a hardcoded rule, it treats speaker choice as a context-dependent routing problem, reading the full chat history and emitting the name of the most appropriate agent.
What SelectorGroupChat actually is
AutoGen’s agentchat module ships two team coordinators: RoundRobinGroupChat and SelectorGroupChat. The former cycles through participants in order. The latter defers the ordering decision to an LLM call. Both inherit the same streaming and termination machinery, but only SelectorGroupChat implements dynamic autogen selectorgroupchat speaker selection.
The class signature is minimal:
from autogen_agentchat.teams import SelectorGroupChat
group = SelectorGroupChat(
participants=[agent_a, agent_b, agent_c],
model_client=model_client,
selector_prompt="...",
max_rounds=20,
)
The model_client is any OpenAI-compatible chat completion client from autogen_ext.models.openai. The selector_prompt is a system message that tells the model how to choose. If omitted, AutoGen supplies a default that lists agent names and asks for a single name in response.
How the selection call works
When the team reaches a point where a new speaker is needed, SelectorGroupChat builds a temporary message list:
- The
selector_promptas the system message. - The recent conversation history (truncated to the context window).
- A final instruction repeating the allowed agent names.
The model is expected to return only a valid participant name. AutoGen parses the response, strips whitespace, and checks membership. If the output is ambiguous or invalid, the team falls back to the previous speaker or a random pick depending on version—never silently hangs.
The key property: the selection model sees the same transcript the agents see. That means speaker selection is aware of who just spoke, what they produced, and what the task state looks like. This is fundamentally different from a round-robin counter.
selector_prompt = """You are a conversation router.
Given the transcript, pick the single agent best suited for the next turn.
Respond with exactly one of: Planner, Coder, Critic.
Do not explain your choice."""
Why dynamic speaker selection matters
In research and automation pipelines, agent roles are not evenly weighted per turn. A typical trio:
- Planner decomposes a query into steps.
- Coder writes and executes a script.
- Critic validates the output against the original intent.
After the Planner speaks, the Coder should almost always go next. After the Coder returns a traceback, the Critic may flag it and hand back to Coder. A round-robin would force Critic to speak even when nothing needs reviewing, polluting context and burning tokens.
autogen selectorgroupchat speaker selection collapses that control flow into one learned policy. You stop writing if/else state machines and let the model route based on content.
Concrete example: a triage team
Below is a runnable skeleton. It uses three AssistantAgent instances with distinct system messages. The selector prompt injects role descriptions so the router understands competencies.
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import SelectorGroupChat
from autogen_ext.models.openai import OpenAIChatCompletionClient
model_client = OpenAIChatCompletionClient(model="gpt-4o-mini")
planner = AssistantAgent(
"Planner",
model_client=model_client,
system_message="Break the user request into ordered research steps.",
)
coder = AssistantAgent(
"Coder",
model_client=model_client,
system_message="Write Python to execute the current step. Use tools if available.",
)
critic = AssistantAgent(
"Critic",
model_client=model_client,
system_message="Check whether the last result satisfies the step. Say APPROVED or specify gaps.",
)
selector_prompt = """You route turns between: Planner, Coder, Critic.
Planner: splits goals. Coder: implements. Critic: validates.
Pick the next speaker. Output only the name."""
team = SelectorGroupChat(
participants=[planner, coder, critic],
model_client=model_client,
selector_prompt=selector_prompt,
max_rounds=12,
)
async def run():
stream = team.run_stream(task="Summarize arXiv trends in LLM inference for 2024.")
async for event in stream:
print(event)
The first selection call will likely pick Planner. After the plan appears, the router sees a concrete step list and selects Coder. If the Coder’s output is incomplete, Critic routes back. This emergent loop is the entire point of autogen selectorgroupchat speaker selection: you describe roles, not transitions.
Tuning the selector prompt
The default prompt is deliberately generic. For production, tighten it:
- List each agent’s competency in one line.
- Forbid any output beyond the name.
- If you have a termination agent (e.g.,
UserProxy), exclude it from the selectable set or give it a explicit “END” token.
A weak prompt produces flips between agents and longer convergence. A strong prompt with role boundaries cuts rounds by 30–50% in our internal tests on planning tasks.
Common misconceptions
“It’s just round-robin with an LLM wrapper.”
No. Round-robin is deterministic and ignores content. SelectorGroupChat’s output varies with every transcript. The LLM is making a fresh decision each turn.
“Selection is free.”
Each turn adds one inference call. With gpt-4o as the router on a 10-agent chat, that’s noticeable latency and cost. Use a small model (gpt-4o-mini or equivalent) for the model_client dedicated to selection; agent answers can use a stronger model.
“The selector never picks the same agent twice.”
It can. If the transcript shows an unaddressed error, the router may call Coder three times consecutively. That’s correct behavior.
“I can use SelectorGroupChat without a model client.”
Impossible. The class requires an LLM to function. If you want zero LLM overhead, use RoundRobinGroupChat.
“It understands tool calls natively.”
The selector sees text. If an agent emitted a tool call and result, that’s in the history as messages. The router has no special tool schema—it reasons over the rendered conversation.
Deployment notes for the selection model
The selection call is latency-sensitive but tolerant of provider hiccups. Point the model_client at any OpenAI-compatible endpoint. In practice, routing calls are small (a few hundred tokens of history) and benefit from high availability. If you configure the client to target n4n.ai, you get automatic fallback when a provider is rate-limited or degraded, which keeps the group chat from stalling on a router timeout.
When self-hosting, set a low timeout on the selection client and catch ModelClientError to fall back to round-robin for that single turn. AutoGen does not ship this retry by default, so add it at the orchestration layer.
When not to use it
If your agent team has a strict, known topology—say, exactly Agent A → Agent B → Agent C → stop—then a static RoundRobinGroupChat or a hand-coded GroupChatManager with speaker_selection_method="manual" is simpler and cheaper. autogen selectorgroupchat speaker selection earns its keep when the branch factor exceeds two or the task length is unbounded.
For open-ended research assistants, bug-triage bots, or multi-step document pipelines, the dynamic router removes a class of brittle control code. You trade a predictable cycle for a system that adapts to what the agents actually said.