ag2 0.9.7__py3-none-any.whl → 0.9.9__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.7.dist-info → ag2-0.9.9.dist-info}/METADATA +102 -75
  2. ag2-0.9.9.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 +292 -290
  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 +60 -63
  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 +38 -27
  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 +2 -1
  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 +113 -139
  186. autogen/oai/client_utils.py +3 -3
  187. autogen/oai/cohere.py +34 -11
  188. autogen/oai/gemini.py +39 -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 +19 -9
  200. autogen/oai/openai_responses.py +40 -17
  201. autogen/oai/openai_utils.py +48 -38
  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 +8 -6
  230. autogen/types.py +2 -2
  231. autogen/version.py +1 -1
  232. ag2-0.9.7.dist-info/RECORD +0 -421
  233. autogen/llm_config.py +0 -385
  234. {ag2-0.9.7.dist-info → ag2-0.9.9.dist-info}/WHEEL +0 -0
  235. {ag2-0.9.7.dist-info → ag2-0.9.9.dist-info}/licenses/LICENSE +0 -0
  236. {ag2-0.9.7.dist-info → ag2-0.9.9.dist-info}/licenses/NOTICE.md +0 -0
@@ -14,7 +14,8 @@ import json
14
14
  import logging
15
15
  import time
16
16
  import warnings
17
- from typing import Annotated, Any, Callable, Dict, List, Optional, Tuple, Type, Union
17
+ from collections.abc import Callable
18
+ from typing import Annotated, Any
18
19
 
19
20
  from pydantic import BaseModel, ConfigDict, Field, ValidationError
20
21
 
@@ -61,13 +62,13 @@ class ExecutionAttempt(BaseModel):
61
62
 
62
63
  model_config = ConfigDict(arbitrary_types_allowed=True)
63
64
  timestamp: float = Field(default_factory=time.time)
64
- attempt_args: List[Any] = Field(default_factory=list)
65
- attempt_kwargs: Dict[str, Any] = Field(default_factory=dict)
66
- hypothesis: Optional[str] = None
67
- error: Optional[str] = None
68
- result_data: Optional[Any] = None
69
- result_str: Optional[str] = None
70
- validation: Optional[ValidationResult] = None
65
+ attempt_args: list[Any] = Field(default_factory=list)
66
+ attempt_kwargs: dict[str, Any] = Field(default_factory=dict)
67
+ hypothesis: str | None = None
68
+ error: str | None = None
69
+ result_data: Any | None = None
70
+ result_str: str | None = None
71
+ validation: ValidationResult | None = None
71
72
 
72
73
  @property
73
74
  def did_execute_successfully(self) -> bool:
@@ -87,14 +88,12 @@ class ReliableToolContext(BaseModel):
87
88
  task: str
88
89
  reliable_tool_name: str
89
90
  start_time: float = Field(default_factory=time.time)
90
- dynamic_validation_input: Optional[str] = None
91
- attempts: List[ExecutionAttempt] = Field(default_factory=list)
92
- initial_messages: Optional[List[dict[str, Any]]] = Field(
91
+ dynamic_validation_input: str | None = None
92
+ attempts: list[ExecutionAttempt] = Field(default_factory=list)
93
+ initial_messages: list[dict[str, Any]] | None = Field(
93
94
  default=None, description="Initial messages provided to the tool run."
94
95
  )
95
- initial_ground_truth: Optional[List[str]] = Field(
96
- default=None, description="Initial ground truth strings provided."
97
- )
96
+ initial_ground_truth: list[str] | None = Field(default=None, description="Initial ground truth strings provided.")
98
97
 
99
98
  @property
100
99
  def attempt_count(self) -> int:
@@ -102,7 +101,7 @@ class ReliableToolContext(BaseModel):
102
101
  return len(self.attempts)
103
102
 
104
103
  @property
105
- def latest_attempt(self) -> Optional[ExecutionAttempt]:
104
+ def latest_attempt(self) -> ExecutionAttempt | None:
106
105
  """Return the most recent attempt, if any."""
107
106
  return self.attempts[-1] if self.attempts else None
108
107
 
@@ -143,8 +142,8 @@ class SuccessfulExecutionParameters(BaseModel):
143
142
  """Holds the arguments of a successful tool function execution."""
144
143
 
145
144
  model_config = ConfigDict(arbitrary_types_allowed=True)
146
- attempt_args: List[Any]
147
- attempt_kwargs: Dict[str, Any]
145
+ attempt_args: list[Any]
146
+ attempt_kwargs: dict[str, Any]
148
147
 
149
148
 
150
149
  class ToolExecutionDetails(BaseModel):
@@ -153,14 +152,14 @@ class ToolExecutionDetails(BaseModel):
153
152
  model_config = ConfigDict(arbitrary_types_allowed=True)
154
153
  task: str
155
154
  is_overall_successful: bool
156
- failure_reason: Optional[str] = None
157
- successful_parameters: Optional[SuccessfulExecutionParameters] = None
155
+ failure_reason: str | None = None
156
+ successful_parameters: SuccessfulExecutionParameters | None = None
158
157
  final_tool_context: ReliableToolContext
159
158
 
160
159
 
161
160
  def _configure_llm_for_structured_output(
162
- llm_config: Optional[Union[LLMConfig, dict[str, Any]]], structured_output_type: Type[BaseModel]
163
- ) -> Union[LLMConfig, dict[str, Any]]: # Return type changed, False is no longer a valid return
161
+ llm_config: LLMConfig | dict[str, Any] | None, structured_output_type: type[BaseModel]
162
+ ) -> LLMConfig | dict[str, Any]: # Return type changed, False is no longer a valid return
164
163
  """Configure LLM config for structured output using a Pydantic model."""
165
164
  if llm_config is None or llm_config is False:
166
165
  raise ValueError("LLMConfig cannot be None or False for structured output.")
@@ -174,7 +173,7 @@ def _configure_llm_for_structured_output(
174
173
 
175
174
  response_format_set = False
176
175
 
177
- def _set_format_and_remove_conflicts(config_item: Union[LLMConfig, Dict[str, Any]]) -> None:
176
+ def _set_format_and_remove_conflicts(config_item: LLMConfig | dict[str, Any]) -> None:
178
177
  nonlocal response_format_set
179
178
  conflicting_keys = ["tools", "tool_choice", "functions"]
180
179
  removed_keys = []
@@ -192,7 +191,7 @@ def _configure_llm_for_structured_output(
192
191
  for key in conflicting_keys:
193
192
  if hasattr(config_item, key) and getattr(config_item, key, None):
194
193
  # Try setting to None or empty list/dict as appropriate
195
- default_empty: Optional[List[str]] = [] if key in ["tools", "functions"] else None
194
+ default_empty: list[str] | None = [] if key in ["tools", "functions"] else None
196
195
  setattr(config_item, key, default_empty)
197
196
  removed_keys.append(key)
198
197
  else:
@@ -243,7 +242,7 @@ def _configure_llm_for_structured_output(
243
242
  return llm_config_obj
244
243
 
245
244
 
246
- def _get_last_non_empty_message_content(messages: Optional[List[dict[str, Any]]]) -> Optional[str]:
245
+ def _get_last_non_empty_message_content(messages: list[dict[str, Any]] | None) -> str | None:
247
246
  """Get content of the last message with non-empty content."""
248
247
  if not messages:
249
248
  return None
@@ -342,7 +341,7 @@ Current Task:
342
341
 
343
342
 
344
343
  def get_validator_prompt(
345
- task: str, base_validator_system_message: str, dynamic_validation_addition: Optional[str] = None
344
+ task: str, base_validator_system_message: str, dynamic_validation_addition: str | None = None
346
345
  ) -> str:
347
346
  """Generate the system prompt for the internal validator agent."""
348
347
  dynamic_section = (
@@ -517,7 +516,7 @@ def reliable_function_wrapper(
517
516
  class ReliableToolError(Exception):
518
517
  """Custom exception for errors during ReliableTool execution."""
519
518
 
520
- def __init__(self, message: str, final_context: Optional[ReliableToolContext] = None):
519
+ def __init__(self, message: str, final_context: ReliableToolContext | None = None):
521
520
  super().__init__(message)
522
521
  self.final_context = final_context
523
522
 
@@ -529,19 +528,18 @@ class ReliableTool(Tool):
529
528
  def __init__(
530
529
  self,
531
530
  name: str,
532
- func_or_tool: Union[Callable[..., Any], Tool],
533
- runner_llm_config: Union[LLMConfig, dict[str, Any]],
534
- validator_llm_config: Union[LLMConfig, dict[str, Any]],
535
- description: Optional[str] = None,
531
+ func_or_tool: Callable[..., Any] | Tool,
532
+ runner_llm_config: LLMConfig | dict[str, Any],
533
+ validator_llm_config: LLMConfig | dict[str, Any],
534
+ description: str | None = None,
536
535
  system_message_addition_for_tool_calling: str = "",
537
536
  system_message_addition_for_result_validation: str = "",
538
537
  max_tool_invocations: int = 3,
539
538
  enable_dynamic_validation: bool = False,
540
- messages: Optional[List[dict[str, Any]]] = None,
541
- ground_truth: Optional[List[str]] = None,
539
+ messages: list[dict[str, Any]] | None = None,
540
+ ground_truth: list[str] | None = None,
542
541
  ) -> None:
543
- """
544
- A ReliableTool wraps an existing function or tool.
542
+ """A ReliableTool wraps an existing function or tool.
545
543
  When the ReliableTool is invoked, it kicks off an internal Group Chat where a Runner
546
544
  and Validator agent will iteratively invoke the wrapped function or tool until
547
545
  *the output of a single invocation of the original function or tool satisfies the provided validation criteria.*
@@ -703,9 +701,7 @@ class ReliableTool(Tool):
703
701
  if not is_async:
704
702
  if enable_dynamic:
705
703
 
706
- def sync_entry_point_with_validation(
707
- task: str, validation_prompt_addition: Optional[str] = None
708
- ) -> Any:
704
+ def sync_entry_point_with_validation(task: str, validation_prompt_addition: str | None = None) -> Any:
709
705
  return self.run(task=task, validation_prompt_addition=validation_prompt_addition)
710
706
 
711
707
  return sync_entry_point_with_validation
@@ -719,7 +715,7 @@ class ReliableTool(Tool):
719
715
  if enable_dynamic:
720
716
 
721
717
  async def async_entry_point_with_validation(
722
- task: str, validation_prompt_addition: Optional[str] = None
718
+ task: str, validation_prompt_addition: str | None = None
723
719
  ) -> Any:
724
720
  return await self.a_run(task=task, validation_prompt_addition=validation_prompt_addition)
725
721
 
@@ -731,9 +727,7 @@ class ReliableTool(Tool):
731
727
 
732
728
  return async_entry_point_without_validation
733
729
 
734
- def _extract_func_details(
735
- self, func_or_tool: Union[Callable[..., Any], Tool]
736
- ) -> Tuple[Callable[..., Any], str, str]:
730
+ def _extract_func_details(self, func_or_tool: Callable[..., Any] | Tool) -> tuple[Callable[..., Any], str, str]:
737
731
  default_desc_template = "Executes the '{name}' function."
738
732
  if isinstance(func_or_tool, Tool):
739
733
  func = getattr(func_or_tool, "func", None)
@@ -806,8 +800,8 @@ class ReliableTool(Tool):
806
800
  self._runner.register_hook(hookable_method="process_message_before_send", hook=self._ensure_function_call_hook)
807
801
 
808
802
  def _validator_structured_output_hook(
809
- self, sender: Agent, message: Union[dict[str, Any], str], recipient: Agent, silent: bool
810
- ) -> Union[dict[str, Any], str]:
803
+ self, sender: Agent, message: dict[str, Any] | str, recipient: Agent, silent: bool
804
+ ) -> dict[str, Any] | str:
811
805
  if not isinstance(message, str):
812
806
  logger.error(
813
807
  f"Validator Hook: Expected a JSON string message from LLM, but got {type(message)}. Content: {str(message)[:200]}"
@@ -885,8 +879,8 @@ class ReliableTool(Tool):
885
879
  return final_messages
886
880
 
887
881
  def _ensure_function_call_hook(
888
- self, sender: Agent, message: Union[dict[str, Any], str], recipient: Agent, silent: bool
889
- ) -> Union[dict[str, Any], str]:
882
+ self, sender: Agent, message: dict[str, Any] | str, recipient: Agent, silent: bool
883
+ ) -> dict[str, Any] | str:
890
884
  if sender.name != self._runner_name:
891
885
  return message
892
886
 
@@ -941,8 +935,8 @@ class ReliableTool(Tool):
941
935
  self,
942
936
  task: str,
943
937
  initial_context_vars: ContextVariables, # Renamed for clarity
944
- dynamic_validation_str: Optional[str] = None,
945
- ) -> Tuple[ChatResult, ContextVariables, Agent]:
938
+ dynamic_validation_str: str | None = None,
939
+ ) -> tuple[ChatResult, ContextVariables, Agent]:
946
940
  internal_tool_name = f"{self.INTERNAL_TOOL_NAME_PREFIX}{self._original_func_name}"
947
941
 
948
942
  # update_system_message should not fail if agent is properly initialized
@@ -1008,9 +1002,9 @@ class ReliableTool(Tool):
1008
1002
  self,
1009
1003
  task: str,
1010
1004
  current_context_variables: ContextVariables,
1011
- validation_prompt_addition: Optional[str] = None,
1012
- messages: Optional[list[dict[str, Any]]] = None,
1013
- ground_truth: Optional[List[str]] = None,
1005
+ validation_prompt_addition: str | None = None,
1006
+ messages: list[dict[str, Any]] | None = None,
1007
+ ground_truth: list[str] | None = None,
1014
1008
  ) -> ReliableToolContext:
1015
1009
  """Initializes or updates the ReliableToolContext for the current run."""
1016
1010
  effective_messages = copy.deepcopy(messages) if messages is not None else self._init_messages
@@ -1029,10 +1023,10 @@ class ReliableTool(Tool):
1029
1023
  def _process_run(
1030
1024
  self,
1031
1025
  task: str,
1032
- context_variables: Optional[ContextVariables] = None,
1033
- validation_prompt_addition: Optional[str] = None,
1034
- messages: Optional[list[dict[str, Any]]] = None,
1035
- ground_truth: Optional[List[str]] = None,
1026
+ context_variables: ContextVariables | None = None,
1027
+ validation_prompt_addition: str | None = None,
1028
+ messages: list[dict[str, Any]] | None = None,
1029
+ ground_truth: list[str] | None = None,
1036
1030
  ) -> Any:
1037
1031
  current_context_variables = context_variables if context_variables is not None else ContextVariables()
1038
1032
  if not isinstance(current_context_variables, ContextVariables):
@@ -1082,10 +1076,10 @@ class ReliableTool(Tool):
1082
1076
  def run(
1083
1077
  self,
1084
1078
  task: str,
1085
- context_variables: Optional[ContextVariables] = None,
1086
- validation_prompt_addition: Optional[str] = None,
1087
- messages: Optional[list[dict[str, Any]]] = None,
1088
- ground_truth: Optional[List[str]] = None,
1079
+ context_variables: ContextVariables | None = None,
1080
+ validation_prompt_addition: str | None = None,
1081
+ messages: list[dict[str, Any]] | None = None,
1082
+ ground_truth: list[str] | None = None,
1089
1083
  ) -> Any:
1090
1084
  if self._is_original_func_async:
1091
1085
  raise TypeError(f"Sync 'run()' called for async tool '{self.name}'. Use 'a_run()'.")
@@ -1100,10 +1094,10 @@ class ReliableTool(Tool):
1100
1094
  async def a_run(
1101
1095
  self,
1102
1096
  task: str,
1103
- context_variables: Optional[ContextVariables] = None,
1104
- validation_prompt_addition: Optional[str] = None,
1105
- messages: Optional[list[dict[str, Any]]] = None,
1106
- ground_truth: Optional[List[str]] = None,
1097
+ context_variables: ContextVariables | None = None,
1098
+ validation_prompt_addition: str | None = None,
1099
+ messages: list[dict[str, Any]] | None = None,
1100
+ ground_truth: list[str] | None = None,
1107
1101
  ) -> Any:
1108
1102
  if not self._is_original_func_async:
1109
1103
  warnings.warn(
@@ -1127,10 +1121,10 @@ class ReliableTool(Tool):
1127
1121
  def _process_run_with_details(
1128
1122
  self,
1129
1123
  task: str,
1130
- context_variables: Optional[ContextVariables] = None,
1131
- validation_prompt_addition: Optional[str] = None,
1132
- messages: Optional[list[dict[str, Any]]] = None,
1133
- ground_truth: Optional[List[str]] = None,
1124
+ context_variables: ContextVariables | None = None,
1125
+ validation_prompt_addition: str | None = None,
1126
+ messages: list[dict[str, Any]] | None = None,
1127
+ ground_truth: list[str] | None = None,
1134
1128
  ) -> ToolExecutionDetails:
1135
1129
  current_context_variables = context_variables if context_variables is not None else ContextVariables()
1136
1130
  if not isinstance(current_context_variables, ContextVariables):
@@ -1251,10 +1245,10 @@ class ReliableTool(Tool):
1251
1245
  def run_and_get_details(
1252
1246
  self,
1253
1247
  task: str,
1254
- context_variables: Optional[ContextVariables] = None,
1255
- validation_prompt_addition: Optional[str] = None,
1256
- messages: Optional[list[dict[str, Any]]] = None,
1257
- ground_truth: Optional[List[str]] = None,
1248
+ context_variables: ContextVariables | None = None,
1249
+ validation_prompt_addition: str | None = None,
1250
+ messages: list[dict[str, Any]] | None = None,
1251
+ ground_truth: list[str] | None = None,
1258
1252
  ) -> ToolExecutionDetails:
1259
1253
  if self._is_original_func_async:
1260
1254
  raise TypeError(
@@ -1272,10 +1266,10 @@ class ReliableTool(Tool):
1272
1266
  async def a_run_and_get_details(
1273
1267
  self,
1274
1268
  task: str,
1275
- context_variables: Optional[ContextVariables] = None,
1276
- validation_prompt_addition: Optional[str] = None,
1277
- messages: Optional[list[dict[str, Any]]] = None,
1278
- ground_truth: Optional[List[str]] = None,
1269
+ context_variables: ContextVariables | None = None,
1270
+ validation_prompt_addition: str | None = None,
1271
+ messages: list[dict[str, Any]] | None = None,
1272
+ ground_truth: list[str] | None = None,
1279
1273
  ) -> ToolExecutionDetails:
1280
1274
  if not self._is_original_func_async:
1281
1275
  warnings.warn(
@@ -1,13 +1,12 @@
1
1
  # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
- """
5
- SearxNG Search Tool
4
+ """SearxNG Search Tool
6
5
  A simple tool to perform web searches using a SearxNG instance.
7
6
  """
8
7
 
9
8
  import logging
10
- from typing import Annotated, Any, List, Optional
9
+ from typing import Annotated, Any
11
10
 
12
11
  import requests
13
12
 
@@ -20,18 +19,19 @@ logger = logging.getLogger(__name__)
20
19
  def _execute_searxng_query(
21
20
  query: str,
22
21
  max_results: int = 5,
23
- categories: Optional[List[str]] = None,
24
- language: Optional[str] = None,
22
+ categories: list[str] | None = None,
23
+ language: str | None = None,
25
24
  base_url: str = "https://searxng.site/search",
26
25
  ) -> list[dict[str, Any]]:
27
- """
28
- Execute a search query using a SearxNG instance.
26
+ """Execute a search query using a SearxNG instance.
27
+
29
28
  Args:
30
29
  query (str): The search query string.
31
30
  max_results (int, optional): The maximum number of results to return. Defaults to 5.
32
31
  categories (Optional[List[str]]): List of categories to search in.
33
32
  language (Optional[str]): Language code.
34
33
  base_url (str): SearxNG instance URL.
34
+
35
35
  Returns:
36
36
  list[dict[str, Any]]: A list of search results from SearxNG.
37
37
  """
@@ -64,18 +64,19 @@ def _execute_searxng_query(
64
64
  def _searxng_search(
65
65
  query: str,
66
66
  max_results: int = 5,
67
- categories: Optional[List[str]] = None,
68
- language: Optional[str] = None,
67
+ categories: list[str] | None = None,
68
+ language: str | None = None,
69
69
  base_url: str = "https://searxng.site/search",
70
70
  ) -> list[dict[str, Any]]:
71
- """
72
- Perform a SearxNG search and format the results.
71
+ """Perform a SearxNG search and format the results.
72
+
73
73
  Args:
74
74
  query (str): The search query string.
75
75
  max_results (int, optional): The maximum number of results to return. Defaults to 5.
76
76
  categories (Optional[List[str]]): List of categories to search in.
77
77
  language (Optional[str]): Language code.
78
78
  base_url (str): SearxNG instance URL.
79
+
79
80
  Returns:
80
81
  list[dict[str, Any]]: A list of dictionaries with 'title', 'link', and 'snippet'.
81
82
  """
@@ -95,16 +96,15 @@ def _searxng_search(
95
96
 
96
97
  @export_module("autogen.tools.experimental")
97
98
  class SearxngSearchTool(Tool):
98
- """
99
- SearxngSearchTool is a tool that uses SearxNG to perform a search.
99
+ """SearxngSearchTool is a tool that uses SearxNG to perform a search.
100
100
 
101
101
  This tool allows agents to leverage the SearxNG search engine for information retrieval.
102
102
  SearxNG does not require an API key by default, making it easy to use.
103
103
  """
104
104
 
105
105
  def __init__(self, base_url: str = "https://searxng.site/search") -> None:
106
- """
107
- Initializes the SearxngSearchTool.
106
+ """Initializes the SearxngSearchTool.
107
+
108
108
  Args:
109
109
  base_url (str): The SearxNG instance URL.
110
110
  """
@@ -119,16 +119,17 @@ class SearxngSearchTool(Tool):
119
119
  self,
120
120
  query: Annotated[str, "The search query."],
121
121
  max_results: Annotated[int, "The number of results to return."] = 5,
122
- categories: Annotated[Optional[List[str]], "List of categories to search in."] = None,
123
- language: Annotated[Optional[str], "Language code (e.g., 'en-US')."] = None,
122
+ categories: Annotated[list[str] | None, "List of categories to search in."] = None,
123
+ language: Annotated[str | None, "Language code (e.g., 'en-US')."] = None,
124
124
  ) -> list[dict[str, Any]]:
125
- """
126
- Performs a search using the SearxNG API and returns formatted results.
125
+ """Performs a search using the SearxNG API and returns formatted results.
126
+
127
127
  Args:
128
128
  query: The search query string.
129
129
  max_results: The maximum number of results to return. Defaults to 5.
130
130
  categories: List of categories to search in.
131
131
  language: Language code.
132
+
132
133
  Returns:
133
134
  A list of dictionaries, each containing 'title', 'link', and 'snippet' of a search result.
134
135
  """
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  import os
5
- from typing import Annotated, Any, Optional, Union
5
+ from typing import Annotated, Any
6
6
 
7
7
  from ....doc_utils import export_module
8
8
  from ....import_utils import optional_import_block, require_optional_import
@@ -30,8 +30,7 @@ def _execute_tavily_query(
30
30
  include_domains: list[str] = [],
31
31
  num_results: int = 5,
32
32
  ) -> Any:
33
- """
34
- Execute a search query using the Tavily API.
33
+ """Execute a search query using the Tavily API.
35
34
 
36
35
  Args:
37
36
  query (str): The search query string.
@@ -68,8 +67,7 @@ def _tavily_search(
68
67
  include_domains: list[str] = [],
69
68
  num_results: int = 5,
70
69
  ) -> list[dict[str, Any]]:
71
- """
72
- Perform a Tavily search and format the results.
70
+ """Perform a Tavily search and format the results.
73
71
 
74
72
  This function takes search parameters, executes the query using `_execute_tavily_query`,
75
73
  and formats the results into a list of dictionaries containing title, link, and snippet.
@@ -107,8 +105,7 @@ def _tavily_search(
107
105
 
108
106
  @export_module("autogen.tools.experimental")
109
107
  class TavilySearchTool(Tool):
110
- """
111
- TavilySearchTool is a tool that uses the Tavily Search API to perform a search.
108
+ """TavilySearchTool is a tool that uses the Tavily Search API to perform a search.
112
109
 
113
110
  This tool allows agents to leverage the Tavily search engine for information retrieval.
114
111
  It requires a Tavily API key, which can be provided during initialization or set as
@@ -118,11 +115,8 @@ class TavilySearchTool(Tool):
118
115
  tavily_api_key (str): The API key used for authenticating with the Tavily API.
119
116
  """
120
117
 
121
- def __init__(
122
- self, *, llm_config: Optional[Union[LLMConfig, dict[str, Any]]] = None, tavily_api_key: Optional[str] = None
123
- ):
124
- """
125
- Initializes the TavilySearchTool.
118
+ def __init__(self, *, llm_config: LLMConfig | dict[str, Any] | None = None, tavily_api_key: str | None = None):
119
+ """Initializes the TavilySearchTool.
126
120
 
127
121
  Args:
128
122
  llm_config (Optional[Union[LLMConfig, dict[str, Any]]]): LLM configuration. (Currently unused but kept for potential future integration).
@@ -139,15 +133,14 @@ class TavilySearchTool(Tool):
139
133
 
140
134
  def tavily_search(
141
135
  query: Annotated[str, "The search query."],
142
- tavily_api_key: Annotated[Optional[str], Depends(on(self.tavily_api_key))],
143
- search_depth: Annotated[Optional[str], "Either 'advanced' or 'basic'"] = "basic",
144
- include_answer: Annotated[Optional[str], "Either 'advanced' or 'basic'"] = "basic",
145
- include_raw_content: Annotated[Optional[bool], "Include the raw contents"] = False,
146
- include_domains: Annotated[Optional[list[str]], "Specific web domains to search"] = [],
136
+ tavily_api_key: Annotated[str | None, Depends(on(self.tavily_api_key))],
137
+ search_depth: Annotated[str | None, "Either 'advanced' or 'basic'"] = "basic",
138
+ include_answer: Annotated[str | None, "Either 'advanced' or 'basic'"] = "basic",
139
+ include_raw_content: Annotated[bool | None, "Include the raw contents"] = False,
140
+ include_domains: Annotated[list[str] | None, "Specific web domains to search"] = [],
147
141
  num_results: Annotated[int, "The number of results to return."] = 5,
148
142
  ) -> list[dict[str, Any]]:
149
- """
150
- Performs a search using the Tavily API and returns formatted results.
143
+ """Performs a search using the Tavily API and returns formatted results.
151
144
 
152
145
  Args:
153
146
  query: The search query string.
@@ -6,7 +6,7 @@
6
6
  import copy
7
7
  import logging
8
8
  import os
9
- from typing import Annotated, Any, Literal, Optional, Type, Union
9
+ from typing import Annotated, Any, Literal
10
10
 
11
11
  from pydantic import BaseModel
12
12
 
@@ -29,11 +29,11 @@ class WebSearchPreviewTool(Tool):
29
29
  def __init__(
30
30
  self,
31
31
  *,
32
- llm_config: Union[LLMConfig, dict[str, Any]],
32
+ llm_config: LLMConfig | dict[str, Any],
33
33
  search_context_size: Literal["low", "medium", "high"] = "medium",
34
- user_location: Optional[dict[str, str]] = None,
35
- instructions: Optional[str] = None,
36
- text_format: Optional[Type[BaseModel]] = None,
34
+ user_location: dict[str, str] | None = None,
35
+ instructions: str | None = None,
36
+ text_format: type[BaseModel] | None = None,
37
37
  ):
38
38
  """Initialize the WebSearchPreviewTool.
39
39
 
@@ -85,7 +85,7 @@ class WebSearchPreviewTool(Tool):
85
85
 
86
86
  def web_search_preview(
87
87
  query: Annotated[str, "The search query. Add all relevant context to the query."],
88
- ) -> Union[str, Optional[BaseModel]]:
88
+ ) -> str | BaseModel | None:
89
89
  client = OpenAI()
90
90
 
91
91
  if not self.text_format:
@@ -95,7 +95,13 @@ class WebSearchPreviewTool(Tool):
95
95
  input=query,
96
96
  instructions=self.instructions,
97
97
  )
98
- return response.output_text
98
+ text = []
99
+ for output in response.output:
100
+ if output.type == "message":
101
+ for content in output.content:
102
+ if content.type == "output_text":
103
+ text.append(content.text)
104
+ return "\n".join(text)
99
105
 
100
106
  else:
101
107
  response = client.responses.parse(
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Any, Optional, Union
5
+ from typing import Any
6
6
 
7
7
  import requests
8
8
  from pydantic import BaseModel
@@ -102,7 +102,7 @@ class WikipediaClient:
102
102
  search_data = data.get("query", {}).get("search", [])
103
103
  return search_data
104
104
 
105
- def get_page(self, title: str) -> Optional[Any]:
105
+ def get_page(self, title: str) -> Any | None:
106
106
  """Retrieve a WikipediaPage object by title.
107
107
 
108
108
  Args:
@@ -158,7 +158,7 @@ class WikipediaQueryRunTool(Tool):
158
158
  func_or_tool=self.query_run,
159
159
  )
160
160
 
161
- def query_run(self, query: str) -> Union[list[str], str]:
161
+ def query_run(self, query: str) -> list[str] | str:
162
162
  """Search Wikipedia and return formatted page summaries.
163
163
 
164
164
  Truncates `query` to MAX_QUERY_LENGTH before searching.
@@ -194,8 +194,7 @@ class WikipediaQueryRunTool(Tool):
194
194
 
195
195
  @require_optional_import(["wikipediaapi"], "wikipedia")
196
196
  class WikipediaPageLoadTool(Tool):
197
- """
198
- A tool to load up to N characters of Wikipedia page content along with metadata.
197
+ """A tool to load up to N characters of Wikipedia page content along with metadata.
199
198
 
200
199
  This tool uses a language-specific Wikipedia client to search for relevant articles
201
200
  and returns a list of Document objects containing truncated page content and metadata
@@ -212,8 +211,7 @@ class WikipediaPageLoadTool(Tool):
212
211
  """
213
212
 
214
213
  def __init__(self, language: str = "en", top_k: int = 3, truncate: int = 4000, verbose: bool = False) -> None:
215
- """
216
- Initializes the WikipediaPageLoadTool with configurable language, result count, and content length.
214
+ """Initializes the WikipediaPageLoadTool with configurable language, result count, and content length.
217
215
 
218
216
  Args:
219
217
  language (str): The language code for the Wikipedia edition (default is "en").
@@ -240,9 +238,8 @@ class WikipediaPageLoadTool(Tool):
240
238
  func_or_tool=self.content_search,
241
239
  )
242
240
 
243
- def content_search(self, query: str) -> Union[list[Document], str]:
244
- """
245
- Executes a Wikipedia search and returns page content plus metadata.
241
+ def content_search(self, query: str) -> list[Document] | str:
242
+ """Executes a Wikipedia search and returns page content plus metadata.
246
243
 
247
244
  Args:
248
245
  query (str): The search term to query Wikipedia.