ag2 0.9.6__py3-none-any.whl → 0.9.8.post1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ag2 might be problematic. Click here for more details.

Files changed (236) hide show
  1. {ag2-0.9.6.dist-info → ag2-0.9.8.post1.dist-info}/METADATA +102 -75
  2. ag2-0.9.8.post1.dist-info/RECORD +387 -0
  3. autogen/__init__.py +1 -2
  4. autogen/_website/generate_api_references.py +4 -5
  5. autogen/_website/generate_mkdocs.py +9 -15
  6. autogen/_website/notebook_processor.py +13 -14
  7. autogen/_website/process_notebooks.py +10 -10
  8. autogen/_website/utils.py +5 -4
  9. autogen/agentchat/agent.py +13 -13
  10. autogen/agentchat/assistant_agent.py +7 -6
  11. autogen/agentchat/contrib/agent_eval/agent_eval.py +3 -3
  12. autogen/agentchat/contrib/agent_eval/critic_agent.py +3 -3
  13. autogen/agentchat/contrib/agent_eval/quantifier_agent.py +3 -3
  14. autogen/agentchat/contrib/agent_eval/subcritic_agent.py +3 -3
  15. autogen/agentchat/contrib/agent_optimizer.py +3 -3
  16. autogen/agentchat/contrib/capabilities/generate_images.py +11 -11
  17. autogen/agentchat/contrib/capabilities/teachability.py +15 -15
  18. autogen/agentchat/contrib/capabilities/transforms.py +17 -18
  19. autogen/agentchat/contrib/capabilities/transforms_util.py +5 -5
  20. autogen/agentchat/contrib/capabilities/vision_capability.py +4 -3
  21. autogen/agentchat/contrib/captainagent/agent_builder.py +30 -30
  22. autogen/agentchat/contrib/captainagent/captainagent.py +22 -21
  23. autogen/agentchat/contrib/captainagent/tool_retriever.py +2 -3
  24. autogen/agentchat/contrib/gpt_assistant_agent.py +9 -9
  25. autogen/agentchat/contrib/graph_rag/document.py +3 -3
  26. autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +3 -3
  27. autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +6 -6
  28. autogen/agentchat/contrib/graph_rag/graph_query_engine.py +3 -3
  29. autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +5 -11
  30. autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +6 -6
  31. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +7 -7
  32. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +6 -6
  33. autogen/agentchat/contrib/img_utils.py +1 -1
  34. autogen/agentchat/contrib/llamaindex_conversable_agent.py +11 -11
  35. autogen/agentchat/contrib/llava_agent.py +18 -4
  36. autogen/agentchat/contrib/math_user_proxy_agent.py +11 -11
  37. autogen/agentchat/contrib/multimodal_conversable_agent.py +8 -8
  38. autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +6 -5
  39. autogen/agentchat/contrib/rag/chromadb_query_engine.py +22 -26
  40. autogen/agentchat/contrib/rag/llamaindex_query_engine.py +14 -17
  41. autogen/agentchat/contrib/rag/mongodb_query_engine.py +27 -37
  42. autogen/agentchat/contrib/rag/query_engine.py +7 -5
  43. autogen/agentchat/contrib/retrieve_assistant_agent.py +5 -5
  44. autogen/agentchat/contrib/retrieve_user_proxy_agent.py +8 -7
  45. autogen/agentchat/contrib/society_of_mind_agent.py +15 -14
  46. autogen/agentchat/contrib/swarm_agent.py +76 -98
  47. autogen/agentchat/contrib/text_analyzer_agent.py +7 -7
  48. autogen/agentchat/contrib/vectordb/base.py +10 -18
  49. autogen/agentchat/contrib/vectordb/chromadb.py +2 -1
  50. autogen/agentchat/contrib/vectordb/couchbase.py +18 -20
  51. autogen/agentchat/contrib/vectordb/mongodb.py +6 -5
  52. autogen/agentchat/contrib/vectordb/pgvectordb.py +40 -41
  53. autogen/agentchat/contrib/vectordb/qdrant.py +5 -5
  54. autogen/agentchat/contrib/web_surfer.py +20 -19
  55. autogen/agentchat/conversable_agent.py +311 -295
  56. autogen/agentchat/group/context_str.py +1 -3
  57. autogen/agentchat/group/context_variables.py +15 -25
  58. autogen/agentchat/group/group_tool_executor.py +10 -10
  59. autogen/agentchat/group/group_utils.py +15 -15
  60. autogen/agentchat/group/guardrails.py +7 -7
  61. autogen/agentchat/group/handoffs.py +19 -36
  62. autogen/agentchat/group/multi_agent_chat.py +7 -7
  63. autogen/agentchat/group/on_condition.py +4 -7
  64. autogen/agentchat/group/on_context_condition.py +4 -7
  65. autogen/agentchat/group/patterns/auto.py +8 -7
  66. autogen/agentchat/group/patterns/manual.py +7 -6
  67. autogen/agentchat/group/patterns/pattern.py +13 -12
  68. autogen/agentchat/group/patterns/random.py +3 -3
  69. autogen/agentchat/group/patterns/round_robin.py +3 -3
  70. autogen/agentchat/group/reply_result.py +2 -4
  71. autogen/agentchat/group/speaker_selection_result.py +5 -5
  72. autogen/agentchat/group/targets/group_chat_target.py +7 -6
  73. autogen/agentchat/group/targets/group_manager_target.py +4 -4
  74. autogen/agentchat/group/targets/transition_target.py +2 -1
  75. autogen/agentchat/groupchat.py +58 -61
  76. autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +4 -4
  77. autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +4 -4
  78. autogen/agentchat/realtime/experimental/clients/gemini/client.py +7 -7
  79. autogen/agentchat/realtime/experimental/clients/oai/base_client.py +8 -8
  80. autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +6 -6
  81. autogen/agentchat/realtime/experimental/clients/realtime_client.py +10 -9
  82. autogen/agentchat/realtime/experimental/realtime_agent.py +10 -9
  83. autogen/agentchat/realtime/experimental/realtime_observer.py +3 -3
  84. autogen/agentchat/realtime/experimental/realtime_swarm.py +44 -44
  85. autogen/agentchat/user_proxy_agent.py +10 -9
  86. autogen/agentchat/utils.py +3 -3
  87. autogen/agents/contrib/time/time_reply_agent.py +6 -5
  88. autogen/agents/contrib/time/time_tool_agent.py +2 -1
  89. autogen/agents/experimental/deep_research/deep_research.py +3 -3
  90. autogen/agents/experimental/discord/discord.py +2 -2
  91. autogen/agents/experimental/document_agent/chroma_query_engine.py +29 -44
  92. autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +9 -14
  93. autogen/agents/experimental/document_agent/document_agent.py +15 -16
  94. autogen/agents/experimental/document_agent/document_conditions.py +3 -3
  95. autogen/agents/experimental/document_agent/document_utils.py +5 -9
  96. autogen/agents/experimental/document_agent/inmemory_query_engine.py +14 -20
  97. autogen/agents/experimental/document_agent/parser_utils.py +4 -4
  98. autogen/agents/experimental/document_agent/url_utils.py +14 -23
  99. autogen/agents/experimental/reasoning/reasoning_agent.py +33 -33
  100. autogen/agents/experimental/slack/slack.py +2 -2
  101. autogen/agents/experimental/telegram/telegram.py +2 -3
  102. autogen/agents/experimental/websurfer/websurfer.py +4 -4
  103. autogen/agents/experimental/wikipedia/wikipedia.py +5 -7
  104. autogen/browser_utils.py +8 -8
  105. autogen/cache/abstract_cache_base.py +5 -5
  106. autogen/cache/cache.py +12 -12
  107. autogen/cache/cache_factory.py +4 -4
  108. autogen/cache/cosmos_db_cache.py +9 -9
  109. autogen/cache/disk_cache.py +6 -6
  110. autogen/cache/in_memory_cache.py +4 -4
  111. autogen/cache/redis_cache.py +4 -4
  112. autogen/code_utils.py +18 -18
  113. autogen/coding/base.py +6 -6
  114. autogen/coding/docker_commandline_code_executor.py +9 -9
  115. autogen/coding/func_with_reqs.py +7 -6
  116. autogen/coding/jupyter/base.py +3 -3
  117. autogen/coding/jupyter/docker_jupyter_server.py +3 -4
  118. autogen/coding/jupyter/import_utils.py +3 -3
  119. autogen/coding/jupyter/jupyter_client.py +5 -5
  120. autogen/coding/jupyter/jupyter_code_executor.py +3 -4
  121. autogen/coding/jupyter/local_jupyter_server.py +2 -6
  122. autogen/coding/local_commandline_code_executor.py +8 -7
  123. autogen/coding/markdown_code_extractor.py +1 -2
  124. autogen/coding/utils.py +1 -2
  125. autogen/doc_utils.py +3 -2
  126. autogen/environments/docker_python_environment.py +19 -29
  127. autogen/environments/python_environment.py +8 -17
  128. autogen/environments/system_python_environment.py +3 -4
  129. autogen/environments/venv_python_environment.py +8 -12
  130. autogen/environments/working_directory.py +1 -2
  131. autogen/events/agent_events.py +106 -109
  132. autogen/events/base_event.py +6 -5
  133. autogen/events/client_events.py +15 -14
  134. autogen/events/helpers.py +1 -1
  135. autogen/events/print_event.py +4 -5
  136. autogen/fast_depends/_compat.py +10 -15
  137. autogen/fast_depends/core/build.py +17 -36
  138. autogen/fast_depends/core/model.py +64 -113
  139. autogen/fast_depends/dependencies/model.py +2 -1
  140. autogen/fast_depends/dependencies/provider.py +3 -2
  141. autogen/fast_depends/library/model.py +4 -4
  142. autogen/fast_depends/schema.py +7 -7
  143. autogen/fast_depends/use.py +17 -25
  144. autogen/fast_depends/utils.py +10 -30
  145. autogen/formatting_utils.py +6 -6
  146. autogen/graph_utils.py +1 -4
  147. autogen/import_utils.py +13 -13
  148. autogen/interop/crewai/crewai.py +2 -2
  149. autogen/interop/interoperable.py +2 -2
  150. autogen/interop/langchain/langchain_chat_model_factory.py +3 -2
  151. autogen/interop/langchain/langchain_tool.py +2 -6
  152. autogen/interop/litellm/litellm_config_factory.py +6 -7
  153. autogen/interop/pydantic_ai/pydantic_ai.py +4 -7
  154. autogen/interop/registry.py +2 -1
  155. autogen/io/base.py +5 -5
  156. autogen/io/run_response.py +33 -32
  157. autogen/io/websockets.py +6 -5
  158. autogen/json_utils.py +1 -2
  159. autogen/llm_config/__init__.py +11 -0
  160. autogen/llm_config/client.py +58 -0
  161. autogen/llm_config/config.py +384 -0
  162. autogen/llm_config/entry.py +154 -0
  163. autogen/logger/base_logger.py +4 -3
  164. autogen/logger/file_logger.py +2 -1
  165. autogen/logger/logger_factory.py +2 -2
  166. autogen/logger/logger_utils.py +2 -2
  167. autogen/logger/sqlite_logger.py +3 -2
  168. autogen/math_utils.py +4 -5
  169. autogen/mcp/__main__.py +6 -6
  170. autogen/mcp/helpers.py +4 -4
  171. autogen/mcp/mcp_client.py +170 -29
  172. autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +3 -4
  173. autogen/mcp/mcp_proxy/mcp_proxy.py +23 -26
  174. autogen/mcp/mcp_proxy/operation_grouping.py +4 -5
  175. autogen/mcp/mcp_proxy/operation_renaming.py +6 -10
  176. autogen/mcp/mcp_proxy/security.py +2 -3
  177. autogen/messages/agent_messages.py +96 -98
  178. autogen/messages/base_message.py +6 -5
  179. autogen/messages/client_messages.py +15 -14
  180. autogen/messages/print_message.py +4 -5
  181. autogen/oai/__init__.py +1 -2
  182. autogen/oai/anthropic.py +42 -41
  183. autogen/oai/bedrock.py +68 -57
  184. autogen/oai/cerebras.py +26 -25
  185. autogen/oai/client.py +118 -138
  186. autogen/oai/client_utils.py +3 -3
  187. autogen/oai/cohere.py +34 -11
  188. autogen/oai/gemini.py +40 -17
  189. autogen/oai/gemini_types.py +11 -12
  190. autogen/oai/groq.py +22 -10
  191. autogen/oai/mistral.py +17 -11
  192. autogen/oai/oai_models/__init__.py +14 -2
  193. autogen/oai/oai_models/_models.py +2 -2
  194. autogen/oai/oai_models/chat_completion.py +13 -14
  195. autogen/oai/oai_models/chat_completion_message.py +11 -9
  196. autogen/oai/oai_models/chat_completion_message_tool_call.py +26 -3
  197. autogen/oai/oai_models/chat_completion_token_logprob.py +3 -4
  198. autogen/oai/oai_models/completion_usage.py +8 -9
  199. autogen/oai/ollama.py +22 -10
  200. autogen/oai/openai_responses.py +40 -17
  201. autogen/oai/openai_utils.py +159 -85
  202. autogen/oai/together.py +29 -14
  203. autogen/retrieve_utils.py +6 -7
  204. autogen/runtime_logging.py +5 -4
  205. autogen/token_count_utils.py +7 -4
  206. autogen/tools/contrib/time/time.py +0 -1
  207. autogen/tools/dependency_injection.py +5 -6
  208. autogen/tools/experimental/browser_use/browser_use.py +10 -10
  209. autogen/tools/experimental/code_execution/python_code_execution.py +5 -7
  210. autogen/tools/experimental/crawl4ai/crawl4ai.py +12 -15
  211. autogen/tools/experimental/deep_research/deep_research.py +9 -8
  212. autogen/tools/experimental/duckduckgo/duckduckgo_search.py +5 -11
  213. autogen/tools/experimental/firecrawl/firecrawl_tool.py +98 -115
  214. autogen/tools/experimental/google/authentication/credentials_local_provider.py +1 -1
  215. autogen/tools/experimental/google/drive/drive_functions.py +4 -4
  216. autogen/tools/experimental/google/drive/toolkit.py +5 -5
  217. autogen/tools/experimental/google_search/google_search.py +5 -5
  218. autogen/tools/experimental/google_search/youtube_search.py +5 -5
  219. autogen/tools/experimental/messageplatform/discord/discord.py +8 -12
  220. autogen/tools/experimental/messageplatform/slack/slack.py +14 -20
  221. autogen/tools/experimental/messageplatform/telegram/telegram.py +8 -12
  222. autogen/tools/experimental/perplexity/perplexity_search.py +18 -29
  223. autogen/tools/experimental/reliable/reliable.py +68 -74
  224. autogen/tools/experimental/searxng/searxng_search.py +20 -19
  225. autogen/tools/experimental/tavily/tavily_search.py +12 -19
  226. autogen/tools/experimental/web_search_preview/web_search_preview.py +13 -7
  227. autogen/tools/experimental/wikipedia/wikipedia.py +7 -10
  228. autogen/tools/function_utils.py +7 -7
  229. autogen/tools/tool.py +6 -5
  230. autogen/types.py +2 -2
  231. autogen/version.py +1 -1
  232. ag2-0.9.6.dist-info/RECORD +0 -421
  233. autogen/llm_config.py +0 -385
  234. {ag2-0.9.6.dist-info → ag2-0.9.8.post1.dist-info}/WHEEL +0 -0
  235. {ag2-0.9.6.dist-info → ag2-0.9.8.post1.dist-info}/licenses/LICENSE +0 -0
  236. {ag2-0.9.6.dist-info → ag2-0.9.8.post1.dist-info}/licenses/NOTICE.md +0 -0
@@ -2,7 +2,6 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Optional
6
5
 
7
6
  from pydantic import BaseModel
8
7
 
@@ -20,7 +19,7 @@ class ContextStr(BaseModel):
20
19
  """The string to be substituted with context variables. It is expected that the string will contain `{var}` placeholders and that string format will be able to replace all values."""
21
20
  template: str
22
21
 
23
- def format(self, context_variables: ContextVariables) -> Optional[str]:
22
+ def format(self, context_variables: ContextVariables) -> str | None:
24
23
  """Substitute context variables into the string.
25
24
 
26
25
  Args:
@@ -29,7 +28,6 @@ class ContextStr(BaseModel):
29
28
  Returns:
30
29
  Optional[str]: The formatted string with context variables substituted.
31
30
  """
32
-
33
31
  context = context_variables.to_dict()
34
32
 
35
33
  if not context:
@@ -2,7 +2,8 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Any, Generator, Iterable, Optional
5
+ from collections.abc import Generator, Iterable
6
+ from typing import Any
6
7
 
7
8
  from pydantic import BaseModel, Field
8
9
 
@@ -15,8 +16,7 @@ __CONTEXT_VARIABLES_PARAM_NAME__ = "context_variables"
15
16
 
16
17
 
17
18
  class ContextVariables(BaseModel):
18
- """
19
- Stores and manages context variables for agentic workflows.
19
+ """Stores and manages context variables for agentic workflows.
20
20
 
21
21
  Utilises a dictionary-like interface for setting, getting, and removing variables.
22
22
  """
@@ -24,7 +24,7 @@ class ContextVariables(BaseModel):
24
24
  # Internal storage for context variables
25
25
  data: dict[str, Any] = Field(default_factory=dict)
26
26
 
27
- def __init__(self, data: Optional[dict[str, Any]] = None, **kwargs: Any) -> None:
27
+ def __init__(self, data: dict[str, Any] | None = None, **kwargs: Any) -> None:
28
28
  """Initialize with data dictionary as an optional positional parameter.
29
29
 
30
30
  Args:
@@ -34,9 +34,8 @@ class ContextVariables(BaseModel):
34
34
  init_data = data or {}
35
35
  super().__init__(data=init_data, **kwargs)
36
36
 
37
- def get(self, key: str, default: Optional[Any] = None) -> Optional[Any]:
38
- """
39
- Get a value from the context by key.
37
+ def get(self, key: str, default: Any | None = None) -> Any | None:
38
+ """Get a value from the context by key.
40
39
 
41
40
  Args:
42
41
  key: The key to retrieve
@@ -48,8 +47,7 @@ class ContextVariables(BaseModel):
48
47
  return self.data.get(key, default)
49
48
 
50
49
  def set(self, key: str, value: Any) -> None:
51
- """
52
- Set a value in the context by key.
50
+ """Set a value in the context by key.
53
51
 
54
52
  Args:
55
53
  key: The key to set
@@ -58,8 +56,7 @@ class ContextVariables(BaseModel):
58
56
  self.data[key] = value
59
57
 
60
58
  def remove(self, key: str) -> bool:
61
- """
62
- Remove a key from the context.
59
+ """Remove a key from the context.
63
60
 
64
61
  Args:
65
62
  key: The key to remove
@@ -73,8 +70,7 @@ class ContextVariables(BaseModel):
73
70
  return False
74
71
 
75
72
  def keys(self) -> Iterable[str]:
76
- """
77
- Get all keys in the context.
73
+ """Get all keys in the context.
78
74
 
79
75
  Returns:
80
76
  An iterable of all keys
@@ -82,8 +78,7 @@ class ContextVariables(BaseModel):
82
78
  return self.data.keys()
83
79
 
84
80
  def values(self) -> Iterable[Any]:
85
- """
86
- Get all values in the context.
81
+ """Get all values in the context.
87
82
 
88
83
  Returns:
89
84
  An iterable of all values
@@ -91,8 +86,7 @@ class ContextVariables(BaseModel):
91
86
  return self.data.values()
92
87
 
93
88
  def items(self) -> Iterable[tuple[str, Any]]:
94
- """
95
- Get all key-value pairs in the context.
89
+ """Get all key-value pairs in the context.
96
90
 
97
91
  Returns:
98
92
  An iterable of all key-value pairs
@@ -104,8 +98,7 @@ class ContextVariables(BaseModel):
104
98
  self.data.clear()
105
99
 
106
100
  def contains(self, key: str) -> bool:
107
- """
108
- Check if a key exists in the context.
101
+ """Check if a key exists in the context.
109
102
 
110
103
  Args:
111
104
  key: The key to check
@@ -116,8 +109,7 @@ class ContextVariables(BaseModel):
116
109
  return key in self.data
117
110
 
118
111
  def update(self, other: dict[str, Any]) -> None:
119
- """
120
- Update context with key-value pairs from another dictionary.
112
+ """Update context with key-value pairs from another dictionary.
121
113
 
122
114
  Args:
123
115
  other: Dictionary containing key-value pairs to add
@@ -125,8 +117,7 @@ class ContextVariables(BaseModel):
125
117
  self.data.update(other)
126
118
 
127
119
  def to_dict(self) -> dict[str, Any]:
128
- """
129
- Convert context variables to a dictionary.
120
+ """Convert context variables to a dictionary.
130
121
 
131
122
  Returns:
132
123
  Dictionary representation of all context variables
@@ -176,8 +167,7 @@ class ContextVariables(BaseModel):
176
167
  # Utility methods
177
168
  @classmethod
178
169
  def from_dict(cls, data: dict[str, Any]) -> "ContextVariables":
179
- """
180
- Create a new ContextVariables instance from a dictionary.
170
+ """Create a new ContextVariables instance from a dictionary.
181
171
 
182
172
  E.g.:
183
173
  my_context = {"user_id": "12345", "settings": {"theme": "dark"}}
@@ -3,8 +3,9 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  import inspect
6
+ from collections.abc import Callable
6
7
  from copy import deepcopy
7
- from typing import Annotated, Any, Callable, Optional
8
+ from typing import Annotated, Any
8
9
 
9
10
  from ...oai import OpenAIWrapper
10
11
  from ...tools import Depends, Tool
@@ -30,7 +31,7 @@ class GroupToolExecutor(ConversableAgent):
30
31
  )
31
32
 
32
33
  # Store the next target from a tool call
33
- self._group_next_target: Optional[TransitionTarget] = None
34
+ self._group_next_target: TransitionTarget | None = None
34
35
 
35
36
  # Primary tool reply function for handling the tool reply and the ReplyResult and TransitionTarget returns
36
37
  self.register_reply([Agent, None], self._generate_group_tool_reply, remove_other_reply_funcs=True)
@@ -91,7 +92,6 @@ class GroupToolExecutor(ConversableAgent):
91
92
  self, agent: ConversableAgent, current_tool: Tool, context_variables: ContextVariables
92
93
  ) -> None:
93
94
  """Checks for the context_variables parameter in the tool and updates it to use dependency injection."""
94
-
95
95
  # If the tool has a context_variables parameter, remove the tool and reregister it without the parameter
96
96
  if __CONTEXT_VARIABLES_PARAM_NAME__ in current_tool.tool_schema["function"]["parameters"]["properties"]:
97
97
  # We'll replace the tool, so start with getting the underlying function
@@ -129,17 +129,17 @@ class GroupToolExecutor(ConversableAgent):
129
129
  def _generate_group_tool_reply(
130
130
  self,
131
131
  agent: ConversableAgent,
132
- messages: Optional[list[dict[str, Any]]] = None,
133
- sender: Optional[Agent] = None,
134
- config: Optional[OpenAIWrapper] = None,
135
- ) -> tuple[bool, Optional[dict[str, Any]]]:
132
+ messages: list[dict[str, Any]] | None = None,
133
+ sender: Agent | None = None,
134
+ config: OpenAIWrapper | None = None,
135
+ ) -> tuple[bool, dict[str, Any] | None]:
136
136
  """Pre-processes and generates tool call replies.
137
137
 
138
138
  This function:
139
139
  1. Adds context_variables back to the tool call for the function, if necessary.
140
140
  2. Generates the tool calls reply.
141
- 3. Updates context_variables and next_agent based on the tool call response."""
142
-
141
+ 3. Updates context_variables and next_agent based on the tool call response.
142
+ """
143
143
  if config is None:
144
144
  config = agent # type: ignore[assignment]
145
145
  if messages is None:
@@ -150,7 +150,7 @@ class GroupToolExecutor(ConversableAgent):
150
150
  tool_call_count = len(message["tool_calls"])
151
151
 
152
152
  # Loop through tool calls individually (so context can be updated after each function call)
153
- next_target: Optional[TransitionTarget] = None
153
+ next_target: TransitionTarget | None = None
154
154
  tool_responses_inner = []
155
155
  contents = []
156
156
  for index in range(tool_call_count):
@@ -3,9 +3,10 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
  import copy
6
+ from collections.abc import Callable
6
7
  from functools import partial
7
8
  from types import MethodType
8
- from typing import TYPE_CHECKING, Any, Callable, Optional, Union
9
+ from typing import TYPE_CHECKING, Any, Optional
9
10
 
10
11
  from ..agent import Agent
11
12
  from ..groupchat import GroupChat, GroupChatManager
@@ -86,7 +87,7 @@ def _evaluate_after_works_conditions(
86
87
  agent: "ConversableAgent",
87
88
  groupchat: GroupChat,
88
89
  user_agent: Optional["ConversableAgent"],
89
- ) -> Optional[Union[Agent, str]]:
90
+ ) -> Agent | str | None:
90
91
  """Evaluate after_works context conditions for an agent.
91
92
 
92
93
  Args:
@@ -124,10 +125,10 @@ def _evaluate_after_works_conditions(
124
125
 
125
126
  def _run_oncontextconditions(
126
127
  agent: "ConversableAgent",
127
- messages: Optional[list[dict[str, Any]]] = None,
128
- sender: Optional[Agent] = None,
129
- config: Optional[Any] = None,
130
- ) -> tuple[bool, Optional[Union[str, dict[str, Any]]]]:
128
+ messages: list[dict[str, Any]] | None = None,
129
+ sender: Agent | None = None,
130
+ config: Any | None = None,
131
+ ) -> tuple[bool, str | dict[str, Any] | None]:
131
132
  """Run OnContextConditions for an agent before any other reply function."""
132
133
  for on_condition in agent.handoffs.context_conditions: # type: ignore[attr-defined]
133
134
  is_available = (
@@ -267,7 +268,7 @@ def prepare_group_agents(
267
268
  tool_execution = GroupToolExecutor()
268
269
 
269
270
  # Wrap handoff targets in agents that need to be wrapped
270
- wrapped_chat_agents: list["ConversableAgent"] = []
271
+ wrapped_chat_agents: list[ConversableAgent] = []
271
272
  for agent in agents:
272
273
  wrap_agent_handoff_targets(agent, wrapped_chat_agents)
273
274
 
@@ -318,7 +319,7 @@ def wrap_agent_handoff_targets(agent: "ConversableAgent", wrapped_agent_list: li
318
319
 
319
320
 
320
321
  def process_initial_messages(
321
- messages: Union[list[dict[str, Any]], str],
322
+ messages: list[dict[str, Any]] | str,
322
323
  user_agent: Optional["ConversableAgent"],
323
324
  agents: list["ConversableAgent"],
324
325
  wrapped_agents: list["ConversableAgent"],
@@ -346,8 +347,8 @@ def process_initial_messages(
346
347
 
347
348
  # If there's only one message and there's no identified group agent
348
349
  # Start with a user proxy agent, creating one if they haven't passed one in
349
- last_agent: Optional[ConversableAgent]
350
- temp_user_proxy: Optional[ConversableAgent] = None
350
+ last_agent: ConversableAgent | None
351
+ temp_user_proxy: ConversableAgent | None = None
351
352
  temp_user_list: list[Agent] = []
352
353
  if len(messages) == 1 and "name" not in messages[0] and not user_agent:
353
354
  temp_user_proxy = ConversableAgent(name="_User", code_execution_config=False, human_input_mode="ALWAYS")
@@ -425,7 +426,7 @@ def determine_next_agent(
425
426
  group_agent_names: list[str],
426
427
  user_agent: Optional["ConversableAgent"],
427
428
  group_after_work: TransitionTarget,
428
- ) -> Optional[Union[Agent, str]]:
429
+ ) -> Agent | str | None:
429
430
  """Determine the next agent in the conversation.
430
431
 
431
432
  Args:
@@ -441,7 +442,6 @@ def determine_next_agent(
441
442
  Returns:
442
443
  Optional[Union[Agent, str]]: The next agent or speaker selection method.
443
444
  """
444
-
445
445
  # Logic for determining the next target (anything based on Transition Target: an agent, wrapped agent, TerminateTarget, StayTarget, RevertToUserTarget, GroupManagerTarget, etc.
446
446
  # 1. If it's the first response -> initial agent
447
447
  # 2. If the last message is a tool call -> tool execution agent
@@ -513,7 +513,7 @@ def create_group_transition(
513
513
  group_agent_names: list[str],
514
514
  user_agent: Optional["ConversableAgent"],
515
515
  group_after_work: TransitionTarget,
516
- ) -> Callable[["ConversableAgent", GroupChat], Optional[Union[Agent, str]]]:
516
+ ) -> Callable[["ConversableAgent", GroupChat], Agent | str | None]:
517
517
  """Creates a transition function for group chat with enclosed state for the use_initial_agent.
518
518
 
519
519
  Args:
@@ -530,7 +530,7 @@ def create_group_transition(
530
530
  # of group_transition
531
531
  state = {"use_initial_agent": True}
532
532
 
533
- def group_transition(last_speaker: "ConversableAgent", groupchat: GroupChat) -> Optional[Union[Agent, str]]:
533
+ def group_transition(last_speaker: "ConversableAgent", groupchat: GroupChat) -> Agent | str | None:
534
534
  result = determine_next_agent(
535
535
  last_speaker=last_speaker,
536
536
  groupchat=groupchat,
@@ -549,7 +549,7 @@ def create_group_transition(
549
549
 
550
550
  def create_group_manager(
551
551
  groupchat: GroupChat,
552
- group_manager_args: Optional[dict[str, Any]],
552
+ group_manager_args: dict[str, Any] | None,
553
553
  agents: list["ConversableAgent"],
554
554
  group_after_work: TransitionTarget,
555
555
  ) -> GroupChatManager:
@@ -5,7 +5,7 @@
5
5
  import json
6
6
  import re
7
7
  from abc import ABC, abstractmethod
8
- from typing import TYPE_CHECKING, Any, Optional, Union
8
+ from typing import TYPE_CHECKING, Any
9
9
 
10
10
  from pydantic import BaseModel, Field
11
11
 
@@ -46,7 +46,7 @@ class Guardrail(ABC):
46
46
  """Abstract base class for guardrails."""
47
47
 
48
48
  def __init__(
49
- self, name: str, condition: str, target: "TransitionTarget", activation_message: Optional[str] = None
49
+ self, name: str, condition: str, target: "TransitionTarget", activation_message: str | None = None
50
50
  ) -> None:
51
51
  self.name = name
52
52
  self.condition = condition
@@ -58,7 +58,7 @@ class Guardrail(ABC):
58
58
  @abstractmethod
59
59
  def check(
60
60
  self,
61
- context: Union[str, list[dict[str, Any]]],
61
+ context: str | list[dict[str, Any]],
62
62
  ) -> GuardrailResult:
63
63
  """Checks the text against the guardrail and returns a GuardrailResult.
64
64
 
@@ -80,7 +80,7 @@ class LLMGuardrail(Guardrail):
80
80
  condition: str,
81
81
  target: "TransitionTarget",
82
82
  llm_config: "LLMConfig",
83
- activation_message: Optional[str] = None,
83
+ activation_message: str | None = None,
84
84
  ) -> None:
85
85
  super().__init__(name, condition, target, activation_message)
86
86
 
@@ -98,7 +98,7 @@ You will activate the guardrail only if the condition is met.
98
98
 
99
99
  def check(
100
100
  self,
101
- context: Union[str, list[dict[str, Any]]],
101
+ context: str | list[dict[str, Any]],
102
102
  ) -> GuardrailResult:
103
103
  """Checks the context against the guardrail using an LLM.
104
104
 
@@ -131,7 +131,7 @@ class RegexGuardrail(Guardrail):
131
131
  name: str,
132
132
  condition: str,
133
133
  target: "TransitionTarget",
134
- activation_message: Optional[str] = None,
134
+ activation_message: str | None = None,
135
135
  ) -> None:
136
136
  super().__init__(name, condition, target, activation_message)
137
137
  # Compile the regular expression condition
@@ -142,7 +142,7 @@ class RegexGuardrail(Guardrail):
142
142
 
143
143
  def check(
144
144
  self,
145
- context: Union[str, list[dict[str, Any]]],
145
+ context: str | list[dict[str, Any]],
146
146
  ) -> GuardrailResult:
147
147
  """Checks the context against the guardrail using a regular expression.
148
148
 
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Union, overload
5
+ from typing import overload
6
6
 
7
7
  from pydantic import BaseModel, Field
8
8
 
@@ -14,8 +14,7 @@ __all__ = ["Handoffs"]
14
14
 
15
15
 
16
16
  class Handoffs(BaseModel):
17
- """
18
- Container for all handoff transition conditions of a ConversableAgent.
17
+ """Container for all handoff transition conditions of a ConversableAgent.
19
18
 
20
19
  Three types of conditions can be added, each with a different order and time of use:
21
20
  1. OnContextConditions (evaluated without an LLM)
@@ -33,8 +32,7 @@ class Handoffs(BaseModel):
33
32
  after_works: list[OnContextCondition] = Field(default_factory=list)
34
33
 
35
34
  def add_context_condition(self, condition: OnContextCondition) -> "Handoffs":
36
- """
37
- Add a single context condition.
35
+ """Add a single context condition.
38
36
 
39
37
  Args:
40
38
  condition: The OnContextCondition to add
@@ -50,8 +48,7 @@ class Handoffs(BaseModel):
50
48
  return self
51
49
 
52
50
  def add_context_conditions(self, conditions: list[OnContextCondition]) -> "Handoffs":
53
- """
54
- Add multiple context conditions.
51
+ """Add multiple context conditions.
55
52
 
56
53
  Args:
57
54
  conditions: List of OnContextConditions to add
@@ -67,8 +64,7 @@ class Handoffs(BaseModel):
67
64
  return self
68
65
 
69
66
  def add_llm_condition(self, condition: OnCondition) -> "Handoffs":
70
- """
71
- Add a single LLM condition.
67
+ """Add a single LLM condition.
72
68
 
73
69
  Args:
74
70
  condition: The OnCondition to add
@@ -84,8 +80,7 @@ class Handoffs(BaseModel):
84
80
  return self
85
81
 
86
82
  def add_llm_conditions(self, conditions: list[OnCondition]) -> "Handoffs":
87
- """
88
- Add multiple LLM conditions.
83
+ """Add multiple LLM conditions.
89
84
 
90
85
  Args:
91
86
  conditions: List of OnConditions to add
@@ -101,8 +96,7 @@ class Handoffs(BaseModel):
101
96
  return self
102
97
 
103
98
  def set_after_work(self, target: TransitionTarget) -> "Handoffs":
104
- """
105
- Set the after work target (replaces all after_works with single entry).
99
+ """Set the after work target (replaces all after_works with single entry).
106
100
 
107
101
  For backward compatibility, this creates an OnContextCondition with no condition (always true).
108
102
 
@@ -121,8 +115,7 @@ class Handoffs(BaseModel):
121
115
  return self
122
116
 
123
117
  def add_after_work(self, condition: OnContextCondition) -> "Handoffs":
124
- """
125
- Add a single after-work condition.
118
+ """Add a single after-work condition.
126
119
 
127
120
  If the condition has condition=None, it will replace any existing
128
121
  condition=None entry and be placed at the end.
@@ -158,8 +151,7 @@ class Handoffs(BaseModel):
158
151
  return self
159
152
 
160
153
  def add_after_works(self, conditions: list[OnContextCondition]) -> "Handoffs":
161
- """
162
- Add multiple after-work conditions.
154
+ """Add multiple after-work conditions.
163
155
 
164
156
  Special handling for condition=None entries:
165
157
  - Only one condition=None entry is allowed (the fallback)
@@ -198,9 +190,8 @@ class Handoffs(BaseModel):
198
190
  @overload
199
191
  def add(self, condition: OnCondition) -> "Handoffs": ...
200
192
 
201
- def add(self, condition: Union[OnContextCondition, OnCondition]) -> "Handoffs":
202
- """
203
- Add a single condition (OnContextCondition or OnCondition).
193
+ def add(self, condition: OnContextCondition | OnCondition) -> "Handoffs":
194
+ """Add a single condition (OnContextCondition or OnCondition).
204
195
 
205
196
  Args:
206
197
  condition: The condition to add (OnContextCondition or OnCondition)
@@ -220,9 +211,8 @@ class Handoffs(BaseModel):
220
211
  else:
221
212
  raise TypeError(f"Unsupported condition type: {type(condition).__name__}")
222
213
 
223
- def add_many(self, conditions: list[Union[OnContextCondition, OnCondition]]) -> "Handoffs":
224
- """
225
- Add multiple conditions of any supported types (OnContextCondition and OnCondition).
214
+ def add_many(self, conditions: list[OnContextCondition | OnCondition]) -> "Handoffs":
215
+ """Add multiple conditions of any supported types (OnContextCondition and OnCondition).
226
216
 
227
217
  Args:
228
218
  conditions: List of conditions to add
@@ -254,8 +244,7 @@ class Handoffs(BaseModel):
254
244
  return self
255
245
 
256
246
  def clear(self) -> "Handoffs":
257
- """
258
- Clear all handoff conditions.
247
+ """Clear all handoff conditions.
259
248
 
260
249
  Returns:
261
250
  Self for method chaining
@@ -266,8 +255,7 @@ class Handoffs(BaseModel):
266
255
  return self
267
256
 
268
257
  def get_llm_conditions_by_target_type(self, target_type: type) -> list[OnCondition]:
269
- """
270
- Get OnConditions for a specific target type.
258
+ """Get OnConditions for a specific target type.
271
259
 
272
260
  Args:
273
261
  target_type: The type of condition to retrieve
@@ -278,8 +266,7 @@ class Handoffs(BaseModel):
278
266
  return [on_condition for on_condition in self.llm_conditions if on_condition.has_target_type(target_type)]
279
267
 
280
268
  def get_context_conditions_by_target_type(self, target_type: type) -> list[OnContextCondition]:
281
- """
282
- Get OnContextConditions for a specific target type.
269
+ """Get OnContextConditions for a specific target type.
283
270
 
284
271
  Args:
285
272
  target_type: The type of condition to retrieve
@@ -294,8 +281,7 @@ class Handoffs(BaseModel):
294
281
  ]
295
282
 
296
283
  def get_llm_conditions_requiring_wrapping(self) -> list[OnCondition]:
297
- """
298
- Get LLM conditions that have targets that require wrapping.
284
+ """Get LLM conditions that have targets that require wrapping.
299
285
 
300
286
  Returns:
301
287
  List of LLM conditions that require wrapping
@@ -303,8 +289,7 @@ class Handoffs(BaseModel):
303
289
  return [condition for condition in self.llm_conditions if condition.target_requires_wrapping()]
304
290
 
305
291
  def get_context_conditions_requiring_wrapping(self) -> list[OnContextCondition]:
306
- """
307
- Get context conditions that have targets that require wrapping.
292
+ """Get context conditions that have targets that require wrapping.
308
293
 
309
294
  Returns:
310
295
  List of context conditions that require wrapping
@@ -312,9 +297,7 @@ class Handoffs(BaseModel):
312
297
  return [condition for condition in self.context_conditions if condition.target_requires_wrapping()]
313
298
 
314
299
  def set_llm_function_names(self) -> None:
315
- """
316
- Set the LLM function names for all LLM conditions, creating unique names for each function.
317
- """
300
+ """Set the LLM function names for all LLM conditions, creating unique names for each function."""
318
301
  for i, condition in enumerate(self.llm_conditions):
319
302
  # Function names are made unique and allow multiple OnCondition's to the same agent
320
303
  condition.llm_function_name = f"transfer_to_{condition.target.normalized_name()}_{i + 1}"
@@ -4,7 +4,7 @@
4
4
 
5
5
  import asyncio
6
6
  import threading
7
- from typing import TYPE_CHECKING, Any, Union
7
+ from typing import TYPE_CHECKING, Any
8
8
 
9
9
  from ...doc_utils import export_module
10
10
  from ...events.agent_events import ErrorEvent, RunCompletionEvent
@@ -30,7 +30,7 @@ __all__ = [
30
30
  @export_module("autogen")
31
31
  def initiate_group_chat(
32
32
  pattern: "Pattern",
33
- messages: Union[list[dict[str, Any]], str],
33
+ messages: list[dict[str, Any]] | str,
34
34
  max_rounds: int = 20,
35
35
  ) -> tuple[ChatResult, ContextVariables, "Agent"]:
36
36
  """Initialize and run a group chat using a pattern for configuration.
@@ -92,7 +92,7 @@ def initiate_group_chat(
92
92
  @export_module("autogen.agentchat")
93
93
  async def a_initiate_group_chat(
94
94
  pattern: "Pattern",
95
- messages: Union[list[dict[str, Any]], str],
95
+ messages: list[dict[str, Any]] | str,
96
96
  max_rounds: int = 20,
97
97
  ) -> tuple[ChatResult, ContextVariables, "Agent"]:
98
98
  """Initialize and run a group chat using a pattern for configuration, asynchronously.
@@ -154,7 +154,7 @@ async def a_initiate_group_chat(
154
154
  @export_module("autogen.agentchat")
155
155
  def run_group_chat(
156
156
  pattern: "Pattern",
157
- messages: Union[list[dict[str, Any]], str],
157
+ messages: list[dict[str, Any]] | str,
158
158
  max_rounds: int = 20,
159
159
  ) -> RunResponseProtocol:
160
160
  iostream = ThreadIOStream()
@@ -163,7 +163,7 @@ def run_group_chat(
163
163
 
164
164
  def _initiate_group_chat(
165
165
  pattern: "Pattern" = pattern,
166
- messages: Union[list[dict[str, Any]], str] = messages,
166
+ messages: list[dict[str, Any]] | str = messages,
167
167
  max_rounds: int = max_rounds,
168
168
  iostream: ThreadIOStream = iostream,
169
169
  response: RunResponse = response,
@@ -198,7 +198,7 @@ def run_group_chat(
198
198
  @export_module("autogen.agentchat")
199
199
  async def a_run_group_chat(
200
200
  pattern: "Pattern",
201
- messages: Union[list[dict[str, Any]], str],
201
+ messages: list[dict[str, Any]] | str,
202
202
  max_rounds: int = 20,
203
203
  ) -> AsyncRunResponseProtocol:
204
204
  iostream = AsyncThreadIOStream()
@@ -207,7 +207,7 @@ async def a_run_group_chat(
207
207
 
208
208
  async def _initiate_group_chat(
209
209
  pattern: "Pattern" = pattern,
210
- messages: Union[list[dict[str, Any]], str] = messages,
210
+ messages: list[dict[str, Any]] | str = messages,
211
211
  max_rounds: int = max_rounds,
212
212
  iostream: AsyncThreadIOStream = iostream,
213
213
  response: AsyncRunResponse = response,
@@ -2,7 +2,6 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Optional
6
5
 
7
6
  from pydantic import BaseModel
8
7
 
@@ -33,12 +32,11 @@ class OnCondition(BaseModel): # noqa: N801
33
32
 
34
33
  target: TransitionTarget
35
34
  condition: LLMCondition
36
- available: Optional[AvailableCondition] = None
37
- llm_function_name: Optional[str] = None
35
+ available: AvailableCondition | None = None
36
+ llm_function_name: str | None = None
38
37
 
39
38
  def has_target_type(self, target_type: type) -> bool:
40
- """
41
- Check if the target type matches the specified type.
39
+ """Check if the target type matches the specified type.
42
40
 
43
41
  Args:
44
42
  target_type (type): The target type to check against, which should be a subclass of TransitionTarget
@@ -49,8 +47,7 @@ class OnCondition(BaseModel): # noqa: N801
49
47
  return isinstance(self.target, target_type)
50
48
 
51
49
  def target_requires_wrapping(self) -> bool:
52
- """
53
- Check if the target requires wrapping in an agent.
50
+ """Check if the target requires wrapping in an agent.
54
51
 
55
52
  Returns:
56
53
  bool: True if the target requires wrapping, False otherwise
@@ -2,7 +2,6 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Optional
6
5
 
7
6
  from pydantic import BaseModel
8
7
 
@@ -29,12 +28,11 @@ class OnContextCondition(BaseModel): # noqa: N801
29
28
  """
30
29
 
31
30
  target: TransitionTarget
32
- condition: Optional[ContextCondition] = None
33
- available: Optional[AvailableCondition] = None
31
+ condition: ContextCondition | None = None
32
+ available: AvailableCondition | None = None
34
33
 
35
34
  def has_target_type(self, target_type: type) -> bool:
36
- """
37
- Check if the target type matches the specified type.
35
+ """Check if the target type matches the specified type.
38
36
 
39
37
  Args:
40
38
  target_type (type): The target type to check against. Should be a subclass of TransitionTarget.
@@ -45,8 +43,7 @@ class OnContextCondition(BaseModel): # noqa: N801
45
43
  return isinstance(self.target, target_type)
46
44
 
47
45
  def target_requires_wrapping(self) -> bool:
48
- """
49
- Check if the target requires wrapping in an agent.
46
+ """Check if the target requires wrapping in an agent.
50
47
 
51
48
  Returns:
52
49
  bool: True if the target requires wrapping, False otherwise