Agent Orchestration: Coordinating Multiple Agents - AG2

Agent Orchestration: Coordinating Multiple Agents

In our financial compliance example, we've successfully implemented a human-in-the-loop agent that processes transactions and flags suspicious ones for human approval. This works well for basic compliance checking, but what if we need to provide detailed summary reports after all transactions are processed?

We could expand the system message of our finance_bot to include this functionality, but this approach isn't scalable as requirements grow more complex. The finance_bot would have multiple responsibilities, making it harder to maintain and extend.

The Need for Specialized Agents

As our financial compliance system evolves, we might need to:

Each of these tasks requires different specialized knowledge and skills. This is where AG2's orchestration patterns come in - they allow us to coordinate multiple specialized agents to work together seamlessly.

Introducing the Group Chat Pattern

AG2 offers several orchestration patterns, and for our evolving financial compliance system, the Group Chat pattern is particularly powerful. It allows specialized agents to collaborate with dynamic handoffs to achieve complex workflows.

An Analogy for Group Chat Pattern:

Continuing our hospital treatment system analogy from the HITL. Think of the Group Chat pattern like a hospital emergency in the hospital:

This pattern leverages specialized skills while maintaining a cohesive workflow across multiple participants, with both direct handoffs and intelligent coordination when needed.

From Concept to Implementation

Implementing a group chat in AG2 is a simple two-step process:

The pattern defines the orchestration logic - which agents are involved, who speaks first, and how to transition between agents. AG2 provides several pre-defined patterns to choose from:

The easiest pattern to get started with is the AutoPattern, where a group manager agent automatically selects agents to speak by evaluating the messages in the chat and the descriptions of the agents. This creates a natural workflow where the most appropriate agent responds based on the conversation context.

Here's how you implement a basic group chat:

from autogen import ConversableAgent, LLMConfig
from autogen.agentchat import initiate_group_chat
from autogen.agentchat.group.patterns import AutoPattern

# build a Config List
llm_config = LLMConfig(
    config_list={
        "api_type": "openai",
        "model": "gpt-5-nano",
        "api_key": os.environ.get("OPENAI_API_KEY"),
    }
)

# Create your specialized agents
agent_1 = ConversableAgent(name="agent_1", llm_config=llm_config, system_message="goto agent_2")
agent_2 = ConversableAgent(name="agent_2", llm_config=llm_config, system_message="go back to agent_1")

# Create human agent if needed
human = ConversableAgent(name="human", human_input_mode="ALWAYS")

# Set up the pattern for orchestration
pattern = AutoPattern(
    initial_agent=agent_1,              # Agent that starts the workflow
    agents=[agent_1, agent_2],          # All agents in the group chat
    user_agent=human,                   # Human agent for interaction
    group_manager_args={"llm_config": llm_config}  # Config for group manager
)

# Initialize the group chat
result, context_variables, last_agent = initiate_group_chat(
    pattern=pattern,
    messages="Initial request",         # Starting message
)

Enhancing Our Financial Compliance System with Group Chat

Now that we understand the group chat pattern, let's see how it solves our challenge of adding specialized summary reporting to our financial compliance system.

The Challenge

In our Human in the Loop example, we built a finance_bot that could process transactions and get human approval for suspicious ones. However, we now need professional, formatted summary reports of all the transactions.

Our Group Chat Solution

Here's how we'll enhance our system:

Implementation: Creating the Necessary Agents

Let's create a new specialized agent for generating summary reports. We'll also keep our existing finance_bot for transaction processing and a human agent for oversight.

from autogen import ConversableAgent, LLMConfig
from autogen.agentchat import initiate_group_chat
from autogen.agentchat.group.patterns import AutoPattern

import os
import random
from dotenv import load_dotenv

load_dotenv()

# Note: Make sure to set your API key in your environment first

# Build a LLM Config List
llm_config = LLMConfig(
    config_list={
        "api_type": "openai",
        "model": "gpt-5-nano",
        "api_key": os.environ.get("OPENAI_API_KEY"),
    }
)

# Define the system message for our finance bot
finance_system_message = """
You are a financial compliance assistant. You will be given a set of transaction descriptions.
For each transaction:
- If it seems suspicious (e.g., amount > $10,000, vendor is unusual, memo is vague), ask the human agent for approval.
- Otherwise, approve it automatically.
Provide the full set of transactions to approve at one time.
If the human gives a general approval, it applies to all transactions requiring approval.
When all transactions are processed, summarize the results and say "You can type exit to finish".
"""

# Define the system message for the summary agent
summary_system_message = """
You are a financial summary assistant. You will be given a set of transaction details and their approval status.
Your task is to summarize the results of the transactions processed by the finance bot.
Generate a markdown table with the following columns:
- Vendor
- Memo
- Amount
- Status (Approved/Rejected)
The summary should include the total number of transactions, the number of approved transactions, and the number of rejected transactions.
The summary should be concise and clear.
"""

# Create the finance agent with LLM intelligence
finance_bot = ConversableAgent(
    name="finance_bot",
    llm_config=llm_config,
    system_message=finance_system_message,
)
summary_bot = ConversableAgent(
    name="summary_bot",
    llm_config=llm_config,
    system_message=summary_system_message,
)

# Create the human agent for oversight
human = ConversableAgent(
    name="human",
    human_input_mode="ALWAYS",
)

# Generate sample transactions - this creates different transactions each time you run
VENDORS = ["Staples", "Acme Corp", "CyberSins Ltd", "Initech", "Globex", "Unicorn LLC"]
MEMOS = ["Quarterly supplies", "Confidential", "NDA services", "Routine payment", "Urgent request", "Reimbursement"]

def generate_transaction():
    amount = random.choice([500, 1500, 9999, 12000, 23000, 4000])
    vendor = random.choice(VENDORS)
    memo = random.choice(MEMOS)
    return f"Transaction: ${amount} to {vendor}. Memo: {memo}."

# Generate 3 random transactions
transactions = [generate_transaction() for _ in range(3)]

# Format the initial message
initial_prompt = (
    "Please process the following transactions one at a time:\n\n" +
    "\n".join([f"{i+1}. {tx}" for i, tx in enumerate(transactions)])
)

# Create pattern for the group chat
pattern = AutoPattern(
    initial_agent=finance_bot,                   # Start with the finance bot
    agents=[finance_bot, summary_bot],           # All agents in the group chat
    user_agent=human,                            # Provide our human-in-the-loop agent
    group_manager_args={"llm_config": llm_config}  # Config for group manager
)

# Initialize the group chat
result, context_variables, last_agent = initiate_group_chat(
    pattern=pattern,
    messages=initial_prompt,                     # Initial request with transactions
)