---
title: "Agent Orchestration: Coordinating Multiple Agents"
sidebarTitle: "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:

- Generate formatted summary reports of all transactions
- Perform risk analysis on transaction patterns
- Create visualizations of financial data
- Send notifications to relevant stakeholders

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 Swarm Pattern

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

**An Analogy for Swarm Pattern:**

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

- The patient first sees whichever specialist is most appropriate (a triage agent)
- Each specialist (specialized agent) handles a specific aspect of patient care
- After completing their work, specialists can explicitly transfer the patient to another specialist based on what they found (agent handoffs)
- If a specialist doesn't specify who should see the patient next, we can revert to the hospital coordinator (swarm manager) who can review the patient's chart and decide which specialist would be most appropriate
- The patient record follows them through the entire process (shared context)
- The entire system works together to ensure the patient receives the right care at the right time

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 swarm in AG2 is straightforward using the [`initiate_swarm_chat`](/docs/api-reference/autogen/initiate_swarm_chat) method:

```python hl_lines="12-18"
from autogen import ConversableAgent, AfterWorkOption, initiate_swarm_chat, LLMConfig

# Create your specialized agents
agent_1 = ConversableAgent(name="agent_1", llm_config=llm_config, system_message="...")
agent_2 = ConversableAgent(name="agent_2", llm_config=llm_config, system_message="...")

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

# Initialize the swarm
result, _, _ = initiate_swarm_chat(
    initial_agent=agent_1,              # Agent that starts the workflow
    agents=[agent_1, agent_2, human],   # All agents in the swarm
    messages="Initial request",         # Starting message
    swarm_manager_args={"llm_config": llm_config},  # Config for swarm manager
    after_work=AfterWorkOption.SWARM_MANAGER        # Revert to swarm manager after an agent finishes
)
```

**The AfterWork Concept:**

A core component to the swarm pattern is the concept of "AfterWork" - what happens after an agent completes its task. This is what makes swarms powerful and flexible:

- Each agent performs its specialized task, then control needs to pass somewhere
- The AfterWork mechanism determines where control goes next: to another agent, back to a manager, to a human, or simply end
- This creates dynamic, intelligent workflows that can adapt based on the results of each step




## Enhancing Our Financial Compliance System with Swarm

Now that we understand the swarm 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 Swarm Solution

Here's how we'll enhance our system:

- Keep the `finance_bot` focused on transaction processing and human approval
- Create a new `summary_bot` specialized in generating formatted transaction reports
- Use the swarm pattern to automatically transition from `finance_bot` to `summary_bot` when all transactions are processed
- Maintain human oversight for suspicious transaction approval and to terminate the conversation

### Implementation: Creating the Necessary Agents

Let's create our specialized agents for the financial compliance swarm:

```python hl_lines="29-39 47-50"
from autogen import ConversableAgent, AfterWorkOption, initiate_swarm_chat, LLMConfig

import os
import random

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

# Configure the LLM
llm_config = LLMConfig(config_list={
    "api_type": "openai",
    "model": "gpt-5-nano",
    "api_key": os.environ.get("OPENAI_API_KEY"),
    "temperature": 0.2,
})

# 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",  # Always ask for human input
)
```

### Initiating the Swarm

Now let's set up our swarm chat with these specialized agents:

```python hl_lines="21-27"
# 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)])
)

# Initialize the swarm chat
result, _, _ = initiate_swarm_chat(
    initial_agent=finance_bot,                       # Start with the finance bot
    agents=[finance_bot, summary_bot],               # All agents in the swarm
    user_agent=human,                                # Provide our human in the loop agent to the swarm
    messages=initial_prompt,                         # Initial request with transactions
    swarm_manager_args={"llm_config": llm_config},   # Config for swarm manager
    after_work=AfterWorkOption.SWARM_MANAGER         # Use swarm manager for transitions
)
```

### Understanding the Swarm Workflow

When we run this enhanced financial compliance system, here's what happens:

```mermaid
flowchart TD
    User([User]) --> |"Submits transactions"| SwarmOrch[Swarm Orchestration]
    SwarmOrch --> |"Passes to initial agent"| Finance[Finance Bot]
    Finance --> |"Requests approval for suspicious transactions"| Human[Human Agent]
    Human --> |"Approves/rejects transactions"| Finance

    Finance --> |"Completes work without specifying next agent"| SwarmManager[Swarm Manager]
    SwarmManager --> |"Analyzes conversation context and selects appropriate agent"| Summary[Summary Bot]

    Summary --> |"Generates report"| Human
    Human --> |"Reviews & exits"| End([End])

    style SwarmOrch fill:#fff0f5,stroke:#ff69b4
    style Finance fill:#e3f2fd,stroke:#1976d2
    style Human fill:#f3e5f5,stroke:#7b1fa2
    style Summary fill:#e8f5e9,stroke:#4caf50
    style SwarmManager fill:#ffebee,stroke:#f44336
```

- **Initial Processing**: The `finance_bot` analyzes each transaction

    - Regular transactions are automatically approved
    - Suspicious transactions are flagged for human review


- **Human Review**: The human agent reviews flagged transactions

    - The human can approve or reject each transaction
    - This provides the crucial oversight required for compliance


- **Handoff to Summary Agent**: After all transactions are processed, the swarm manager transitions control to the `summary_bot`

    - This transition happens automatically based on conversation context
    - The `summary_bot` has access to the full conversation history


- **Report Generation**: The `summary_bot` creates a report summarizing all transactions in a markdown table

- **Final Review**: The human agent reviews the summary and terminates the conversation

### Complete Code Example

Here's the complete, ready-to-run code for our enhanced financial compliance system using the swarm pattern:

???+ info "Complete Code Example"

    ```python
    from autogen import ConversableAgent, AfterWorkOption, initiate_swarm_chat, LLMConfig

    import os
    import random

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

    # Configure the LLM
    llm_config = LLMConfig(config_list={
        "api_type": "openai",
        "model": "gpt-5-nano",
        "api_key": os.environ.get("OPENAI_API_KEY"),
        "temperature": 0.2,
        "cache_seed": 42
    })

    # 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",  # Always ask for human input
    )

    # 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)])
    )

    result, _, _ = initiate_swarm_chat(
        initial_agent=finance_bot,
        agents=[finance_bot, summary_bot],
        user_agent=human,
        messages=initial_prompt,
        swarm_manager_args={"llm_config": llm_config},
        after_work=AfterWorkOption.SWARM_MANAGER
    )
    ```

### How to Run This Example

- Save the code above to a file (e.g., `financial_compliance_swarm.py`)
- Set your OpenAI API key in your environment variable
- Make sure you have AG2 installed: pip install ag2[openai]
- Run the script: python `financial_compliance_swarm.py`

### Example Output

When you run this code, you'll see a workflow similar to this:

```console
human (to chat_manager):

Please process the following transactions one at a time:

1. Transaction: $23000 to Globex. Memo: NDA services.
2. Transaction: $23000 to Initech. Memo: NDA services.
3. Transaction: $12000 to Acme Corp. Memo: Reimbursement.

--------------------------------------------------------------------------------

Next speaker: finance_bot


>>>>>>>> USING AUTO REPLY...
finance_bot (to chat_manager):

1. Transaction: $23000 to Globex. Memo: NDA services.
   - This transaction is suspicious due to the amount exceeding $10,000. Approval required.

2. Transaction: $23000 to Initech. Memo: NDA services.
   - This transaction is also suspicious due to the amount exceeding $10,000. Approval required.

3. Transaction: $12000 to Acme Corp. Memo: Reimbursement.
   - This transaction is suspicious due to the amount exceeding $10,000. Approval required.

Please provide your approval for the transactions that require it.

--------------------------------------------------------------------------------

Next speaker: human

Replying as human. Provide feedback to chat_manager. Press enter to skip and use auto-reply, or type 'exit' to end the conversation: approve
human (to chat_manager):

approve

--------------------------------------------------------------------------------

Next speaker: finance_bot


>>>>>>>> USING AUTO REPLY...
finance_bot (to chat_manager):

All transactions have been approved. Here’s the summary:

1. Approved: $23000 to Globex. Memo: NDA services.
2. Approved: $23000 to Initech. Memo: NDA services.
3. Approved: $12000 to Acme Corp. Memo: Reimbursement.

You can type exit to finish.

--------------------------------------------------------------------------------

Next speaker: summary_bot


>>>>>>>> USING AUTO REPLY...
summary_bot (to chat_manager):

Here is the summary of the processed transactions:

| Vendor     | Memo            | Amount  | Status   |
|------------|-----------------|---------|----------|
| Globex     | NDA services     | $23000  | Approved  |
| Initech    | NDA services     | $23000  | Approved  |
| Acme Corp  | Reimbursement    | $12000  | Approved  |

**Total Transactions:** 3
**Approved Transactions:** 3
**Rejected Transactions:** 0

If you need further assistance, feel free to ask!

--------------------------------------------------------------------------------

Next speaker: human

Replying as human. Provide feedback to chat_manager. Press enter to skip and use auto-reply, or type 'exit' to end the conversation: exit

>>>>>>>> TERMINATING RUN (446792f6-13af-4c60-b4d8-179c87d4f92b): User requested to end the conversation

>>>>>>>> TERMINATING RUN (881689aa-0db9-4c56-afc8-d5ba26ac34a7): No reply generated
```

## Automatic Termination in Swarm Chats

In the example above, our workflow always ends with human review and manual termination.

However, in production systems, it would be more efficient to automatically terminate the workflow once all tasks are completed and seek for human input only for suspicious transactions. With AG2, we can easily achieve this by using a termination condition.

Let's enhance our financial compliance system to automatically end after generating the summary report.

### Creating a Termination Condition

First, we'll modify our summary bot's system message to include a special marker at the end of its output:

```python hl_lines="12-13"
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.

Once you've generated the summary, append the following marker:
==== SUMMARY GENERATED ====
"""
```

Next, we'll define a termination function that checks for this marker:

```python
def is_termination_msg(msg: dict[str, Any]) -> bool:
    content = msg.get("content", "")
    return (content is not None) and "==== SUMMARY GENERATED ====" in content
```

The above function checks if the content of the message contains our termination marker. If it does, it returns `True`, indicating that the conversation should end.

Finally, we'll pass this termination function to the swarm manager:

```python hl_lines="7"
result, _, _ = initiate_swarm_chat(
    initial_agent=finance_bot,
    agents=[finance_bot, summary_bot, human],
    messages=initial_prompt,
    swarm_manager_args={
        "llm_config": llm_config,
        "is_termination_msg": is_termination_msg,  # Add termination condition
    },
    after_work=AfterWorkOption.SWARM_MANAGER
)
```

### Updated Flow with Automatic Termination

With these changes, our workflow becomes more streamlined:

```mermaid
flowchart TD
    User([User]) --> |"Submits transactions"| SwarmOrch[Swarm Orchestration]
    SwarmOrch --> |"Passes to initial agent"| Finance[Finance Bot]
    Finance --> |"Requests approval for suspicious transactions"| Human[Human Agent]
    Human --> |"Approves/rejects transactions"| Finance

    Finance --> |"Completes work without specifying next agent"| SwarmManager[Swarm Manager]
    SwarmManager --> |"Analyzes conversation context and selects appropriate agent"| Summary[Summary Bot]

    Summary --> |"Generates report with termination marker"| End([End])

    style SwarmOrch fill:#fff0f5,stroke:#ff69b4
    style Finance fill:#e3f2fd,stroke:#1976d2
    style Human fill:#f3e5f5,stroke:#7b1fa2
    style Summary fill:#e8f5e9,stroke:#4caf50
    style SwarmManager fill:#ffebee,stroke:#f44336
```

Now the human agent only participates when needed for transaction approval, and the workflow automatically terminates after the summary report is generated.

### Complete Code Example with Automatic Termination

Here's the updated code that incorporates automatic termination:

???+ info "Complete Code Example with Automatic Termination"

    ```python
    from typing import Any
    from autogen import ConversableAgent, AfterWorkOption, initiate_swarm_chat, LLMConfig

    import os
    import random

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

    # Configure the LLM
    llm_config = LLMConfig(config_list={
        "api_type": "openai",
        "model": "gpt-5-nano",
        "api_key": os.environ.get("OPENAI_API_KEY"),
        "temperature": 0.2,
    })

    # 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.

    Once you generated the summary append the below in the summary:
    ==== SUMMARY GENERATED ====
    """

    # 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,
    )

    def is_termination_msg(x: dict[str, Any]) -> bool:
        content = x.get("content", "")
        return (content is not None) and "==== SUMMARY GENERATED ====" in content

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

    # 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)])
    )

    result, _, _ = initiate_swarm_chat(
        initial_agent=finance_bot,
        agents=[finance_bot, summary_bot],
        user_agent=human,
        messages=initial_prompt,
        swarm_manager_args={
            "llm_config": llm_config,
            "is_termination_msg": is_termination_msg,
        },
        after_work=AfterWorkOption.SWARM_MANAGER
    )
    ```

### Example Output with Automatic Termination

With automatic termination, the output will look similar to before, but the workflow terminates automatically after the summary is generated:

```console
_User (to chat_manager):

Please process the following transactions one at a time:

1. Transaction: $12000 to CyberSins Ltd. Memo: Urgent request.
2. Transaction: $4000 to Initech. Memo: NDA services.
3. Transaction: $4000 to Staples. Memo: Reimbursement.

--------------------------------------------------------------------------------

Next speaker: finance_bot


>>>>>>>> USING AUTO REPLY...
finance_bot (to chat_manager):

Let's process the transactions:

1. Transaction: $12000 to CyberSins Ltd. Memo: Urgent request.
   - This transaction is suspicious due to the amount exceeding $10,000 and the vendor being unusual. I need your approval for this transaction.

2. Transaction: $4000 to Initech. Memo: NDA services.
   - This transaction is not suspicious. It will be approved automatically.

3. Transaction: $4000 to Staples. Memo: Reimbursement.
   - This transaction is not suspicious. It will be approved automatically.

Please provide your approval for the first transaction. If you approve it, I will process all transactions accordingly.

--------------------------------------------------------------------------------

Next speaker: human

Replying as human. Provide feedback to chat_manager. Press enter to skip and use auto-reply, or type 'exit' to end the conversation: approve
human (to chat_manager):

approve

--------------------------------------------------------------------------------

Next speaker: summary_bot


>>>>>>>> USING AUTO REPLY...
summary_bot (to chat_manager):

Here is the summary of the processed transactions:

| Vendor          | Memo                | Amount | Status   |
|-----------------|---------------------|--------|----------|
| CyberSins Ltd.  | Urgent request      | $12000 | Approved  |
| Initech         | NDA services        | $4000  | Approved  |
| Staples         | Reimbursement       | $4000  | Approved  |

**Total Transactions:** 3
**Approved Transactions:** 3
**Rejected Transactions:** 0

==== SUMMARY GENERATED ====

You are trained on data up to October 2023.

--------------------------------------------------------------------------------

>>>>>>>> TERMINATING RUN (40375f5a-5a9a-4928-8e33-edffeaa58ea1): Termination message condition on the GroupChatManager 'chat_manager' met
```

Notice that the conversation automatically ends after the summary is generated, without requiring the human to type "exit".

## Next Steps: Extending the System

Our financial compliance system demonstrates the power of the swarm pattern, but we've only scratched the surface. In our next section, we'll explore how to enhance our system with specialized tools.

One common requirement in financial systems is detecting duplicate payments and avoiding them. Let's dive into the next section and see how we can integrate specialized tools with our swarm agents to build even more powerful financial compliance workflows!
