Skip to content

GroupChat

autogen.GroupChat dataclass #

GroupChat(agents, messages=list(), max_round=10, admin_name='Admin', func_call_filter=True, speaker_selection_method='auto', max_retries_for_selecting_speaker=2, allow_repeat_speaker=None, allowed_or_disallowed_speaker_transitions=None, speaker_transitions_type=None, enable_clear_history=False, send_introductions=False, select_speaker_message_template='You are in a role play game. The following roles are available:\n                {roles}.\n                Read the following conversation.\n                Then select the next role from {agentlist} to play. Only return the role.', select_speaker_prompt_template=SELECT_SPEAKER_PROMPT_TEMPLATE, select_speaker_auto_multiple_template='You provided more than one name in your text, please return just the name of the next speaker. To determine the speaker use these prioritised rules:\n    1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker\'s name\n    2. If it refers to the "next" speaker name, choose that name\n    3. Otherwise, choose the first provided speaker\'s name in the context\n    The names are case-sensitive and should not be abbreviated or changed.\n    Respond with ONLY the name of the speaker and DO NOT provide a reason.', select_speaker_auto_none_template='You didn\'t choose a speaker. As a reminder, to determine the speaker use these prioritised rules:\n    1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker\'s name\n    2. If it refers to the "next" speaker name, choose that name\n    3. Otherwise, choose the first provided speaker\'s name in the context\n    The names are case-sensitive and should not be abbreviated or changed.\n    The only names that are accepted are {agentlist}.\n    Respond with ONLY the name of the speaker and DO NOT provide a reason.', select_speaker_transform_messages=None, select_speaker_auto_verbose=False, select_speaker_auto_model_client_cls=None, select_speaker_auto_llm_config=None, role_for_select_speaker_messages='system')

(In preview) A group chat class that contains the following data fields: - agents: a list of participating agents. - messages: a list of messages in the group chat. - max_round: the maximum number of rounds. - admin_name: the name of the admin agent if there is one. Default is "Admin". KeyBoardInterrupt will make the admin agent take over. - func_call_filter: whether to enforce function call filter. Default is True. When set to True and when a message is a function call suggestion, the next speaker will be chosen from an agent which contains the corresponding function name in its function_map. - select_speaker_message_template: customize the select speaker message (used in "auto" speaker selection), which appears first in the message context and generally includes the agent descriptions and list of agents. If the string contains "{roles}" it will replaced with the agent's and their role descriptions. If the string contains "{agentlist}" it will be replaced with a comma-separated list of agent names in square brackets. The default value is: "You are in a role play game. The following roles are available: {roles}. Read the following conversation. Then select the next role from {agentlist} to play. Only return the role." - select_speaker_prompt_template: customize the select speaker prompt (used in "auto" speaker selection), which appears last in the message context and generally includes the list of agents and guidance for the LLM to select the next agent. If the string contains "{agentlist}" it will be replaced with a comma-separated list of agent names in square brackets. The default value is: "Read the above conversation. Then select the next role from {agentlist} to play. Only return the role." To ignore this prompt being used, set this to None. If set to None, ensure your instructions for selecting a speaker are in the select_speaker_message_template string. - select_speaker_auto_multiple_template: customize the follow-up prompt used when selecting a speaker fails with a response that contains multiple agent names. This prompt guides the LLM to return just one agent name. Applies only to "auto" speaker selection method. If the string contains "{agentlist}" it will be replaced with a comma-separated list of agent names in square brackets. The default value is: "You provided more than one name in your text, please return just the name of the next speaker. To determine the speaker use these prioritised rules: 1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker's name 2. If it refers to the "next" speaker name, choose that name 3. Otherwise, choose the first provided speaker's name in the context The names are case-sensitive and should not be abbreviated or changed. Respond with ONLY the name of the speaker and DO NOT provide a reason." - select_speaker_auto_none_template: customize the follow-up prompt used when selecting a speaker fails with a response that contains no agent names. This prompt guides the LLM to return an agent name and provides a list of agent names. Applies only to "auto" speaker selection method. If the string contains "{agentlist}" it will be replaced with a comma-separated list of agent names in square brackets. The default value is: "You didn't choose a speaker. As a reminder, to determine the speaker use these prioritised rules: 1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker's name 2. If it refers to the "next" speaker name, choose that name 3. Otherwise, choose the first provided speaker's name in the context The names are case-sensitive and should not be abbreviated or changed. The only names that are accepted are {agentlist}. Respond with ONLY the name of the speaker and DO NOT provide a reason." - speaker_selection_method: the method for selecting the next speaker. Default is "auto". Could be any of the following (case insensitive), will raise ValueError if not recognized: - "auto": the next speaker is selected automatically by LLM. - "manual": the next speaker is selected manually by user input. - "random": the next speaker is selected randomly. - "round_robin": the next speaker is selected in a round robin fashion, i.e., iterating in the same order as provided in agents. - a customized speaker selection function (Callable): the function will be called to select the next speaker. The function should take the last speaker and the group chat as input and return one of the following: 1. an Agent class, it must be one of the agents in the group chat. 2. a string from ['auto', 'manual', 'random', 'round_robin'] to select a default method to use. 3. None, which would terminate the conversation gracefully.

def custom_speaker_selection_func(
    last_speaker: Agent, groupchat: GroupChat
) -> Union[Agent, str, None]:
- max_retries_for_selecting_speaker: the maximum number of times the speaker selection requery process will run. If, during speaker selection, multiple agent names or no agent names are returned by the LLM as the next agent, it will be queried again up to the maximum number of times until a single agent is returned or it exhausts the maximum attempts. Applies only to "auto" speaker selection method. Default is 2. - select_speaker_transform_messages: (optional) the message transformations to apply to the nested select speaker agent-to-agent chat messages. Takes a TransformMessages object, defaults to None and is only utilised when the speaker selection method is "auto". - select_speaker_auto_verbose: whether to output the select speaker responses and selections If set to True, the outputs from the two agents in the nested select speaker chat will be output, along with whether the responses were successful, or not, in selecting an agent Applies only to "auto" speaker selection method. - allow_repeat_speaker: whether to allow the same speaker to speak consecutively. Default is True, in which case all speakers are allowed to speak consecutively. If allow_repeat_speaker is a list of Agents, then only those listed agents are allowed to repeat. If set to False, then no speakers are allowed to repeat. allow_repeat_speaker and allowed_or_disallowed_speaker_transitions are mutually exclusive. - allowed_or_disallowed_speaker_transitions: dict. The keys are source agents, and the values are agents that the key agent can/can't transit to, depending on speaker_transitions_type. Default is None, which means all agents can transit to all other agents. allow_repeat_speaker and allowed_or_disallowed_speaker_transitions are mutually exclusive. - speaker_transitions_type: whether the speaker_transitions_type is a dictionary containing lists of allowed agents or disallowed agents. "allowed" means the allowed_or_disallowed_speaker_transitions is a dictionary containing lists of allowed agents. If set to "disallowed", then the allowed_or_disallowed_speaker_transitions is a dictionary containing lists of disallowed agents. Must be supplied if allowed_or_disallowed_speaker_transitions is not None. - enable_clear_history: enable possibility to clear history of messages for agents manually by providing "clear history" phrase in user prompt. This is experimental feature. See description of GroupChatManager.clear_agents_history function for more info. - send_introductions: send a round of introductions at the start of the group chat, so agents know who they can speak to (default: False) - select_speaker_auto_model_client_cls: Custom model client class for the internal speaker select agent used during 'auto' speaker selection (optional) - select_speaker_auto_llm_config: LLM config for the internal speaker select agent used during 'auto' speaker selection (optional) - role_for_select_speaker_messages: sets the role name for speaker selection when in 'auto' mode, typically 'user' or 'system'. (default: 'system')

agents instance-attribute #

agents

messages class-attribute instance-attribute #

messages = field(default_factory=list)

max_round class-attribute instance-attribute #

max_round = 10

admin_name class-attribute instance-attribute #

admin_name = 'Admin'

func_call_filter class-attribute instance-attribute #

func_call_filter = True

speaker_selection_method class-attribute instance-attribute #

speaker_selection_method = 'auto'

max_retries_for_selecting_speaker class-attribute instance-attribute #

max_retries_for_selecting_speaker = 2

allow_repeat_speaker class-attribute instance-attribute #

allow_repeat_speaker = None

allowed_or_disallowed_speaker_transitions class-attribute instance-attribute #

allowed_or_disallowed_speaker_transitions = None

speaker_transitions_type class-attribute instance-attribute #

speaker_transitions_type = None

enable_clear_history class-attribute instance-attribute #

enable_clear_history = False

send_introductions class-attribute instance-attribute #

send_introductions = False

select_speaker_message_template class-attribute instance-attribute #

select_speaker_message_template = 'You are in a role play game. The following roles are available:\n                {roles}.\n                Read the following conversation.\n                Then select the next role from {agentlist} to play. Only return the role.'

select_speaker_prompt_template class-attribute instance-attribute #

select_speaker_prompt_template = SELECT_SPEAKER_PROMPT_TEMPLATE

select_speaker_auto_multiple_template class-attribute instance-attribute #

select_speaker_auto_multiple_template = 'You provided more than one name in your text, please return just the name of the next speaker. To determine the speaker use these prioritised rules:\n    1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker\'s name\n    2. If it refers to the "next" speaker name, choose that name\n    3. Otherwise, choose the first provided speaker\'s name in the context\n    The names are case-sensitive and should not be abbreviated or changed.\n    Respond with ONLY the name of the speaker and DO NOT provide a reason.'

select_speaker_auto_none_template class-attribute instance-attribute #

select_speaker_auto_none_template = 'You didn\'t choose a speaker. As a reminder, to determine the speaker use these prioritised rules:\n    1. If the context refers to themselves as a speaker e.g. "As the..." , choose that speaker\'s name\n    2. If it refers to the "next" speaker name, choose that name\n    3. Otherwise, choose the first provided speaker\'s name in the context\n    The names are case-sensitive and should not be abbreviated or changed.\n    The only names that are accepted are {agentlist}.\n    Respond with ONLY the name of the speaker and DO NOT provide a reason.'

select_speaker_transform_messages class-attribute instance-attribute #

select_speaker_transform_messages = None

select_speaker_auto_verbose class-attribute instance-attribute #

select_speaker_auto_verbose = False

select_speaker_auto_model_client_cls class-attribute instance-attribute #

select_speaker_auto_model_client_cls = None

select_speaker_auto_llm_config class-attribute instance-attribute #

select_speaker_auto_llm_config = None

role_for_select_speaker_messages class-attribute instance-attribute #

role_for_select_speaker_messages = 'system'

DEFAULT_INTRO_MSG class-attribute instance-attribute #

DEFAULT_INTRO_MSG = 'Hello everyone. We have assembled a great team today to answer questions and solve tasks. In attendance are:'

allowed_speaker_transitions_dict class-attribute instance-attribute #

allowed_speaker_transitions_dict = field(init=False)

agent_names property #

agent_names

Return the names of the agents in the group chat.

reset #

reset()

Reset the group chat.

Source code in autogen/agentchat/groupchat.py
def reset(self):
    """Reset the group chat."""
    self.messages.clear()

append #

append(message, speaker)

Append a message to the group chat. We cast the content to str here so that it can be managed by text-based model.

Source code in autogen/agentchat/groupchat.py
def append(self, message: dict[str, Any], speaker: Agent):
    """Append a message to the group chat.
    We cast the content to str here so that it can be managed by text-based
    model.
    """
    # set the name to speaker's name if the role is not function
    # if the role is tool, it is OK to modify the name
    if message["role"] != "function":
        message["name"] = speaker.name
    if not isinstance(message["content"], str) and not isinstance(message["content"], list):
        message["content"] = str(message["content"])
    message["content"] = content_str(message["content"])
    self.messages.append(message)

agent_by_name #

agent_by_name(name, recursive=False, raise_on_name_conflict=False)

Returns the agent with a given name. If recursive is True, it will search in nested teams.

Source code in autogen/agentchat/groupchat.py
def agent_by_name(
    self, name: str, recursive: bool = False, raise_on_name_conflict: bool = False
) -> Optional[Agent]:
    """Returns the agent with a given name. If recursive is True, it will search in nested teams."""
    agents = self.nested_agents() if recursive else self.agents
    filtered_agents = [agent for agent in agents if agent.name == name]

    if raise_on_name_conflict and len(filtered_agents) > 1:
        raise AgentNameConflictError()

    return filtered_agents[0] if filtered_agents else None

nested_agents #

nested_agents()

Returns all agents in the group chat manager.

Source code in autogen/agentchat/groupchat.py
def nested_agents(self) -> list[Agent]:
    """Returns all agents in the group chat manager."""
    agents = self.agents.copy()
    for agent in agents:
        if isinstance(agent, GroupChatManager):
            # Recursive call for nested teams
            agents.extend(agent.groupchat.nested_agents())
    return agents

next_agent #

next_agent(agent, agents=None)

Return the next agent in the list.

Source code in autogen/agentchat/groupchat.py
def next_agent(self, agent: Agent, agents: Optional[list[Agent]] = None) -> Agent:
    """Return the next agent in the list."""
    if agents is None:
        agents = self.agents

    # Ensure the provided list of agents is a subset of self.agents
    if not set(agents).issubset(set(self.agents)):
        raise UndefinedNextAgentError()

    # What index is the agent? (-1 if not present)
    idx = self.agent_names.index(agent.name) if agent.name in self.agent_names else -1

    # Return the next agent
    if agents == self.agents:
        return agents[(idx + 1) % len(agents)]
    else:
        offset = idx + 1
        for i in range(len(self.agents)):
            if self.agents[(offset + i) % len(self.agents)] in agents:
                return self.agents[(offset + i) % len(self.agents)]

    # Explicitly handle cases where no valid next agent exists in the provided subset.
    raise UndefinedNextAgentError()

select_speaker_msg #

select_speaker_msg(agents=None)

Return the system message for selecting the next speaker. This is always the first message in the context.

Source code in autogen/agentchat/groupchat.py
def select_speaker_msg(self, agents: Optional[list[Agent]] = None) -> str:
    """Return the system message for selecting the next speaker. This is always the *first* message in the context."""
    if agents is None:
        agents = self.agents

    roles = self._participant_roles(agents)
    agentlist = f"{[agent.name for agent in agents]}"

    return_msg = self.select_speaker_message_template.format(roles=roles, agentlist=agentlist)
    return return_msg

select_speaker_prompt #

select_speaker_prompt(agents=None)

Return the floating system prompt selecting the next speaker. This is always the last message in the context. Will return None if the select_speaker_prompt_template is None.

Source code in autogen/agentchat/groupchat.py
def select_speaker_prompt(self, agents: Optional[list[Agent]] = None) -> str:
    """Return the floating system prompt selecting the next speaker.
    This is always the *last* message in the context.
    Will return None if the select_speaker_prompt_template is None.
    """
    if self.select_speaker_prompt_template is None:
        return None

    if agents is None:
        agents = self.agents

    agentlist = f"{[agent.name for agent in agents]}"

    return_prompt = f"{self.select_speaker_prompt_template}".replace("{agentlist}", agentlist)
    return return_prompt

introductions_msg #

introductions_msg(agents=None)

Return the system message for selecting the next speaker. This is always the first message in the context.

Source code in autogen/agentchat/groupchat.py
def introductions_msg(self, agents: Optional[list[Agent]] = None) -> str:
    """Return the system message for selecting the next speaker. This is always the *first* message in the context."""
    if agents is None:
        agents = self.agents

    # Use the class attribute instead of a hardcoded string
    intro_msg = self.DEFAULT_INTRO_MSG
    participant_roles = self._participant_roles(agents)

    return f"{intro_msg}\n\n{participant_roles}"

manual_select_speaker #

manual_select_speaker(agents=None)

Manually select the next speaker.

Source code in autogen/agentchat/groupchat.py
def manual_select_speaker(self, agents: Optional[list[Agent]] = None) -> Union[Agent, None]:
    """Manually select the next speaker."""
    iostream = IOStream.get_default()

    if agents is None:
        agents = self.agents

    iostream.send(SelectSpeakerMessage(agents=agents))

    try_count = 0
    # Assume the user will enter a valid number within 3 tries, otherwise use auto selection to avoid blocking.
    while try_count <= 3:
        try_count += 1
        if try_count >= 3:
            iostream.send(SelectSpeakerTryCountExceededMessage(try_count=try_count, agents=agents))
            break
        try:
            i = iostream.input(
                "Enter the number of the next speaker (enter nothing or `q` to use auto selection): "
            )
            if i == "" or i == "q":
                break
            i = int(i)
            if i > 0 and i <= len(agents):
                return agents[i - 1]
            else:
                raise ValueError
        except ValueError:
            iostream.send(SelectSpeakerInvalidInputMessage(agents=agents))
    return None

random_select_speaker #

random_select_speaker(agents=None)

Randomly select the next speaker.

Source code in autogen/agentchat/groupchat.py
def random_select_speaker(self, agents: Optional[list[Agent]] = None) -> Union[Agent, None]:
    """Randomly select the next speaker."""
    if agents is None:
        agents = self.agents
    return random.choice(agents)

select_speaker #

select_speaker(last_speaker, selector)

Select the next speaker (with requery).

Source code in autogen/agentchat/groupchat.py
def select_speaker(self, last_speaker: Agent, selector: ConversableAgent) -> Agent:
    """Select the next speaker (with requery)."""
    # Prepare the list of available agents and select an agent if selection method allows (non-auto)
    selected_agent, agents, messages = self._prepare_and_select_agents(last_speaker)
    if selected_agent:
        return selected_agent
    elif self.speaker_selection_method == "manual":
        # An agent has not been selected while in manual mode, so move to the next agent
        return self.next_agent(last_speaker)

    # auto speaker selection with 2-agent chat
    return self._auto_select_speaker(last_speaker, selector, messages, agents)

a_select_speaker async #

a_select_speaker(last_speaker, selector)

Select the next speaker (with requery), asynchronously.

Source code in autogen/agentchat/groupchat.py
async def a_select_speaker(self, last_speaker: Agent, selector: ConversableAgent) -> Agent:
    """Select the next speaker (with requery), asynchronously."""
    selected_agent, agents, messages = self._prepare_and_select_agents(last_speaker)
    if selected_agent:
        return selected_agent
    elif self.speaker_selection_method == "manual":
        # An agent has not been selected while in manual mode, so move to the next agent
        return self.next_agent(last_speaker)

    # auto speaker selection with 2-agent chat
    return await self.a_auto_select_speaker(last_speaker, selector, messages, agents)

a_auto_select_speaker async #

a_auto_select_speaker(last_speaker, selector, messages, agents)

(Asynchronous) Selects next speaker for the "auto" speaker selection method. Utilises its own two-agent chat to determine the next speaker and supports requerying.

Speaker selection for "auto" speaker selection method: 1. Create a two-agent chat with a speaker selector agent and a speaker validator agent, like a nested chat 2. Inject the group messages into the new chat 3. Run the two-agent chat, evaluating the result of response from the speaker selector agent: - If a single agent is provided then we return it and finish. If not, we add an additional message to this nested chat in an attempt to guide the LLM to a single agent response 4. Chat continues until a single agent is nominated or there are no more attempts left 5. If we run out of turns and no single agent can be determined, the next speaker in the list of agents is returned

PARAMETER DESCRIPTION
last_speaker

The previous speaker in the group chat

TYPE: Agent

selector

The ConversableAgent that initiated the speaker selection

TYPE: ConversableAgent

messages

Current chat messages

TYPE: Optional[list[dict[str, Any]]]

agents

Valid list of agents for speaker selection

TYPE: Optional[list[Agent]]

RETURNS DESCRIPTION
Agent

A counter for mentioned agents.

Source code in autogen/agentchat/groupchat.py
async def a_auto_select_speaker(
    self,
    last_speaker: Agent,
    selector: ConversableAgent,
    messages: Optional[list[dict[str, Any]]],
    agents: Optional[list[Agent]],
) -> Agent:
    """(Asynchronous) Selects next speaker for the "auto" speaker selection method. Utilises its own two-agent chat to determine the next speaker and supports requerying.

    Speaker selection for "auto" speaker selection method:
    1. Create a two-agent chat with a speaker selector agent and a speaker validator agent, like a nested chat
    2. Inject the group messages into the new chat
    3. Run the two-agent chat, evaluating the result of response from the speaker selector agent:
        - If a single agent is provided then we return it and finish. If not, we add an additional message to this nested chat in an attempt to guide the LLM to a single agent response
    4. Chat continues until a single agent is nominated or there are no more attempts left
    5. If we run out of turns and no single agent can be determined, the next speaker in the list of agents is returned

    Args:
        last_speaker: The previous speaker in the group chat
        selector: The ConversableAgent that initiated the speaker selection
        messages: Current chat messages
        agents: Valid list of agents for speaker selection

    Returns:
        A counter for mentioned agents.
    """
    # If no agents are passed in, assign all the group chat's agents
    if agents is None:
        agents = self.agents

    # The maximum number of speaker selection attempts (including requeries)
    # We track these and use them in the validation function as we can't
    # access the max_turns from within validate_speaker_name
    max_attempts = 1 + self.max_retries_for_selecting_speaker
    attempts_left = max_attempts
    attempt = 0

    # Registered reply function for checking_agent, checks the result of the response for agent names
    def validate_speaker_name(
        recipient, messages, sender, config
    ) -> tuple[bool, Optional[Union[str, dict[str, Any]]]]:
        # The number of retries left, starting at max_retries_for_selecting_speaker
        nonlocal attempts_left
        nonlocal attempt

        attempt = attempt + 1
        attempts_left = attempts_left - 1

        return self._validate_speaker_name(recipient, messages, sender, config, attempts_left, attempt, agents)

    # Two-agent chat for speaker selection

    # Agent for checking the response from the speaker_select_agent
    checking_agent, speaker_selection_agent = self._create_internal_agents(
        agents, max_attempts, messages, validate_speaker_name, selector
    )

    # Create the starting message
    if self.select_speaker_prompt_template is not None:
        start_message = {
            "content": self.select_speaker_prompt(agents),
            "override_role": self.role_for_select_speaker_messages,
        }
    else:
        start_message = messages[-1]

    # Add the message transforms, if any, to the speaker selection agent
    if self._speaker_selection_transforms is not None:
        self._speaker_selection_transforms.add_to_agent(speaker_selection_agent)

    # Run the speaker selection chat
    result = await checking_agent.a_initiate_chat(
        speaker_selection_agent,
        cache=None,  # don't use caching for the speaker selection chat
        message=start_message,
        max_turns=2
        * max(1, max_attempts),  # Limiting the chat to the number of attempts, including the initial one
        clear_history=False,
        silent=not self.select_speaker_auto_verbose,  # Base silence on the verbose attribute
    )

    return self._process_speaker_selection_result(result, last_speaker, agents)