← Back to DevBytes

AutoGen GroupChat: Coordinating Multiple AI Agents

AutoGen GroupChat: Coordinating Multiple AI Agents

AutoGen GroupChat is a powerful orchestration pattern that allows multiple AI agents to collaborate in a shared conversation space to solve complex tasks. Instead of rigid, predefined pipelines, GroupChat enables dynamic, multi-turn discussions where agents with different roles, tools, and expertise can interact naturally to arrive at better solutions.

What Is AutoGen GroupChat?

At its core, GroupChat is a conversation manager that hosts multiple agents in a single chat thread. Each agent can be a different AI model, have access to different tools, or be assigned a specific role (like a planner, critic, coder, or reviewer). The GroupChat manager orchestrates the flow by selecting which agent speaks next based on configurable rules, allowing for emergent collaboration patterns that often outperform single-agent approaches.

Key components of the GroupChat architecture include:

Why GroupChat Matters

Single-agent systems often struggle with complex, multi-step tasks that require diverse skills. A coding agent might write great code but miss edge cases; a reviewer agent catches bugs but can't execute fixes. GroupChat solves this by enabling:

This pattern shines in scenarios like complex software development, data analysis pipelines, creative writing with editing rounds, and multi-step research tasks where different perspectives lead to more robust outcomes.

Setting Up a Basic GroupChat

Let's walk through a complete example of setting up a GroupChat with three agents: a Planner, a Coder, and a Reviewer. This team will collaboratively solve a programming task.

Step 1: Install AutoGen

pip install pyautogen

Step 2: Configure the LLM

Create a configuration for your LLM endpoint. Here we use OpenAI, but AutoGen supports many providers.

import autogen

config_list = [
    {
        "model": "gpt-4",
        "api_key": "your-openai-api-key-here",
        "temperature": 0.7,
    }
]

Step 3: Define Specialized Agents

Each agent gets a distinct system message that defines its role, personality, and constraints. The Planner strategizes, the Coder implements, and the Reviewer critiques.

planner = autogen.AssistantAgent(
    name="Planner",
    system_message="""You are a senior software architect and task planner.
Your role is to:
1. Analyze the user's request carefully
2. Break down complex tasks into clear, actionable steps
3. Propose a high-level plan before any code is written
4. Delegate coding tasks to the Coder agent with precise specifications
5. Do NOT write code yourself — focus on planning and coordination
When the task is complete, say 'PLAN_COMPLETE' to signal readiness for review.""",
    llm_config={"config_list": config_list},
)

coder = autogen.AssistantAgent(
    name="Coder",
    system_message="""You are an expert Python developer.
Your role is to:
1. Receive specifications from the Planner
2. Write clean, well-documented, production-quality Python code
3. Include error handling and edge case coverage
4. Provide complete, runnable code blocks (not fragments)
5. Explain your implementation choices briefly
Only write code when the Planner has given you a clear specification.
When finished, say 'CODE_COMPLETE'.""",
    llm_config={"config_list": config_list},
)

reviewer = autogen.AssistantAgent(
    name="Reviewer",
    system_message="""You are a meticulous code reviewer and quality assurance specialist.
Your role is to:
1. Review all code produced by the Coder
2. Check for bugs, security issues, performance problems, and style violations
3. Verify that the code matches the Planner's specification
4. Suggest concrete improvements
5. If code passes review, say 'APPROVED' and summarize what was accomplished
6. If issues are found, clearly list them so the Coder can fix them""",
    llm_config={"config_list": config_list},
)

Step 4: Create the GroupChat and Manager

The GroupChat holds all agents and the message history. The GroupChatManager orchestrates the conversation using a speaker selection function.

from autogen import GroupChat, GroupChatManager

# Create the group chat with all participating agents
group_chat = GroupChat(
    agents=[planner, coder, reviewer],
    messages=[],  # Will be populated as the conversation proceeds
    max_round=15,  # Safety limit to prevent infinite loops
    speaker_selection_method="auto",  # LLM-based speaker selection
    allow_repeat_speaker=True,  # Allow the same agent to speak consecutively if needed
)

# Create the manager that orchestrates the conversation
manager = GroupChatManager(
    groupchat=group_chat,
    llm_config={"config_list": config_list},
)

Step 5: Initiate the Conversation

A user proxy agent represents the human user and initiates the task. It can also execute code on behalf of agents when needed.

user_proxy = autogen.UserProxyAgent(
    name="User",
    system_message="You are the human user with the ability to execute Python code.",
    code_execution_config={"work_dir": "coding_workspace", "use_docker": False},
    human_input_mode="NEVER",  # Fully automated; set to "TERMINATE" for human approval at end
)

# Start the group chat with a task
user_proxy.initiate_chat(
    manager,
    message="""
I need a Python script that:
1. Fetches data from a public API (https://api.github.com/repos/microsoft/autogen)
2. Parses the JSON response to extract: repo name, star count, open issues count, and primary language
3. Saves the extracted data to a local CSV file
4. Includes proper error handling for network failures and invalid responses
Please plan, code, and review this solution.
""",
)

Custom Speaker Selection Strategies

The default "auto" speaker selection uses an LLM to decide who speaks next, but you can implement custom logic for more control. Here are three common patterns:

Pattern 1: Strict Turn-Based Rotation

Useful when you want a predictable, pipeline-like flow (Planner → Coder → Reviewer → repeat).

def rotation_speaker_selection(last_speaker, group_chat):
    """Rotate through agents in a fixed order."""
    agents = group_chat.agents
    # Define the rotation order
    order = ["Planner", "Coder", "Reviewer"]
    # Find the index of the last speaker
    try:
        last_index = order.index(last_speaker.name) if last_speaker else -1
    except ValueError:
        last_index = -1
    # Pick the next agent in rotation
    next_index = (last_index + 1) % len(order)
    return agents[group_chat.agent_names.index(order[next_index])]

group_chat = GroupChat(
    agents=[planner, coder, reviewer],
    messages=[],
    max_round=15,
    speaker_selection_method=rotation_speaker_selection,
)

Pattern 2: Role-Based Conditional Selection

Route messages based on content signals like "CODE_COMPLETE" or "APPROVED".

def conditional_speaker_selection(last_speaker, group_chat):
    """Select next speaker based on the content of the last message."""
    if last_speaker is None:
        return group_chat.agents_by_name("Planner")
    
    last_message = group_chat.messages[-1]["content"] if group_chat.messages else ""
    
    # After planning, route to coder
    if "PLAN_COMPLETE" in last_message and last_speaker.name == "Planner":
        return group_chat.agents_by_name("Coder")
    # After coding, route to reviewer
    elif "CODE_COMPLETE" in last_message and last_speaker.name == "Coder":
        return group_chat.agents_by_name("Reviewer")
    # If approved, stop or route back to user
    elif "APPROVED" in last_message:
        return None  # End conversation
    # If reviewer found issues, send back to coder
    elif last_speaker.name == "Reviewer" and "APPROVED" not in last_message:
        return group_chat.agents_by_name("Coder")
    # Default: planner decides next steps
    else:
        return group_chat.agents_by_name("Planner")

group_chat = GroupChat(
    agents=[planner, coder, reviewer],
    messages=[],
    max_round=15,
    speaker_selection_method=conditional_speaker_selection,
)

Pattern 3: LLM-Based with Constraints

Use an LLM for nuanced decisions but restrict which agents are eligible based on context.

def constrained_llm_selection(last_speaker, group_chat):
    """Use LLM selection but restrict eligible speakers."""
    # After the coder speaks, only the reviewer or planner can speak next
    if last_speaker and last_speaker.name == "Coder":
        eligible = ["Reviewer", "Planner"]
        # Use a helper to pick among eligible agents via LLM
        return autogen.speaker_selection.message_speaker_selection(
            last_speaker, group_chat, eligible_agents=eligible
        )
    # Otherwise use default auto selection
    return "auto"

group_chat = GroupChat(
    agents=[planner, coder, reviewer],
    messages=[],
    max_round=15,
    speaker_selection_method=constrained_llm_selection,
)

Advanced GroupChat Features

Integrating Tool-Using Agents

You can give specific agents access to tools like code execution, web search, or database queries. Here's how to equip the Coder with code execution capability:

coder_with_tools = autogen.AssistantAgent(
    name="Coder",
    system_message="""You are an expert Python developer with code execution abilities.
Write complete Python scripts and use the code_execution tool to run and verify them.""",
    llm_config={"config_list": config_list},
    code_execution_config={
        "work_dir": "coding_workspace",
        "use_docker": False,
        "timeout": 60,
    },
)

# The user proxy can also execute code requested by agents
user_proxy_with_exec = autogen.UserProxyAgent(
    name="CodeExecutor",
    system_message="You execute Python code and return results.",
    code_execution_config={"work_dir": "coding_workspace", "use_docker": False},
    human_input_mode="NEVER",
)

Adding a Critic with Different Model

Use a different, potentially more capable model for the reviewer to provide higher-quality feedback:

reviewer_config_list = [
    {
        "model": "gpt-4-turbo",
        "api_key": "your-openai-api-key-here",
        "temperature": 0.2,  # Lower temperature for more consistent reviews
    }
]

expert_reviewer = autogen.AssistantAgent(
    name="ExpertReviewer",
    system_message="""You are an elite code reviewer powered by GPT-4 Turbo.
Provide deep, insightful feedback on code quality, architecture, and best practices.""",
    llm_config={"config_list": reviewer_config_list},
)

Nested GroupChats for Complex Workflows

For very complex tasks, you can nest a GroupChat inside another agent's logic. For example, a research agent could spawn a sub-group-chat for literature review:

research_sub_team = GroupChat(
    agents=[researcher_agent, fact_checker_agent, synthesizer_agent],
    messages=[],
    max_round=8,
    speaker_selection_method="auto",
)

def research_orchestrator_logic(agent, messages):
    """Custom agent that spawns a sub-group-chat for research tasks."""
    sub_manager = GroupChatManager(groupchat=research_sub_team, llm_config=config_list)
    # Run the sub-chat and collect results
    result = user_proxy.initiate_chat(sub_manager, message=messages[-1]["content"])
    return True, f"Research complete. Findings: {result}"

research_orchestrator = autogen.AssistantAgent(
    name="ResearchOrchestrator",
    system_message="You coordinate research sub-teams.",
    llm_config={"config_list": config_list},
)

Best Practices for GroupChat

Complete Working Example

Here's a fully self-contained script that implements a Planner-Coder-Reviewer GroupChat. Save it as groupchat_demo.py and run it with your API key.

import autogen
from autogen import GroupChat, GroupChatManager

# ---------- CONFIGURATION ----------
config_list = [
    {
        "model": "gpt-4",
        "api_key": "sk-YOUR-API-KEY-HERE",
        "temperature": 0.7,
    }
]

# ---------- AGENT DEFINITIONS ----------
planner = autogen.AssistantAgent(
    name="Planner",
    system_message="""You are a senior software architect.
Your job: analyze the task, create a step-by-step plan, delegate to the Coder.
Never write code. End your turn with PLAN_COMPLETE when the plan is ready.""",
    llm_config={"config_list": config_list},
)

coder = autogen.AssistantAgent(
    name="Coder",
    system_message="""You are an expert Python developer.
Write complete, runnable Python scripts based on the Planner's specification.
Include error handling, comments, and edge case handling.
End your turn with CODE_COMPLETE when done.""",
    llm_config={"config_list": config_list},
)

reviewer = autogen.AssistantAgent(
    name="Reviewer",
    system_message="""You are a thorough code reviewer.
Check the code against the plan. Look for bugs, security issues, and style problems.
If the code passes, say APPROVED and summarize.
If it fails, list specific issues for the Coder to fix.""",
    llm_config={"config_list": config_list, "temperature": 0.2},
)

user_proxy = autogen.UserProxyAgent(
    name="User",
    code_execution_config={"work_dir": "workspace", "use_docker": False},
    human_input_mode="NEVER",
)

# ---------- SPEAKER SELECTION ----------
def smart_speaker_selection(last_speaker, group_chat):
    """Route based on conversation signals."""
    if last_speaker is None:
        return group_chat.agents_by_name("Planner")
    last_msg = group_chat.messages[-1]["content"]
    name = last_speaker.name
    if "PLAN_COMPLETE" in last_msg and name == "Planner":
        return group_chat.agents_by_name("Coder")
    elif "CODE_COMPLETE" in last_msg and name == "Coder":
        return group_chat.agents_by_name("Reviewer")
    elif "APPROVED" in last_msg:
        return None  # Stop the conversation
    elif name == "Reviewer" and "APPROVED" not in last_msg:
        return group_chat.agents_by_name("Coder")
    else:
        return group_chat.agents_by_name("Planner")

# ---------- GROUP CHAT SETUP ----------
group_chat = GroupChat(
    agents=[planner, coder, reviewer],
    messages=[],
    max_round=20,
    speaker_selection_method=smart_speaker_selection,
    allow_repeat_speaker=True,
)

manager = GroupChatManager(
    groupchat=group_chat,
    llm_config={"config_list": config_list},
)

# ---------- LAUNCH ----------
task = """
Create a Python script that:
1. Connects to a SQLite database (create it if it doesn't exist)
2. Creates a table 'employees' with columns: id, name, department, salary
3. Inserts 5 sample employee records
4. Queries and prints all employees in the 'Engineering' department
5. Calculates and prints the average salary across all employees
Use proper error handling and close database connections cleanly.
"""

user_proxy.initiate_chat(manager, message=task)

Handling Errors and Edge Cases

GroupChat conversations can encounter several failure modes. Here's how to handle them robustly:

import logging

# Enable detailed logging to debug conversation flow
logging.basicConfig(level=logging.INFO)
autogen.logging.basicConfig(level=autogen.logging.INFO)

# Wrap the conversation in try/except
try:
    result = user_proxy.initiate_chat(
        manager,
        message="Your complex task here",
        max_turns=30,  # Additional safety limit on total turns
    )
except Exception as e:
    print(f"GroupChat failed: {e}")
    # Fallback: extract partial results from group_chat.messages
    partial_output = group_chat.messages
    print(f"Partial conversation saved with {len(partial_output)} messages")
    # You can parse partial_output for any usable artifacts

Conclusion

AutoGen GroupChat transforms AI agent systems from single-prompt interactions into rich, collaborative multi-agent workflows. By assigning specialized roles, implementing thoughtful speaker selection strategies, and following best practices around agent design and conversation limits, you can build systems that plan, execute, critique, and refine — producing outputs that are more robust, more accurate, and more nuanced than any single agent could achieve alone. Start with simple configurations, observe the emergent behaviors, and iteratively refine your agent team. The patterns you develop will form the backbone of sophisticated AI-powered automation pipelines.

— Ad —

Google AdSense will appear here after approval

← Back to all articles