Skip to content

Commit e902e94

Browse files
authored
Define AgentEvent, rename tool call messages to events. (#4750)
* Define AgentEvent, rename tool call messages to events. * update doc * Use AgentEvent | ChatMessage to replace AgentMessage * Update docs * update deprecation notice * remove unused * fix doc * format
1 parent 7a7eb74 commit e902e94

34 files changed

+3642
-3615
lines changed

python/packages/autogen-agentchat/src/autogen_agentchat/agents/_assistant_agent.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
from ..base import Handoff as HandoffBase
2222
from ..base import Response
2323
from ..messages import (
24-
AgentMessage,
24+
AgentEvent,
2525
ChatMessage,
2626
HandoffMessage,
2727
MultiModalMessage,
2828
TextMessage,
29-
ToolCallMessage,
30-
ToolCallResultMessage,
29+
ToolCallExecutionEvent,
30+
ToolCallRequestEvent,
3131
)
3232
from ..state import AssistantAgentState
3333
from ._base_chat_agent import BaseChatAgent
@@ -292,15 +292,15 @@ async def on_messages(self, messages: Sequence[ChatMessage], cancellation_token:
292292

293293
async def on_messages_stream(
294294
self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken
295-
) -> AsyncGenerator[AgentMessage | Response, None]:
295+
) -> AsyncGenerator[AgentEvent | ChatMessage | Response, None]:
296296
# Add messages to the model context.
297297
for msg in messages:
298298
if isinstance(msg, MultiModalMessage) and self._model_client.capabilities["vision"] is False:
299299
raise ValueError("The model does not support vision.")
300300
self._model_context.append(UserMessage(content=msg.content, source=msg.source))
301301

302302
# Inner messages.
303-
inner_messages: List[AgentMessage] = []
303+
inner_messages: List[AgentEvent | ChatMessage] = []
304304

305305
# Generate an inference result based on the current model context.
306306
llm_messages = self._system_messages + self._model_context
@@ -321,15 +321,15 @@ async def on_messages_stream(
321321

322322
# Process tool calls.
323323
assert isinstance(result.content, list) and all(isinstance(item, FunctionCall) for item in result.content)
324-
tool_call_msg = ToolCallMessage(content=result.content, source=self.name, models_usage=result.usage)
324+
tool_call_msg = ToolCallRequestEvent(content=result.content, source=self.name, models_usage=result.usage)
325325
event_logger.debug(tool_call_msg)
326326
# Add the tool call message to the output.
327327
inner_messages.append(tool_call_msg)
328328
yield tool_call_msg
329329

330330
# Execute the tool calls.
331331
results = await asyncio.gather(*[self._execute_tool_call(call, cancellation_token) for call in result.content])
332-
tool_call_result_msg = ToolCallResultMessage(content=results, source=self.name)
332+
tool_call_result_msg = ToolCallExecutionEvent(content=results, source=self.name)
333333
event_logger.debug(tool_call_result_msg)
334334
self._model_context.append(FunctionExecutionResultMessage(content=results))
335335
inner_messages.append(tool_call_result_msg)

python/packages/autogen-agentchat/src/autogen_agentchat/agents/_base_chat_agent.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from ..base import ChatAgent, Response, TaskResult
77
from ..messages import (
8-
AgentMessage,
8+
AgentEvent,
99
ChatMessage,
1010
TextMessage,
1111
)
@@ -58,7 +58,7 @@ async def on_messages(self, messages: Sequence[ChatMessage], cancellation_token:
5858

5959
async def on_messages_stream(
6060
self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken
61-
) -> AsyncGenerator[AgentMessage | Response, None]:
61+
) -> AsyncGenerator[AgentEvent | ChatMessage | Response, None]:
6262
"""Handles incoming messages and returns a stream of messages and
6363
and the final item is the response. The base implementation in
6464
:class:`BaseChatAgent` simply calls :meth:`on_messages` and yields
@@ -89,7 +89,7 @@ async def run(
8989
if cancellation_token is None:
9090
cancellation_token = CancellationToken()
9191
input_messages: List[ChatMessage] = []
92-
output_messages: List[AgentMessage] = []
92+
output_messages: List[AgentEvent | ChatMessage] = []
9393
if task is None:
9494
pass
9595
elif isinstance(task, str):
@@ -119,13 +119,13 @@ async def run_stream(
119119
*,
120120
task: str | ChatMessage | List[ChatMessage] | None = None,
121121
cancellation_token: CancellationToken | None = None,
122-
) -> AsyncGenerator[AgentMessage | TaskResult, None]:
122+
) -> AsyncGenerator[AgentEvent | ChatMessage | TaskResult, None]:
123123
"""Run the agent with the given task and return a stream of messages
124124
and the final task result as the last item in the stream."""
125125
if cancellation_token is None:
126126
cancellation_token = CancellationToken()
127127
input_messages: List[ChatMessage] = []
128-
output_messages: List[AgentMessage] = []
128+
output_messages: List[AgentEvent | ChatMessage] = []
129129
if task is None:
130130
pass
131131
elif isinstance(task, str):

python/packages/autogen-agentchat/src/autogen_agentchat/agents/_society_of_mind_agent.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from ..base import TaskResult, Team
1010
from ..messages import (
11-
AgentMessage,
11+
AgentEvent,
1212
ChatMessage,
1313
HandoffMessage,
1414
MultiModalMessage,
@@ -119,13 +119,13 @@ async def on_messages(self, messages: Sequence[ChatMessage], cancellation_token:
119119

120120
async def on_messages_stream(
121121
self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken
122-
) -> AsyncGenerator[AgentMessage | Response, None]:
122+
) -> AsyncGenerator[AgentEvent | ChatMessage | Response, None]:
123123
# Prepare the task for the team of agents.
124124
task = list(messages)
125125

126126
# Run the team of agents.
127127
result: TaskResult | None = None
128-
inner_messages: List[AgentMessage] = []
128+
inner_messages: List[AgentEvent | ChatMessage] = []
129129
count = 0
130130
async for inner_msg in self._team.run_stream(task=task, cancellation_token=cancellation_token):
131131
if isinstance(inner_msg, TaskResult):

python/packages/autogen-agentchat/src/autogen_agentchat/base/_chat_agent.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from autogen_core import CancellationToken
55

6-
from ..messages import AgentMessage, ChatMessage
6+
from ..messages import AgentEvent, ChatMessage
77
from ._task import TaskRunner
88

99

@@ -14,7 +14,7 @@ class Response:
1414
chat_message: ChatMessage
1515
"""A chat message produced by the agent as the response."""
1616

17-
inner_messages: List[AgentMessage] | None = None
17+
inner_messages: List[AgentEvent | ChatMessage] | None = None
1818
"""Inner messages produced by the agent."""
1919

2020

@@ -46,7 +46,7 @@ async def on_messages(self, messages: Sequence[ChatMessage], cancellation_token:
4646

4747
def on_messages_stream(
4848
self, messages: Sequence[ChatMessage], cancellation_token: CancellationToken
49-
) -> AsyncGenerator[AgentMessage | Response, None]:
49+
) -> AsyncGenerator[AgentEvent | ChatMessage | Response, None]:
5050
"""Handles incoming messages and returns a stream of inner messages and
5151
and the final item is the response."""
5252
...

python/packages/autogen-agentchat/src/autogen_agentchat/base/_task.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33

44
from autogen_core import CancellationToken
55

6-
from ..messages import AgentMessage, ChatMessage
6+
from ..messages import AgentEvent, ChatMessage
77

88

99
@dataclass
1010
class TaskResult:
1111
"""Result of running a task."""
1212

13-
messages: Sequence[AgentMessage]
13+
messages: Sequence[AgentEvent | ChatMessage]
1414
"""Messages produced by the task."""
1515

1616
stop_reason: str | None = None
@@ -38,7 +38,7 @@ def run_stream(
3838
*,
3939
task: str | ChatMessage | List[ChatMessage] | None = None,
4040
cancellation_token: CancellationToken | None = None,
41-
) -> AsyncGenerator[AgentMessage | TaskResult, None]:
41+
) -> AsyncGenerator[AgentEvent | ChatMessage | TaskResult, None]:
4242
"""Run the task and produces a stream of messages and the final result
4343
:class:`TaskResult` as the last item in the stream.
4444

python/packages/autogen-agentchat/src/autogen_agentchat/base/_termination.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from abc import ABC, abstractmethod
33
from typing import List, Sequence
44

5-
from ..messages import AgentMessage, StopMessage
5+
from ..messages import AgentEvent, ChatMessage, StopMessage
66

77

88
class TerminatedException(BaseException): ...
@@ -50,7 +50,7 @@ def terminated(self) -> bool:
5050
...
5151

5252
@abstractmethod
53-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
53+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
5454
"""Check if the conversation should be terminated based on the messages received
5555
since the last time the condition was called.
5656
Return a StopMessage if the conversation should be terminated, or None otherwise.
@@ -88,7 +88,7 @@ def __init__(self, *conditions: TerminationCondition) -> None:
8888
def terminated(self) -> bool:
8989
return all(condition.terminated for condition in self._conditions)
9090

91-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
91+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
9292
if self.terminated:
9393
raise TerminatedException("Termination condition has already been reached.")
9494
# Check all remaining conditions.
@@ -120,7 +120,7 @@ def __init__(self, *conditions: TerminationCondition) -> None:
120120
def terminated(self) -> bool:
121121
return any(condition.terminated for condition in self._conditions)
122122

123-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
123+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
124124
if self.terminated:
125125
raise RuntimeError("Termination condition has already been reached")
126126
stop_messages = await asyncio.gather(*[condition(messages) for condition in self._conditions])

python/packages/autogen-agentchat/src/autogen_agentchat/conditions/_terminations.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from typing import List, Sequence
33

44
from ..base import TerminatedException, TerminationCondition
5-
from ..messages import AgentMessage, HandoffMessage, MultiModalMessage, StopMessage, TextMessage
5+
from ..messages import AgentEvent, ChatMessage, HandoffMessage, MultiModalMessage, StopMessage, TextMessage
66

77

88
class StopMessageTermination(TerminationCondition):
@@ -15,7 +15,7 @@ def __init__(self) -> None:
1515
def terminated(self) -> bool:
1616
return self._terminated
1717

18-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
18+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
1919
if self._terminated:
2020
raise TerminatedException("Termination condition has already been reached")
2121
for message in messages:
@@ -43,7 +43,7 @@ def __init__(self, max_messages: int) -> None:
4343
def terminated(self) -> bool:
4444
return self._message_count >= self._max_messages
4545

46-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
46+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
4747
if self.terminated:
4848
raise TerminatedException("Termination condition has already been reached")
4949
self._message_count += len(messages)
@@ -73,7 +73,7 @@ def __init__(self, text: str) -> None:
7373
def terminated(self) -> bool:
7474
return self._terminated
7575

76-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
76+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
7777
if self._terminated:
7878
raise TerminatedException("Termination condition has already been reached")
7979
for message in messages:
@@ -128,7 +128,7 @@ def terminated(self) -> bool:
128128
or (self._max_completion_token is not None and self._completion_token_count >= self._max_completion_token)
129129
)
130130

131-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
131+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
132132
if self.terminated:
133133
raise TerminatedException("Termination condition has already been reached")
134134
for message in messages:
@@ -163,7 +163,7 @@ def __init__(self, target: str) -> None:
163163
def terminated(self) -> bool:
164164
return self._terminated
165165

166-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
166+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
167167
if self._terminated:
168168
raise TerminatedException("Termination condition has already been reached")
169169
for message in messages:
@@ -194,7 +194,7 @@ def __init__(self, timeout_seconds: float) -> None:
194194
def terminated(self) -> bool:
195195
return self._terminated
196196

197-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
197+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
198198
if self._terminated:
199199
raise TerminatedException("Termination condition has already been reached")
200200

@@ -242,7 +242,7 @@ def set(self) -> None:
242242
"""Set the termination condition to terminated."""
243243
self._setted = True
244244

245-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
245+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
246246
if self._terminated:
247247
raise TerminatedException("Termination condition has already been reached")
248248
if self._setted:
@@ -273,7 +273,7 @@ def __init__(self, sources: List[str]) -> None:
273273
def terminated(self) -> bool:
274274
return self._terminated
275275

276-
async def __call__(self, messages: Sequence[AgentMessage]) -> StopMessage | None:
276+
async def __call__(self, messages: Sequence[AgentEvent | ChatMessage]) -> StopMessage | None:
277277
if self._terminated:
278278
raise TerminatedException("Termination condition has already been reached")
279279
if not messages:

python/packages/autogen-agentchat/src/autogen_agentchat/messages.py

+31-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from autogen_core import FunctionCall, Image
1010
from autogen_core.models import FunctionExecutionResult, RequestUsage
1111
from pydantic import BaseModel, ConfigDict, Field
12-
from typing_extensions import Annotated
12+
from typing_extensions import Annotated, deprecated
1313

1414

1515
class BaseMessage(BaseModel):
@@ -63,6 +63,7 @@ class HandoffMessage(BaseMessage):
6363
type: Literal["HandoffMessage"] = "HandoffMessage"
6464

6565

66+
@deprecated("Will be removed in 0.4.0, use ToolCallRequestEvent instead.")
6667
class ToolCallMessage(BaseMessage):
6768
"""A message signaling the use of tools."""
6869

@@ -72,6 +73,7 @@ class ToolCallMessage(BaseMessage):
7273
type: Literal["ToolCallMessage"] = "ToolCallMessage"
7374

7475

76+
@deprecated("Will be removed in 0.4.0, use ToolCallExecutionEvent instead.")
7577
class ToolCallResultMessage(BaseMessage):
7678
"""A message signaling the results of tool calls."""
7779

@@ -81,15 +83,37 @@ class ToolCallResultMessage(BaseMessage):
8183
type: Literal["ToolCallResultMessage"] = "ToolCallResultMessage"
8284

8385

86+
class ToolCallRequestEvent(BaseMessage):
87+
"""An event signaling a request to use tools."""
88+
89+
content: List[FunctionCall]
90+
"""The tool calls."""
91+
92+
type: Literal["ToolCallRequestEvent"] = "ToolCallRequestEvent"
93+
94+
95+
class ToolCallExecutionEvent(BaseMessage):
96+
"""An event signaling the execution of tool calls."""
97+
98+
content: List[FunctionExecutionResult]
99+
"""The tool call results."""
100+
101+
type: Literal["ToolCallExecutionEvent"] = "ToolCallExecutionEvent"
102+
103+
84104
ChatMessage = Annotated[TextMessage | MultiModalMessage | StopMessage | HandoffMessage, Field(discriminator="type")]
85-
"""Messages for agent-to-agent communication."""
105+
"""Messages for agent-to-agent communication only."""
106+
107+
108+
AgentEvent = Annotated[ToolCallRequestEvent | ToolCallExecutionEvent, Field(discriminator="type")]
109+
"""Events emitted by agents and teams when they work, not used for agent-to-agent communication."""
86110

87111

88112
AgentMessage = Annotated[
89-
TextMessage | MultiModalMessage | StopMessage | HandoffMessage | ToolCallMessage | ToolCallResultMessage,
113+
TextMessage | MultiModalMessage | StopMessage | HandoffMessage | ToolCallRequestEvent | ToolCallExecutionEvent,
90114
Field(discriminator="type"),
91115
]
92-
"""All message types."""
116+
"""(Deprecated, will be removed in 0.4.0) All message and event types."""
93117

94118

95119
__all__ = [
@@ -98,8 +122,11 @@ class ToolCallResultMessage(BaseMessage):
98122
"MultiModalMessage",
99123
"StopMessage",
100124
"HandoffMessage",
125+
"ToolCallRequestEvent",
126+
"ToolCallExecutionEvent",
101127
"ToolCallMessage",
102128
"ToolCallResultMessage",
103129
"ChatMessage",
130+
"AgentEvent",
104131
"AgentMessage",
105132
]

python/packages/autogen-agentchat/src/autogen_agentchat/state/_states.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pydantic import BaseModel, Field
77

88
from ..messages import (
9-
AgentMessage,
9+
AgentEvent,
1010
ChatMessage,
1111
)
1212

@@ -36,7 +36,7 @@ class TeamState(BaseState):
3636
class BaseGroupChatManagerState(BaseState):
3737
"""Base state for all group chat managers."""
3838

39-
message_thread: List[AgentMessage] = Field(default_factory=list)
39+
message_thread: List[AgentEvent | ChatMessage] = Field(default_factory=list)
4040
current_turn: int = Field(default=0)
4141
type: str = Field(default="BaseGroupChatManagerState")
4242

0 commit comments

Comments
 (0)