AutoGen Essentials

Course Content

AutoGen Essentials

7 sections · 28 lessons

How do you implement turn-taking and stopping conditions in AutoGen group chats?


Who speaks next is the team classNext speakerRoundRobin — fixedorder, no extra callSelector — LLMreads descriptionsselector_func —code decides firstSwarm — currentagent hands offGraphFlow —conditional edgesMagenticOne —orchestrator ledger
Turn-taking and stopping are separate settings: the team class picks the speaker, the termination condition ends the run.

What you need to know

Turn-taking options in 0.4+

TeamWho speaks nextExtra model call per turn?Good for
RoundRobinGroupChatFixed orderNoWriter and reviewer pairs, fixed pipelines
SelectorGroupChatAn LLM reads descriptions and historyYes (unless selector_func decides)Open tasks where the order varies
SwarmThe current agent hands off with a HandoffMessageNoSupport desks, where the current agent knows who is next
GraphFlowEdges in a directed graph, with conditionsNoKnown workflows with branches and loops (experimental)
MagenticOneGroupChatAn orchestrator agent with a plan and progress ledgerYesOpen-ended web, file and code tasks

SelectorGroupChat extras: selector_prompt (template with {roles}, {participants}, {history}), allow_repeated_speaker (default False), candidate_func to narrow who may be picked, and selector_func returning an agent name or None to fall back to the model.

Stopping conditions in 0.4+

ConditionStops when
TextMentionTermination("X", sources=[...])Text X appears (optionally only from named agents)
MaxMessageTermination(n)n messages have been produced
TokenUsageTermination(max_total_token=...)Token budget is used
TimeoutTermination(timeout_seconds=...)Time runs out
HandoffTermination(target="user")An agent hands off to that target
SourceMatchTermination(["agent"])A named agent has spoken
FunctionCallTermination("fn")A named tool has run
ExternalTermination()Your code calls .set()

Example: travel team with code-first routing

Python
from autogen_agentchat.teams import SelectorGroupChatfrom autogen_agentchat.conditions import TextMentionTermination, MaxMessageTerminationdef route(messages):    last = messages[-1]    if last.source == "user":        return "planner"          # planner always starts    if last.source in ("flights", "hotels"):        return "planner"          # workers report back to the planner    return None                   # otherwise let the LLM chooseteam = SelectorGroupChat(    [planner, flights, hotels],    model_client=client,    selector_func=route,    termination_condition=TextMentionTermination("FINAL PLAN", sources=["planner"])                          | MaxMessageTermination(16),)

The code handles the predictable moves for free; the LLM only chooses when the planner has spoken and could need either worker.

Legacy 0.2

GroupChat(speaker_selection_method=...) took "auto" (the manager's LLM picks), "round_robin", "random", "manual" (a human picks) or a callable f(last_speaker, groupchat). allowed_or_disallowed_speaker_transitions with speaker_transitions_type="allowed" restricted who could follow whom, allow_repeat_speaker controlled repeats, and max_round capped the chat.

A real-life example

The travel startup first used plain SelectorGroupChat for planner, flights and hotels. The selector made one extra model call per turn, about 1,200 tokens each, and sometimes picked hotels right after the user's first message, before any dates were fixed.

Adding the route function above fixed the order for the obvious cases. Selector calls fell by about 60%, runs got 5 seconds faster, and the "hotel before dates" bug disappeared. The termination condition listens only to the planner, so a worker saying "final plan" in passing no longer stops the run.

Follow-up questions to expect

  • "When would you choose round robin over a selector?" — When the order is always the same, such as write then review. It is cheaper and fully predictable.
  • "How do you pause for a human and resume?" — End the run with HandoffTermination(target="user") or max_turns=1, show the output, then call team.run(task=reply) again. The team keeps its history until you call reset().
  • "What happens if the selector returns an invalid name?" — SelectorGroupChat retries up to max_selector_attempts (default 3), then falls back to the previous speaker or the first participant.