You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_group_chat.py 84 kB

Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
fix: Update SKChatCompletionAdapter message conversion (#5749) <!-- Thank you for your contribution! Please review https://microsoft.github.io/autogen/docs/Contribute before opening a pull request. --> <!-- Please add a reviewer to the assignee section when you create a PR. If you don't have the access to it, we will shortly find a reviewer and assign them to your PR. --> ## Why are these changes needed? <!-- Please give a short summary of the change and the problem this solves. --> The PR introduces two changes. The first change is adding a name attribute to `FunctionExecutionResult`. The motivation is that semantic kernel requires it for their function result interface and it seemed like a easy modification as `FunctionExecutionResult` is always created in the context of a `FunctionCall` which will contain the name. I'm unsure if there was a motivation to keep it out but this change makes it easier to trace which tool the result refers to and also increases api compatibility with SK. The second change is an update to how messages are mapped from autogen to semantic kernel, which includes an update/fix in the processing of function results. ## Related issue number <!-- For example: "Closes #1234" --> Related to #5675 but wont fix the underlying issue of anthropic requiring tools during AssistantAgent reflection. ## Checks - [ ] I've included any doc changes needed for <https://microsoft.github.io/autogen/>. See <https://github.com/microsoft/autogen/blob/main/CONTRIBUTING.md> to build and test documentation locally. - [ ] I've added tests (if relevant) corresponding to the changes introduced in this PR. - [ ] I've made sure all auto checks have passed. --------- Co-authored-by: Leonardo Pinheiro <lpinheiro@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
Support for external agent runtime in AgentChat (#5843) Resolves #4075 1. Introduce custom runtime parameter for all AgentChat teams (RoundRobinGroupChat, SelectorGroupChat, etc.). This is done by making sure each team's topics are isolated from other teams, and decoupling state from agent identities. Also, I removed the closure agent from the BaseGroupChat and use the group chat manager agent to relay messages to the output message queue. 2. Added unit tests to test scenarios with custom runtimes by using pytest fixture 3. Refactored existing unit tests to use ReplayChatCompletionClient with a few improvements to the client. 4. Fix a one-liner bug in AssistantAgent that caused deserialized agent to have handoffs. How to use it? ```python import asyncio from autogen_core import SingleThreadedAgentRuntime from autogen_agentchat.agents import AssistantAgent from autogen_agentchat.teams import RoundRobinGroupChat from autogen_agentchat.conditions import TextMentionTermination from autogen_ext.models.replay import ReplayChatCompletionClient async def main() -> None: # Create a runtime runtime = SingleThreadedAgentRuntime() runtime.start() # Create a model client. model_client = ReplayChatCompletionClient( ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"], ) # Create agents agent1 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent2 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") # Create a termination condition termination_condition = TextMentionTermination("10", sources=["assistant1", "assistant2"]) # Create a team team = RoundRobinGroupChat([agent1, agent2], runtime=runtime, termination_condition=termination_condition) # Run the team stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Save the state. state = await team.save_state() # Load the state to an existing team. await team.load_state(state) # Run the team again model_client.reset() stream = team.run_stream(task="Count to 10.") async for message in stream: print(message) # Create a new team, with the same agent names. agent3 = AssistantAgent("assistant1", model_client=model_client, system_message="You are a helpful assistant.") agent4 = AssistantAgent("assistant2", model_client=model_client, system_message="You are a helpful assistant.") new_team = RoundRobinGroupChat([agent3, agent4], runtime=runtime, termination_condition=termination_condition) # Load the state to the new team. await new_team.load_state(state) # Run the new team model_client.reset() new_stream = new_team.run_stream(task="Count to 10.") async for message in new_stream: print(message) # Stop the runtime await runtime.stop() asyncio.run(main()) ``` TODOs as future PRs: 1. Documentation. 2. How to handle errors in custom runtime when the agent has exception? --------- Co-authored-by: Ryan Sweet <rysweet@microsoft.com>
1 year ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946
  1. import asyncio
  2. import json
  3. import logging
  4. import tempfile
  5. from typing import Any, AsyncGenerator, Dict, List, Mapping, Sequence
  6. import pytest
  7. import pytest_asyncio
  8. from autogen_agentchat import EVENT_LOGGER_NAME
  9. from autogen_agentchat.agents import (
  10. AssistantAgent,
  11. BaseChatAgent,
  12. CodeExecutorAgent,
  13. )
  14. from autogen_agentchat.base import Handoff, Response, TaskResult, TerminationCondition
  15. from autogen_agentchat.conditions import (
  16. HandoffTermination,
  17. MaxMessageTermination,
  18. StopMessageTermination,
  19. TextMentionTermination,
  20. )
  21. from autogen_agentchat.messages import (
  22. BaseAgentEvent,
  23. BaseChatMessage,
  24. HandoffMessage,
  25. ModelClientStreamingChunkEvent,
  26. MultiModalMessage,
  27. SelectorEvent,
  28. SelectSpeakerEvent,
  29. StopMessage,
  30. StructuredMessage,
  31. TextMessage,
  32. ToolCallExecutionEvent,
  33. ToolCallRequestEvent,
  34. ToolCallSummaryMessage,
  35. )
  36. from autogen_agentchat.teams import MagenticOneGroupChat, RoundRobinGroupChat, SelectorGroupChat, Swarm
  37. from autogen_agentchat.teams._group_chat._round_robin_group_chat import RoundRobinGroupChatManager
  38. from autogen_agentchat.teams._group_chat._selector_group_chat import SelectorGroupChatManager
  39. from autogen_agentchat.teams._group_chat._swarm_group_chat import SwarmGroupChatManager
  40. from autogen_agentchat.ui import Console
  41. from autogen_core import AgentId, AgentRuntime, CancellationToken, FunctionCall, SingleThreadedAgentRuntime
  42. from autogen_core.model_context import BufferedChatCompletionContext
  43. from autogen_core.models import (
  44. AssistantMessage,
  45. CreateResult,
  46. FunctionExecutionResult,
  47. FunctionExecutionResultMessage,
  48. LLMMessage,
  49. RequestUsage,
  50. UserMessage,
  51. )
  52. from autogen_core.tools import FunctionTool
  53. from autogen_ext.code_executors.local import LocalCommandLineCodeExecutor
  54. from autogen_ext.models.openai import OpenAIChatCompletionClient
  55. from autogen_ext.models.replay import ReplayChatCompletionClient
  56. from pydantic import BaseModel
  57. from utils import FileLogHandler, compare_messages, compare_task_results
  58. logger = logging.getLogger(EVENT_LOGGER_NAME)
  59. logger.setLevel(logging.DEBUG)
  60. logger.addHandler(FileLogHandler("test_group_chat.log"))
  61. class _EchoAgent(BaseChatAgent):
  62. def __init__(self, name: str, description: str) -> None:
  63. super().__init__(name, description)
  64. self._last_message: str | None = None
  65. self._total_messages = 0
  66. @property
  67. def produced_message_types(self) -> Sequence[type[BaseChatMessage]]:
  68. return (TextMessage,)
  69. @property
  70. def total_messages(self) -> int:
  71. return self._total_messages
  72. async def on_messages(self, messages: Sequence[BaseChatMessage], cancellation_token: CancellationToken) -> Response:
  73. if len(messages) > 0:
  74. assert isinstance(messages[0], TextMessage)
  75. self._last_message = messages[0].content
  76. self._total_messages += 1
  77. return Response(chat_message=TextMessage(content=messages[0].content, source=self.name))
  78. else:
  79. assert self._last_message is not None
  80. self._total_messages += 1
  81. return Response(chat_message=TextMessage(content=self._last_message, source=self.name))
  82. async def on_reset(self, cancellation_token: CancellationToken) -> None:
  83. self._last_message = None
  84. async def save_state(self) -> Mapping[str, Any]:
  85. return {
  86. "last_message": self._last_message,
  87. "total_messages": self._total_messages,
  88. }
  89. async def load_state(self, state: Mapping[str, Any]) -> None:
  90. self._last_message = state.get("last_message")
  91. self._total_messages = state.get("total_messages", 0)
  92. class _FlakyAgent(BaseChatAgent):
  93. def __init__(self, name: str, description: str) -> None:
  94. super().__init__(name, description)
  95. self._last_message: str | None = None
  96. self._total_messages = 0
  97. @property
  98. def produced_message_types(self) -> Sequence[type[BaseChatMessage]]:
  99. return (TextMessage,)
  100. @property
  101. def total_messages(self) -> int:
  102. return self._total_messages
  103. async def on_messages(self, messages: Sequence[BaseChatMessage], cancellation_token: CancellationToken) -> Response:
  104. raise ValueError("I am a flaky agent...")
  105. async def on_reset(self, cancellation_token: CancellationToken) -> None:
  106. self._last_message = None
  107. class _FlakyTermination(TerminationCondition):
  108. def __init__(self, raise_on_count: int) -> None:
  109. self._raise_on_count = raise_on_count
  110. self._count = 0
  111. @property
  112. def terminated(self) -> bool:
  113. """Check if the termination condition has been reached"""
  114. return False
  115. async def __call__(self, messages: Sequence[BaseAgentEvent | BaseChatMessage]) -> StopMessage | None:
  116. self._count += 1
  117. if self._count == self._raise_on_count:
  118. raise ValueError("I am a flaky termination...")
  119. return None
  120. async def reset(self) -> None:
  121. pass
  122. class _UnknownMessageType(BaseChatMessage):
  123. content: str
  124. def to_model_message(self) -> UserMessage:
  125. raise NotImplementedError("This message type is not supported.")
  126. def to_model_text(self) -> str:
  127. raise NotImplementedError("This message type is not supported.")
  128. def to_text(self) -> str:
  129. raise NotImplementedError("This message type is not supported.")
  130. def dump(self) -> Mapping[str, Any]:
  131. return {}
  132. @classmethod
  133. def load(cls, data: Mapping[str, Any]) -> "_UnknownMessageType":
  134. return cls(**data)
  135. class _UnknownMessageTypeAgent(BaseChatAgent):
  136. def __init__(self, name: str, description: str) -> None:
  137. super().__init__(name, description)
  138. @property
  139. def produced_message_types(self) -> Sequence[type[BaseChatMessage]]:
  140. return (_UnknownMessageType,)
  141. async def on_messages(self, messages: Sequence[BaseChatMessage], cancellation_token: CancellationToken) -> Response:
  142. return Response(chat_message=_UnknownMessageType(content="Unknown message type", source=self.name))
  143. async def on_reset(self, cancellation_token: CancellationToken) -> None:
  144. pass
  145. class _StopAgent(_EchoAgent):
  146. def __init__(self, name: str, description: str, *, stop_at: int = 1) -> None:
  147. super().__init__(name, description)
  148. self._count = 0
  149. self._stop_at = stop_at
  150. @property
  151. def produced_message_types(self) -> Sequence[type[BaseChatMessage]]:
  152. return (TextMessage, StopMessage)
  153. async def on_messages(self, messages: Sequence[BaseChatMessage], cancellation_token: CancellationToken) -> Response:
  154. self._count += 1
  155. if self._count < self._stop_at:
  156. return await super().on_messages(messages, cancellation_token)
  157. return Response(chat_message=StopMessage(content="TERMINATE", source=self.name))
  158. def _pass_function(input: str) -> str:
  159. return "pass"
  160. class _InputTask1(BaseModel):
  161. task: str
  162. data: List[str]
  163. class _InputTask2(BaseModel):
  164. task: str
  165. data: str
  166. TaskType = str | List[BaseChatMessage] | BaseChatMessage
  167. @pytest_asyncio.fixture(params=["single_threaded", "embedded"]) # type: ignore
  168. async def runtime(request: pytest.FixtureRequest) -> AsyncGenerator[AgentRuntime | None, None]:
  169. if request.param == "single_threaded":
  170. runtime = SingleThreadedAgentRuntime()
  171. runtime.start()
  172. yield runtime
  173. await runtime.stop()
  174. elif request.param == "embedded":
  175. yield None
  176. @pytest.mark.asyncio
  177. async def test_round_robin_group_chat(runtime: AgentRuntime | None) -> None:
  178. model_client = ReplayChatCompletionClient(
  179. [
  180. 'Here is the program\n ```python\nprint("Hello, world!")\n```',
  181. "TERMINATE",
  182. ],
  183. )
  184. with tempfile.TemporaryDirectory() as temp_dir:
  185. code_executor_agent = CodeExecutorAgent(
  186. "code_executor", code_executor=LocalCommandLineCodeExecutor(work_dir=temp_dir)
  187. )
  188. coding_assistant_agent = AssistantAgent(
  189. "coding_assistant",
  190. model_client=model_client,
  191. )
  192. termination = TextMentionTermination("TERMINATE")
  193. team = RoundRobinGroupChat(
  194. participants=[coding_assistant_agent, code_executor_agent],
  195. termination_condition=termination,
  196. runtime=runtime,
  197. )
  198. result = await team.run(
  199. task="Write a program that prints 'Hello, world!'",
  200. )
  201. expected_messages = [
  202. "Write a program that prints 'Hello, world!'",
  203. 'Here is the program\n ```python\nprint("Hello, world!")\n```',
  204. "Hello, world!",
  205. "TERMINATE",
  206. ]
  207. for i in range(len(expected_messages)):
  208. produced_message = result.messages[i]
  209. assert isinstance(produced_message, TextMessage)
  210. content = produced_message.content.replace("\r\n", "\n").rstrip("\n")
  211. assert content == expected_messages[i]
  212. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  213. # Test streaming with default output_task_messages=True.
  214. model_client.reset()
  215. await team.reset()
  216. streamed_messages: List[BaseAgentEvent | BaseChatMessage] = []
  217. final_stream_result: TaskResult | None = None
  218. async for message in team.run_stream(
  219. task="Write a program that prints 'Hello, world!'",
  220. ):
  221. if isinstance(message, TaskResult):
  222. final_stream_result = message
  223. else:
  224. streamed_messages.append(message)
  225. assert final_stream_result is not None
  226. assert compare_task_results(final_stream_result, result)
  227. # Verify streamed messages match the complete result.messages
  228. assert len(streamed_messages) == len(result.messages)
  229. for streamed_msg, expected_msg in zip(streamed_messages, result.messages, strict=False):
  230. assert compare_messages(streamed_msg, expected_msg)
  231. # Test message input.
  232. # Text message.
  233. model_client.reset()
  234. await team.reset()
  235. result_2 = await team.run(
  236. task=TextMessage(content="Write a program that prints 'Hello, world!'", source="user")
  237. )
  238. assert compare_task_results(result, result_2)
  239. # Test multi-modal message.
  240. model_client.reset()
  241. await team.reset()
  242. task = MultiModalMessage(content=["Write a program that prints 'Hello, world!'"], source="user")
  243. result_2 = await team.run(task=task)
  244. assert isinstance(result.messages[0], TextMessage)
  245. assert isinstance(result_2.messages[0], MultiModalMessage)
  246. assert result.messages[0].content == task.content[0]
  247. assert len(result.messages[1:]) == len(result_2.messages[1:])
  248. for i in range(1, len(result.messages)):
  249. assert compare_messages(result.messages[i], result_2.messages[i])
  250. @pytest.mark.asyncio
  251. async def test_round_robin_group_chat_output_task_messages_false(runtime: AgentRuntime | None) -> None:
  252. model_client = ReplayChatCompletionClient(
  253. [
  254. 'Here is the program\n ```python\nprint("Hello, world!")\n```',
  255. "TERMINATE",
  256. ],
  257. )
  258. with tempfile.TemporaryDirectory() as temp_dir:
  259. code_executor_agent = CodeExecutorAgent(
  260. "code_executor", code_executor=LocalCommandLineCodeExecutor(work_dir=temp_dir)
  261. )
  262. coding_assistant_agent = AssistantAgent(
  263. "coding_assistant",
  264. model_client=model_client,
  265. )
  266. termination = TextMentionTermination("TERMINATE")
  267. team = RoundRobinGroupChat(
  268. participants=[coding_assistant_agent, code_executor_agent],
  269. termination_condition=termination,
  270. runtime=runtime,
  271. )
  272. result = await team.run(
  273. task="Write a program that prints 'Hello, world!'",
  274. output_task_messages=False,
  275. )
  276. expected_messages = [
  277. 'Here is the program\n ```python\nprint("Hello, world!")\n```',
  278. "Hello, world!",
  279. "TERMINATE",
  280. ]
  281. for i in range(len(expected_messages)):
  282. produced_message = result.messages[i]
  283. assert isinstance(produced_message, TextMessage)
  284. content = produced_message.content.replace("\r\n", "\n").rstrip("\n")
  285. assert content == expected_messages[i]
  286. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  287. # Test streaming with output_task_messages=False.
  288. model_client.reset()
  289. await team.reset()
  290. streamed_messages: List[BaseAgentEvent | BaseChatMessage] = []
  291. final_stream_result: TaskResult | None = None
  292. async for message in team.run_stream(
  293. task="Write a program that prints 'Hello, world!'",
  294. output_task_messages=False,
  295. ):
  296. if isinstance(message, TaskResult):
  297. final_stream_result = message
  298. else:
  299. streamed_messages.append(message)
  300. assert final_stream_result is not None
  301. assert compare_task_results(final_stream_result, result)
  302. # Verify streamed messages match the complete result.messages excluding the first task message
  303. assert len(streamed_messages) == len(result.messages) # Exclude task message
  304. for streamed_msg, expected_msg in zip(streamed_messages, result.messages, strict=False):
  305. assert compare_messages(streamed_msg, expected_msg)
  306. # Test message input with output_task_messages=False.
  307. # Text message.
  308. model_client.reset()
  309. await team.reset()
  310. streamed_messages_2: List[BaseAgentEvent | BaseChatMessage] = []
  311. final_stream_result_2: TaskResult | None = None
  312. async for message in team.run_stream(
  313. task=TextMessage(content="Write a program that prints 'Hello, world!'", source="user"),
  314. output_task_messages=False,
  315. ):
  316. if isinstance(message, TaskResult):
  317. final_stream_result_2 = message
  318. else:
  319. streamed_messages_2.append(message)
  320. assert final_stream_result_2 is not None
  321. assert compare_task_results(final_stream_result_2, result)
  322. # Verify streamed messages match the complete result.messages excluding the first task message
  323. assert len(streamed_messages_2) == len(result.messages)
  324. for streamed_msg, expected_msg in zip(streamed_messages_2, result.messages, strict=False):
  325. assert compare_messages(streamed_msg, expected_msg)
  326. # Test multi-modal message with output_task_messages=False.
  327. model_client.reset()
  328. await team.reset()
  329. task = MultiModalMessage(content=["Write a program that prints 'Hello, world!'"], source="user")
  330. streamed_messages_3: List[BaseAgentEvent | BaseChatMessage] = []
  331. final_stream_result_3: TaskResult | None = None
  332. async for message in team.run_stream(task=task, output_task_messages=False):
  333. if isinstance(message, TaskResult):
  334. final_stream_result_3 = message
  335. else:
  336. streamed_messages_3.append(message)
  337. assert final_stream_result_3 is not None
  338. # Verify streamed messages exclude the task message
  339. assert len(streamed_messages_3) == len(final_stream_result_3.messages)
  340. for streamed_msg, expected_msg in zip(streamed_messages_3, final_stream_result_3.messages, strict=False):
  341. assert compare_messages(streamed_msg, expected_msg)
  342. @pytest.mark.asyncio
  343. async def test_round_robin_group_chat_with_team_event(runtime: AgentRuntime | None) -> None:
  344. model_client = ReplayChatCompletionClient(
  345. [
  346. 'Here is the program\n ```python\nprint("Hello, world!")\n```',
  347. "TERMINATE",
  348. ],
  349. )
  350. with tempfile.TemporaryDirectory() as temp_dir:
  351. code_executor_agent = CodeExecutorAgent(
  352. "code_executor", code_executor=LocalCommandLineCodeExecutor(work_dir=temp_dir)
  353. )
  354. coding_assistant_agent = AssistantAgent(
  355. "coding_assistant",
  356. model_client=model_client,
  357. )
  358. termination = TextMentionTermination("TERMINATE")
  359. team = RoundRobinGroupChat(
  360. participants=[coding_assistant_agent, code_executor_agent],
  361. termination_condition=termination,
  362. runtime=runtime,
  363. emit_team_events=True,
  364. )
  365. result = await team.run(
  366. task="Write a program that prints 'Hello, world!'",
  367. )
  368. assert len(result.messages) == 7
  369. assert isinstance(result.messages[0], TextMessage)
  370. assert isinstance(result.messages[1], SelectSpeakerEvent)
  371. assert isinstance(result.messages[2], TextMessage)
  372. assert isinstance(result.messages[3], SelectSpeakerEvent)
  373. assert isinstance(result.messages[4], TextMessage)
  374. assert isinstance(result.messages[5], SelectSpeakerEvent)
  375. assert isinstance(result.messages[6], TextMessage)
  376. # Test streaming with default output_task_messages=True.
  377. model_client.reset()
  378. await team.reset()
  379. streamed_messages: List[BaseAgentEvent | BaseChatMessage] = []
  380. final_stream_result: TaskResult | None = None
  381. async for message in team.run_stream(
  382. task="Write a program that prints 'Hello, world!'",
  383. ):
  384. if isinstance(message, TaskResult):
  385. final_stream_result = message
  386. else:
  387. streamed_messages.append(message)
  388. assert final_stream_result is not None
  389. assert compare_task_results(final_stream_result, result)
  390. # Verify streamed messages match the complete result.messages
  391. assert len(streamed_messages) == len(result.messages)
  392. for streamed_msg, expected_msg in zip(streamed_messages, result.messages, strict=False):
  393. assert compare_messages(streamed_msg, expected_msg)
  394. # Test multi-modal message.
  395. model_client.reset()
  396. await team.reset()
  397. task = MultiModalMessage(content=["Write a program that prints 'Hello, world!'"], source="user")
  398. result_2 = await team.run(task=task)
  399. assert isinstance(result.messages[0], TextMessage)
  400. assert isinstance(result_2.messages[0], MultiModalMessage)
  401. assert result.messages[0].content == task.content[0]
  402. assert len(result.messages[1:]) == len(result_2.messages[1:])
  403. for i in range(1, len(result.messages)):
  404. assert compare_messages(result.messages[i], result_2.messages[i])
  405. @pytest.mark.asyncio
  406. async def test_round_robin_group_chat_unknown_task_message_type(runtime: AgentRuntime | None) -> None:
  407. model_client = ReplayChatCompletionClient([])
  408. agent1 = AssistantAgent("agent1", model_client=model_client)
  409. agent2 = AssistantAgent("agent2", model_client=model_client)
  410. termination = TextMentionTermination("TERMINATE")
  411. team1 = RoundRobinGroupChat(
  412. participants=[agent1, agent2],
  413. termination_condition=termination,
  414. runtime=runtime,
  415. custom_message_types=[StructuredMessage[_InputTask2]],
  416. )
  417. with pytest.raises(ValueError, match=r"Message type .*StructuredMessage\[_InputTask1\].* is not registered"):
  418. await team1.run(
  419. task=StructuredMessage[_InputTask1](
  420. content=_InputTask1(task="Write a program that prints 'Hello, world!'", data=["a", "b", "c"]),
  421. source="user",
  422. )
  423. )
  424. @pytest.mark.asyncio
  425. async def test_round_robin_group_chat_unknown_agent_message_type() -> None:
  426. model_client = ReplayChatCompletionClient(["Hello"])
  427. agent1 = AssistantAgent("agent1", model_client=model_client)
  428. agent2 = _UnknownMessageTypeAgent("agent2", "I am an unknown message type agent")
  429. termination = TextMentionTermination("TERMINATE")
  430. team1 = RoundRobinGroupChat(participants=[agent1, agent2], termination_condition=termination)
  431. with pytest.raises(RuntimeError, match=".* Message type .*UnknownMessageType.* not registered"):
  432. await team1.run(task=TextMessage(content="Write a program that prints 'Hello, world!'", source="user"))
  433. @pytest.mark.asyncio
  434. @pytest.mark.parametrize(
  435. "task",
  436. [
  437. "Write a program that prints 'Hello, world!'",
  438. [TextMessage(content="Write a program that prints 'Hello, world!'", source="user")],
  439. [MultiModalMessage(content=["Write a program that prints 'Hello, world!'"], source="user")],
  440. [
  441. StructuredMessage[_InputTask1](
  442. content=_InputTask1(task="Write a program that prints 'Hello, world!'", data=["a", "b", "c"]),
  443. source="user",
  444. ),
  445. StructuredMessage[_InputTask2](
  446. content=_InputTask2(task="Write a program that prints 'Hello, world!'", data="a"), source="user"
  447. ),
  448. ],
  449. ],
  450. ids=["text", "text_message", "multi_modal_message", "structured_message"],
  451. )
  452. async def test_round_robin_group_chat_state(task: TaskType, runtime: AgentRuntime | None) -> None:
  453. model_client = ReplayChatCompletionClient(
  454. ["No facts", "No plan", "print('Hello, world!')", "TERMINATE"],
  455. )
  456. agent1 = AssistantAgent("agent1", model_client=model_client)
  457. agent2 = AssistantAgent("agent2", model_client=model_client)
  458. termination = TextMentionTermination("TERMINATE")
  459. team1 = RoundRobinGroupChat(
  460. participants=[agent1, agent2],
  461. termination_condition=termination,
  462. runtime=runtime,
  463. custom_message_types=[StructuredMessage[_InputTask1], StructuredMessage[_InputTask2]],
  464. )
  465. await team1.run(task=task)
  466. state = await team1.save_state()
  467. agent3 = AssistantAgent("agent1", model_client=model_client)
  468. agent4 = AssistantAgent("agent2", model_client=model_client)
  469. team2 = RoundRobinGroupChat(
  470. participants=[agent3, agent4],
  471. termination_condition=termination,
  472. runtime=runtime,
  473. custom_message_types=[StructuredMessage[_InputTask1], StructuredMessage[_InputTask2]],
  474. )
  475. await team2.load_state(state)
  476. state2 = await team2.save_state()
  477. assert state == state2
  478. agent1_model_ctx_messages = await agent1._model_context.get_messages() # pyright: ignore
  479. agent2_model_ctx_messages = await agent2._model_context.get_messages() # pyright: ignore
  480. agent3_model_ctx_messages = await agent3._model_context.get_messages() # pyright: ignore
  481. agent4_model_ctx_messages = await agent4._model_context.get_messages() # pyright: ignore
  482. assert agent3_model_ctx_messages == agent1_model_ctx_messages
  483. assert agent4_model_ctx_messages == agent2_model_ctx_messages
  484. manager_1 = await team1._runtime.try_get_underlying_agent_instance( # pyright: ignore
  485. AgentId(f"{team1._group_chat_manager_name}_{team1._team_id}", team1._team_id), # pyright: ignore
  486. RoundRobinGroupChatManager, # pyright: ignore
  487. ) # pyright: ignore
  488. manager_2 = await team2._runtime.try_get_underlying_agent_instance( # pyright: ignore
  489. AgentId(f"{team2._group_chat_manager_name}_{team2._team_id}", team2._team_id), # pyright: ignore
  490. RoundRobinGroupChatManager, # pyright: ignore
  491. ) # pyright: ignore
  492. assert manager_1._current_turn == manager_2._current_turn # pyright: ignore
  493. assert manager_1._message_thread == manager_2._message_thread # pyright: ignore
  494. @pytest.mark.asyncio
  495. async def test_round_robin_group_chat_with_tools(runtime: AgentRuntime | None) -> None:
  496. model_client = ReplayChatCompletionClient(
  497. chat_completions=[
  498. CreateResult(
  499. finish_reason="function_calls",
  500. content=[FunctionCall(id="1", name="pass", arguments=json.dumps({"input": "pass"}))],
  501. usage=RequestUsage(prompt_tokens=0, completion_tokens=0),
  502. cached=False,
  503. ),
  504. "Hello",
  505. "TERMINATE",
  506. ],
  507. model_info={
  508. "family": "gpt-4.1-nano",
  509. "function_calling": True,
  510. "json_output": True,
  511. "vision": True,
  512. "structured_output": True,
  513. },
  514. )
  515. tool = FunctionTool(_pass_function, name="pass", description="pass function")
  516. tool_use_agent = AssistantAgent("tool_use_agent", model_client=model_client, tools=[tool])
  517. echo_agent = _EchoAgent("echo_agent", description="echo agent")
  518. termination = TextMentionTermination("TERMINATE")
  519. team = RoundRobinGroupChat(
  520. participants=[tool_use_agent, echo_agent], termination_condition=termination, runtime=runtime
  521. )
  522. result = await team.run(
  523. task="Write a program that prints 'Hello, world!'",
  524. )
  525. assert len(result.messages) == 8
  526. assert isinstance(result.messages[0], TextMessage) # task
  527. assert isinstance(result.messages[1], ToolCallRequestEvent) # tool call
  528. assert isinstance(result.messages[2], ToolCallExecutionEvent) # tool call result
  529. assert isinstance(result.messages[3], ToolCallSummaryMessage) # tool use agent response
  530. assert result.messages[3].content == "pass" # ensure the tool call was executed
  531. assert isinstance(result.messages[4], TextMessage) # echo agent response
  532. assert isinstance(result.messages[5], TextMessage) # tool use agent response
  533. assert isinstance(result.messages[6], TextMessage) # echo agent response
  534. assert isinstance(result.messages[7], TextMessage) # tool use agent response, that has TERMINATE
  535. assert result.messages[7].content == "TERMINATE"
  536. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  537. # Test streaming.
  538. await tool_use_agent._model_context.clear() # pyright: ignore
  539. model_client.reset()
  540. result_index = 0 # Include task message in result since output_task_messages=True by default
  541. await team.reset()
  542. async for message in team.run_stream(
  543. task="Write a program that prints 'Hello, world!'",
  544. ):
  545. if isinstance(message, TaskResult):
  546. assert compare_task_results(message, result)
  547. else:
  548. assert compare_messages(message, result.messages[result_index])
  549. result_index += 1
  550. # Test Console.
  551. await tool_use_agent._model_context.clear() # pyright: ignore
  552. model_client.reset()
  553. await team.reset()
  554. result2 = await Console(team.run_stream(task="Write a program that prints 'Hello, world!'"))
  555. assert compare_task_results(result2, result)
  556. @pytest.mark.asyncio
  557. async def test_round_robin_group_chat_with_resume_and_reset(runtime: AgentRuntime | None) -> None:
  558. agent_1 = _EchoAgent("agent_1", description="echo agent 1")
  559. agent_2 = _EchoAgent("agent_2", description="echo agent 2")
  560. agent_3 = _EchoAgent("agent_3", description="echo agent 3")
  561. agent_4 = _EchoAgent("agent_4", description="echo agent 4")
  562. termination = MaxMessageTermination(3)
  563. team = RoundRobinGroupChat(
  564. participants=[agent_1, agent_2, agent_3, agent_4], termination_condition=termination, runtime=runtime
  565. )
  566. result = await team.run(
  567. task="Write a program that prints 'Hello, world!'",
  568. )
  569. assert len(result.messages) == 3
  570. assert result.messages[1].source == "agent_1"
  571. assert result.messages[2].source == "agent_2"
  572. assert result.stop_reason is not None
  573. # Resume.
  574. result = await team.run()
  575. assert len(result.messages) == 3
  576. assert result.messages[0].source == "agent_3"
  577. assert result.messages[1].source == "agent_4"
  578. assert result.messages[2].source == "agent_1"
  579. assert result.stop_reason is not None
  580. # Reset.
  581. await team.reset()
  582. result = await team.run(task="Write a program that prints 'Hello, world!'")
  583. assert len(result.messages) == 3
  584. assert result.messages[1].source == "agent_1"
  585. assert result.messages[2].source == "agent_2"
  586. assert result.stop_reason is not None
  587. @pytest.mark.asyncio
  588. async def test_round_robin_group_chat_with_exception_raised_from_agent(runtime: AgentRuntime | None) -> None:
  589. agent_1 = _EchoAgent("agent_1", description="echo agent 1")
  590. agent_2 = _FlakyAgent("agent_2", description="echo agent 2")
  591. agent_3 = _EchoAgent("agent_3", description="echo agent 3")
  592. termination = MaxMessageTermination(3)
  593. team = RoundRobinGroupChat(
  594. participants=[agent_1, agent_2, agent_3],
  595. termination_condition=termination,
  596. runtime=runtime,
  597. )
  598. with pytest.raises(RuntimeError, match="I am a flaky agent..."):
  599. await team.run(
  600. task="Write a program that prints 'Hello, world!'",
  601. )
  602. @pytest.mark.asyncio
  603. async def test_round_robin_group_chat_with_exception_raised_from_termination_condition(
  604. runtime: AgentRuntime | None,
  605. ) -> None:
  606. agent_1 = _EchoAgent("agent_1", description="echo agent 1")
  607. agent_2 = _FlakyAgent("agent_2", description="echo agent 2")
  608. agent_3 = _EchoAgent("agent_3", description="echo agent 3")
  609. team = RoundRobinGroupChat(
  610. participants=[agent_1, agent_2, agent_3],
  611. termination_condition=_FlakyTermination(raise_on_count=1),
  612. runtime=runtime,
  613. )
  614. with pytest.raises(Exception, match="I am a flaky termination..."):
  615. await team.run(
  616. task="Write a program that prints 'Hello, world!'",
  617. )
  618. @pytest.mark.asyncio
  619. async def test_round_robin_group_chat_max_turn(runtime: AgentRuntime | None) -> None:
  620. agent_1 = _EchoAgent("agent_1", description="echo agent 1")
  621. agent_2 = _EchoAgent("agent_2", description="echo agent 2")
  622. agent_3 = _EchoAgent("agent_3", description="echo agent 3")
  623. agent_4 = _EchoAgent("agent_4", description="echo agent 4")
  624. team = RoundRobinGroupChat(participants=[agent_1, agent_2, agent_3, agent_4], max_turns=3, runtime=runtime)
  625. result = await team.run(
  626. task="Write a program that prints 'Hello, world!'",
  627. )
  628. assert len(result.messages) == 4
  629. assert result.messages[1].source == "agent_1"
  630. assert result.messages[2].source == "agent_2"
  631. assert result.messages[3].source == "agent_3"
  632. assert result.stop_reason is not None
  633. # Resume.
  634. result = await team.run()
  635. assert len(result.messages) == 3
  636. assert result.messages[0].source == "agent_4"
  637. assert result.messages[1].source == "agent_1"
  638. assert result.messages[2].source == "agent_2"
  639. assert result.stop_reason is not None
  640. # Reset.
  641. await team.reset()
  642. result = await team.run(task="Write a program that prints 'Hello, world!'")
  643. assert len(result.messages) == 4
  644. assert result.messages[1].source == "agent_1"
  645. assert result.messages[2].source == "agent_2"
  646. assert result.messages[3].source == "agent_3"
  647. assert result.stop_reason is not None
  648. @pytest.mark.asyncio
  649. async def test_round_robin_group_chat_cancellation(runtime: AgentRuntime | None) -> None:
  650. agent_1 = _EchoAgent("agent_1", description="echo agent 1")
  651. agent_2 = _EchoAgent("agent_2", description="echo agent 2")
  652. agent_3 = _EchoAgent("agent_3", description="echo agent 3")
  653. agent_4 = _EchoAgent("agent_4", description="echo agent 4")
  654. # Set max_turns to a large number to avoid stopping due to max_turns before cancellation.
  655. team = RoundRobinGroupChat(participants=[agent_1, agent_2, agent_3, agent_4], max_turns=1000, runtime=runtime)
  656. cancellation_token = CancellationToken()
  657. run_task = asyncio.create_task(
  658. team.run(
  659. task="Write a program that prints 'Hello, world!'",
  660. cancellation_token=cancellation_token,
  661. )
  662. )
  663. await asyncio.sleep(0.1)
  664. # Cancel the task.
  665. cancellation_token.cancel()
  666. with pytest.raises(asyncio.CancelledError):
  667. await run_task
  668. # Still can run again and finish the task.
  669. result = await team.run()
  670. assert result.stop_reason is not None and result.stop_reason == "Maximum number of turns 1000 reached."
  671. @pytest.mark.asyncio
  672. async def test_selector_group_chat(runtime: AgentRuntime | None) -> None:
  673. model_client = ReplayChatCompletionClient(
  674. chat_completions=[
  675. "agent3",
  676. "agent2",
  677. "agent1",
  678. "agent2",
  679. "agent1",
  680. ]
  681. )
  682. agent1 = _StopAgent("agent1", description="echo agent 1", stop_at=2)
  683. agent2 = _EchoAgent("agent2", description="echo agent 2")
  684. agent3 = _EchoAgent("agent3", description="echo agent 3")
  685. termination = TextMentionTermination("TERMINATE")
  686. team = SelectorGroupChat(
  687. participants=[agent1, agent2, agent3],
  688. model_client=model_client,
  689. termination_condition=termination,
  690. runtime=runtime,
  691. )
  692. result = await team.run(
  693. task="Write a program that prints 'Hello, world!'",
  694. )
  695. assert len(result.messages) == 6
  696. assert isinstance(result.messages[0], TextMessage)
  697. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  698. assert result.messages[1].source == "agent3"
  699. assert result.messages[2].source == "agent2"
  700. assert result.messages[3].source == "agent1"
  701. assert result.messages[4].source == "agent2"
  702. assert result.messages[5].source == "agent1"
  703. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  704. # Test streaming.
  705. model_client.reset()
  706. agent1._count = 0 # pyright: ignore
  707. result_index = 0 # Include task message in result since output_task_messages=True by default
  708. await team.reset()
  709. async for message in team.run_stream(
  710. task="Write a program that prints 'Hello, world!'",
  711. ):
  712. if isinstance(message, TaskResult):
  713. assert compare_task_results(message, result)
  714. else:
  715. assert compare_messages(message, result.messages[result_index])
  716. result_index += 1
  717. # Test Console.
  718. model_client.reset()
  719. agent1._count = 0 # pyright: ignore
  720. await team.reset()
  721. result2 = await Console(team.run_stream(task="Write a program that prints 'Hello, world!'"))
  722. assert compare_task_results(result2, result)
  723. @pytest.mark.asyncio
  724. async def test_selector_group_chat_with_model_context(runtime: AgentRuntime | None) -> None:
  725. buffered_context = BufferedChatCompletionContext(buffer_size=5)
  726. await buffered_context.add_message(UserMessage(content="[User] Prefilled message", source="user"))
  727. selector_group_chat_model_client = ReplayChatCompletionClient(
  728. ["agent2", "agent1", "agent1", "agent2", "agent1", "agent2", "agent1"]
  729. )
  730. agent_one_model_client = ReplayChatCompletionClient(
  731. ["[Agent One] First generation", "[Agent One] Second generation", "[Agent One] Third generation", "TERMINATE"]
  732. )
  733. agent_two_model_client = ReplayChatCompletionClient(
  734. ["[Agent Two] First generation", "[Agent Two] Second generation", "[Agent Two] Third generation"]
  735. )
  736. agent1 = AssistantAgent("agent1", model_client=agent_one_model_client, description="Assistant agent 1")
  737. agent2 = AssistantAgent("agent2", model_client=agent_two_model_client, description="Assistant agent 2")
  738. termination = TextMentionTermination("TERMINATE")
  739. team = SelectorGroupChat(
  740. participants=[agent1, agent2],
  741. model_client=selector_group_chat_model_client,
  742. termination_condition=termination,
  743. runtime=runtime,
  744. emit_team_events=True,
  745. allow_repeated_speaker=True,
  746. model_context=buffered_context,
  747. )
  748. await team.run(
  749. task="[GroupChat] Task",
  750. )
  751. messages_to_check = [
  752. "user: [User] Prefilled message",
  753. "user: [GroupChat] Task",
  754. "agent2: [Agent Two] First generation",
  755. "agent1: [Agent One] First generation",
  756. "agent1: [Agent One] Second generation",
  757. "agent2: [Agent Two] Second generation",
  758. "agent1: [Agent One] Third generation",
  759. "agent2: [Agent Two] Third generation",
  760. ]
  761. create_calls: List[Dict[str, Any]] = selector_group_chat_model_client.create_calls
  762. for idx, call in enumerate(create_calls):
  763. messages = call["messages"]
  764. prompt = messages[0].content
  765. prompt_lines = prompt.split("\n")
  766. chat_history = [value for value in messages_to_check[max(0, idx - 3) : idx + 2]]
  767. assert all(
  768. line.strip() in prompt_lines for line in chat_history
  769. ), f"Expected all lines {chat_history} to be in prompt, but got {prompt_lines}"
  770. @pytest.mark.asyncio
  771. async def test_selector_group_chat_with_team_event(runtime: AgentRuntime | None) -> None:
  772. model_client = ReplayChatCompletionClient(
  773. ["agent3", "agent2", "agent1", "agent2", "agent1"],
  774. )
  775. agent1 = _StopAgent("agent1", description="echo agent 1", stop_at=2)
  776. agent2 = _EchoAgent("agent2", description="echo agent 2")
  777. agent3 = _EchoAgent("agent3", description="echo agent 3")
  778. termination = TextMentionTermination("TERMINATE")
  779. team = SelectorGroupChat(
  780. participants=[agent1, agent2, agent3],
  781. model_client=model_client,
  782. termination_condition=termination,
  783. runtime=runtime,
  784. emit_team_events=True,
  785. )
  786. result = await team.run(
  787. task="Write a program that prints 'Hello, world!'",
  788. )
  789. assert len(result.messages) == 11
  790. assert isinstance(result.messages[0], TextMessage)
  791. assert isinstance(result.messages[1], SelectSpeakerEvent)
  792. assert isinstance(result.messages[2], TextMessage)
  793. assert isinstance(result.messages[3], SelectSpeakerEvent)
  794. assert isinstance(result.messages[4], TextMessage)
  795. assert isinstance(result.messages[5], SelectSpeakerEvent)
  796. assert isinstance(result.messages[6], TextMessage)
  797. assert isinstance(result.messages[7], SelectSpeakerEvent)
  798. assert isinstance(result.messages[8], TextMessage)
  799. assert isinstance(result.messages[9], SelectSpeakerEvent)
  800. assert isinstance(result.messages[10], StopMessage)
  801. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  802. assert result.messages[1].content == ["agent3"]
  803. assert result.messages[2].source == "agent3"
  804. assert result.messages[3].content == ["agent2"]
  805. assert result.messages[4].source == "agent2"
  806. assert result.messages[5].content == ["agent1"]
  807. assert result.messages[6].source == "agent1"
  808. assert result.messages[7].content == ["agent2"]
  809. assert result.messages[8].source == "agent2"
  810. assert result.messages[9].content == ["agent1"]
  811. assert result.messages[10].source == "agent1"
  812. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  813. # Test streaming.
  814. model_client.reset()
  815. agent1._count = 0 # pyright: ignore
  816. result_index = 0 # Include task message in result since output_task_messages=True by default
  817. await team.reset()
  818. async for message in team.run_stream(
  819. task="Write a program that prints 'Hello, world!'",
  820. ):
  821. if isinstance(message, TaskResult):
  822. assert compare_task_results(message, result)
  823. else:
  824. assert compare_messages(message, result.messages[result_index])
  825. result_index += 1
  826. @pytest.mark.asyncio
  827. @pytest.mark.parametrize(
  828. "task",
  829. [
  830. "Write a program that prints 'Hello, world!'",
  831. [TextMessage(content="Write a program that prints 'Hello, world!'", source="user")],
  832. [MultiModalMessage(content=["Write a program that prints 'Hello, world!'"], source="user")],
  833. [
  834. StructuredMessage[_InputTask1](
  835. content=_InputTask1(task="Write a program that prints 'Hello, world!'", data=["a", "b", "c"]),
  836. source="user",
  837. ),
  838. StructuredMessage[_InputTask2](
  839. content=_InputTask2(task="Write a program that prints 'Hello, world!'", data="a"), source="user"
  840. ),
  841. ],
  842. ],
  843. ids=["text", "text_message", "multi_modal_message", "structured_message"],
  844. )
  845. async def test_selector_group_chat_state(task: TaskType, runtime: AgentRuntime | None) -> None:
  846. model_client = ReplayChatCompletionClient(
  847. ["agent1", "No facts", "agent2", "No plan", "agent1", "print('Hello, world!')", "agent2", "TERMINATE"],
  848. )
  849. agent1 = AssistantAgent("agent1", model_client=model_client)
  850. agent2 = AssistantAgent("agent2", model_client=model_client)
  851. termination = TextMentionTermination("TERMINATE")
  852. team1 = SelectorGroupChat(
  853. participants=[agent1, agent2],
  854. termination_condition=termination,
  855. model_client=model_client,
  856. runtime=runtime,
  857. custom_message_types=[StructuredMessage[_InputTask1], StructuredMessage[_InputTask2]],
  858. )
  859. await team1.run(task=task)
  860. state = await team1.save_state()
  861. agent3 = AssistantAgent("agent1", model_client=model_client)
  862. agent4 = AssistantAgent("agent2", model_client=model_client)
  863. team2 = SelectorGroupChat(
  864. participants=[agent3, agent4],
  865. termination_condition=termination,
  866. model_client=model_client,
  867. custom_message_types=[StructuredMessage[_InputTask1], StructuredMessage[_InputTask2]],
  868. )
  869. await team2.load_state(state)
  870. state2 = await team2.save_state()
  871. assert state == state2
  872. agent1_model_ctx_messages = await agent1._model_context.get_messages() # pyright: ignore
  873. agent2_model_ctx_messages = await agent2._model_context.get_messages() # pyright: ignore
  874. agent3_model_ctx_messages = await agent3._model_context.get_messages() # pyright: ignore
  875. agent4_model_ctx_messages = await agent4._model_context.get_messages() # pyright: ignore
  876. assert agent3_model_ctx_messages == agent1_model_ctx_messages
  877. assert agent4_model_ctx_messages == agent2_model_ctx_messages
  878. manager_1 = await team1._runtime.try_get_underlying_agent_instance( # pyright: ignore
  879. AgentId(f"{team1._group_chat_manager_name}_{team1._team_id}", team1._team_id), # pyright: ignore
  880. SelectorGroupChatManager, # pyright: ignore
  881. ) # pyright: ignore
  882. manager_2 = await team2._runtime.try_get_underlying_agent_instance( # pyright: ignore
  883. AgentId(f"{team2._group_chat_manager_name}_{team2._team_id}", team2._team_id), # pyright: ignore
  884. SelectorGroupChatManager, # pyright: ignore
  885. ) # pyright: ignore
  886. assert manager_1._message_thread == manager_2._message_thread # pyright: ignore
  887. assert manager_1._previous_speaker == manager_2._previous_speaker # pyright: ignore
  888. @pytest.mark.asyncio
  889. async def test_selector_group_chat_two_speakers(runtime: AgentRuntime | None) -> None:
  890. model_client = ReplayChatCompletionClient(["agent2"])
  891. agent1 = _StopAgent("agent1", description="echo agent 1", stop_at=2)
  892. agent2 = _EchoAgent("agent2", description="echo agent 2")
  893. termination = TextMentionTermination("TERMINATE")
  894. team = SelectorGroupChat(
  895. participants=[agent1, agent2],
  896. termination_condition=termination,
  897. model_client=model_client,
  898. runtime=runtime,
  899. )
  900. result = await team.run(
  901. task="Write a program that prints 'Hello, world!'",
  902. )
  903. assert len(result.messages) == 5
  904. assert isinstance(result.messages[0], TextMessage)
  905. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  906. assert result.messages[1].source == "agent2"
  907. assert result.messages[2].source == "agent1"
  908. assert result.messages[3].source == "agent2"
  909. assert result.messages[4].source == "agent1"
  910. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  911. # Test streaming.
  912. model_client.reset()
  913. agent1._count = 0 # pyright: ignore
  914. result_index = 0 # Include task message in result since output_task_messages=True by default
  915. await team.reset()
  916. async for message in team.run_stream(task="Write a program that prints 'Hello, world!'"):
  917. if isinstance(message, TaskResult):
  918. assert compare_task_results(message, result)
  919. else:
  920. assert compare_messages(message, result.messages[result_index])
  921. result_index += 1
  922. # Test Console.
  923. model_client.reset()
  924. agent1._count = 0 # pyright: ignore
  925. await team.reset()
  926. result2 = await Console(team.run_stream(task="Write a program that prints 'Hello, world!'"))
  927. assert compare_task_results(result2, result)
  928. @pytest.mark.asyncio
  929. async def test_selector_group_chat_two_speakers_allow_repeated(runtime: AgentRuntime | None) -> None:
  930. model_client = ReplayChatCompletionClient(
  931. [
  932. "agent2",
  933. "agent2",
  934. "agent1",
  935. ]
  936. )
  937. agent1 = _StopAgent("agent1", description="echo agent 1", stop_at=1)
  938. agent2 = _EchoAgent("agent2", description="echo agent 2")
  939. termination = TextMentionTermination("TERMINATE")
  940. team = SelectorGroupChat(
  941. participants=[agent1, agent2],
  942. model_client=model_client,
  943. termination_condition=termination,
  944. allow_repeated_speaker=True,
  945. runtime=runtime,
  946. )
  947. result = await team.run(task="Write a program that prints 'Hello, world!'")
  948. assert len(result.messages) == 4
  949. assert isinstance(result.messages[0], TextMessage)
  950. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  951. assert result.messages[1].source == "agent2"
  952. assert result.messages[2].source == "agent2"
  953. assert result.messages[3].source == "agent1"
  954. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  955. # Test streaming.
  956. model_client.reset()
  957. result_index = 0 # Include task message in result since output_task_messages=True by default
  958. await team.reset()
  959. async for message in team.run_stream(task="Write a program that prints 'Hello, world!'"):
  960. if isinstance(message, TaskResult):
  961. assert compare_task_results(message, result)
  962. else:
  963. assert compare_messages(message, result.messages[result_index])
  964. result_index += 1
  965. # Test Console.
  966. model_client.reset()
  967. await team.reset()
  968. result2 = await Console(team.run_stream(task="Write a program that prints 'Hello, world!'"))
  969. assert compare_task_results(result2, result)
  970. @pytest.mark.asyncio
  971. async def test_selector_group_chat_succcess_after_2_attempts(runtime: AgentRuntime | None) -> None:
  972. model_client = ReplayChatCompletionClient(
  973. ["agent2, agent3", "agent2"],
  974. )
  975. agent1 = _StopAgent("agent1", description="echo agent 1", stop_at=1)
  976. agent2 = _EchoAgent("agent2", description="echo agent 2")
  977. agent3 = _EchoAgent("agent3", description="echo agent 3")
  978. team = SelectorGroupChat(
  979. participants=[agent1, agent2, agent3],
  980. model_client=model_client,
  981. max_turns=1,
  982. runtime=runtime,
  983. )
  984. result = await team.run(task="Write a program that prints 'Hello, world!'")
  985. assert len(result.messages) == 2
  986. assert isinstance(result.messages[0], TextMessage)
  987. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  988. assert result.messages[1].source == "agent2"
  989. @pytest.mark.asyncio
  990. async def test_selector_group_chat_fall_back_to_first_after_3_attempts(runtime: AgentRuntime | None) -> None:
  991. model_client = ReplayChatCompletionClient(
  992. [
  993. "agent2, agent3", # Multiple speakers
  994. "agent5", # Non-existent speaker
  995. "agent3, agent1", # Multiple speakers
  996. ]
  997. )
  998. agent1 = _StopAgent("agent1", description="echo agent 1", stop_at=1)
  999. agent2 = _EchoAgent("agent2", description="echo agent 2")
  1000. agent3 = _EchoAgent("agent3", description="echo agent 3")
  1001. team = SelectorGroupChat(
  1002. participants=[agent1, agent2, agent3],
  1003. model_client=model_client,
  1004. max_turns=1,
  1005. runtime=runtime,
  1006. )
  1007. result = await team.run(task="Write a program that prints 'Hello, world!'")
  1008. assert len(result.messages) == 2
  1009. assert isinstance(result.messages[0], TextMessage)
  1010. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  1011. assert result.messages[1].source == "agent1"
  1012. @pytest.mark.asyncio
  1013. async def test_selector_group_chat_fall_back_to_previous_after_3_attempts(runtime: AgentRuntime | None) -> None:
  1014. model_client = ReplayChatCompletionClient(
  1015. ["agent2", "agent2", "agent2", "agent2"],
  1016. )
  1017. agent1 = _StopAgent("agent1", description="echo agent 1", stop_at=1)
  1018. agent2 = _EchoAgent("agent2", description="echo agent 2")
  1019. agent3 = _EchoAgent("agent3", description="echo agent 3")
  1020. team = SelectorGroupChat(
  1021. participants=[agent1, agent2, agent3],
  1022. model_client=model_client,
  1023. max_turns=2,
  1024. runtime=runtime,
  1025. )
  1026. result = await team.run(task="Write a program that prints 'Hello, world!'")
  1027. assert len(result.messages) == 3
  1028. assert isinstance(result.messages[0], TextMessage)
  1029. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  1030. assert result.messages[1].source == "agent2"
  1031. assert result.messages[2].source == "agent2"
  1032. @pytest.mark.asyncio
  1033. async def test_selector_group_chat_custom_selector(runtime: AgentRuntime | None) -> None:
  1034. model_client = ReplayChatCompletionClient(["agent3"])
  1035. agent1 = _EchoAgent("agent1", description="echo agent 1")
  1036. agent2 = _EchoAgent("agent2", description="echo agent 2")
  1037. agent3 = _EchoAgent("agent3", description="echo agent 3")
  1038. agent4 = _EchoAgent("agent4", description="echo agent 4")
  1039. def _select_agent(messages: Sequence[BaseAgentEvent | BaseChatMessage]) -> str | None:
  1040. if len(messages) == 0:
  1041. return "agent1"
  1042. elif messages[-1].source == "agent1":
  1043. return "agent2"
  1044. elif messages[-1].source == "agent2":
  1045. return None
  1046. elif messages[-1].source == "agent3":
  1047. return "agent4"
  1048. else:
  1049. return "agent1"
  1050. termination = MaxMessageTermination(6)
  1051. team = SelectorGroupChat(
  1052. participants=[agent1, agent2, agent3, agent4],
  1053. model_client=model_client,
  1054. selector_func=_select_agent,
  1055. termination_condition=termination,
  1056. runtime=runtime,
  1057. )
  1058. result = await team.run(task="task")
  1059. assert len(result.messages) == 6
  1060. assert result.messages[1].source == "agent1"
  1061. assert result.messages[2].source == "agent2"
  1062. assert result.messages[3].source == "agent3"
  1063. assert result.messages[4].source == "agent4"
  1064. assert result.messages[5].source == "agent1"
  1065. assert (
  1066. result.stop_reason is not None
  1067. and result.stop_reason == "Maximum number of messages 6 reached, current message count: 6"
  1068. )
  1069. @pytest.mark.asyncio
  1070. async def test_selector_group_chat_custom_candidate_func(runtime: AgentRuntime | None) -> None:
  1071. model_client = ReplayChatCompletionClient(["agent3"])
  1072. agent1 = _EchoAgent("agent1", description="echo agent 1")
  1073. agent2 = _EchoAgent("agent2", description="echo agent 2")
  1074. agent3 = _EchoAgent("agent3", description="echo agent 3")
  1075. agent4 = _EchoAgent("agent4", description="echo agent 4")
  1076. def _candidate_func(messages: Sequence[BaseAgentEvent | BaseChatMessage]) -> List[str]:
  1077. if len(messages) == 0:
  1078. return ["agent1"]
  1079. elif messages[-1].source == "agent1":
  1080. return ["agent2"]
  1081. elif messages[-1].source == "agent2":
  1082. return ["agent2", "agent3"] # will generate agent3
  1083. elif messages[-1].source == "agent3":
  1084. return ["agent4"]
  1085. else:
  1086. return ["agent1"]
  1087. termination = MaxMessageTermination(6)
  1088. team = SelectorGroupChat(
  1089. participants=[agent1, agent2, agent3, agent4],
  1090. model_client=model_client,
  1091. candidate_func=_candidate_func,
  1092. termination_condition=termination,
  1093. runtime=runtime,
  1094. )
  1095. result = await team.run(task="task")
  1096. assert len(result.messages) == 6
  1097. assert result.messages[1].source == "agent1"
  1098. assert result.messages[2].source == "agent2"
  1099. assert result.messages[3].source == "agent3"
  1100. assert result.messages[4].source == "agent4"
  1101. assert result.messages[5].source == "agent1"
  1102. assert (
  1103. result.stop_reason is not None
  1104. and result.stop_reason == "Maximum number of messages 6 reached, current message count: 6"
  1105. )
  1106. class _HandOffAgent(BaseChatAgent):
  1107. def __init__(self, name: str, description: str, next_agent: str) -> None:
  1108. super().__init__(name, description)
  1109. self._next_agent = next_agent
  1110. @property
  1111. def produced_message_types(self) -> Sequence[type[BaseChatMessage]]:
  1112. return (HandoffMessage,)
  1113. async def on_messages(self, messages: Sequence[BaseChatMessage], cancellation_token: CancellationToken) -> Response:
  1114. return Response(
  1115. chat_message=HandoffMessage(
  1116. content=f"Transferred to {self._next_agent}.", target=self._next_agent, source=self.name
  1117. )
  1118. )
  1119. async def on_reset(self, cancellation_token: CancellationToken) -> None:
  1120. pass
  1121. @pytest.mark.asyncio
  1122. async def test_swarm_handoff(runtime: AgentRuntime | None) -> None:
  1123. first_agent = _HandOffAgent("first_agent", description="first agent", next_agent="second_agent")
  1124. second_agent = _HandOffAgent("second_agent", description="second agent", next_agent="third_agent")
  1125. third_agent = _HandOffAgent("third_agent", description="third agent", next_agent="first_agent")
  1126. termination = MaxMessageTermination(6)
  1127. team = Swarm([second_agent, first_agent, third_agent], termination_condition=termination, runtime=runtime)
  1128. result = await team.run(task="task")
  1129. assert len(result.messages) == 6
  1130. assert isinstance(result.messages[0], TextMessage)
  1131. assert isinstance(result.messages[1], HandoffMessage)
  1132. assert isinstance(result.messages[2], HandoffMessage)
  1133. assert isinstance(result.messages[3], HandoffMessage)
  1134. assert isinstance(result.messages[4], HandoffMessage)
  1135. assert isinstance(result.messages[5], HandoffMessage)
  1136. assert result.messages[0].content == "task"
  1137. assert result.messages[1].content == "Transferred to third_agent."
  1138. assert result.messages[2].content == "Transferred to first_agent."
  1139. assert result.messages[3].content == "Transferred to second_agent."
  1140. assert result.messages[4].content == "Transferred to third_agent."
  1141. assert result.messages[5].content == "Transferred to first_agent."
  1142. assert (
  1143. result.stop_reason is not None
  1144. and result.stop_reason == "Maximum number of messages 6 reached, current message count: 6"
  1145. )
  1146. # Test streaming.
  1147. result_index = 0 # Include task message in result since output_task_messages=True by default
  1148. await team.reset()
  1149. stream = team.run_stream(task="task")
  1150. async for message in stream:
  1151. if isinstance(message, TaskResult):
  1152. assert compare_task_results(message, result)
  1153. else:
  1154. assert compare_messages(message, result.messages[result_index])
  1155. result_index += 1
  1156. # Test save and load.
  1157. state = await team.save_state()
  1158. first_agent2 = _HandOffAgent("first_agent", description="first agent", next_agent="second_agent")
  1159. second_agent2 = _HandOffAgent("second_agent", description="second agent", next_agent="third_agent")
  1160. third_agent2 = _HandOffAgent("third_agent", description="third agent", next_agent="first_agent")
  1161. team2 = Swarm([second_agent2, first_agent2, third_agent2], termination_condition=termination, runtime=runtime)
  1162. await team2.load_state(state)
  1163. state2 = await team2.save_state()
  1164. assert state == state2
  1165. manager_1 = await team._runtime.try_get_underlying_agent_instance( # pyright: ignore
  1166. AgentId(f"{team._group_chat_manager_name}_{team._team_id}", team._team_id), # pyright: ignore
  1167. SwarmGroupChatManager, # pyright: ignore
  1168. ) # pyright: ignore
  1169. manager_2 = await team2._runtime.try_get_underlying_agent_instance( # pyright: ignore
  1170. AgentId(f"{team2._group_chat_manager_name}_{team2._team_id}", team2._team_id), # pyright: ignore
  1171. SwarmGroupChatManager, # pyright: ignore
  1172. ) # pyright: ignore
  1173. assert manager_1._message_thread == manager_2._message_thread # pyright: ignore
  1174. assert manager_1._current_speaker == manager_2._current_speaker # pyright: ignore
  1175. @pytest.mark.asyncio
  1176. async def test_swarm_handoff_with_team_events(runtime: AgentRuntime | None) -> None:
  1177. first_agent = _HandOffAgent("first_agent", description="first agent", next_agent="second_agent")
  1178. second_agent = _HandOffAgent("second_agent", description="second agent", next_agent="third_agent")
  1179. third_agent = _HandOffAgent("third_agent", description="third agent", next_agent="first_agent")
  1180. termination = MaxMessageTermination(6)
  1181. team = Swarm(
  1182. [second_agent, first_agent, third_agent],
  1183. termination_condition=termination,
  1184. runtime=runtime,
  1185. emit_team_events=True,
  1186. )
  1187. result = await team.run(task="task")
  1188. assert len(result.messages) == 11
  1189. assert isinstance(result.messages[0], TextMessage)
  1190. assert isinstance(result.messages[1], SelectSpeakerEvent)
  1191. assert isinstance(result.messages[2], HandoffMessage)
  1192. assert isinstance(result.messages[3], SelectSpeakerEvent)
  1193. assert isinstance(result.messages[4], HandoffMessage)
  1194. assert isinstance(result.messages[5], SelectSpeakerEvent)
  1195. assert isinstance(result.messages[6], HandoffMessage)
  1196. assert isinstance(result.messages[7], SelectSpeakerEvent)
  1197. assert isinstance(result.messages[8], HandoffMessage)
  1198. assert isinstance(result.messages[9], SelectSpeakerEvent)
  1199. assert isinstance(result.messages[10], HandoffMessage)
  1200. assert result.messages[0].content == "task"
  1201. assert result.messages[1].content == ["second_agent"]
  1202. assert result.messages[2].content == "Transferred to third_agent."
  1203. assert result.messages[3].content == ["third_agent"]
  1204. assert result.messages[4].content == "Transferred to first_agent."
  1205. assert result.messages[5].content == ["first_agent"]
  1206. assert result.messages[6].content == "Transferred to second_agent."
  1207. assert result.messages[7].content == ["second_agent"]
  1208. assert result.messages[8].content == "Transferred to third_agent."
  1209. assert result.messages[9].content == ["third_agent"]
  1210. assert result.messages[10].content == "Transferred to first_agent."
  1211. assert (
  1212. result.stop_reason is not None
  1213. and result.stop_reason == "Maximum number of messages 6 reached, current message count: 6"
  1214. )
  1215. # Test streaming.
  1216. result_index = 0 # Include task message in result since output_task_messages=True by default
  1217. await team.reset()
  1218. stream = team.run_stream(task="task")
  1219. async for message in stream:
  1220. if isinstance(message, TaskResult):
  1221. assert compare_task_results(message, result)
  1222. else:
  1223. assert compare_messages(message, result.messages[result_index])
  1224. result_index += 1
  1225. @pytest.mark.asyncio
  1226. @pytest.mark.parametrize(
  1227. "task",
  1228. [
  1229. "Write a program that prints 'Hello, world!'",
  1230. [TextMessage(content="Write a program that prints 'Hello, world!'", source="user")],
  1231. [MultiModalMessage(content=["Write a program that prints 'Hello, world!'"], source="user")],
  1232. [
  1233. StructuredMessage[_InputTask1](
  1234. content=_InputTask1(task="Write a program that prints 'Hello, world!'", data=["a", "b", "c"]),
  1235. source="user",
  1236. ),
  1237. StructuredMessage[_InputTask2](
  1238. content=_InputTask2(task="Write a program that prints 'Hello, world!'", data="a"), source="user"
  1239. ),
  1240. ],
  1241. ],
  1242. ids=["text", "text_message", "multi_modal_message", "structured_message"],
  1243. )
  1244. async def test_swarm_handoff_state(task: TaskType, runtime: AgentRuntime | None) -> None:
  1245. first_agent = _HandOffAgent("first_agent", description="first agent", next_agent="second_agent")
  1246. second_agent = _HandOffAgent("second_agent", description="second agent", next_agent="third_agent")
  1247. third_agent = _HandOffAgent("third_agent", description="third agent", next_agent="first_agent")
  1248. termination = MaxMessageTermination(6)
  1249. team1 = Swarm(
  1250. [second_agent, first_agent, third_agent],
  1251. termination_condition=termination,
  1252. runtime=runtime,
  1253. custom_message_types=[StructuredMessage[_InputTask1], StructuredMessage[_InputTask2]],
  1254. )
  1255. await team1.run(task=task)
  1256. state = await team1.save_state()
  1257. first_agent2 = _HandOffAgent("first_agent", description="first agent", next_agent="second_agent")
  1258. second_agent2 = _HandOffAgent("second_agent", description="second agent", next_agent="third_agent")
  1259. third_agent2 = _HandOffAgent("third_agent", description="third agent", next_agent="first_agent")
  1260. team2 = Swarm(
  1261. [second_agent2, first_agent2, third_agent2],
  1262. termination_condition=termination,
  1263. runtime=runtime,
  1264. custom_message_types=[StructuredMessage[_InputTask1], StructuredMessage[_InputTask2]],
  1265. )
  1266. await team2.load_state(state)
  1267. state2 = await team2.save_state()
  1268. assert state == state2
  1269. manager_1 = await team1._runtime.try_get_underlying_agent_instance( # pyright: ignore
  1270. AgentId(f"{team1._group_chat_manager_name}_{team1._team_id}", team1._team_id), # pyright: ignore
  1271. SwarmGroupChatManager, # pyright: ignore
  1272. )
  1273. manager_2 = await team2._runtime.try_get_underlying_agent_instance( # pyright: ignore
  1274. AgentId(f"{team2._group_chat_manager_name}_{team2._team_id}", team2._team_id), # pyright: ignore
  1275. SwarmGroupChatManager, # pyright: ignore
  1276. )
  1277. assert manager_1._message_thread == manager_2._message_thread # pyright: ignore
  1278. assert manager_1._current_speaker == manager_2._current_speaker # pyright: ignore
  1279. @pytest.mark.asyncio
  1280. async def test_swarm_handoff_using_tool_calls(runtime: AgentRuntime | None) -> None:
  1281. model_client = ReplayChatCompletionClient(
  1282. chat_completions=[
  1283. CreateResult(
  1284. finish_reason="function_calls",
  1285. content=[FunctionCall(id="1", name="handoff_to_agent2", arguments=json.dumps({}))],
  1286. usage=RequestUsage(prompt_tokens=0, completion_tokens=0),
  1287. cached=False,
  1288. ),
  1289. "Hello",
  1290. "TERMINATE",
  1291. ],
  1292. model_info={
  1293. "family": "gpt-4.1-nano",
  1294. "function_calling": True,
  1295. "json_output": True,
  1296. "vision": True,
  1297. "structured_output": True,
  1298. },
  1299. )
  1300. agent1 = AssistantAgent(
  1301. "agent1",
  1302. model_client=model_client,
  1303. handoffs=[Handoff(target="agent2", name="handoff_to_agent2", message="handoff to agent2")],
  1304. )
  1305. agent2 = _HandOffAgent("agent2", description="agent 2", next_agent="agent1")
  1306. termination = TextMentionTermination("TERMINATE")
  1307. team = Swarm([agent1, agent2], termination_condition=termination, runtime=runtime)
  1308. result = await team.run(task="task")
  1309. assert len(result.messages) == 7
  1310. assert isinstance(result.messages[0], TextMessage)
  1311. assert result.messages[0].content == "task"
  1312. assert isinstance(result.messages[1], ToolCallRequestEvent)
  1313. assert isinstance(result.messages[2], ToolCallExecutionEvent)
  1314. assert isinstance(result.messages[3], HandoffMessage)
  1315. assert isinstance(result.messages[4], HandoffMessage)
  1316. assert isinstance(result.messages[5], TextMessage)
  1317. assert isinstance(result.messages[6], TextMessage)
  1318. assert result.messages[3].content == "handoff to agent2"
  1319. assert result.messages[4].content == "Transferred to agent1."
  1320. assert result.messages[5].content == "Hello"
  1321. assert result.messages[6].content == "TERMINATE"
  1322. assert result.stop_reason is not None and result.stop_reason == "Text 'TERMINATE' mentioned"
  1323. # Test streaming.
  1324. await agent1._model_context.clear() # pyright: ignore
  1325. model_client.reset()
  1326. result_index = 0 # Include task message in result since output_task_messages=True by default
  1327. await team.reset()
  1328. stream = team.run_stream(task="task")
  1329. async for message in stream:
  1330. if isinstance(message, TaskResult):
  1331. assert compare_task_results(message, result)
  1332. else:
  1333. assert compare_messages(message, result.messages[result_index])
  1334. result_index += 1
  1335. # Test Console
  1336. await agent1._model_context.clear() # pyright: ignore
  1337. model_client.reset()
  1338. await team.reset()
  1339. result2 = await Console(team.run_stream(task="task"))
  1340. assert compare_task_results(result2, result)
  1341. @pytest.mark.asyncio
  1342. async def test_swarm_pause_and_resume(runtime: AgentRuntime | None) -> None:
  1343. first_agent = _HandOffAgent("first_agent", description="first agent", next_agent="second_agent")
  1344. second_agent = _HandOffAgent("second_agent", description="second agent", next_agent="third_agent")
  1345. third_agent = _HandOffAgent("third_agent", description="third agent", next_agent="first_agent")
  1346. team = Swarm([second_agent, first_agent, third_agent], max_turns=1, runtime=runtime)
  1347. result = await team.run(task="task")
  1348. assert len(result.messages) == 2
  1349. assert isinstance(result.messages[0], TextMessage)
  1350. assert isinstance(result.messages[1], HandoffMessage)
  1351. assert result.messages[0].content == "task"
  1352. assert result.messages[1].content == "Transferred to third_agent."
  1353. # Resume with a new task.
  1354. result = await team.run(task="new task")
  1355. assert len(result.messages) == 2
  1356. assert isinstance(result.messages[0], TextMessage)
  1357. assert isinstance(result.messages[1], HandoffMessage)
  1358. assert result.messages[0].content == "new task"
  1359. assert result.messages[1].content == "Transferred to first_agent."
  1360. # Resume with the same task.
  1361. result = await team.run()
  1362. assert len(result.messages) == 1
  1363. assert isinstance(result.messages[0], HandoffMessage)
  1364. assert result.messages[0].content == "Transferred to second_agent."
  1365. @pytest.mark.asyncio
  1366. async def test_swarm_with_parallel_tool_calls(runtime: AgentRuntime | None) -> None:
  1367. model_client = ReplayChatCompletionClient(
  1368. [
  1369. CreateResult(
  1370. finish_reason="function_calls",
  1371. content=[
  1372. FunctionCall(id="1", name="tool1", arguments="{}"),
  1373. FunctionCall(id="2", name="tool2", arguments="{}"),
  1374. FunctionCall(id="3", name="handoff_to_agent2", arguments=json.dumps({})),
  1375. ],
  1376. usage=RequestUsage(prompt_tokens=0, completion_tokens=0),
  1377. cached=False,
  1378. ),
  1379. "Hello",
  1380. "TERMINATE",
  1381. ],
  1382. model_info={
  1383. "family": "gpt-4.1-nano",
  1384. "function_calling": True,
  1385. "json_output": True,
  1386. "vision": True,
  1387. "structured_output": True,
  1388. },
  1389. )
  1390. expected_handoff_context: List[LLMMessage] = [
  1391. AssistantMessage(
  1392. source="agent1",
  1393. content=[
  1394. FunctionCall(id="1", name="tool1", arguments="{}"),
  1395. FunctionCall(id="2", name="tool2", arguments="{}"),
  1396. ],
  1397. ),
  1398. FunctionExecutionResultMessage(
  1399. content=[
  1400. FunctionExecutionResult(content="tool1", call_id="1", is_error=False, name="tool1"),
  1401. FunctionExecutionResult(content="tool2", call_id="2", is_error=False, name="tool2"),
  1402. ]
  1403. ),
  1404. ]
  1405. def tool1() -> str:
  1406. return "tool1"
  1407. def tool2() -> str:
  1408. return "tool2"
  1409. agent1 = AssistantAgent(
  1410. "agent1",
  1411. model_client=model_client,
  1412. handoffs=[Handoff(target="agent2", name="handoff_to_agent2", message="handoff to agent2")],
  1413. tools=[tool1, tool2],
  1414. )
  1415. agent2 = AssistantAgent(
  1416. "agent2",
  1417. model_client=model_client,
  1418. )
  1419. termination = TextMentionTermination("TERMINATE")
  1420. team = Swarm([agent1, agent2], termination_condition=termination, runtime=runtime)
  1421. result = await team.run(task="task")
  1422. assert len(result.messages) == 6
  1423. assert compare_messages(result.messages[0], TextMessage(content="task", source="user"))
  1424. assert isinstance(result.messages[1], ToolCallRequestEvent)
  1425. assert isinstance(result.messages[2], ToolCallExecutionEvent)
  1426. assert compare_messages(
  1427. result.messages[3],
  1428. HandoffMessage(
  1429. content="handoff to agent2",
  1430. target="agent2",
  1431. source="agent1",
  1432. context=expected_handoff_context,
  1433. ),
  1434. )
  1435. assert isinstance(result.messages[4], TextMessage)
  1436. assert result.messages[4].content == "Hello"
  1437. assert result.messages[4].source == "agent2"
  1438. assert isinstance(result.messages[5], TextMessage)
  1439. assert result.messages[5].content == "TERMINATE"
  1440. assert result.messages[5].source == "agent2"
  1441. # Verify the tool calls are in agent2's context.
  1442. agent2_model_ctx_messages = await agent2._model_context.get_messages() # pyright: ignore
  1443. assert agent2_model_ctx_messages[0] == UserMessage(content="task", source="user")
  1444. assert agent2_model_ctx_messages[1] == expected_handoff_context[0]
  1445. assert agent2_model_ctx_messages[2] == expected_handoff_context[1]
  1446. @pytest.mark.asyncio
  1447. async def test_swarm_with_handoff_termination(runtime: AgentRuntime | None) -> None:
  1448. first_agent = _HandOffAgent("first_agent", description="first agent", next_agent="second_agent")
  1449. second_agent = _HandOffAgent("second_agent", description="second agent", next_agent="third_agent")
  1450. third_agent = _HandOffAgent("third_agent", description="third agent", next_agent="first_agent")
  1451. # Handoff to an existing agent.
  1452. termination = HandoffTermination(target="third_agent")
  1453. team = Swarm([second_agent, first_agent, third_agent], termination_condition=termination, runtime=runtime)
  1454. # Start
  1455. result = await team.run(task="task")
  1456. assert len(result.messages) == 2
  1457. assert isinstance(result.messages[0], TextMessage)
  1458. assert isinstance(result.messages[1], HandoffMessage)
  1459. assert result.messages[0].content == "task"
  1460. assert result.messages[1].content == "Transferred to third_agent."
  1461. # Resume existing.
  1462. result = await team.run()
  1463. assert len(result.messages) == 3
  1464. assert isinstance(result.messages[0], HandoffMessage)
  1465. assert isinstance(result.messages[1], HandoffMessage)
  1466. assert isinstance(result.messages[2], HandoffMessage)
  1467. assert result.messages[0].content == "Transferred to first_agent."
  1468. assert result.messages[1].content == "Transferred to second_agent."
  1469. assert result.messages[2].content == "Transferred to third_agent."
  1470. # Resume new task.
  1471. result = await team.run(task="new task")
  1472. assert len(result.messages) == 4
  1473. assert isinstance(result.messages[0], TextMessage)
  1474. assert isinstance(result.messages[1], HandoffMessage)
  1475. assert isinstance(result.messages[2], HandoffMessage)
  1476. assert isinstance(result.messages[3], HandoffMessage)
  1477. assert result.messages[0].content == "new task"
  1478. assert result.messages[1].content == "Transferred to first_agent."
  1479. assert result.messages[2].content == "Transferred to second_agent."
  1480. assert result.messages[3].content == "Transferred to third_agent."
  1481. # Handoff to a non-existing agent.
  1482. third_agent = _HandOffAgent("third_agent", description="third agent", next_agent="non_existing_agent")
  1483. termination = HandoffTermination(target="non_existing_agent")
  1484. team = Swarm([second_agent, first_agent, third_agent], termination_condition=termination, runtime=runtime)
  1485. # Start
  1486. result = await team.run(task="task")
  1487. assert len(result.messages) == 3
  1488. assert isinstance(result.messages[0], TextMessage)
  1489. assert isinstance(result.messages[1], HandoffMessage)
  1490. assert isinstance(result.messages[2], HandoffMessage)
  1491. assert result.messages[0].content == "task"
  1492. assert result.messages[1].content == "Transferred to third_agent."
  1493. assert result.messages[2].content == "Transferred to non_existing_agent."
  1494. # Attempt to resume.
  1495. with pytest.raises(ValueError):
  1496. await team.run()
  1497. # Attempt to resume with a new task.
  1498. with pytest.raises(ValueError):
  1499. await team.run(task="new task")
  1500. # Resume with a HandoffMessage
  1501. result = await team.run(task=HandoffMessage(content="Handoff to first_agent.", target="first_agent", source="user"))
  1502. assert len(result.messages) == 4
  1503. assert isinstance(result.messages[0], HandoffMessage)
  1504. assert isinstance(result.messages[1], HandoffMessage)
  1505. assert isinstance(result.messages[2], HandoffMessage)
  1506. assert isinstance(result.messages[3], HandoffMessage)
  1507. assert result.messages[0].content == "Handoff to first_agent."
  1508. assert result.messages[1].content == "Transferred to second_agent."
  1509. assert result.messages[2].content == "Transferred to third_agent."
  1510. assert result.messages[3].content == "Transferred to non_existing_agent."
  1511. @pytest.mark.asyncio
  1512. async def test_round_robin_group_chat_with_message_list(runtime: AgentRuntime | None) -> None:
  1513. # Create a simple team with echo agents
  1514. agent1 = _EchoAgent("Agent1", "First agent")
  1515. agent2 = _EchoAgent("Agent2", "Second agent")
  1516. termination = MaxMessageTermination(4) # Stop after 4 messages
  1517. team = RoundRobinGroupChat([agent1, agent2], termination_condition=termination, runtime=runtime)
  1518. # Create a list of messages
  1519. messages: List[BaseChatMessage] = [
  1520. TextMessage(content="Message 1", source="user"),
  1521. TextMessage(content="Message 2", source="user"),
  1522. TextMessage(content="Message 3", source="user"),
  1523. ]
  1524. # Run the team with the message list
  1525. result = await team.run(task=messages)
  1526. # Verify the messages were processed in order
  1527. assert len(result.messages) == 4 # Initial messages + echo until termination
  1528. assert isinstance(result.messages[0], TextMessage)
  1529. assert isinstance(result.messages[1], TextMessage)
  1530. assert isinstance(result.messages[2], TextMessage)
  1531. assert isinstance(result.messages[3], TextMessage)
  1532. assert result.messages[0].content == "Message 1" # First message
  1533. assert result.messages[1].content == "Message 2" # Second message
  1534. assert result.messages[2].content == "Message 3" # Third message
  1535. assert result.messages[3].content == "Message 1" # Echo from first agent
  1536. assert result.stop_reason == "Maximum number of messages 4 reached, current message count: 4"
  1537. # Test with streaming
  1538. await team.reset()
  1539. result_index = 0 # Include the 3 task messages in result since output_task_messages=True by default
  1540. async for message in team.run_stream(task=messages):
  1541. if isinstance(message, TaskResult):
  1542. assert compare_task_results(message, result)
  1543. else:
  1544. assert compare_messages(message, result.messages[result_index])
  1545. result_index += 1
  1546. # Test with invalid message list
  1547. with pytest.raises(ValueError, match="All messages in task list must be valid BaseChatMessage types"):
  1548. await team.run(task=["not a message"]) # type: ignore[list-item, arg-type] # intentionally testing invalid input
  1549. # Test with empty message list
  1550. with pytest.raises(ValueError, match="Task list cannot be empty"):
  1551. await team.run(task=[])
  1552. @pytest.mark.asyncio
  1553. async def test_declarative_groupchats_with_config(runtime: AgentRuntime | None) -> None:
  1554. # Create basic agents and components for testing
  1555. agent1 = AssistantAgent(
  1556. "agent_1",
  1557. model_client=OpenAIChatCompletionClient(model="gpt-4.1-nano-2025-04-14", api_key=""),
  1558. handoffs=["agent_2"],
  1559. )
  1560. agent2 = AssistantAgent(
  1561. "agent_2", model_client=OpenAIChatCompletionClient(model="gpt-4.1-nano-2025-04-14", api_key="")
  1562. )
  1563. termination = MaxMessageTermination(4)
  1564. model_client = OpenAIChatCompletionClient(model="gpt-4.1-nano-2025-04-14", api_key="")
  1565. # Test round robin - verify config is preserved
  1566. round_robin = RoundRobinGroupChat(participants=[agent1, agent2], termination_condition=termination, max_turns=5)
  1567. config = round_robin.dump_component()
  1568. loaded = RoundRobinGroupChat.load_component(config)
  1569. assert loaded.dump_component() == config
  1570. # Test selector group chat - verify config is preserved
  1571. selector_prompt = "Custom selector prompt with {roles}, {participants}, {history}"
  1572. selector = SelectorGroupChat(
  1573. participants=[agent1, agent2],
  1574. model_client=model_client,
  1575. termination_condition=termination,
  1576. max_turns=10,
  1577. selector_prompt=selector_prompt,
  1578. allow_repeated_speaker=True,
  1579. runtime=runtime,
  1580. )
  1581. selector_config = selector.dump_component()
  1582. selector_loaded = SelectorGroupChat.load_component(selector_config)
  1583. assert selector_loaded.dump_component() == selector_config
  1584. # Test swarm with handoff termination
  1585. handoff_termination = HandoffTermination(target="Agent2")
  1586. swarm = Swarm(
  1587. participants=[agent1, agent2], termination_condition=handoff_termination, max_turns=5, runtime=runtime
  1588. )
  1589. swarm_config = swarm.dump_component()
  1590. swarm_loaded = Swarm.load_component(swarm_config)
  1591. assert swarm_loaded.dump_component() == swarm_config
  1592. # Test MagenticOne with custom parameters
  1593. magentic = MagenticOneGroupChat(
  1594. participants=[agent1],
  1595. model_client=model_client,
  1596. max_turns=15,
  1597. max_stalls=5,
  1598. final_answer_prompt="Custom prompt",
  1599. runtime=runtime,
  1600. )
  1601. magentic_config = magentic.dump_component()
  1602. magentic_loaded = MagenticOneGroupChat.load_component(magentic_config)
  1603. assert magentic_loaded.dump_component() == magentic_config
  1604. # Verify component types are correctly set for each
  1605. for team in [loaded, selector, swarm, magentic]:
  1606. assert team.component_type == "team"
  1607. # Verify provider strings are correctly set
  1608. assert round_robin.dump_component().provider == "autogen_agentchat.teams.RoundRobinGroupChat"
  1609. assert selector.dump_component().provider == "autogen_agentchat.teams.SelectorGroupChat"
  1610. assert swarm.dump_component().provider == "autogen_agentchat.teams.Swarm"
  1611. assert magentic.dump_component().provider == "autogen_agentchat.teams.MagenticOneGroupChat"
  1612. class _StructuredContent(BaseModel):
  1613. message: str
  1614. class _StructuredAgent(BaseChatAgent):
  1615. def __init__(self, name: str, description: str) -> None:
  1616. super().__init__(name, description)
  1617. self._message = _StructuredContent(message="Structured hello")
  1618. @property
  1619. def produced_message_types(self) -> Sequence[type[BaseChatMessage]]:
  1620. return (StructuredMessage[_StructuredContent],)
  1621. async def on_messages(self, messages: Sequence[BaseChatMessage], cancellation_token: CancellationToken) -> Response:
  1622. return Response(
  1623. chat_message=StructuredMessage[_StructuredContent](
  1624. source=self.name,
  1625. content=self._message,
  1626. format_string="Structured says: {message}",
  1627. )
  1628. )
  1629. async def on_reset(self, cancellation_token: CancellationToken) -> None:
  1630. pass
  1631. @pytest.mark.asyncio
  1632. async def test_message_type_auto_registration(runtime: AgentRuntime | None) -> None:
  1633. agent1 = _StructuredAgent("structured", description="emits structured messages")
  1634. agent2 = _EchoAgent("echo", description="echoes input")
  1635. team = RoundRobinGroupChat(participants=[agent1, agent2], max_turns=2, runtime=runtime)
  1636. result = await team.run(task="Say something structured")
  1637. assert len(result.messages) == 3
  1638. assert isinstance(result.messages[0], TextMessage)
  1639. assert isinstance(result.messages[1], StructuredMessage)
  1640. assert isinstance(result.messages[2], TextMessage)
  1641. assert result.messages[1].to_text() == "Structured says: Structured hello"
  1642. @pytest.mark.asyncio
  1643. async def test_structured_message_state_roundtrip(runtime: AgentRuntime | None) -> None:
  1644. agent1 = _StructuredAgent("structured", description="sends structured")
  1645. agent2 = _EchoAgent("echo", description="echoes")
  1646. team1 = RoundRobinGroupChat(
  1647. participants=[agent1, agent2],
  1648. termination_condition=MaxMessageTermination(2),
  1649. runtime=runtime,
  1650. )
  1651. await team1.run(task="Say something structured")
  1652. state1 = await team1.save_state()
  1653. # Recreate team without needing custom_message_types
  1654. agent3 = _StructuredAgent("structured", description="sends structured")
  1655. agent4 = _EchoAgent("echo", description="echoes")
  1656. team2 = RoundRobinGroupChat(
  1657. participants=[agent3, agent4],
  1658. termination_condition=MaxMessageTermination(2),
  1659. runtime=runtime,
  1660. )
  1661. await team2.load_state(state1)
  1662. state2 = await team2.save_state()
  1663. # Assert full state equality
  1664. assert state1 == state2
  1665. # Assert message thread content match
  1666. manager1 = await team1._runtime.try_get_underlying_agent_instance( # pyright: ignore
  1667. AgentId(f"{team1._group_chat_manager_name}_{team1._team_id}", team1._team_id), # pyright: ignore
  1668. RoundRobinGroupChatManager,
  1669. )
  1670. manager2 = await team2._runtime.try_get_underlying_agent_instance( # pyright: ignore
  1671. AgentId(f"{team2._group_chat_manager_name}_{team2._team_id}", team2._team_id), # pyright: ignore
  1672. RoundRobinGroupChatManager,
  1673. )
  1674. assert manager1._message_thread == manager2._message_thread # pyright: ignore
  1675. @pytest.mark.asyncio
  1676. async def test_selector_group_chat_streaming(runtime: AgentRuntime | None) -> None:
  1677. model_client = ReplayChatCompletionClient(
  1678. ["the agent should be agent2"],
  1679. )
  1680. agent2 = _StopAgent("agent2", description="stop agent 2", stop_at=0)
  1681. agent3 = _EchoAgent("agent3", description="echo agent 3")
  1682. termination = StopMessageTermination()
  1683. team = SelectorGroupChat(
  1684. participants=[agent2, agent3],
  1685. model_client=model_client,
  1686. termination_condition=termination,
  1687. runtime=runtime,
  1688. emit_team_events=True,
  1689. model_client_streaming=True,
  1690. )
  1691. result = await team.run(
  1692. task="Write a program that prints 'Hello, world!'",
  1693. )
  1694. assert len(result.messages) == 4
  1695. assert isinstance(result.messages[0], TextMessage)
  1696. assert isinstance(result.messages[1], SelectorEvent)
  1697. assert isinstance(result.messages[2], SelectSpeakerEvent)
  1698. assert isinstance(result.messages[3], StopMessage)
  1699. assert result.messages[0].content == "Write a program that prints 'Hello, world!'"
  1700. assert result.messages[1].content == "the agent should be agent2"
  1701. assert result.messages[2].content == ["agent2"]
  1702. assert result.messages[3].source == "agent2"
  1703. assert result.stop_reason is not None and result.stop_reason == "Stop message received"
  1704. # Test streaming
  1705. await team.reset()
  1706. model_client.reset()
  1707. result_index = 0 # Include task message in result since output_task_messages=True by default
  1708. streamed_chunks: List[str] = []
  1709. final_result: TaskResult | None = None
  1710. async for message in team.run_stream(
  1711. task="Write a program that prints 'Hello, world!'",
  1712. ):
  1713. if isinstance(message, TaskResult):
  1714. final_result = message
  1715. assert compare_task_results(message, result)
  1716. elif isinstance(message, ModelClientStreamingChunkEvent):
  1717. streamed_chunks.append(message.content)
  1718. else:
  1719. if streamed_chunks:
  1720. assert isinstance(message, SelectorEvent)
  1721. assert message.content == "".join(streamed_chunks)
  1722. streamed_chunks = []
  1723. assert compare_messages(message, result.messages[result_index])
  1724. result_index += 1
  1725. # Verify we got the expected messages without relying on fragile ordering
  1726. assert final_result is not None
  1727. assert len(streamed_chunks) == 0 # All chunks should have been processed
  1728. # Content-based verification instead of index-based
  1729. # Note: The streaming test verifies the streaming behavior, not the final result content