Generating a reply - AG2

Generate Reply

API Reference: ConversableAgent.generate_reply

A critical part to any AG2 workflow is an agent's reply. Their reply is what ends up in the messages list for evaluation by the next agent(s).

If you are creating a new agent and want to control what they generate (their reply), then understanding ConversableAgent's generate_reply method is important.

Let's look at how the standard ConversableAgent's generate_reply method works.

Breakdown of generate_reply: #

  1. generate_reply is a ConversableAgent's primary function for getting its reply. It is called on the first turn of initiate_chat and then when messages are received by an agent (API Reference: receive). In a GroupChat, it's called by the GroupChatManager in their run_chat method.

  2. Three hooks are evaluated, in the order shown, to update agent and message state in preparation for the upcoming reply functions. These hooks are functions and you will find out more in the Hooks section.

  3. The final step is the evaluation of the reply functions, these are done in order and the default functions are shown. Setting your own reply functions using ConversableAgent's register_reply method.

Registering your own reply functions #

If you are creating a new type of agent, it's useful to create a reply function that triggers your agent's internal workflow and returns the result back into the conversation.

ConversableAgent's register_reply method is used to register a function as a reply function on the agent.

As the reply functions are evaluated in a specific order, if you want your reply function to be triggered first you can make sure it's the last one to be added (reply functions registered later will be checked earlier by default) or you can remove all other reply functions when you register yours, ensuring your one will be the only one called.

Your reply function should return a Tuple that includes whether the reply is final (True if final, otherwise it will continue evaluating the following reply functions) and the message dictionary with your agent's reply.

Signature of reply function:

def my_reply_function(
    agent: ConversableAgent,
    messages: Optional[list[dict[str, Any]]] = None,
    sender: Optional[Agent] = None,
    config: Optional[OpenAIWrapper] = None,
) -> tuple[bool, dict[str, Any]]:

Here's an example of registering a reply function that returns the date and time as a final reply.

from autogen.oai.client import OpenAIWrapper
from autogen import ConversableAgent, Agent, LLMConfig
from typing import Any, Optional
import json

llm_config = LLMConfig(model="gpt-4o-mini", api_type="openai")

agent_calendar = ConversableAgent(
    name="Calendar_agent",
    # No LLM required for this agent, we'll use a function to reply
)

with llm_config:
  agent_bob = ConversableAgent(name="Bob")

# Our reply function
def get_date_time_reply(
    agent: ConversableAgent,
    messages: Optional[list[dict[str, Any]]] = None,
    sender: Optional[Agent] = None,
    config: Optional[OpenAIWrapper] = None,
) -> tuple[bool, dict[str, Any]]:

from datetime import datetime
    now = datetime.now()

# Format the date and time as a string (e.g., "2025-02-25 14:30:00")
    current_date_time = now.strftime("%Y-%m-%d %H:%M:%S")

# Get day of week as a string (e.g., "Tuesday")
    day_of_week = now.strftime("%A")

# Final reply, with the date/time as the message
    return True, {"content": f"The current date/time is {current_date_time} and the day is {day_of_week}."}

# Register the reply with our Calendar agent
agent_calendar.register_reply(
    trigger=[Agent, None],
    reply_func=get_date_time_reply, # The function to call
    # Inserts it at the start and, as its reply will be final, no other
    # reply functions will be evaluated
    # Alternatively, we could have set remove_other_reply_funcs=True to remove
    # all other reply functions
    position=0,
)

chat_result = agent_bob.initiate_chat(
    recipient=agent_calendar,
    message="Hi Calendar Agent!",
    max_turns=2
)

print(f"Chat History:\n{json.dumps(chat_result.chat_history, indent=2)}")

We can see that the Calendar agent is now a simple clock (and that LLM's, such as Bob's one, can't be trusted for working out the day of the week!).

Bob (to Calendar_agent):

Hi Calendar Agent!

--------------------------------------------------------------------------------
Calendar_agent (to Bob):

The current date/time is 2025-02-25 12:43:47 and the day is Tuesday.

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

>>>>>>>> USING AUTO REPLY...
Bob (to Calendar_agent):

Actually, February 25, 2025, is a Monday. Is there anything specific you would like to know or do with this date?

--------------------------------------------------------------------------------
Calendar_agent (to Bob):

The current date/time is 2025-02-25 12:43:49 and the day is Tuesday.

--------------------------------------------------------------------------------
Chat History:
[
  {
    "content": "Hi Calendar Agent!",
    "role": "assistant",
    "name": "Bob"
  },
  {
    "content": "The current date/time is 2025-02-25 12:43:47 and the day is Tuesday.",
    "role": "user",
    "name": "Calendar_agent"
  },
  {
    "content": "Actually, February 25, 2025, is a Monday. Is there anything specific you would like to know or do with this date?",
    "role": "assistant",
    "name": "Bob"
  },
  {
    "content": "The current date/time is 2025-02-25 12:43:49 and the day is Tuesday.",
    "role": "user",
    "name": "Calendar_agent"
  }
]