autogen
autogen copied to clipboard
AgentChat task message type and group chat state validation for Swarm
Resolves #4199
taskcan be ChatMessage type- Add group chat state validation step,and address swarm state valiation
- Change handling of start and reset to RPC and capture any error from running without affecting the group chat runtime state.
- Misc fixes for docs
Example of Swarm + HandoffTermination:
import asyncio
from autogen_ext.models import OpenAIChatCompletionClient
from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import Swarm
from autogen_agentchat.task import HandoffTermination, Console, MaxMessageTermination
from autogen_agentchat.messages import HandoffMessage
async def main() -> None:
model_client = OpenAIChatCompletionClient(model="gpt-4o")
agent = AssistantAgent(
"Alice",
model_client=model_client,
handoffs=["user"],
system_message="You are Alice and you only answer questions about yourself, ask the user for help if needed.",
)
termination = HandoffTermination(target="user") | MaxMessageTermination(3)
team = Swarm([agent], termination_condition=termination)
# Start the conversation.
await Console(team.run_stream(task="What is bob's birthday?"))
# Resume with user feedback.
await Console(team.run_stream(task=HandoffMessage(source="user", target="Alice", content="Bob's birthday is on 1st January.")))
asyncio.run(main())
---------- user ----------
What is bob's birthday?
---------- Alice ----------
I can only answer questions about myself. If you need information about Bob's birthday, you might need to ask directly or consult someone who knows him.
[Prompt tokens: 63, Completion tokens: 31]
---------- Alice ----------
[FunctionCall(id='call_5mA1B4MigcfS7Ebpz2al1Q5X', arguments='{}', name='transfer_to_user')]
[Prompt tokens: 99, Completion tokens: 11]
---------- Alice ----------
[FunctionExecutionResult(content='Transferred to user, adopting the role of user immediately.', call_id='call_5mA1B4MigcfS7Ebpz2al1Q5X')]
---------- Alice ----------
Transferred to user, adopting the role of user immediately.
---------- Summary ----------
Number of messages: 5
Finish reason: Handoff to user from Alice detected., Maximum number of messages 3 reached, current message count: 5
Total prompt tokens: 162
Total completion tokens: 42
Duration: 1.26 seconds
---------- user ----------
Bob's birthday is on 1st January.
---------- Alice ----------
Thank you for providing that information! If you have any questions about me, feel free to ask.
[Prompt tokens: 147, Completion tokens: 21]
---------- Alice ----------
Do you have any questions about me, Alice?
[Prompt tokens: 173, Completion tokens: 11]
---------- Summary ----------
Number of messages: 3
Finish reason: Maximum number of messages 3 reached, current message count: 3
Total prompt tokens: 320
Total completion tokens: 32
Duration: 1.00 seconds
Example of getting error if the resuming message is not a handoff message:
# same as above until resume
# Resume with a wrong message type.
await Console(team.run_stream(task="Bob's birthday is on 1st January."))
---------- user ----------
What is bob's birthday?
---------- Alice ----------
[FunctionCall(id='call_WtpRq2NKtRh9EqYtqAKpS9vm', arguments='{}', name='transfer_to_user')]
[Prompt tokens: 63, Completion tokens: 11]
---------- Alice ----------
[FunctionExecutionResult(content='Transferred to user, adopting the role of user immediately.', call_id='call_WtpRq2NKtRh9EqYtqAKpS9vm')]
---------- Alice ----------
Transferred to user, adopting the role of user immediately.
---------- Summary ----------
Number of messages: 4
Finish reason: Handoff to user from Alice detected., Maximum number of messages 3 reached, current message count: 4
Total prompt tokens: 63
Total completion tokens: 11
Duration: 0.56 seconds
Traceback (most recent call last):
File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/test.py", line 28, in <module>
asyncio.run(main())
File "/Users/ekzhu/miniconda3/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/Users/ekzhu/miniconda3/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ekzhu/miniconda3/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/test.py", line 25, in main
await Console(team.run_stream(task="Bob's birthday is on 1st January."))
File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/task/_console.py", line 33, in Console
async for message in stream:
File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_base_group_chat.py", line 288, in run_stream
await self._runtime.send_message(
File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/application/_single_threaded_agent_runtime.py", line 233, in send_message
return await future
^^^^^^^^^^^^
File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/application/_single_threaded_agent_runtime.py", line 315, in _process_send
response = await recipient_agent.on_message(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_sequential_routed_agent.py", line 49, in on_message
return await super().on_message(message, ctx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/components/_routed_agent.py", line 468, in on_message
return await h(self, message, ctx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ekzhu/autogen/python/packages/autogen-core/src/autogen_core/components/_routed_agent.py", line 388, in wrapper
return_value = await func(self, message, ctx)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_base_group_chat_manager.py", line 74, in handle_start
await self.validate_group_state(message.message)
File "/Users/ekzhu/autogen/python/packages/autogen-agentchat/src/autogen_agentchat/teams/_group_chat/_swarm_group_chat.py", line 49, in validate_group_state
raise ValueError(
ValueError: The existing handoff target user is not one of the participants ['Alice']. If you are resuming Swarm with a new task make sure to include in your task a HandoffMessage with a valid participant as the target. For example, if you are resuming from a HandoffTermination, make sure the new task is a HandoffMessage with a valid participant as the target.