skip to content

Teams & Group Chat

You will learn AutoGen's orchestration primitives: round-robin turns, an LLM selector that picks the next speaker, Swarm-style handoffs, and the termination conditions that stop a conversation. Interviewers ask “how does it end?” more often than “how does it start?”.

part ofAI agent & RAG frameworksoverview, primer and where to startread it →
on this pageshow

questions

6

In AutoGen, how does RoundRobinGroupChat pick the next speaker and what does each agent see?

level: juniorimportance: must knowfreq 68%

answer

  1. order comes from the constructor list
  2. no model decides the speaker
  3. everyone hears everything
  4. nothing stops it by itself

basics

~20 s

RoundRobinGroupChat cycles participants in the exact order passed to its constructor, one response per turn, with no model deciding anything. Every response is broadcast to all participants, so each agent sees the whole shared conversation.

solid answer

~40 s

`RoundRobinGroupChat(participants, termination_condition=..., max_turns=...)` is AutoGen AgentChat's simplest team: it walks the participant list in order, gives each agent one turn, then wraps around. Selection is purely positional — there is no extra model call to decide who speaks, which makes runs cheap, reproducible and easy to debug. The team broadcasts every message to all participants, so agents share one growing context rather than each holding a private thread. `await team.run(task=...)` drives it and returns a `TaskResult` with `messages` and `stop_reason`. Because the rotation never stops on its own, you must give the team a `termination_condition` (or `max_turns`); otherwise it will loop until something else kills it. It fits fixed pipelines — writer then critic, generator then reviewer — and stops fitting as soon as the right next speaker depends on content.

go deeper

for a junior

Know that participants speak in the order you passed them, that all agents see the same messages, and that you must supply a termination condition or the loop never ends.

for a middle

Explain the mechanics: a positional cursor, broadcast of every response to all participants, one TaskResult with a stop_reason at the end, and why prompt size grows each turn.

for a senior

Show judgment about when the fixed rotation stops paying — content-dependent routing, agents that pass most turns, and history growth that makes long runs expensive rather than slow.

for a principal

Frame it as a control-flow commitment: deterministic rotation buys reproducibility and cheap debugging, and you trade that away the moment you adopt content-aware selection. Say which workloads justify the trade.

## What it is `RoundRobinGroupChat` lives in `autogen_agentchat.teams` and is the baseline team type in AutoGen AgentChat (0.7.x). You construct it with a list of participants — usually `AssistantAgent` instances, optionally a `UserProxyAgent` — plus an optional `termination_condition` and `max_turns`. ``` team = RoundRobinGroupChat([writer, critic], termination_condition=cond, max_turns=12) ``` ## How a turn works The team's internal group-chat manager keeps a cursor over the participant list. On each turn it selects the participant at the cursor, asks it to respond to the current message thread, publishes that response, and advances the cursor, wrapping around at the end. There is no scoring, no voting and no model call involved in the selection itself — position in the list *is* the policy. That has three practical consequences: turn order is deterministic and reproducible across runs; the team adds zero selection tokens on top of what the agents themselves spend; and a failure is easy to localise, because you always know who was supposed to speak. ## What each agent sees Agent responses are broadcast to every participant, not just to the next speaker. All participants therefore observe the same message thread, which is what lets a critic critique a writer's draft without any explicit plumbing. The cost is that the shared thread grows with every turn, and each agent re-sends a longer history to its model on its next turn. In a long round-robin run, token spend per turn climbs steadily even though the team logic is trivial — this, not the orchestration, is where the money goes. ## How a run ends A round-robin rotation has no natural end, so ending is entirely your job. Two mechanisms exist: - `termination_condition` — an object from `autogen_agentchat.conditions` (for example `TextMentionTermination("APPROVE")` or `MaxMessageTermination(10)`) that is checked as messages flow and stops the run when it fires. - `max_turns` — a hard cap on the number of agent turns, independent of any condition. When either fires, `run()` returns a `TaskResult` whose `stop_reason` string tells you which one it was. A team constructed with neither is a bug waiting to happen: it will rotate indefinitely. ## Where it fits and where it stops fitting Round robin is the right team when the workflow really is a fixed cycle: draft → critique → revise, or produce → validate. It is the wrong team when the next speaker depends on the content of the last message — a routing decision that positional order cannot express. Trying to encode routing inside agents' system prompts ("only answer if the question is about billing") produces the classic anti-pattern: every agent speaks every round, most of them saying "not my turn", burning a model call each time. That is the signal to move to a team type whose selection is content-aware, or to split the work into separate runs. A second limit is scale of participants. Because everyone speaks every cycle and everyone reads everything, cost grows with participants × turns × history. Round robin with eight agents is rarely what you want; two or three is the sweet spot. ## Common mistakes - Assuming the list order is "a hint" and that the framework will reorder based on relevance. It will not. - Forgetting that participants share the context, then being surprised that an agent references something it was never directly told. - Constructing the team without a termination condition and discovering the loop only via the bill or a timeout. - Expecting a single participant to behave differently in a team than alone — with one participant, round robin is just that agent talking to itself each turn until termination.

  • What happens if you build a RoundRobinGroupChat with no termination_condition and no max_turns?
    The rotation never ends on its own — agents keep taking turns until the process is cancelled, an exception propagates, or an external limit such as a rate limit or timeout intervenes. In practice you see cost climb and the run hang. Always pass a termination condition, and usually a `max_turns` cap as well, so there is a hard ceiling even if the semantic condition never matches.
  • Why does the cost of a round-robin run grow faster than the number of turns?
    Because the team broadcasts every message to every participant, each agent re-sends the whole accumulated thread as prompt context on its next turn. So per-turn prompt size grows with the conversation, and total spend grows roughly with turns squared rather than linearly. Long round-robin runs need either an aggressive termination condition, fewer participants, or shorter agent outputs.
  • Your two-agent round robin ends because the reviewer said "looks good" but never the exact word your condition matches. What do you change?
    Two fixes, and you usually want both. Make the completion signal explicit in the reviewer's system message so it emits a fixed token you can match on, and keep a `MaxMessageTermination` or `max_turns` safety net composed alongside it so a missed signal degrades into a bounded run rather than an endless one.

saying these in an interview costs you the question

  • Thinks a model picks the speaker in RoundRobinGroupChat
  • Assumes each agent keeps its own private conversation thread
  • Believes the team stops automatically when the task looks done
  • Claims round robin reorders agents by relevance to the task
  • Ignores that shared history inflates prompt cost every turn

context

open as a page

In AutoGen AgentChat, how do termination conditions end a team run, and what do | and & do?

level: middleimportance: must knowfreq 84%

basics

~20 s

Termination conditions from autogen_agentchat.conditions are evaluated as messages flow through a team; when one fires the team stops and run() returns a TaskResult whose stop_reason names it. The | operator means stop when either condition fires; & means stop only once all of them have.

open as a page

In AutoGen's Swarm team, how does one agent actually hand control to another agent?

level: middleimportance: should knowfreq 54%

basics

~20 s

You configure an agent with handoffs=["other_agent"], which gives its model a transfer_to_other_agent tool. Calling that tool makes the agent emit a HandoffMessage whose target names the next speaker, and the Swarm team makes that agent speak next.

open as a page

Why does an AutoGen team's second run() see the first task's history, and what does team.reset() do?

level: seniorimportance: should knowfreq 45%

basics

~20 s

AutoGen teams are stateful: the group-chat manager and every participant keep the message thread between run() calls, so a second task is appended to the first conversation. await team.reset() clears that accumulated state on the team and its participants, returning them to their initial condition.

open as a page

In AutoGen's SelectorGroupChat, how is the next speaker chosen and how do you override it?

level: seniorimportance: should knowfreq 56%

basics

~20 s

SelectorGroupChat calls its model_client every turn with a rendered selector_prompt and asks it to name the next participant. Supplying selector_func short-circuits that: return a participant name to force the choice, or None to fall back to the model.

open as a page

How do you bound cost and runtime for an AutoGen team running unattended in production?

level: principalimportance: should knowfreq 34%

basics

~20 s

Layer the stops: one semantic condition that marks real success, ORed with hard fuses on messages, turns, tokens and wall clock, plus limits outside the framework at the model client. Then alert on TaskResult.stop_reason, because a fuse firing routinely means the design is not converging.

open as a page