Skip to main content

AutoGen Conversation Patterns

Conversation patterns in AutoGen define how messages flow between agents, users, and tools to accomplish a task. Instead of a rigid, pre‑defined graph, AutoGen models interactions as dynamic, event‑driven dialogues. This article is your implementation‑focused guide to the essential patterns—one‑to‑one, group, supervisor, routing, escalation, and human‑in‑the‑loop—with code examples, flow diagrams, and best practices.

What Are Conversation Patterns in AutoGen

A conversation pattern is a template for message exchange that structures how agents collaborate. It determines who speaks when, how decisions are made, and when the conversation ends. Patterns range from simple two‑party chats to complex multi‑agent deliberations with dynamic routing.

The core idea: agents communicate via typed messages. The runtime delivers these messages, maintains the conversation history, and manages turn‑taking. The pattern you choose defines the control flow—but it’s implemented by composing standard AutoGen components: agents, group chat managers, handoffs, and event handlers.

A minimal example: a user and an assistant exchanging text.

from autogen_agentchat.messages import TextMessage

user_msg = TextMessage(content="What is AutoGen?", source="user")
response = await assistant.on_messages([user_msg], cancellation_token=None)

Under the hood, the agent processes the message, may call tools, and returns a response. This is the one‑to‑one pattern at its simplest.

Why Conversation Patterns Matter

  • Predictable execution – With a clear pattern, you know exactly how a conversation will progress and can reason about termination.
  • Agent collaboration – Different patterns enable different forms of teamwork: chain of specialists, brainstorming groups, supervised teams.
  • Workflow control – You decide when to involve a human, when to escalate, and when to stop.
  • Maintainability – Well‑defined patterns make it easy to swap agents or add new ones without rewriting the whole system.
  • Debuggability – Tracing the message flow reveals where an agent made a poor decision or a tool failed.

Choosing the right pattern is as important as designing the agents themselves.

How Conversations Work in AutoGen

At the engine level, a conversation is a sequence of messages. The flow is:

User Request → Message(s) → Agent receives → Agent processes (LLM + tools) → Agent responds → Next agent (or end)

In a multi‑agent setting, the runtime (via a group chat manager or handoffs) decides which agent speaks next and delivers the message history. The state is the message list, which grows with each turn.

Core Conversation Concepts

ConceptRole
MessageThe atomic unit of communication (text, tool call, handoff, event).
ConversationAn ordered sequence of messages.
ParticipantAn agent or user that sends/receives messages.
ContextThe shared message history available to all participants.
TurnOne cycle of message sending and response.

In AutoGen, all participants see the same conversation history (unless explicitly filtered). This shared context is the foundation for multi‑agent collaboration.

Message Lifecycle

Every message goes through a clear lifecycle:

  1. Creation – An agent or user creates a message object (e.g., TextMessage).
  2. Routing – The runtime places the message in the conversation and determines the next participant (using a manager or handoff logic).
  3. Processing – The current agent receives the updated message list, invokes its logic (LLM, tools).
  4. Response generation – The agent produces one or more new messages.
  5. Context update – The new messages are appended to the conversation history.

This loop continues until a termination condition is met (e.g., StopMessage, turn limit, or a custom termination_condition).

One‑to‑One Conversation Pattern

The simplest pattern: a user interacts with a single assistant agent.

Flow:

User ↔ Agent

Implementation:

assistant = AssistantAgent(
name="assistant",
system_message="You are a helpful assistant.",
model_client=model_client,
tools=[...]
)

user_message = TextMessage(content="Hello!", source="user")
response = await assistant.on_messages([user_message], cancellation_token=None)

The agent processes the message, may call tools, and returns a final answer. This pattern is ideal for chatbots, QA assistants, or any single‑role agent. It’s the starting point for more complex designs.

Benefits: Simple, fast, easy to test. Limitations: No delegation, no parallel work.

Multi‑Agent Conversation Pattern (Sequential Chain)

Multiple agents collaborate by passing the conversation along a chain. Each agent receives the full history and contributes its part. This can be implemented using handoffs—an agent delegates to the next by sending a HandoffMessage.

Flow:

User → Agent A → Agent B → Agent C → Response

Example with handoffs:

researcher = AssistantAgent(name="researcher", ...)
writer = AssistantAgent(name="writer", ...)

# Researcher, after collecting data, hands off to writer
# Inside researcher's logic (or via a handoff tool), it returns:
await researcher.on_messages(history) # returns a HandoffMessage(target="writer")

A cleaner approach is to use a TaskRunner that executes agents sequentially, feeding the output of one as input to the next. For handoff‑based flows, AutoGen provides HandoffMessage and the Swarm pattern (where agents decide dynamically to hand off). The core idea: each agent specializes in a step, and the conversation moves forward like a pipeline.

This pattern works well for research → write → review pipelines.

Group Conversation Pattern

Multiple agents participate in a shared conversation, with a manager controlling who speaks next. All agents see the full message list. The manager can be a simple round‑robin selector or an LLM‑powered SelectorGroupChat that decides the next speaker based on the conversation state.

Flow:

User ↔ GroupChatManager
↔ Agent A
↔ Agent B
↔ Agent C

Implementation with a round‑robin group chat:

from autogen_agentchat.teams import RoundRobinGroupChat, GroupChatManager

team = RoundRobinGroupChat([agent_a, agent_b, agent_c])
manager = GroupChatManager(team)
# Or using the convenience function:
result = await team.run(task="Analyze this data", ...)

For more intelligent selection, use SelectorGroupChat which uses an LLM to pick the next speaker:

from autogen_agentchat.teams import SelectorGroupChat

team = SelectorGroupChat([analyst, coder, reviewer], model_client=llm_client)
await team.run(task="...")

In a group conversation, agents can build on each other’s ideas, challenge assertions, or collaboratively debug. The manager ensures a single turn at a time, preventing chaos.

Benefits: Robust collaboration, shared reasoning. Limitations: More latency, potential for circular debates.

Supervisor Pattern

A supervisor agent coordinates specialist agents. The supervisor receives the user’s request, breaks it down, delegates subtasks, and aggregates the results. This is a common pattern for complex tasks where a central coordinator is needed.

Flow:

User → Supervisor → Specialist A
→ Specialist B
→ Specialist C
Supervisor → Aggregation → Final Response

In AutoGen, the supervisor can be implemented using a group chat where the supervisor agent is the only speaker that directly interacts with the user, and it calls other agents via handoffs or by sending specific messages. Alternatively, a custom manager can act as the supervisor.

Implementation sketch using handoffs:

supervisor = AssistantAgent(name="supervisor", ...)
coder = AssistantAgent(name="coder", tools=[code_executor], ...)
reviewer = AssistantAgent(name="reviewer", ...)

# Supervisor decides to hand off to coder, then to reviewer, then compiles final answer.
# This can be done through the supervisor's LLM logic generating HandoffMessages.

A more structured approach: use a GroupChat with the supervisor as the only participant that can initiate handoffs. The supervisor’s system prompt instructs it to delegate.

The supervisor pattern is powerful for maintaining control over the workflow, ensuring the user receives a consolidated answer.

Routing Pattern

Messages are dynamically directed to the most appropriate agent based on intent, content, or context. Routing can be rule‑based (keywords, regex) or LLM‑driven (the LLM classifies the request and selects the next speaker).

Implementation with an LLM‑based router:

from autogen_agentchat.teams import SelectorGroupChat

# The selector function (or LLM) examines the conversation and chooses the next participant
async def select_speaker(messages):
# Analyze last user message and current state
last_msg = messages[-1].content
if "code" in last_msg:
return "coder"
elif "data" in last_msg:
return "analyst"
else:
return "general_assistant"

team = SelectorGroupChat([general, coder, analyst], selector_func=select_speaker)

Or use SelectorGroupChat with an LLM model client—it will decide based on agent descriptions.

Benefits: Efficient, scales to many agents, reduces unnecessary chatter.

Escalation Pattern

When an agent cannot handle a request (low confidence, missing skills), it escalates to a more specialized or senior agent. This is a form of routing based on capability and context.

Example: A general support agent receives a refund request. It recognizes the complexity and hands off to a RefundSpecialist.

# Inside general agent's logic:
if intent == "refund" and not can_handle:
return HandoffMessage(target="refund_specialist", context="Customer wants a refund...")

The escalation can be manual (the agent explicitly returns a handoff) or triggered by a confidence threshold. This pattern ensures that complex tasks reach the right expert without overloading simple agents.

Event‑Driven Conversation Pattern

AutoGen’s event system allows conversations to react to runtime signals. For example, you can pause a conversation when a tool call is about to be made, send it for human approval, and resume.

Flow:

Agent emits ToolCallRequestEvent → Interceptor pauses → Human decides → Event injected → Conversation continues

Implementation:

from autogen_core import EVENT_TOPIC

async def approval_handler(event, context):
if isinstance(event, ToolCallRequestEvent):
# Pause the conversation, ask for human approval
approval = await ask_human(event.content)
if not approval:
# Modify the conversation to skip the tool
...

# Register handler on the runtime or agent
runtime.subscribe(EVENT_TOPIC, approval_handler)

This pattern enables sophisticated workflows like “always ask before sending an email” without modifying agent code.

Human‑in‑the‑Loop Conversation Pattern

Human intervention is inserted at critical points: approval of tool calls, review of agent outputs, or providing additional instructions.

AutoGen supports HITL through:

  • UserProxyAgent – A special agent that represents a human user. It can be added to group chats, and the conversation pauses until the human responds.
  • Event handlers – Intercept events like ToolCallRequestEvent and require human approval before execution.
  • TaskRunner with user input – The workflow can pause for human feedback.

Example using UserProxyAgent in a group chat:

user_proxy = UserProxyAgent(name="human", ...)
team = RoundRobinGroupChat([assistant, user_proxy])
await team.run(task="...")

The conversation will wait for the UserProxyAgent to provide input (e.g., via a console or custom input method). This is ideal for approval workflows, multi‑turn clarifications, and manual review gates.

Context Management

In any non‑trivial conversation, the message list can grow large. Effective context management is critical.

  • Message history – By default, all messages are kept. For long conversations, implement a buffer that retains only the last N messages.
  • Context propagation – When handing off to another agent, you can pass a summary or selected messages to keep the context lean.
  • Conversation memory – Use a vector store to store important facts across separate conversation sessions.
  • State synchronization – All agents in a group chat see the same messages, ensuring consistent context.
# Example: truncating message history before passing to an agent
trimmed = messages[-20:] # keep last 20 messages
response = await agent.on_messages(trimmed)

AutoGen’s runtime provides hooks to pre‑process messages before they reach an agent, making it easy to inject summarization or filtering.

Conversation Control Mechanisms

To keep conversations productive, you can enforce boundaries:

MechanismDescription
Turn limitsStop after N speaker turns (max_turns).
Termination conditionsCustom function that checks if the task is complete (e.g., a TextMentionTermination that stops when a specific phrase is detected).
Context windowsLimit the number of messages sent to the LLM.
Response validationRequire structured output; if invalid, loop back for correction.

Example: termination on a keyword.

from autogen_agentchat.teams import TextMentionTermination

termination = TextMentionTermination("DONE")
team = RoundRobinGroupChat([...], termination_condition=termination)

The conversation stops as soon as any agent says “DONE”.

Error Handling

Conversations can go wrong. Build resilience with:

  • Failed conversations – Wrap the team run in try/except; if an agent raises an exception, catch it and either retry or return a graceful fallback.
  • Invalid messages – Use strict message types; validate tool call arguments. If an agent produces malformed output, feed back an error message and let it self‑correct.
  • Context corruption – If the conversation state becomes inconsistent (e.g., due to a bug), reset to a known checkpoint or restart.
  • Infinite loops – Enforce max_turns and termination conditions.
  • Recovery strategies – Implement a “reset” keyword that clears history, or an escalation to a human.

Performance Considerations

  • Message volume – Each turn adds latency. Avoid unnecessary back‑and‑forth. Use direct handoffs instead of full group chats when possible.
  • Context growth – Large histories slow LLM calls and increase token costs. Implement early truncation.
  • Conversation latency – In group chats, waiting for LLM speaker selection adds overhead. For simple flows, a sequential chain is faster.
  • Optimization techniques – Cache tool results, reuse LLM client connections, and run tools asynchronously.

Common Beginner Mistakes

  • Excessive agent chatter – Agents talking in circles. Always set a max_turns or a strong termination condition.
  • Missing termination conditions – Conversations that never end. Define when the task is done (e.g., a final message format).
  • Poor context management – Keeping every message bloats tokens and costs. Trim or summarize.
  • Overly complex routing – Too many conditional branches make the flow unpredictable.
  • Large message histories – Not pruning history leads to context‑window overflow.

Best Practices

PracticeWhy
Keep conversations focusedEach conversation should have a clear goal.
Minimize unnecessary turnsUse tools to fetch data directly rather than asking the user.
Define termination conditionsUse TextMentionTermination, MaxTurnTermination, or custom functions.
Maintain structured messagesUse the appropriate message type (HandoffMessage, StopMessage) for control.
Monitor context growthLog message count per conversation; alert if exceeding thresholds.
Use specialized agents wiselyDon’t create an agent for every micro‑task; keep the team lean.
Leverage event handlersFor cross‑cutting concerns like logging, security, and human approval.

Practical Example: Research & Report Workflow

Let’s build a team that researches a topic, verifies facts, writes a report, and reviews it. We’ll use handoffs to create a sequential chain with dynamic routing—the researcher hands off to the fact‑checker, who hands off to the writer, who hands off to the reviewer.

1. Define the agents

from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from autogen_core.tools import FunctionTool

model_client = OpenAIChatCompletionClient(model="gpt-4o")

# Tools
def web_search(query: str) -> str: ...
def check_fact(statement: str) -> str: ... # returns "true" or "false" with evidence

researcher = AssistantAgent(
name="Researcher",
system_message="You research topics. Use web_search tool. After gathering data, hand off to FactChecker with a summary.",
tools=[FunctionTool(web_search, description="Search web")],
model_client=model_client
)

fact_checker = AssistantAgent(
name="FactChecker",
system_message="You verify facts. Use check_fact tool. After verification, hand off to Writer with verified facts.",
tools=[FunctionTool(check_fact, description="Verify fact")],
model_client=model_client
)

writer = AssistantAgent(
name="Writer",
system_message="You write a report from verified facts. After writing, hand off to Reviewer.",
model_client=model_client
)

reviewer = AssistantAgent(
name="Reviewer",
system_message="You review the report for quality. If OK, say 'APPROVED' and the final report. Otherwise, give feedback and hand back to Writer.",
model_client=model_client
)

2. Orchestrate with handoffs

We’ll use a custom team manager or simply chain on_messages manually for demonstration. A cleaner production approach is to use AutoGen’s TaskRunner with handoffs, but here we illustrate the core pattern:

async def run_research_workflow(topic: str):
# Start with user message
history = [TextMessage(content=topic, source="user")]

# Step 1: Researcher
res = await researcher.on_messages(history, cancellation_token=None)
# Assume researcher's response contains a handoff (or we simulate by constructing next message)
# In reality, you'd inspect res for HandoffMessage, but for simplicity we directly chain:
history.append(res.chat_message)

# Step 2: FactChecker
res = await fact_checker.on_messages(history)
history.append(res.chat_message)

# Step 3: Writer
res = await writer.on_messages(history)
history.append(res.chat_message)

# Step 4: Reviewer
res = await reviewer.on_messages(history)
# If reviewer says "APPROVED", we return the final report; otherwise, loop back.
return res.chat_message.content

In a production system, you’d use a GroupChat with allowed_or_disallowed_speaker_transitions to enforce the exact sequence: Researcher→FactChecker→Writer→Reviewer, with the Reviewer allowed to speak to Writer again.

Diagram of the handoff chain:

This pattern ensures each step adds value and the final output is reviewed.

Conversation Patterns in Real‑World Systems

  • Customer Support – Triage agent routes to billing, technical, or sales; escalates if needed; human approves refund.
  • Research Assistants – Multi‑source search → cross‑reference → synthesis → review.
  • Content Generation – SEO researcher → writer → editor → publisher, with human review at editor stage.
  • Workflow Automation – Event triggers agent team to process documents, verify data, and update systems.
  • Internal Business Assistants – Supervisor agent delegates to HR, IT, Finance agents; human in the loop for sensitive actions.

These patterns are composable—a group chat might internally use routing and escalation patterns.

Conversation Patterns and Other AutoGen Concepts

Conversation patterns sit at the heart of AutoGen, but they rely on the framework’s other capabilities:

  • Core Concepts – Agents, messages, tools, and runtime are the building blocks.
  • Tools & Code Execution – Tools enable agents to take action mid‑conversation; tool events can modify the conversation flow.
  • Workflows – Higher‑level constructs like TaskRunner provide pre‑built conversation patterns.
  • Production – Robust conversation patterns need error handling, termination, and persistence.

For other frameworks’ approaches to communication, see the LangGraph and CrewAI guides, and the framework comparison. For tool standardization, visit the MCP Guide.

FAQ

1. What is a conversation pattern in AutoGen?

A reusable template for how messages flow between agents, tools, and users during execution, such as one‑to‑one, group, or supervisor patterns.

2. How do AutoGen agents communicate?

Via typed messages (e.g., TextMessage, HandoffMessage). The runtime delivers these messages to the next participant in the conversation.

3. What is the supervisor pattern?

A central supervisor agent coordinates specialist agents, delegating tasks and aggregating responses.

4. What is the routing pattern?

Dynamically directing a user’s request to the most appropriate agent based on intent or content, using rule‑based or LLM‑driven selection.

5. How is context shared among agents?

All agents in a conversation receive the same message list. In group chats, the full history is visible to every participant.

6. How do conversations end?

Via termination conditions like TextMentionTermination (a specific phrase), MaxTurnTermination, or an agent sending a StopMessage.

7. Are conversation patterns production‑ready?

Yes. With proper error handling, termination conditions, and context management, these patterns power robust, multi‑agent applications.

8. Can I change the pattern mid‑conversation?

Yes. You can use event handlers or custom agents that dynamically switch between patterns (e.g., from one‑to‑one to group) based on context.

9. What is the difference between group chat and handoff?

In a group chat, all agents share a common conversation and a manager selects the next speaker. Handoffs explicitly transfer control to a specific agent.

10. How do I implement human‑in‑the‑loop?

Add a UserProxyAgent to the conversation, or intercept tool call events and pause until a human provides input.

11. Can agents call tools during a conversation?

Yes. Tools are defined as FunctionTool and agents can request them. The runtime executes tools and returns results as messages.

12. How do I prevent conversations from growing too large?

Use message buffer (trim history), implement summarization before passing to LLM, or set a context window limit.

Use sequential handoffs or a TaskRunner that chains agents one after another, feeding output into the next.

14. Can I use multiple patterns in the same application?

Absolutely. A single workflow might start with one‑to‑one, then switch to a group brainstorm, then escalate to a supervisor.

15. Where can I learn more about building complex workflows?

Proceed to the AutoGen Workflows article, which covers TaskRunner, custom teams, and advanced orchestration.

Conclusion

AutoGen Conversation Patterns are the blueprint for agent interaction. By mastering one‑to‑one chats, group collaborations, supervisors, routing, and escalation, you can design workflows that are both flexible and controllable. The event‑driven nature of AutoGen gives you deep visibility and the ability to inject human judgment precisely where needed.

Key takeaways:

  • Conversations are sequences of typed messages flowing through a runtime.
  • Patterns like group chat, handoffs, and supervisor provide different coordination styles.
  • Termination conditions and context management keep conversations focused and performant.
  • Human‑in‑the‑loop is seamlessly integrated via user proxies or event handlers.

Now, deepen your expertise with these handbook articles:

For a broader view, revisit the AutoGen Core Concepts and explore cross‑framework comparisons: LangGraph, CrewAI, and the complete comparison guide. To standardize your tools with MCP, see the MCP Guide.

Start a conversation—let your agents talk, and watch them collaborate.