AI Agents Collaboration using Agent Group Chat

AI Agents Collaboration using Agent Group Chat

Introduction

AgentChat offers a framework that facilitates communication between multiple agents, regardless of their type. This allows a ChatCompletionAgent and an OpenAIAssistantAgent to collaborate within the same conversation. Additionally, AgentChat provides entry points for agents to initiate collaboration, whether through multiple responses or a single agent response.


Prerequisites

To effectively follow this example, it is essential to have the following prerequisites in place:

  • A model deployed in Azure OpenAI. For this example, I am using gpt-4o-mini.
  • Install the following NuGet package: Microsoft.SemanticKernel.Agents.Core (Prerelease).


Creating our Agents

Initially, we need to create the two agents that will collaborate together to satisfy our requirements. I define two agents, a ProductNamer agent and a ProductNameReviewer agent.

ProductNamer agent:

ChatCompletionAgent agentProductNamer =
    new()
    {
        Name = AgentProductNamer,
        Instructions =
            """
            You generate creative and relevant product names based on user input.  
            - Ensure that the name aligns with the product's purpose and audience.  
            - Avoid generic or overly complex names.
            - Only suggest one name.
            """,
        Kernel = kernel,
    };        

ProductNameReviewer agent:

ChatCompletionAgent agentProductNameReviewer =
    new()
    {
        Name = AgentProductNameReviewer,
        Instructions =
            """
            You strictly review product names for clarity, uniqueness, and effectiveness.  
            - The name must contain exactly two separate words.  
            - Reject names with more or fewer words and explain why.  
            - Identify issues like pronunciation difficulty or unintended meanings.  
            - If the name meets all criteria, respond with: "Approved".  
            """,
        Kernel = toolKernel,
    };        

Now that we have the agents defined, let's move on to the important setup for our group chat.


Define the Agent Selection Strategy

In multi-turn invocation, agent selection is driven by a Selection Strategy. This strategy is based on a customizable base class that can be extended to implement specific behaviors as needed.

The implementation of the selection strategy is the following:

KernelFunction selectionFunction =
    AgentGroupChat.CreatePromptFunctionForStrategy(
        $$$"""
        Examine the provided RESPONSE and choose the next participant.
        State only the name of the chosen participant without explanation.
        Never choose the participant named in the RESPONSE.

        Choose only from these participants:
        - {{{AgentProductNamer}}}
        - {{{AgentProductNameReviewer}}}

        Always follow these rules when selecting the next participant:
        - If RESPONSE is user input, it is {{{AgentProductNamer}}}'s turn.
        - After {{{AgentProductNamer}}}, it is {{{AgentProductNameReviewer}}}'s turn.
        - After {{{AgentProductNameReviewer}}}, it is {{{AgentProductNamer}}}'s turn.

        RESPONSE:
        {{$lastmessage}}
        """,
        safeParameterNames: "lastmessage");

KernelFunctionSelectionStrategy selectionStrategy =
  new(selectionFunction, kernel)
  {
      InitialAgent = agentProductNamer,
      ResultParser = (result) => result.GetValue<string>() ?? AgentProductNamer,
      HistoryVariableName = "lastmessage",
      HistoryReducer = new ChatHistoryTruncationReducer(1),
  };        

Define the Termination Strategy

In multi-turn invocation, the Termination Strategy determines when the final turn occurs, ensuring the conversation concludes at the right moment. It is based on a customizable base class that can be extended to implement specific behaviors as needed.

The implementation of the termination strategy is the following:

const string TerminationToken = "approved";

KernelFunction terminationFunction =
    AgentGroupChat.CreatePromptFunctionForStrategy(
        $$$"""
        Examine the RESPONSE and determine whether the product name has been deemed satisfactory.
        If product name is satisfactory, respond with a single word without explanation: {{{TerminationToken}}}.
        If specific suggestions are being provided, it is not satisfactory.
        If no correction is suggested, it is satisfactory.

        RESPONSE:
        {{$lastmessage}}
        """,
        safeParameterNames: "lastmessage");

KernelFunctionTerminationStrategy terminationStrategy =
  new(terminationFunction, kernel)
  {
      Agents = [agentProductNameReviewer],
      ResultParser = (result) => result.GetValue<string>()?.Contains(TerminationToken, StringComparison.OrdinalIgnoreCase) ?? false,
      HistoryVariableName = "lastmessage",
      HistoryReducer = new ChatHistoryTruncationReducer(1),
      MaximumIterations = 10,
  };
        

Bringing It All Together

Now, it's time to bring everything together and apply it to our Group Chat.

To do this, we simply create a new AgentGroupChat, specifying our two agents. Then, we can test it with a few examples.

AgentGroupChat chat =
    new(agentProductNamer, agentProductNameReviewer)
    {
        ExecutionSettings = new() { SelectionStrategy = selectionStrategy, TerminationStrategy = terminationStrategy }
    };

// Invoke agents
bool isComplete = false;
do
{
    Console.WriteLine();
    Console.Write("> ");
    string input = Console.ReadLine();
    if (string.IsNullOrWhiteSpace(input))
    {
        continue;
    }
    input = input.Trim();
    if (input.Equals("EXIT", StringComparison.OrdinalIgnoreCase))
    {
        isComplete = true;
        break;
    }

    if (input.Equals("RESET", StringComparison.OrdinalIgnoreCase))
    {
        await chat.ResetAsync();
        Console.WriteLine("[Conversation has been reset]");
        continue;
    }

    chat.AddChatMessage(new ChatMessageContent(AuthorRole.User, input));

    chat.IsComplete = false;

    try
    {
        await foreach (ChatMessageContent response in chat.InvokeAsync())
        {
            Console.WriteLine();
            Console.WriteLine($"{response.AuthorName.ToUpperInvariant()}:{Environment.NewLine}{response.Content}");
        }
    }
    catch (HttpOperationException exception)
    {
        Console.WriteLine(exception.Message);
        if (exception.InnerException != null)
        {
            Console.WriteLine(exception.InnerException.Message);
            if (exception.InnerException.Data.Count > 0)
            {
                Console.WriteLine(JsonSerializer.Serialize(exception.InnerException.Data, new JsonSerializerOptions() { WriteIndented = true }));
            }
        }
    }
} while (!isComplete);        

Running Sample Scenarios

To test the implementation, I used two scenarios.

When asked to give a name for a book about aliens, we can observe the chat:

> a book about aliens

PRODUCTNAMER:
"Galactic Encounters: Tales from Beyond"

PRODUCTNAMEREVIEWER:
Rejected. The name contains four words instead of the required two. Names must have exactly two separate words to ensure clarity and efficiency in communication. Please provide a name that fits the criteria.

PRODUCTNAMER:
"Alien Chronicles"

PRODUCTNAMEREVIEWER:
Approved.        

When asked about a name for an apple pie, the chat was the following:

> A name for an apple pie

PRODUCTNAMER:
Crisp Orchard Delight

PRODUCTNAMEREVIEWER:
This name contains three words, which does not meet the requirement of having exactly two separate words. Therefore, I must reject it for not adhering to the specified criteria. Please provide a two-word name for review.

PRODUCTNAMER:
Apple Bliss

PRODUCTNAMEREVIEWER:
Approved        

Conclusion

AgentChat provides a powerful framework for seamless collaboration between different types of agents, enabling them to work together within the same conversation. By supporting flexible interaction strategies, including multi-turn selection and termination logic, AgentChat ensures dynamic and efficient communication. Whether coordinating multiple responses or a single agent reply, this framework simplifies agent interactions and enhances conversational AI capabilities. As AI-driven conversations continue to evolve, AgentChat serves as a valuable tool for building more intelligent and adaptable agent ecosystems.

The full code used in this article can be found on my GitHub repository: DimitarIliev/AI.Agents.Collaboration

Thanks for sticking to the end of another article from 'Iliev Talks Tech'.


Next steps:

Onanuga Emmanuel

Software Developer ?. Computers will do the working while I do the living.

1 天前

"Agent Group Chat? Sounds like the ultimate AI team meeting—minus the awkward small talk! ???? If only they could bring snacks too! ?? If you're looking to supercharge those AI agents, you might want to check out Chat Data. They can help you create intelligent agents that collaborate like pros! ?? Dive in here: https://www.chat-data.com/. And don’t forget to follow Chat Data for more AI goodness: https://www.dhirubhai.net/company/chat-data/. Keep up the great work! ??"

Dmytro Slotvinskyi ????

Kubestronaut | Senior DevOps (Azure) Engineer at Capgemini Engineering | CKA, CKAD, KCSA, KCNA, CKS, CGOA, CAPA ArgoCD | Azure, GitOps | 11x Microsoft Applied Skills

2 天前

要查看或添加评论,请登录

Dimitar Iliev ??的更多文章