ag2 0.9.1a1__py3-none-any.whl → 0.9.1.post0__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 (357) hide show
  1. {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info}/METADATA +264 -73
  2. ag2-0.9.1.post0.dist-info/RECORD +392 -0
  3. {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info}/WHEEL +1 -2
  4. autogen/__init__.py +89 -0
  5. autogen/_website/__init__.py +3 -0
  6. autogen/_website/generate_api_references.py +427 -0
  7. autogen/_website/generate_mkdocs.py +1174 -0
  8. autogen/_website/notebook_processor.py +476 -0
  9. autogen/_website/process_notebooks.py +656 -0
  10. autogen/_website/utils.py +412 -0
  11. autogen/agentchat/__init__.py +44 -0
  12. autogen/agentchat/agent.py +182 -0
  13. autogen/agentchat/assistant_agent.py +85 -0
  14. autogen/agentchat/chat.py +309 -0
  15. autogen/agentchat/contrib/__init__.py +5 -0
  16. autogen/agentchat/contrib/agent_eval/README.md +7 -0
  17. autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
  18. autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
  19. autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
  20. autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
  21. autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
  22. autogen/agentchat/contrib/agent_eval/task.py +42 -0
  23. autogen/agentchat/contrib/agent_optimizer.py +429 -0
  24. autogen/agentchat/contrib/capabilities/__init__.py +5 -0
  25. autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
  26. autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
  27. autogen/agentchat/contrib/capabilities/teachability.py +393 -0
  28. autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
  29. autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
  30. autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
  31. autogen/agentchat/contrib/capabilities/transforms.py +566 -0
  32. autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
  33. autogen/agentchat/contrib/capabilities/vision_capability.py +214 -0
  34. autogen/agentchat/contrib/captainagent/__init__.py +9 -0
  35. autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
  36. autogen/agentchat/contrib/captainagent/captainagent.py +512 -0
  37. autogen/agentchat/contrib/captainagent/tool_retriever.py +335 -0
  38. autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
  39. autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
  40. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
  41. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
  42. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
  43. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
  44. autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
  45. autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
  46. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
  47. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
  48. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
  49. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
  50. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
  51. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
  52. autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
  53. autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
  54. autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
  55. autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
  56. autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
  57. autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
  58. autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
  59. autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
  60. autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
  61. autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
  62. autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
  63. autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
  64. autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
  65. autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
  66. autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
  67. autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
  68. autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
  69. autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
  70. autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
  71. autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
  72. autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
  73. autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
  74. autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
  75. autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
  76. autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
  77. autogen/agentchat/contrib/graph_rag/document.py +29 -0
  78. autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +170 -0
  79. autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
  80. autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
  81. autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
  82. autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +268 -0
  83. autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
  84. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
  85. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
  86. autogen/agentchat/contrib/img_utils.py +397 -0
  87. autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
  88. autogen/agentchat/contrib/llava_agent.py +187 -0
  89. autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
  90. autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
  91. autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +324 -0
  92. autogen/agentchat/contrib/rag/__init__.py +10 -0
  93. autogen/agentchat/contrib/rag/chromadb_query_engine.py +272 -0
  94. autogen/agentchat/contrib/rag/llamaindex_query_engine.py +198 -0
  95. autogen/agentchat/contrib/rag/mongodb_query_engine.py +329 -0
  96. autogen/agentchat/contrib/rag/query_engine.py +74 -0
  97. autogen/agentchat/contrib/retrieve_assistant_agent.py +56 -0
  98. autogen/agentchat/contrib/retrieve_user_proxy_agent.py +703 -0
  99. autogen/agentchat/contrib/society_of_mind_agent.py +199 -0
  100. autogen/agentchat/contrib/swarm_agent.py +1425 -0
  101. autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
  102. autogen/agentchat/contrib/vectordb/__init__.py +5 -0
  103. autogen/agentchat/contrib/vectordb/base.py +232 -0
  104. autogen/agentchat/contrib/vectordb/chromadb.py +315 -0
  105. autogen/agentchat/contrib/vectordb/couchbase.py +407 -0
  106. autogen/agentchat/contrib/vectordb/mongodb.py +550 -0
  107. autogen/agentchat/contrib/vectordb/pgvectordb.py +928 -0
  108. autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
  109. autogen/agentchat/contrib/vectordb/utils.py +126 -0
  110. autogen/agentchat/contrib/web_surfer.py +303 -0
  111. autogen/agentchat/conversable_agent.py +4020 -0
  112. autogen/agentchat/group/__init__.py +64 -0
  113. autogen/agentchat/group/available_condition.py +91 -0
  114. autogen/agentchat/group/context_condition.py +77 -0
  115. autogen/agentchat/group/context_expression.py +238 -0
  116. autogen/agentchat/group/context_str.py +41 -0
  117. autogen/agentchat/group/context_variables.py +192 -0
  118. autogen/agentchat/group/group_tool_executor.py +202 -0
  119. autogen/agentchat/group/group_utils.py +591 -0
  120. autogen/agentchat/group/handoffs.py +244 -0
  121. autogen/agentchat/group/llm_condition.py +93 -0
  122. autogen/agentchat/group/multi_agent_chat.py +237 -0
  123. autogen/agentchat/group/on_condition.py +58 -0
  124. autogen/agentchat/group/on_context_condition.py +54 -0
  125. autogen/agentchat/group/patterns/__init__.py +18 -0
  126. autogen/agentchat/group/patterns/auto.py +159 -0
  127. autogen/agentchat/group/patterns/manual.py +176 -0
  128. autogen/agentchat/group/patterns/pattern.py +288 -0
  129. autogen/agentchat/group/patterns/random.py +106 -0
  130. autogen/agentchat/group/patterns/round_robin.py +117 -0
  131. autogen/agentchat/group/reply_result.py +26 -0
  132. autogen/agentchat/group/speaker_selection_result.py +41 -0
  133. autogen/agentchat/group/targets/__init__.py +4 -0
  134. autogen/agentchat/group/targets/group_chat_target.py +132 -0
  135. autogen/agentchat/group/targets/group_manager_target.py +151 -0
  136. autogen/agentchat/group/targets/transition_target.py +413 -0
  137. autogen/agentchat/group/targets/transition_utils.py +6 -0
  138. autogen/agentchat/groupchat.py +1694 -0
  139. autogen/agentchat/realtime/__init__.py +3 -0
  140. autogen/agentchat/realtime/experimental/__init__.py +20 -0
  141. autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
  142. autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
  143. autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
  144. autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
  145. autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
  146. autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
  147. autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
  148. autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
  149. autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
  150. autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
  151. autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
  152. autogen/agentchat/realtime/experimental/clients/realtime_client.py +190 -0
  153. autogen/agentchat/realtime/experimental/function_observer.py +85 -0
  154. autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
  155. autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
  156. autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
  157. autogen/agentchat/realtime/experimental/realtime_swarm.py +475 -0
  158. autogen/agentchat/realtime/experimental/websockets.py +21 -0
  159. autogen/agentchat/realtime_agent/__init__.py +21 -0
  160. autogen/agentchat/user_proxy_agent.py +111 -0
  161. autogen/agentchat/utils.py +206 -0
  162. autogen/agents/__init__.py +3 -0
  163. autogen/agents/contrib/__init__.py +10 -0
  164. autogen/agents/contrib/time/__init__.py +8 -0
  165. autogen/agents/contrib/time/time_reply_agent.py +73 -0
  166. autogen/agents/contrib/time/time_tool_agent.py +51 -0
  167. autogen/agents/experimental/__init__.py +27 -0
  168. autogen/agents/experimental/deep_research/__init__.py +7 -0
  169. autogen/agents/experimental/deep_research/deep_research.py +52 -0
  170. autogen/agents/experimental/discord/__init__.py +7 -0
  171. autogen/agents/experimental/discord/discord.py +66 -0
  172. autogen/agents/experimental/document_agent/__init__.py +19 -0
  173. autogen/agents/experimental/document_agent/chroma_query_engine.py +316 -0
  174. autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +118 -0
  175. autogen/agents/experimental/document_agent/document_agent.py +461 -0
  176. autogen/agents/experimental/document_agent/document_conditions.py +50 -0
  177. autogen/agents/experimental/document_agent/document_utils.py +380 -0
  178. autogen/agents/experimental/document_agent/inmemory_query_engine.py +220 -0
  179. autogen/agents/experimental/document_agent/parser_utils.py +130 -0
  180. autogen/agents/experimental/document_agent/url_utils.py +426 -0
  181. autogen/agents/experimental/reasoning/__init__.py +7 -0
  182. autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
  183. autogen/agents/experimental/slack/__init__.py +7 -0
  184. autogen/agents/experimental/slack/slack.py +73 -0
  185. autogen/agents/experimental/telegram/__init__.py +7 -0
  186. autogen/agents/experimental/telegram/telegram.py +77 -0
  187. autogen/agents/experimental/websurfer/__init__.py +7 -0
  188. autogen/agents/experimental/websurfer/websurfer.py +62 -0
  189. autogen/agents/experimental/wikipedia/__init__.py +7 -0
  190. autogen/agents/experimental/wikipedia/wikipedia.py +90 -0
  191. autogen/browser_utils.py +309 -0
  192. autogen/cache/__init__.py +10 -0
  193. autogen/cache/abstract_cache_base.py +75 -0
  194. autogen/cache/cache.py +203 -0
  195. autogen/cache/cache_factory.py +88 -0
  196. autogen/cache/cosmos_db_cache.py +144 -0
  197. autogen/cache/disk_cache.py +102 -0
  198. autogen/cache/in_memory_cache.py +58 -0
  199. autogen/cache/redis_cache.py +123 -0
  200. autogen/code_utils.py +596 -0
  201. autogen/coding/__init__.py +22 -0
  202. autogen/coding/base.py +119 -0
  203. autogen/coding/docker_commandline_code_executor.py +268 -0
  204. autogen/coding/factory.py +47 -0
  205. autogen/coding/func_with_reqs.py +202 -0
  206. autogen/coding/jupyter/__init__.py +23 -0
  207. autogen/coding/jupyter/base.py +36 -0
  208. autogen/coding/jupyter/docker_jupyter_server.py +167 -0
  209. autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
  210. autogen/coding/jupyter/import_utils.py +82 -0
  211. autogen/coding/jupyter/jupyter_client.py +231 -0
  212. autogen/coding/jupyter/jupyter_code_executor.py +160 -0
  213. autogen/coding/jupyter/local_jupyter_server.py +172 -0
  214. autogen/coding/local_commandline_code_executor.py +405 -0
  215. autogen/coding/markdown_code_extractor.py +45 -0
  216. autogen/coding/utils.py +56 -0
  217. autogen/doc_utils.py +34 -0
  218. autogen/events/__init__.py +7 -0
  219. autogen/events/agent_events.py +1010 -0
  220. autogen/events/base_event.py +99 -0
  221. autogen/events/client_events.py +167 -0
  222. autogen/events/helpers.py +36 -0
  223. autogen/events/print_event.py +46 -0
  224. autogen/exception_utils.py +73 -0
  225. autogen/extensions/__init__.py +5 -0
  226. autogen/fast_depends/__init__.py +16 -0
  227. autogen/fast_depends/_compat.py +80 -0
  228. autogen/fast_depends/core/__init__.py +14 -0
  229. autogen/fast_depends/core/build.py +225 -0
  230. autogen/fast_depends/core/model.py +576 -0
  231. autogen/fast_depends/dependencies/__init__.py +15 -0
  232. autogen/fast_depends/dependencies/model.py +29 -0
  233. autogen/fast_depends/dependencies/provider.py +39 -0
  234. autogen/fast_depends/library/__init__.py +10 -0
  235. autogen/fast_depends/library/model.py +46 -0
  236. autogen/fast_depends/py.typed +6 -0
  237. autogen/fast_depends/schema.py +66 -0
  238. autogen/fast_depends/use.py +280 -0
  239. autogen/fast_depends/utils.py +187 -0
  240. autogen/formatting_utils.py +83 -0
  241. autogen/function_utils.py +13 -0
  242. autogen/graph_utils.py +178 -0
  243. autogen/import_utils.py +526 -0
  244. autogen/interop/__init__.py +22 -0
  245. autogen/interop/crewai/__init__.py +7 -0
  246. autogen/interop/crewai/crewai.py +88 -0
  247. autogen/interop/interoperability.py +71 -0
  248. autogen/interop/interoperable.py +46 -0
  249. autogen/interop/langchain/__init__.py +8 -0
  250. autogen/interop/langchain/langchain_chat_model_factory.py +155 -0
  251. autogen/interop/langchain/langchain_tool.py +82 -0
  252. autogen/interop/litellm/__init__.py +7 -0
  253. autogen/interop/litellm/litellm_config_factory.py +113 -0
  254. autogen/interop/pydantic_ai/__init__.py +7 -0
  255. autogen/interop/pydantic_ai/pydantic_ai.py +168 -0
  256. autogen/interop/registry.py +69 -0
  257. autogen/io/__init__.py +15 -0
  258. autogen/io/base.py +151 -0
  259. autogen/io/console.py +56 -0
  260. autogen/io/processors/__init__.py +12 -0
  261. autogen/io/processors/base.py +21 -0
  262. autogen/io/processors/console_event_processor.py +56 -0
  263. autogen/io/run_response.py +293 -0
  264. autogen/io/thread_io_stream.py +63 -0
  265. autogen/io/websockets.py +213 -0
  266. autogen/json_utils.py +43 -0
  267. autogen/llm_config.py +379 -0
  268. autogen/logger/__init__.py +11 -0
  269. autogen/logger/base_logger.py +128 -0
  270. autogen/logger/file_logger.py +261 -0
  271. autogen/logger/logger_factory.py +42 -0
  272. autogen/logger/logger_utils.py +57 -0
  273. autogen/logger/sqlite_logger.py +523 -0
  274. autogen/math_utils.py +339 -0
  275. autogen/mcp/__init__.py +7 -0
  276. autogen/mcp/mcp_client.py +208 -0
  277. autogen/messages/__init__.py +7 -0
  278. autogen/messages/agent_messages.py +948 -0
  279. autogen/messages/base_message.py +107 -0
  280. autogen/messages/client_messages.py +171 -0
  281. autogen/messages/print_message.py +49 -0
  282. autogen/oai/__init__.py +53 -0
  283. autogen/oai/anthropic.py +714 -0
  284. autogen/oai/bedrock.py +628 -0
  285. autogen/oai/cerebras.py +299 -0
  286. autogen/oai/client.py +1435 -0
  287. autogen/oai/client_utils.py +169 -0
  288. autogen/oai/cohere.py +479 -0
  289. autogen/oai/gemini.py +990 -0
  290. autogen/oai/gemini_types.py +129 -0
  291. autogen/oai/groq.py +305 -0
  292. autogen/oai/mistral.py +303 -0
  293. autogen/oai/oai_models/__init__.py +11 -0
  294. autogen/oai/oai_models/_models.py +16 -0
  295. autogen/oai/oai_models/chat_completion.py +87 -0
  296. autogen/oai/oai_models/chat_completion_audio.py +32 -0
  297. autogen/oai/oai_models/chat_completion_message.py +86 -0
  298. autogen/oai/oai_models/chat_completion_message_tool_call.py +37 -0
  299. autogen/oai/oai_models/chat_completion_token_logprob.py +63 -0
  300. autogen/oai/oai_models/completion_usage.py +60 -0
  301. autogen/oai/ollama.py +643 -0
  302. autogen/oai/openai_utils.py +881 -0
  303. autogen/oai/together.py +370 -0
  304. autogen/retrieve_utils.py +491 -0
  305. autogen/runtime_logging.py +160 -0
  306. autogen/token_count_utils.py +267 -0
  307. autogen/tools/__init__.py +20 -0
  308. autogen/tools/contrib/__init__.py +9 -0
  309. autogen/tools/contrib/time/__init__.py +7 -0
  310. autogen/tools/contrib/time/time.py +41 -0
  311. autogen/tools/dependency_injection.py +254 -0
  312. autogen/tools/experimental/__init__.py +43 -0
  313. autogen/tools/experimental/browser_use/__init__.py +7 -0
  314. autogen/tools/experimental/browser_use/browser_use.py +161 -0
  315. autogen/tools/experimental/crawl4ai/__init__.py +7 -0
  316. autogen/tools/experimental/crawl4ai/crawl4ai.py +153 -0
  317. autogen/tools/experimental/deep_research/__init__.py +7 -0
  318. autogen/tools/experimental/deep_research/deep_research.py +328 -0
  319. autogen/tools/experimental/duckduckgo/__init__.py +7 -0
  320. autogen/tools/experimental/duckduckgo/duckduckgo_search.py +109 -0
  321. autogen/tools/experimental/google/__init__.py +14 -0
  322. autogen/tools/experimental/google/authentication/__init__.py +11 -0
  323. autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
  324. autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
  325. autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
  326. autogen/tools/experimental/google/drive/__init__.py +9 -0
  327. autogen/tools/experimental/google/drive/drive_functions.py +124 -0
  328. autogen/tools/experimental/google/drive/toolkit.py +88 -0
  329. autogen/tools/experimental/google/model.py +17 -0
  330. autogen/tools/experimental/google/toolkit_protocol.py +19 -0
  331. autogen/tools/experimental/google_search/__init__.py +8 -0
  332. autogen/tools/experimental/google_search/google_search.py +93 -0
  333. autogen/tools/experimental/google_search/youtube_search.py +181 -0
  334. autogen/tools/experimental/messageplatform/__init__.py +17 -0
  335. autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
  336. autogen/tools/experimental/messageplatform/discord/discord.py +288 -0
  337. autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
  338. autogen/tools/experimental/messageplatform/slack/slack.py +391 -0
  339. autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
  340. autogen/tools/experimental/messageplatform/telegram/telegram.py +275 -0
  341. autogen/tools/experimental/perplexity/__init__.py +7 -0
  342. autogen/tools/experimental/perplexity/perplexity_search.py +260 -0
  343. autogen/tools/experimental/tavily/__init__.py +7 -0
  344. autogen/tools/experimental/tavily/tavily_search.py +183 -0
  345. autogen/tools/experimental/web_search_preview/__init__.py +7 -0
  346. autogen/tools/experimental/web_search_preview/web_search_preview.py +114 -0
  347. autogen/tools/experimental/wikipedia/__init__.py +7 -0
  348. autogen/tools/experimental/wikipedia/wikipedia.py +287 -0
  349. autogen/tools/function_utils.py +411 -0
  350. autogen/tools/tool.py +187 -0
  351. autogen/tools/toolkit.py +86 -0
  352. autogen/types.py +29 -0
  353. autogen/version.py +7 -0
  354. ag2-0.9.1a1.dist-info/RECORD +0 -6
  355. ag2-0.9.1a1.dist-info/top_level.txt +0 -1
  356. {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/LICENSE +0 -0
  357. {ag2-0.9.1a1.dist-info → ag2-0.9.1.post0.dist-info/licenses}/NOTICE.md +0 -0
@@ -0,0 +1,591 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import copy
6
+ from functools import partial
7
+ from types import MethodType
8
+ from typing import TYPE_CHECKING, Any, Callable, Optional, Union
9
+
10
+ from ..agent import Agent
11
+ from ..groupchat import GroupChat, GroupChatManager
12
+ from .context_variables import ContextVariables
13
+ from .group_tool_executor import GroupToolExecutor
14
+ from .targets.group_manager_target import GroupManagerTarget
15
+ from .targets.transition_target import (
16
+ AgentNameTarget,
17
+ AgentTarget,
18
+ TransitionTarget,
19
+ )
20
+
21
+ if TYPE_CHECKING:
22
+ from ..conversable_agent import ConversableAgent
23
+
24
+ # Utility functions for group chat preparation and management
25
+ # These are extracted from multi_agent_chat.py to avoid circular imports
26
+
27
+
28
+ def update_conditional_functions(agent: "ConversableAgent", messages: list[dict[str, Any]]) -> None:
29
+ """Updates the agent's functions based on the OnCondition's available condition.
30
+
31
+ All functions are removed and then added back if they are available
32
+ """
33
+ for on_condition in agent.handoffs.llm_conditions:
34
+ is_available = on_condition.available.is_available(agent, messages) if on_condition.available else True
35
+
36
+ # Remove it from their tools
37
+ for tool in agent.tools:
38
+ if tool.name == on_condition.llm_function_name:
39
+ agent.remove_tool_for_llm(tool)
40
+ break
41
+
42
+ # then add the function if it is available, so that the function signature is updated
43
+ if is_available:
44
+ agent._add_single_function(
45
+ _create_on_condition_handoff_function(on_condition.target),
46
+ on_condition.llm_function_name,
47
+ on_condition.condition.get_prompt(agent, messages),
48
+ )
49
+
50
+
51
+ def establish_group_agent(agent: "ConversableAgent") -> None:
52
+ """Establish the group agent with the group-related attributes and hooks. Not for the tool executor.
53
+
54
+ Args:
55
+ agent ("ConversableAgent"): The agent to establish as a group agent.
56
+ """
57
+
58
+ def _group_agent_str(self: "ConversableAgent") -> str:
59
+ """Customise the __str__ method to show the agent name for transition messages."""
60
+ return f"Group agent --> {self.name}"
61
+
62
+ # Register the hook to update agent state (except tool executor)
63
+ agent.register_hook("update_agent_state", update_conditional_functions)
64
+
65
+ # Register a reply function to run Python function-based OnContextConditions before any other reply function
66
+ agent.register_reply(trigger=([Agent, None]), reply_func=_run_oncontextconditions, position=0)
67
+
68
+ agent._get_display_name = MethodType(_group_agent_str, agent) # type: ignore[method-assign]
69
+
70
+ # Mark this agent as established as a group agent
71
+ agent._group_is_established = True # type: ignore[attr-defined]
72
+
73
+
74
+ def link_agents_to_group_manager(agents: list[Agent], group_chat_manager: Agent) -> None:
75
+ """Link all agents to the GroupChatManager so they can access the underlying GroupChat and other agents.
76
+
77
+ This is primarily used so that agents can get to the tool executor to help set the next agent.
78
+
79
+ Does not link the Tool Executor agent.
80
+ """
81
+ for agent in agents:
82
+ agent._group_manager = group_chat_manager # type: ignore[attr-defined]
83
+
84
+
85
+ def _run_oncontextconditions(
86
+ agent: "ConversableAgent",
87
+ messages: Optional[list[dict[str, Any]]] = None,
88
+ sender: Optional[Agent] = None,
89
+ config: Optional[Any] = None,
90
+ ) -> tuple[bool, Optional[Union[str, dict[str, Any]]]]:
91
+ """Run OnContextConditions for an agent before any other reply function."""
92
+ for on_condition in agent.handoffs.context_conditions: # type: ignore[attr-defined]
93
+ is_available = (
94
+ on_condition.available.is_available(agent, messages if messages else []) if on_condition.available else True
95
+ )
96
+
97
+ if is_available and on_condition.condition.evaluate(agent.context_variables):
98
+ # Condition has been met, we'll set the Tool Executor's next target
99
+ # attribute and that will be picked up on the next iteration when
100
+ # _determine_next_agent is called
101
+ for agent in agent._group_manager.groupchat.agents: # type: ignore[attr-defined]
102
+ if isinstance(agent, GroupToolExecutor):
103
+ agent.set_next_target(on_condition.target)
104
+ break
105
+
106
+ transfer_name = on_condition.target.display_name()
107
+
108
+ return True, "[Handing off to " + transfer_name + "]"
109
+
110
+ return False, None
111
+
112
+
113
+ def _create_on_condition_handoff_function(target: TransitionTarget) -> Callable[[], TransitionTarget]:
114
+ """Creates a function that will be used by the tool call reply function when the condition is met.
115
+
116
+ Args:
117
+ target (TransitionTarget): The target to transfer to.
118
+
119
+ Returns:
120
+ Callable: The transfer function.
121
+ """
122
+
123
+ def transfer_to_target() -> TransitionTarget:
124
+ return target
125
+
126
+ return transfer_to_target
127
+
128
+
129
+ def create_on_condition_handoff_functions(agent: "ConversableAgent") -> None:
130
+ """Creates the functions for the OnConditions so that the current tool handling works.
131
+
132
+ Args:
133
+ agent ("ConversableAgent"): The agent to create the functions for.
134
+ """
135
+ # Populate the function names for the handoffs
136
+ agent.handoffs.set_llm_function_names()
137
+
138
+ # Create a function for each OnCondition
139
+ for on_condition in agent.handoffs.llm_conditions:
140
+ # Create a function that will be called when the condition is met
141
+ agent._add_single_function(
142
+ _create_on_condition_handoff_function(on_condition.target),
143
+ on_condition.llm_function_name,
144
+ on_condition.condition.get_prompt(agent, []),
145
+ )
146
+
147
+
148
+ def ensure_handoff_agents_in_group(agents: list["ConversableAgent"]) -> None:
149
+ """Ensure the agents in handoffs are in the group chat."""
150
+ agent_names = [agent.name for agent in agents]
151
+ for agent in agents:
152
+ for llm_conditions in agent.handoffs.llm_conditions:
153
+ if (
154
+ isinstance(llm_conditions.target, (AgentTarget, AgentNameTarget))
155
+ and llm_conditions.target.agent_name not in agent_names
156
+ ):
157
+ raise ValueError("Agent in OnCondition Hand-offs must be in the agents list")
158
+ for context_conditions in agent.handoffs.context_conditions:
159
+ if (
160
+ isinstance(context_conditions.target, (AgentTarget, AgentNameTarget))
161
+ and context_conditions.target.agent_name not in agent_names
162
+ ):
163
+ raise ValueError("Agent in OnContextCondition Hand-offs must be in the agents list")
164
+ if (
165
+ agent.handoffs.after_work is not None
166
+ and isinstance(agent.handoffs.after_work, (AgentTarget, AgentNameTarget))
167
+ and agent.handoffs.after_work.agent_name not in agent_names
168
+ ):
169
+ raise ValueError("Agent in after work target Hand-offs must be in the agents list")
170
+
171
+
172
+ def prepare_exclude_transit_messages(agents: list["ConversableAgent"]) -> None:
173
+ """Preparation for excluding transit messages by getting all tool names and registering a hook on agents to remove those messages."""
174
+ # get all transit functions names
175
+ to_be_removed: list[str] = []
176
+ for agent in agents:
177
+ for on_condition in agent.handoffs.llm_conditions:
178
+ if on_condition.llm_function_name:
179
+ to_be_removed.append(on_condition.llm_function_name)
180
+ else:
181
+ raise ValueError("OnCondition must have a function name")
182
+
183
+ remove_function = make_remove_function(to_be_removed)
184
+
185
+ # register hook to remove transit messages for group agents
186
+ for agent in agents:
187
+ agent.register_hook("process_all_messages_before_reply", remove_function)
188
+
189
+
190
+ def prepare_group_agents(
191
+ agents: list["ConversableAgent"],
192
+ context_variables: ContextVariables,
193
+ exclude_transit_message: bool = True,
194
+ ) -> tuple[GroupToolExecutor, list["ConversableAgent"]]:
195
+ """Validates agents, create the tool executor, wrap necessary targets in agents.
196
+
197
+ Args:
198
+ agents (list["ConversableAgent"]): List of all agents in the conversation.
199
+ context_variables (ContextVariables): Context variables to assign to all agents.
200
+ exclude_transit_message (bool): Whether to exclude transit messages from the agents.
201
+
202
+ Returns:
203
+ "ConversableAgent": The tool executor agent.
204
+ list["ConversableAgent"]: List of wrapped agents.
205
+ """
206
+ # Initialise all agents as group agents
207
+ for agent in agents:
208
+ if not hasattr(agent, "_group_is_established"):
209
+ establish_group_agent(agent)
210
+
211
+ # Ensure all agents in hand-off after-works are in the passed in agents list
212
+ ensure_handoff_agents_in_group(agents)
213
+
214
+ # Create Tool Executor for the group
215
+ tool_execution = GroupToolExecutor()
216
+
217
+ # Wrap handoff targets in agents that need to be wrapped
218
+ wrapped_chat_agents: list["ConversableAgent"] = []
219
+ for agent in agents:
220
+ wrap_agent_handoff_targets(agent, wrapped_chat_agents)
221
+
222
+ # Create the functions for the OnConditions so that the current tool handling works
223
+ for agent in agents:
224
+ create_on_condition_handoff_functions(agent)
225
+
226
+ # Register all the agents' functions with the tool executor and
227
+ # use dependency injection for the context variables parameter
228
+ # Update tool execution agent with all the functions from all the agents
229
+ tool_execution.register_agents_functions(agents + wrapped_chat_agents, context_variables)
230
+
231
+ if exclude_transit_message:
232
+ prepare_exclude_transit_messages(agents)
233
+
234
+ return tool_execution, wrapped_chat_agents
235
+
236
+
237
+ def wrap_agent_handoff_targets(agent: "ConversableAgent", wrapped_agent_list: list["ConversableAgent"]) -> None:
238
+ """Wrap handoff targets in agents that need to be wrapped to be part of the group chat.
239
+
240
+ Example is NestedChatTarget.
241
+
242
+ Args:
243
+ agent ("ConversableAgent"): The agent to wrap the handoff targets for.
244
+ wrapped_agent_list (list["ConversableAgent"]): List of wrapped chat agents that will be appended to.
245
+ """
246
+ # Wrap OnCondition targets
247
+ for i, handoff_oncondition_requiring_wrapping in enumerate(agent.handoffs.get_llm_conditions_requiring_wrapping()):
248
+ # Create wrapper agent
249
+ wrapper_agent = handoff_oncondition_requiring_wrapping.target.create_wrapper_agent(parent_agent=agent, index=i)
250
+ wrapped_agent_list.append(wrapper_agent)
251
+
252
+ # Change this handoff target to point to the newly created agent
253
+ handoff_oncondition_requiring_wrapping.target = AgentTarget(wrapper_agent)
254
+
255
+ for i, handoff_oncontextcondition_requiring_wrapping in enumerate(
256
+ agent.handoffs.get_context_conditions_requiring_wrapping()
257
+ ):
258
+ # Create wrapper agent
259
+ wrapper_agent = handoff_oncontextcondition_requiring_wrapping.target.create_wrapper_agent(
260
+ parent_agent=agent, index=i
261
+ )
262
+ wrapped_agent_list.append(wrapper_agent)
263
+
264
+ # Change this handoff target to point to the newly created agent
265
+ handoff_oncontextcondition_requiring_wrapping.target = AgentTarget(wrapper_agent)
266
+
267
+
268
+ def process_initial_messages(
269
+ messages: Union[list[dict[str, Any]], str],
270
+ user_agent: Optional["ConversableAgent"],
271
+ agents: list["ConversableAgent"],
272
+ wrapped_agents: list["ConversableAgent"],
273
+ ) -> tuple[list[dict[str, Any]], Optional["ConversableAgent"], list[str], list[Agent]]:
274
+ """Process initial messages, validating agent names against messages, and determining the last agent to speak.
275
+
276
+ Args:
277
+ messages: Initial messages to process.
278
+ user_agent: Optional user proxy agent passed in to a_/initiate_group_chat.
279
+ agents: Agents in the group.
280
+ wrapped_agents: List of wrapped agents.
281
+
282
+ Returns:
283
+ list[dict[str, Any]]: Processed message(s).
284
+ Agent: Last agent to speak.
285
+ list[str]: List of agent names.
286
+ list[Agent]: List of temporary user proxy agents to add to GroupChat.
287
+ """
288
+ from ..conversable_agent import ConversableAgent # NEED SOLUTION
289
+
290
+ if isinstance(messages, str):
291
+ messages = [{"role": "user", "content": messages}]
292
+
293
+ group_agent_names = [agent.name for agent in agents + wrapped_agents]
294
+
295
+ # If there's only one message and there's no identified group agent
296
+ # Start with a user proxy agent, creating one if they haven't passed one in
297
+ last_agent: Optional[ConversableAgent]
298
+ temp_user_proxy: Optional[ConversableAgent] = None
299
+ temp_user_list: list[Agent] = []
300
+ if len(messages) == 1 and "name" not in messages[0] and not user_agent:
301
+ temp_user_proxy = ConversableAgent(name="_User", code_execution_config=False, human_input_mode="ALWAYS")
302
+ last_agent = temp_user_proxy
303
+ temp_user_list.append(temp_user_proxy)
304
+ else:
305
+ last_message = messages[0]
306
+ if "name" in last_message:
307
+ if last_message["name"] in group_agent_names:
308
+ last_agent = next(agent for agent in agents + wrapped_agents if agent.name == last_message["name"]) # type: ignore[assignment]
309
+ elif user_agent and last_message["name"] == user_agent.name:
310
+ last_agent = user_agent
311
+ else:
312
+ raise ValueError(f"Invalid group agent name in last message: {last_message['name']}")
313
+ else:
314
+ last_agent = user_agent if user_agent else temp_user_proxy
315
+
316
+ return messages, last_agent, group_agent_names, temp_user_list
317
+
318
+
319
+ def setup_context_variables(
320
+ tool_execution: "ConversableAgent",
321
+ agents: list["ConversableAgent"],
322
+ manager: GroupChatManager,
323
+ context_variables: ContextVariables,
324
+ ) -> None:
325
+ """Assign a common context_variables reference to all agents in the group, including the tool executor and group chat manager.
326
+
327
+ Args:
328
+ tool_execution: The tool execution agent.
329
+ agents: List of all agents in the conversation.
330
+ manager: GroupChatManager instance.
331
+ context_variables: Context variables to assign to all agents.
332
+ """
333
+ for agent in agents + [tool_execution] + [manager]:
334
+ agent.context_variables = context_variables
335
+
336
+
337
+ def cleanup_temp_user_messages(chat_result: Any) -> None:
338
+ """Remove temporary user proxy agent name from messages before returning.
339
+
340
+ Args:
341
+ chat_result: ChatResult instance.
342
+ """
343
+ for message in chat_result.chat_history:
344
+ if "name" in message and message["name"] == "_User":
345
+ del message["name"]
346
+
347
+
348
+ def get_last_agent_speaker(
349
+ groupchat: GroupChat, group_agent_names: list[str], tool_executor: GroupToolExecutor
350
+ ) -> Agent:
351
+ """Get the last group agent from the group chat messages. Not including the tool executor."""
352
+ last_group_speaker = None
353
+ for message in reversed(groupchat.messages):
354
+ if "name" in message and message["name"] in group_agent_names and message["name"] != tool_executor.name:
355
+ agent = groupchat.agent_by_name(name=message["name"])
356
+ if agent:
357
+ last_group_speaker = agent
358
+ break
359
+ if last_group_speaker is None:
360
+ raise ValueError("No group agent found in the message history")
361
+
362
+ return last_group_speaker
363
+
364
+
365
+ def determine_next_agent(
366
+ last_speaker: "ConversableAgent",
367
+ groupchat: GroupChat,
368
+ initial_agent: "ConversableAgent",
369
+ use_initial_agent: bool,
370
+ tool_executor: GroupToolExecutor,
371
+ group_agent_names: list[str],
372
+ user_agent: Optional["ConversableAgent"],
373
+ group_after_work: TransitionTarget,
374
+ ) -> Optional[Union[Agent, str]]:
375
+ """Determine the next agent in the conversation.
376
+
377
+ Args:
378
+ last_speaker ("ConversableAgent"): The last agent to speak.
379
+ groupchat (GroupChat): GroupChat instance.
380
+ initial_agent ("ConversableAgent"): The initial agent in the conversation.
381
+ use_initial_agent (bool): Whether to use the initial agent straight away.
382
+ tool_executor ("ConversableAgent"): The tool execution agent.
383
+ group_agent_names (list[str]): List of agent names.
384
+ user_agent (UserProxyAgent): Optional user proxy agent.
385
+ group_after_work (TransitionTarget): Group-level Transition option when an agent doesn't select the next agent.
386
+
387
+ Returns:
388
+ Optional[Union[Agent, str]]: The next agent or speaker selection method.
389
+ """
390
+
391
+ # Logic for determining the next target (anything based on Transition Target: an agent, wrapped agent, TerminateTarget, StayTarget, RevertToUserTarget, GroupManagerTarget, etc.
392
+ # 1. If it's the first response -> initial agent
393
+ # 2. If the last message is a tool call -> tool execution agent
394
+ # 3. If the Tool Executor has determined a next target (e.g. ReplyResult specified target) -> transition to tool reply target
395
+ # 4. If the user last spoke -> return to the previous agent
396
+ # NOW "AFTER WORK":
397
+ # 5. Get the After Work condition (if the agent doesn't have one, get the group-level one)
398
+ # 6. Resolve and return the After Work condition -> agent / wrapped agent / TerminateTarget / StayTarget / RevertToUserTarget / GroupManagerTarget / etc.
399
+
400
+ # 1. If it's the first response, return the initial agent
401
+ if use_initial_agent:
402
+ return initial_agent
403
+
404
+ # 2. If the last message is a tool call, return the tool execution agent
405
+ if "tool_calls" in groupchat.messages[-1]:
406
+ return tool_executor
407
+
408
+ # 3. If the Tool Executor has determined a next target, return that
409
+ if tool_executor.has_next_target():
410
+ next_agent = tool_executor.get_next_target()
411
+ tool_executor.clear_next_target()
412
+
413
+ if next_agent.can_resolve_for_speaker_selection():
414
+ return next_agent.resolve(groupchat, last_speaker, user_agent).get_speaker_selection_result(groupchat)
415
+ else:
416
+ raise ValueError(
417
+ "Tool Executor next target must be a valid TransitionTarget that can resolve for speaker selection."
418
+ )
419
+
420
+ # get the last group agent
421
+ last_agent_speaker = get_last_agent_speaker(groupchat, group_agent_names, tool_executor)
422
+
423
+ # If we are returning from a tool execution, return to the last agent that spoke
424
+ if groupchat.messages[-1]["role"] == "tool":
425
+ return last_agent_speaker
426
+
427
+ # If the user last spoke, return to the agent prior to them (if they don't have an after work, otherwise it's treated like any other agent)
428
+ if user_agent and last_speaker == user_agent:
429
+ if user_agent.handoffs.after_work is None:
430
+ return last_agent_speaker
431
+ else:
432
+ last_agent_speaker = user_agent
433
+
434
+ # AFTER WORK:
435
+
436
+ # Get the appropriate After Work condition (from the agent if they have one, otherwise the group level one)
437
+ after_work_condition = (
438
+ last_agent_speaker.handoffs.after_work # type: ignore[attr-defined]
439
+ if last_agent_speaker.handoffs.after_work is not None # type: ignore[attr-defined]
440
+ else group_after_work
441
+ )
442
+
443
+ # Resolve the next agent, termination, or speaker selection method
444
+ resolved_speaker_selection_result = after_work_condition.resolve(
445
+ groupchat,
446
+ last_agent_speaker, # type: ignore[arg-type]
447
+ user_agent,
448
+ ).get_speaker_selection_result(groupchat)
449
+
450
+ return resolved_speaker_selection_result
451
+
452
+
453
+ def create_group_transition(
454
+ initial_agent: "ConversableAgent",
455
+ tool_execution: GroupToolExecutor,
456
+ group_agent_names: list[str],
457
+ user_agent: Optional["ConversableAgent"],
458
+ group_after_work: TransitionTarget,
459
+ ) -> Callable[["ConversableAgent", GroupChat], Optional[Union[Agent, str]]]:
460
+ """Creates a transition function for group chat with enclosed state for the use_initial_agent.
461
+
462
+ Args:
463
+ initial_agent ("ConversableAgent"): The first agent to speak
464
+ tool_execution (GroupToolExecutor): The tool execution agent
465
+ group_agent_names (list[str]): List of all agent names
466
+ user_agent (UserProxyAgent): Optional user proxy agent
467
+ group_after_work (TransitionTarget): Group-level after work
468
+
469
+ Returns:
470
+ Callable[["ConversableAgent", GroupChat], Optional[Union[Agent, str]]]: The transition function
471
+ """
472
+ # Create enclosed state, this will be set once per creation so will only be True on the first execution
473
+ # of group_transition
474
+ state = {"use_initial_agent": True}
475
+
476
+ def group_transition(last_speaker: "ConversableAgent", groupchat: GroupChat) -> Optional[Union[Agent, str]]:
477
+ result = determine_next_agent(
478
+ last_speaker=last_speaker,
479
+ groupchat=groupchat,
480
+ initial_agent=initial_agent,
481
+ use_initial_agent=state["use_initial_agent"],
482
+ tool_executor=tool_execution,
483
+ group_agent_names=group_agent_names,
484
+ user_agent=user_agent,
485
+ group_after_work=group_after_work,
486
+ )
487
+ state["use_initial_agent"] = False
488
+ return result
489
+
490
+ return group_transition
491
+
492
+
493
+ def create_group_manager(
494
+ groupchat: GroupChat,
495
+ group_manager_args: Optional[dict[str, Any]],
496
+ agents: list["ConversableAgent"],
497
+ group_after_work: TransitionTarget,
498
+ ) -> GroupChatManager:
499
+ """Create a GroupChatManager for the group chat utilising any arguments passed in and ensure an LLM Config exists if needed
500
+
501
+ Args:
502
+ groupchat (GroupChat): The groupchat.
503
+ group_manager_args (dict[str, Any]): Group manager arguments to create the GroupChatManager.
504
+ agents (list["ConversableAgent"]): List of agents in the group to check handoffs and after work.
505
+ group_after_work (TransitionTarget): Group-level after work to check.
506
+
507
+ Returns:
508
+ GroupChatManager: GroupChatManager instance.
509
+ """
510
+ manager_args = (group_manager_args or {}).copy()
511
+ if "groupchat" in manager_args:
512
+ raise ValueError("'groupchat' cannot be specified in group_manager_args as it is set by initiate_group_chat")
513
+ manager = GroupChatManager(groupchat, **manager_args)
514
+
515
+ # Ensure that our manager has an LLM Config if we have any GroupManagerTarget targets used
516
+ if manager.llm_config is False:
517
+ has_group_manager_target = False
518
+
519
+ if isinstance(group_after_work, GroupManagerTarget):
520
+ # Check group after work
521
+ has_group_manager_target = True
522
+ else:
523
+ # Check agent hand-offs and after work
524
+ for agent in agents:
525
+ if (
526
+ len(agent.handoffs.get_context_conditions_by_target_type(GroupManagerTarget)) > 0
527
+ or len(agent.handoffs.get_llm_conditions_by_target_type(GroupManagerTarget)) > 0
528
+ or (
529
+ agent.handoffs.after_work is not None
530
+ and isinstance(agent.handoffs.after_work, GroupManagerTarget)
531
+ )
532
+ ):
533
+ has_group_manager_target = True
534
+ break
535
+
536
+ if has_group_manager_target:
537
+ raise ValueError(
538
+ "The group manager doesn't have an LLM Config and it is required for any targets or after works using a GroupManagerTarget. Use the 'llm_config' in the group_manager_args parameter to specify the LLM Config for the group manager."
539
+ )
540
+
541
+ return manager
542
+
543
+
544
+ def make_remove_function(tool_msgs_to_remove: list[str]) -> Callable[[list[dict[str, Any]]], list[dict[str, Any]]]:
545
+ """Create a function to remove messages with tool calls from the messages list.
546
+
547
+ The returned function can be registered as a hook to "process_all_messages_before_reply"" to remove messages with tool calls.
548
+ """
549
+
550
+ def remove_messages(messages: list[dict[str, Any]], tool_msgs_to_remove: list[str]) -> list[dict[str, Any]]:
551
+ copied = copy.deepcopy(messages)
552
+ new_messages = []
553
+ removed_tool_ids = []
554
+ for message in copied:
555
+ # remove tool calls
556
+ if message.get("tool_calls") is not None:
557
+ filtered_tool_calls = []
558
+ for tool_call in message["tool_calls"]:
559
+ if tool_call.get("function") is not None and tool_call["function"]["name"] in tool_msgs_to_remove:
560
+ # remove
561
+ removed_tool_ids.append(tool_call["id"])
562
+ else:
563
+ filtered_tool_calls.append(tool_call)
564
+ if len(filtered_tool_calls) > 0:
565
+ message["tool_calls"] = filtered_tool_calls
566
+ else:
567
+ del message["tool_calls"]
568
+ if (
569
+ message.get("content") is None
570
+ or message.get("content") == ""
571
+ or message.get("content") == "None"
572
+ ):
573
+ continue # if no tool call and no content, skip this message
574
+ # else: keep the message with tool_calls removed
575
+ # remove corresponding tool responses
576
+ elif message.get("tool_responses") is not None:
577
+ filtered_tool_responses = []
578
+ for tool_response in message["tool_responses"]:
579
+ if tool_response["tool_call_id"] not in removed_tool_ids:
580
+ filtered_tool_responses.append(tool_response)
581
+
582
+ if len(filtered_tool_responses) > 0:
583
+ message["tool_responses"] = filtered_tool_responses
584
+ else:
585
+ continue
586
+
587
+ new_messages.append(message)
588
+
589
+ return new_messages
590
+
591
+ return partial(remove_messages, tool_msgs_to_remove=tool_msgs_to_remove)