ag2 0.10.2__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.
Files changed (423) hide show
  1. ag2-0.10.2.dist-info/METADATA +819 -0
  2. ag2-0.10.2.dist-info/RECORD +423 -0
  3. ag2-0.10.2.dist-info/WHEEL +4 -0
  4. ag2-0.10.2.dist-info/licenses/LICENSE +201 -0
  5. ag2-0.10.2.dist-info/licenses/NOTICE.md +19 -0
  6. autogen/__init__.py +88 -0
  7. autogen/_website/__init__.py +3 -0
  8. autogen/_website/generate_api_references.py +426 -0
  9. autogen/_website/generate_mkdocs.py +1216 -0
  10. autogen/_website/notebook_processor.py +475 -0
  11. autogen/_website/process_notebooks.py +656 -0
  12. autogen/_website/utils.py +413 -0
  13. autogen/a2a/__init__.py +36 -0
  14. autogen/a2a/agent_executor.py +86 -0
  15. autogen/a2a/client.py +357 -0
  16. autogen/a2a/errors.py +18 -0
  17. autogen/a2a/httpx_client_factory.py +79 -0
  18. autogen/a2a/server.py +221 -0
  19. autogen/a2a/utils.py +207 -0
  20. autogen/agentchat/__init__.py +47 -0
  21. autogen/agentchat/agent.py +180 -0
  22. autogen/agentchat/assistant_agent.py +86 -0
  23. autogen/agentchat/chat.py +325 -0
  24. autogen/agentchat/contrib/__init__.py +5 -0
  25. autogen/agentchat/contrib/agent_eval/README.md +7 -0
  26. autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
  27. autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
  28. autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
  29. autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
  30. autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
  31. autogen/agentchat/contrib/agent_eval/task.py +42 -0
  32. autogen/agentchat/contrib/agent_optimizer.py +432 -0
  33. autogen/agentchat/contrib/capabilities/__init__.py +5 -0
  34. autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
  35. autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
  36. autogen/agentchat/contrib/capabilities/teachability.py +393 -0
  37. autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
  38. autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
  39. autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
  40. autogen/agentchat/contrib/capabilities/transforms.py +578 -0
  41. autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
  42. autogen/agentchat/contrib/capabilities/vision_capability.py +215 -0
  43. autogen/agentchat/contrib/captainagent/__init__.py +9 -0
  44. autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
  45. autogen/agentchat/contrib/captainagent/captainagent.py +514 -0
  46. autogen/agentchat/contrib/captainagent/tool_retriever.py +334 -0
  47. autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
  48. autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
  49. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
  50. autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
  51. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
  52. autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
  53. autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
  54. autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
  55. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
  56. autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
  57. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
  58. autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
  59. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
  60. autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
  61. autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
  62. autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
  63. autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
  64. autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
  65. autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
  66. autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
  67. autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
  68. autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
  69. autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
  70. autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
  71. autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
  72. autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
  73. autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
  74. autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
  75. autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
  76. autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
  77. autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
  78. autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
  79. autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
  80. autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
  81. autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
  82. autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
  83. autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
  84. autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
  85. autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
  86. autogen/agentchat/contrib/graph_rag/document.py +29 -0
  87. autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +167 -0
  88. autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
  89. autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
  90. autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
  91. autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +263 -0
  92. autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
  93. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
  94. autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
  95. autogen/agentchat/contrib/img_utils.py +397 -0
  96. autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
  97. autogen/agentchat/contrib/llava_agent.py +189 -0
  98. autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
  99. autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
  100. autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +325 -0
  101. autogen/agentchat/contrib/rag/__init__.py +10 -0
  102. autogen/agentchat/contrib/rag/chromadb_query_engine.py +268 -0
  103. autogen/agentchat/contrib/rag/llamaindex_query_engine.py +195 -0
  104. autogen/agentchat/contrib/rag/mongodb_query_engine.py +319 -0
  105. autogen/agentchat/contrib/rag/query_engine.py +76 -0
  106. autogen/agentchat/contrib/retrieve_assistant_agent.py +59 -0
  107. autogen/agentchat/contrib/retrieve_user_proxy_agent.py +704 -0
  108. autogen/agentchat/contrib/society_of_mind_agent.py +200 -0
  109. autogen/agentchat/contrib/swarm_agent.py +1404 -0
  110. autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
  111. autogen/agentchat/contrib/vectordb/__init__.py +5 -0
  112. autogen/agentchat/contrib/vectordb/base.py +224 -0
  113. autogen/agentchat/contrib/vectordb/chromadb.py +316 -0
  114. autogen/agentchat/contrib/vectordb/couchbase.py +405 -0
  115. autogen/agentchat/contrib/vectordb/mongodb.py +551 -0
  116. autogen/agentchat/contrib/vectordb/pgvectordb.py +927 -0
  117. autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
  118. autogen/agentchat/contrib/vectordb/utils.py +126 -0
  119. autogen/agentchat/contrib/web_surfer.py +304 -0
  120. autogen/agentchat/conversable_agent.py +4307 -0
  121. autogen/agentchat/group/__init__.py +67 -0
  122. autogen/agentchat/group/available_condition.py +91 -0
  123. autogen/agentchat/group/context_condition.py +77 -0
  124. autogen/agentchat/group/context_expression.py +238 -0
  125. autogen/agentchat/group/context_str.py +39 -0
  126. autogen/agentchat/group/context_variables.py +182 -0
  127. autogen/agentchat/group/events/transition_events.py +111 -0
  128. autogen/agentchat/group/group_tool_executor.py +324 -0
  129. autogen/agentchat/group/group_utils.py +659 -0
  130. autogen/agentchat/group/guardrails.py +179 -0
  131. autogen/agentchat/group/handoffs.py +303 -0
  132. autogen/agentchat/group/llm_condition.py +93 -0
  133. autogen/agentchat/group/multi_agent_chat.py +291 -0
  134. autogen/agentchat/group/on_condition.py +55 -0
  135. autogen/agentchat/group/on_context_condition.py +51 -0
  136. autogen/agentchat/group/patterns/__init__.py +18 -0
  137. autogen/agentchat/group/patterns/auto.py +160 -0
  138. autogen/agentchat/group/patterns/manual.py +177 -0
  139. autogen/agentchat/group/patterns/pattern.py +295 -0
  140. autogen/agentchat/group/patterns/random.py +106 -0
  141. autogen/agentchat/group/patterns/round_robin.py +117 -0
  142. autogen/agentchat/group/reply_result.py +24 -0
  143. autogen/agentchat/group/safeguards/__init__.py +21 -0
  144. autogen/agentchat/group/safeguards/api.py +241 -0
  145. autogen/agentchat/group/safeguards/enforcer.py +1158 -0
  146. autogen/agentchat/group/safeguards/events.py +140 -0
  147. autogen/agentchat/group/safeguards/validator.py +435 -0
  148. autogen/agentchat/group/speaker_selection_result.py +41 -0
  149. autogen/agentchat/group/targets/__init__.py +4 -0
  150. autogen/agentchat/group/targets/function_target.py +245 -0
  151. autogen/agentchat/group/targets/group_chat_target.py +133 -0
  152. autogen/agentchat/group/targets/group_manager_target.py +151 -0
  153. autogen/agentchat/group/targets/transition_target.py +424 -0
  154. autogen/agentchat/group/targets/transition_utils.py +6 -0
  155. autogen/agentchat/groupchat.py +1832 -0
  156. autogen/agentchat/realtime/__init__.py +3 -0
  157. autogen/agentchat/realtime/experimental/__init__.py +20 -0
  158. autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
  159. autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
  160. autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
  161. autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
  162. autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
  163. autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
  164. autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
  165. autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
  166. autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
  167. autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
  168. autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
  169. autogen/agentchat/realtime/experimental/clients/realtime_client.py +191 -0
  170. autogen/agentchat/realtime/experimental/function_observer.py +84 -0
  171. autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
  172. autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
  173. autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
  174. autogen/agentchat/realtime/experimental/realtime_swarm.py +533 -0
  175. autogen/agentchat/realtime/experimental/websockets.py +21 -0
  176. autogen/agentchat/realtime_agent/__init__.py +21 -0
  177. autogen/agentchat/user_proxy_agent.py +114 -0
  178. autogen/agentchat/utils.py +206 -0
  179. autogen/agents/__init__.py +3 -0
  180. autogen/agents/contrib/__init__.py +10 -0
  181. autogen/agents/contrib/time/__init__.py +8 -0
  182. autogen/agents/contrib/time/time_reply_agent.py +74 -0
  183. autogen/agents/contrib/time/time_tool_agent.py +52 -0
  184. autogen/agents/experimental/__init__.py +27 -0
  185. autogen/agents/experimental/deep_research/__init__.py +7 -0
  186. autogen/agents/experimental/deep_research/deep_research.py +52 -0
  187. autogen/agents/experimental/discord/__init__.py +7 -0
  188. autogen/agents/experimental/discord/discord.py +66 -0
  189. autogen/agents/experimental/document_agent/__init__.py +19 -0
  190. autogen/agents/experimental/document_agent/chroma_query_engine.py +301 -0
  191. autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +113 -0
  192. autogen/agents/experimental/document_agent/document_agent.py +643 -0
  193. autogen/agents/experimental/document_agent/document_conditions.py +50 -0
  194. autogen/agents/experimental/document_agent/document_utils.py +376 -0
  195. autogen/agents/experimental/document_agent/inmemory_query_engine.py +214 -0
  196. autogen/agents/experimental/document_agent/parser_utils.py +134 -0
  197. autogen/agents/experimental/document_agent/url_utils.py +417 -0
  198. autogen/agents/experimental/reasoning/__init__.py +7 -0
  199. autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
  200. autogen/agents/experimental/slack/__init__.py +7 -0
  201. autogen/agents/experimental/slack/slack.py +73 -0
  202. autogen/agents/experimental/telegram/__init__.py +7 -0
  203. autogen/agents/experimental/telegram/telegram.py +76 -0
  204. autogen/agents/experimental/websurfer/__init__.py +7 -0
  205. autogen/agents/experimental/websurfer/websurfer.py +70 -0
  206. autogen/agents/experimental/wikipedia/__init__.py +7 -0
  207. autogen/agents/experimental/wikipedia/wikipedia.py +88 -0
  208. autogen/browser_utils.py +309 -0
  209. autogen/cache/__init__.py +10 -0
  210. autogen/cache/abstract_cache_base.py +71 -0
  211. autogen/cache/cache.py +203 -0
  212. autogen/cache/cache_factory.py +88 -0
  213. autogen/cache/cosmos_db_cache.py +144 -0
  214. autogen/cache/disk_cache.py +97 -0
  215. autogen/cache/in_memory_cache.py +54 -0
  216. autogen/cache/redis_cache.py +119 -0
  217. autogen/code_utils.py +598 -0
  218. autogen/coding/__init__.py +30 -0
  219. autogen/coding/base.py +120 -0
  220. autogen/coding/docker_commandline_code_executor.py +283 -0
  221. autogen/coding/factory.py +56 -0
  222. autogen/coding/func_with_reqs.py +203 -0
  223. autogen/coding/jupyter/__init__.py +23 -0
  224. autogen/coding/jupyter/base.py +36 -0
  225. autogen/coding/jupyter/docker_jupyter_server.py +160 -0
  226. autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
  227. autogen/coding/jupyter/import_utils.py +82 -0
  228. autogen/coding/jupyter/jupyter_client.py +224 -0
  229. autogen/coding/jupyter/jupyter_code_executor.py +154 -0
  230. autogen/coding/jupyter/local_jupyter_server.py +164 -0
  231. autogen/coding/local_commandline_code_executor.py +341 -0
  232. autogen/coding/markdown_code_extractor.py +44 -0
  233. autogen/coding/utils.py +55 -0
  234. autogen/coding/yepcode_code_executor.py +197 -0
  235. autogen/doc_utils.py +35 -0
  236. autogen/environments/__init__.py +10 -0
  237. autogen/environments/docker_python_environment.py +365 -0
  238. autogen/environments/python_environment.py +125 -0
  239. autogen/environments/system_python_environment.py +85 -0
  240. autogen/environments/venv_python_environment.py +220 -0
  241. autogen/environments/working_directory.py +74 -0
  242. autogen/events/__init__.py +7 -0
  243. autogen/events/agent_events.py +1016 -0
  244. autogen/events/base_event.py +100 -0
  245. autogen/events/client_events.py +168 -0
  246. autogen/events/helpers.py +44 -0
  247. autogen/events/print_event.py +45 -0
  248. autogen/exception_utils.py +73 -0
  249. autogen/extensions/__init__.py +5 -0
  250. autogen/fast_depends/__init__.py +16 -0
  251. autogen/fast_depends/_compat.py +75 -0
  252. autogen/fast_depends/core/__init__.py +14 -0
  253. autogen/fast_depends/core/build.py +206 -0
  254. autogen/fast_depends/core/model.py +527 -0
  255. autogen/fast_depends/dependencies/__init__.py +15 -0
  256. autogen/fast_depends/dependencies/model.py +30 -0
  257. autogen/fast_depends/dependencies/provider.py +40 -0
  258. autogen/fast_depends/library/__init__.py +10 -0
  259. autogen/fast_depends/library/model.py +46 -0
  260. autogen/fast_depends/py.typed +6 -0
  261. autogen/fast_depends/schema.py +66 -0
  262. autogen/fast_depends/use.py +272 -0
  263. autogen/fast_depends/utils.py +177 -0
  264. autogen/formatting_utils.py +83 -0
  265. autogen/function_utils.py +13 -0
  266. autogen/graph_utils.py +173 -0
  267. autogen/import_utils.py +539 -0
  268. autogen/interop/__init__.py +22 -0
  269. autogen/interop/crewai/__init__.py +7 -0
  270. autogen/interop/crewai/crewai.py +88 -0
  271. autogen/interop/interoperability.py +71 -0
  272. autogen/interop/interoperable.py +46 -0
  273. autogen/interop/langchain/__init__.py +8 -0
  274. autogen/interop/langchain/langchain_chat_model_factory.py +156 -0
  275. autogen/interop/langchain/langchain_tool.py +78 -0
  276. autogen/interop/litellm/__init__.py +7 -0
  277. autogen/interop/litellm/litellm_config_factory.py +178 -0
  278. autogen/interop/pydantic_ai/__init__.py +7 -0
  279. autogen/interop/pydantic_ai/pydantic_ai.py +172 -0
  280. autogen/interop/registry.py +70 -0
  281. autogen/io/__init__.py +15 -0
  282. autogen/io/base.py +151 -0
  283. autogen/io/console.py +56 -0
  284. autogen/io/processors/__init__.py +12 -0
  285. autogen/io/processors/base.py +21 -0
  286. autogen/io/processors/console_event_processor.py +61 -0
  287. autogen/io/run_response.py +294 -0
  288. autogen/io/thread_io_stream.py +63 -0
  289. autogen/io/websockets.py +214 -0
  290. autogen/json_utils.py +42 -0
  291. autogen/llm_clients/MIGRATION_TO_V2.md +782 -0
  292. autogen/llm_clients/__init__.py +77 -0
  293. autogen/llm_clients/client_v2.py +122 -0
  294. autogen/llm_clients/models/__init__.py +55 -0
  295. autogen/llm_clients/models/content_blocks.py +389 -0
  296. autogen/llm_clients/models/unified_message.py +145 -0
  297. autogen/llm_clients/models/unified_response.py +83 -0
  298. autogen/llm_clients/openai_completions_client.py +444 -0
  299. autogen/llm_config/__init__.py +11 -0
  300. autogen/llm_config/client.py +59 -0
  301. autogen/llm_config/config.py +461 -0
  302. autogen/llm_config/entry.py +169 -0
  303. autogen/llm_config/types.py +37 -0
  304. autogen/llm_config/utils.py +223 -0
  305. autogen/logger/__init__.py +11 -0
  306. autogen/logger/base_logger.py +129 -0
  307. autogen/logger/file_logger.py +262 -0
  308. autogen/logger/logger_factory.py +42 -0
  309. autogen/logger/logger_utils.py +57 -0
  310. autogen/logger/sqlite_logger.py +524 -0
  311. autogen/math_utils.py +338 -0
  312. autogen/mcp/__init__.py +7 -0
  313. autogen/mcp/__main__.py +78 -0
  314. autogen/mcp/helpers.py +45 -0
  315. autogen/mcp/mcp_client.py +349 -0
  316. autogen/mcp/mcp_proxy/__init__.py +19 -0
  317. autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +62 -0
  318. autogen/mcp/mcp_proxy/mcp_proxy.py +577 -0
  319. autogen/mcp/mcp_proxy/operation_grouping.py +166 -0
  320. autogen/mcp/mcp_proxy/operation_renaming.py +110 -0
  321. autogen/mcp/mcp_proxy/patch_fastapi_code_generator.py +98 -0
  322. autogen/mcp/mcp_proxy/security.py +399 -0
  323. autogen/mcp/mcp_proxy/security_schema_visitor.py +37 -0
  324. autogen/messages/__init__.py +7 -0
  325. autogen/messages/agent_messages.py +946 -0
  326. autogen/messages/base_message.py +108 -0
  327. autogen/messages/client_messages.py +172 -0
  328. autogen/messages/print_message.py +48 -0
  329. autogen/oai/__init__.py +61 -0
  330. autogen/oai/anthropic.py +1516 -0
  331. autogen/oai/bedrock.py +800 -0
  332. autogen/oai/cerebras.py +302 -0
  333. autogen/oai/client.py +1658 -0
  334. autogen/oai/client_utils.py +196 -0
  335. autogen/oai/cohere.py +494 -0
  336. autogen/oai/gemini.py +1045 -0
  337. autogen/oai/gemini_types.py +156 -0
  338. autogen/oai/groq.py +319 -0
  339. autogen/oai/mistral.py +311 -0
  340. autogen/oai/oai_models/__init__.py +23 -0
  341. autogen/oai/oai_models/_models.py +16 -0
  342. autogen/oai/oai_models/chat_completion.py +86 -0
  343. autogen/oai/oai_models/chat_completion_audio.py +32 -0
  344. autogen/oai/oai_models/chat_completion_message.py +97 -0
  345. autogen/oai/oai_models/chat_completion_message_tool_call.py +60 -0
  346. autogen/oai/oai_models/chat_completion_token_logprob.py +62 -0
  347. autogen/oai/oai_models/completion_usage.py +59 -0
  348. autogen/oai/ollama.py +657 -0
  349. autogen/oai/openai_responses.py +451 -0
  350. autogen/oai/openai_utils.py +897 -0
  351. autogen/oai/together.py +387 -0
  352. autogen/remote/__init__.py +18 -0
  353. autogen/remote/agent.py +199 -0
  354. autogen/remote/agent_service.py +197 -0
  355. autogen/remote/errors.py +17 -0
  356. autogen/remote/httpx_client_factory.py +131 -0
  357. autogen/remote/protocol.py +37 -0
  358. autogen/remote/retry.py +102 -0
  359. autogen/remote/runtime.py +96 -0
  360. autogen/retrieve_utils.py +490 -0
  361. autogen/runtime_logging.py +161 -0
  362. autogen/testing/__init__.py +12 -0
  363. autogen/testing/messages.py +45 -0
  364. autogen/testing/test_agent.py +111 -0
  365. autogen/token_count_utils.py +280 -0
  366. autogen/tools/__init__.py +20 -0
  367. autogen/tools/contrib/__init__.py +9 -0
  368. autogen/tools/contrib/time/__init__.py +7 -0
  369. autogen/tools/contrib/time/time.py +40 -0
  370. autogen/tools/dependency_injection.py +249 -0
  371. autogen/tools/experimental/__init__.py +54 -0
  372. autogen/tools/experimental/browser_use/__init__.py +7 -0
  373. autogen/tools/experimental/browser_use/browser_use.py +154 -0
  374. autogen/tools/experimental/code_execution/__init__.py +7 -0
  375. autogen/tools/experimental/code_execution/python_code_execution.py +86 -0
  376. autogen/tools/experimental/crawl4ai/__init__.py +7 -0
  377. autogen/tools/experimental/crawl4ai/crawl4ai.py +150 -0
  378. autogen/tools/experimental/deep_research/__init__.py +7 -0
  379. autogen/tools/experimental/deep_research/deep_research.py +329 -0
  380. autogen/tools/experimental/duckduckgo/__init__.py +7 -0
  381. autogen/tools/experimental/duckduckgo/duckduckgo_search.py +103 -0
  382. autogen/tools/experimental/firecrawl/__init__.py +7 -0
  383. autogen/tools/experimental/firecrawl/firecrawl_tool.py +836 -0
  384. autogen/tools/experimental/google/__init__.py +14 -0
  385. autogen/tools/experimental/google/authentication/__init__.py +11 -0
  386. autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
  387. autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
  388. autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
  389. autogen/tools/experimental/google/drive/__init__.py +9 -0
  390. autogen/tools/experimental/google/drive/drive_functions.py +124 -0
  391. autogen/tools/experimental/google/drive/toolkit.py +88 -0
  392. autogen/tools/experimental/google/model.py +17 -0
  393. autogen/tools/experimental/google/toolkit_protocol.py +19 -0
  394. autogen/tools/experimental/google_search/__init__.py +8 -0
  395. autogen/tools/experimental/google_search/google_search.py +93 -0
  396. autogen/tools/experimental/google_search/youtube_search.py +181 -0
  397. autogen/tools/experimental/messageplatform/__init__.py +17 -0
  398. autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
  399. autogen/tools/experimental/messageplatform/discord/discord.py +284 -0
  400. autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
  401. autogen/tools/experimental/messageplatform/slack/slack.py +385 -0
  402. autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
  403. autogen/tools/experimental/messageplatform/telegram/telegram.py +271 -0
  404. autogen/tools/experimental/perplexity/__init__.py +7 -0
  405. autogen/tools/experimental/perplexity/perplexity_search.py +249 -0
  406. autogen/tools/experimental/reliable/__init__.py +10 -0
  407. autogen/tools/experimental/reliable/reliable.py +1311 -0
  408. autogen/tools/experimental/searxng/__init__.py +7 -0
  409. autogen/tools/experimental/searxng/searxng_search.py +142 -0
  410. autogen/tools/experimental/tavily/__init__.py +7 -0
  411. autogen/tools/experimental/tavily/tavily_search.py +176 -0
  412. autogen/tools/experimental/web_search_preview/__init__.py +7 -0
  413. autogen/tools/experimental/web_search_preview/web_search_preview.py +120 -0
  414. autogen/tools/experimental/wikipedia/__init__.py +7 -0
  415. autogen/tools/experimental/wikipedia/wikipedia.py +284 -0
  416. autogen/tools/function_utils.py +412 -0
  417. autogen/tools/tool.py +188 -0
  418. autogen/tools/toolkit.py +86 -0
  419. autogen/types.py +29 -0
  420. autogen/version.py +7 -0
  421. templates/client_template/main.jinja2 +72 -0
  422. templates/config_template/config.jinja2 +7 -0
  423. templates/main.jinja2 +61 -0
@@ -0,0 +1,387 @@
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
+ # Portions derived from https://github.com/microsoft/autogen are under the MIT License.
6
+ # SPDX-License-Identifier: MIT
7
+ """Create an OpenAI-compatible client using Together.AI's API.
8
+
9
+ Example:
10
+ ```python
11
+ llm_config = {
12
+ "config_list": [
13
+ {
14
+ "api_type": "together",
15
+ "model": "mistralai/Mixtral-8x7B-Instruct-v0.1",
16
+ "api_key": os.environ.get("TOGETHER_API_KEY"),
17
+ }
18
+ ]
19
+ }
20
+
21
+ agent = autogen.AssistantAgent("my_agent", llm_config=llm_config)
22
+ ```
23
+
24
+ Install Together.AI python library using: pip install --upgrade together
25
+
26
+ Resources:
27
+ - https://docs.together.ai/docs/inference-python
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import copy
33
+ import os
34
+ import time
35
+ import warnings
36
+ from typing import Any, Literal
37
+
38
+ from pydantic import Field
39
+ from typing_extensions import Unpack
40
+
41
+ from ..import_utils import optional_import_block, require_optional_import
42
+ from ..llm_config.entry import LLMConfigEntry, LLMConfigEntryDict
43
+ from .client_utils import should_hide_tools, validate_parameter
44
+ from .oai_models import ChatCompletion, ChatCompletionMessage, ChatCompletionMessageToolCall, Choice, CompletionUsage
45
+
46
+ with optional_import_block():
47
+ from together import Together
48
+
49
+
50
+ class TogetherEntryDict(LLMConfigEntryDict, total=False):
51
+ api_type: Literal["together"]
52
+
53
+ stream: bool
54
+ top_k: int | None
55
+ repetition_penalty: float | None
56
+ presence_penalty: float | None
57
+ frequency_penalty: float | None
58
+ min_p: float | None
59
+ safety_model: str | None
60
+ hide_tools: Literal["if_all_run", "if_any_run", "never"]
61
+ price: list[float] | None
62
+ tool_choice: str | dict[str, str | dict[str, str]] | None
63
+
64
+
65
+ class TogetherLLMConfigEntry(LLMConfigEntry):
66
+ api_type: Literal["together"] = "together"
67
+
68
+ max_tokens: int = Field(default=512, ge=0)
69
+
70
+ stream: bool = False
71
+ top_k: int | None = Field(default=None)
72
+ repetition_penalty: float | None = Field(default=None)
73
+ presence_penalty: float | None = Field(default=None, ge=-2, le=2)
74
+ frequency_penalty: float | None = Field(default=None, ge=-2, le=2)
75
+ min_p: float | None = Field(default=None, ge=0, le=1)
76
+ safety_model: str | None = None
77
+ hide_tools: Literal["if_all_run", "if_any_run", "never"] = "never"
78
+ price: list[float] | None = Field(default=None, min_length=2, max_length=2)
79
+ tool_choice: str | dict[str, str | dict[str, str]] | None = (
80
+ None # dict is the tool to call: {"type": "function", "function": {"name": "my_function"}}
81
+ )
82
+
83
+ def create_client(self):
84
+ raise NotImplementedError("TogetherLLMConfigEntry.create_client is not implemented.")
85
+
86
+
87
+ class TogetherClient:
88
+ """Client for Together.AI's API."""
89
+
90
+ RESPONSE_USAGE_KEYS: list[str] = ["prompt_tokens", "completion_tokens", "total_tokens", "cost", "model"]
91
+
92
+ def __init__(self, **kwargs: Unpack[TogetherEntryDict]):
93
+ """Requires api_key or environment variable to be set
94
+
95
+ Args:
96
+ **kwargs: Additional keyword arguments to pass to the client.
97
+ """
98
+ # Ensure we have the api_key upon instantiation
99
+ self.api_key = kwargs.get("api_key")
100
+ if not self.api_key:
101
+ self.api_key = os.getenv("TOGETHER_API_KEY")
102
+
103
+ if "response_format" in kwargs and kwargs["response_format"] is not None:
104
+ warnings.warn("response_format is not supported for Together.AI, it will be ignored.", UserWarning)
105
+
106
+ assert self.api_key, (
107
+ "Please include the api_key in your config list entry for Together.AI or set the TOGETHER_API_KEY env variable."
108
+ )
109
+
110
+ def message_retrieval(self, response) -> list:
111
+ """Retrieve and return a list of strings or a list of Choice.Message from the response.
112
+
113
+ NOTE: if a list of Choice.Message is returned, it currently needs to contain the fields of OpenAI's ChatCompletion Message object,
114
+ since that is expected for function or tool calling in the rest of the codebase at the moment, unless a custom agent is being used.
115
+ """
116
+ return [choice.message for choice in response.choices]
117
+
118
+ def cost(self, response) -> float:
119
+ return response.cost
120
+
121
+ @staticmethod
122
+ def get_usage(response) -> dict:
123
+ """Return usage summary of the response using RESPONSE_USAGE_KEYS."""
124
+ # ... # pragma: no cover
125
+ return {
126
+ "prompt_tokens": response.usage.prompt_tokens,
127
+ "completion_tokens": response.usage.completion_tokens,
128
+ "total_tokens": response.usage.total_tokens,
129
+ "cost": response.cost,
130
+ "model": response.model,
131
+ }
132
+
133
+ def parse_params(self, params: dict[str, Any]) -> dict[str, Any]:
134
+ """Loads the parameters for Together.AI API from the passed in parameters and returns a validated set. Checks types, ranges, and sets defaults"""
135
+ together_params = {}
136
+
137
+ # Check that we have what we need to use Together.AI's API
138
+ together_params["model"] = params.get("model")
139
+ assert together_params["model"], (
140
+ "Please specify the 'model' in your config list entry to nominate the Together.AI model to use."
141
+ )
142
+
143
+ # Validate allowed Together.AI parameters
144
+ # https://github.com/togethercomputer/together-python/blob/94ffb30daf0ac3e078be986af7228f85f79bde99/src/together/resources/completions.py#L44
145
+ together_params["max_tokens"] = validate_parameter(params, "max_tokens", int, True, 512, (0, None), None)
146
+ together_params["stream"] = validate_parameter(params, "stream", bool, False, False, None, None)
147
+ together_params["temperature"] = validate_parameter(params, "temperature", (int, float), True, None, None, None)
148
+ together_params["top_p"] = validate_parameter(params, "top_p", (int, float), True, None, None, None)
149
+ together_params["top_k"] = validate_parameter(params, "top_k", int, True, None, None, None)
150
+ together_params["repetition_penalty"] = validate_parameter(
151
+ params, "repetition_penalty", float, True, None, None, None
152
+ )
153
+ together_params["presence_penalty"] = validate_parameter(
154
+ params, "presence_penalty", (int, float), True, None, (-2, 2), None
155
+ )
156
+ together_params["frequency_penalty"] = validate_parameter(
157
+ params, "frequency_penalty", (int, float), True, None, (-2, 2), None
158
+ )
159
+ together_params["min_p"] = validate_parameter(params, "min_p", (int, float), True, None, (0, 1), None)
160
+ together_params["safety_model"] = validate_parameter(
161
+ params, "safety_model", str, True, None, None, None
162
+ ) # We won't enforce the available models as they are likely to change
163
+
164
+ # Check if they want to stream and use tools, which isn't currently supported (TODO)
165
+ if together_params["stream"] and "tools" in params:
166
+ warnings.warn(
167
+ "Streaming is not supported when using tools, streaming will be disabled.",
168
+ UserWarning,
169
+ )
170
+
171
+ together_params["stream"] = False
172
+
173
+ if "tool_choice" in params:
174
+ together_params["tool_choice"] = params["tool_choice"]
175
+
176
+ return together_params
177
+
178
+ @require_optional_import("together", "together")
179
+ def create(self, params: dict) -> ChatCompletion:
180
+ messages = params.get("messages", [])
181
+
182
+ # Convert AG2 messages to Together.AI messages
183
+ together_messages = oai_messages_to_together_messages(messages)
184
+
185
+ # Parse parameters to Together.AI API's parameters
186
+ together_params = self.parse_params(params)
187
+
188
+ # Add tools to the call if we have them and aren't hiding them
189
+ if "tools" in params:
190
+ hide_tools = validate_parameter(
191
+ params, "hide_tools", str, False, "never", None, ["if_all_run", "if_any_run", "never"]
192
+ )
193
+ if not should_hide_tools(together_messages, params["tools"], hide_tools):
194
+ together_params["tools"] = params["tools"]
195
+
196
+ together_params["messages"] = together_messages
197
+
198
+ # We use chat model by default
199
+ client = Together(api_key=self.api_key)
200
+
201
+ # Token counts will be returned
202
+ prompt_tokens = 0
203
+ completion_tokens = 0
204
+ total_tokens = 0
205
+
206
+ response = client.chat.completions.create(**together_params)
207
+ if together_params["stream"]:
208
+ # Read in the chunks as they stream
209
+ ans = ""
210
+ for chunk in response:
211
+ ans = ans + (chunk.choices[0].delta.content or "")
212
+
213
+ prompt_tokens = chunk.usage.prompt_tokens
214
+ completion_tokens = chunk.usage.completion_tokens
215
+ total_tokens = chunk.usage.total_tokens
216
+ else:
217
+ ans: str = response.choices[0].message.content
218
+
219
+ prompt_tokens = response.usage.prompt_tokens
220
+ completion_tokens = response.usage.completion_tokens
221
+ total_tokens = response.usage.total_tokens
222
+
223
+ if response.choices[0].finish_reason == "tool_calls":
224
+ together_finish = "tool_calls"
225
+ tool_calls = []
226
+ for tool_call in response.choices[0].message.tool_calls:
227
+ tool_calls.append(
228
+ ChatCompletionMessageToolCall(
229
+ id=tool_call.id,
230
+ function={"name": tool_call.function.name, "arguments": tool_call.function.arguments},
231
+ type="function",
232
+ )
233
+ )
234
+ else:
235
+ together_finish = "stop"
236
+ tool_calls = None
237
+
238
+ # 3. convert output
239
+ message = ChatCompletionMessage(
240
+ role="assistant",
241
+ content=response.choices[0].message.content,
242
+ function_call=None,
243
+ tool_calls=tool_calls,
244
+ )
245
+ choices = [Choice(finish_reason=together_finish, index=0, message=message)]
246
+
247
+ response_oai = ChatCompletion(
248
+ id=response.id,
249
+ model=together_params["model"],
250
+ created=int(time.time()),
251
+ object="chat.completion",
252
+ choices=choices,
253
+ usage=CompletionUsage(
254
+ prompt_tokens=prompt_tokens,
255
+ completion_tokens=completion_tokens,
256
+ total_tokens=total_tokens,
257
+ ),
258
+ cost=calculate_together_cost(prompt_tokens, completion_tokens, together_params["model"]),
259
+ )
260
+
261
+ return response_oai
262
+
263
+
264
+ def oai_messages_to_together_messages(messages: list[dict[str, Any]]) -> list[dict[str, Any]]:
265
+ """Convert messages from OAI format to Together.AI format.
266
+ We correct for any specific role orders and types.
267
+ """
268
+ together_messages = copy.deepcopy(messages)
269
+
270
+ # If we have a message with role='tool', which occurs when a function is executed, change it to 'user'
271
+ for msg in together_messages:
272
+ if "role" in msg and msg["role"] == "tool":
273
+ msg["role"] = "user"
274
+
275
+ return together_messages
276
+
277
+
278
+ # MODELS AND COSTS
279
+ chat_lang_code_model_sizes = {
280
+ "zero-one-ai/Yi-34B-Chat": 34,
281
+ "allenai/OLMo-7B-Instruct": 7,
282
+ "allenai/OLMo-7B-Twin-2T": 7,
283
+ "allenai/OLMo-7B": 7,
284
+ "Austism/chronos-hermes-13b": 13,
285
+ "deepseek-ai/deepseek-coder-33b-instruct": 33,
286
+ "deepseek-ai/deepseek-llm-67b-chat": 67,
287
+ "garage-bAInd/Platypus2-70B-instruct": 70,
288
+ "google/gemma-2b-it": 2,
289
+ "google/gemma-7b-it": 7,
290
+ "Gryphe/MythoMax-L2-13b": 13,
291
+ "lmsys/vicuna-13b-v1.5": 13,
292
+ "lmsys/vicuna-7b-v1.5": 7,
293
+ "codellama/CodeLlama-13b-Instruct-hf": 13,
294
+ "codellama/CodeLlama-34b-Instruct-hf": 34,
295
+ "codellama/CodeLlama-70b-Instruct-hf": 70,
296
+ "codellama/CodeLlama-7b-Instruct-hf": 7,
297
+ "meta-llama/Llama-2-70b-chat-hf": 70,
298
+ "meta-llama/Llama-2-13b-chat-hf": 13,
299
+ "meta-llama/Llama-2-7b-chat-hf": 7,
300
+ "meta-llama/Llama-3-8b-chat-hf": 8,
301
+ "meta-llama/Llama-3-70b-chat-hf": 70,
302
+ "mistralai/Mistral-7B-Instruct-v0.1": 7,
303
+ "mistralai/Mistral-7B-Instruct-v0.2": 7,
304
+ "mistralai/Mistral-7B-Instruct-v0.3": 7,
305
+ "NousResearch/Nous-Capybara-7B-V1p9": 7,
306
+ "NousResearch/Nous-Hermes-llama-2-7b": 7,
307
+ "NousResearch/Nous-Hermes-Llama2-13b": 13,
308
+ "NousResearch/Nous-Hermes-2-Yi-34B": 34,
309
+ "openchat/openchat-3.5-1210": 7,
310
+ "Open-Orca/Mistral-7B-OpenOrca": 7,
311
+ "Qwen/Qwen1.5-0.5B-Chat": 0.5,
312
+ "Qwen/Qwen1.5-1.8B-Chat": 1.8,
313
+ "Qwen/Qwen1.5-4B-Chat": 4,
314
+ "Qwen/Qwen1.5-7B-Chat": 7,
315
+ "Qwen/Qwen1.5-14B-Chat": 14,
316
+ "Qwen/Qwen1.5-32B-Chat": 32,
317
+ "Qwen/Qwen1.5-72B-Chat": 72,
318
+ "Qwen/Qwen1.5-110B-Chat": 110,
319
+ "Qwen/Qwen2-72B-Instruct": 72,
320
+ "snorkelai/Snorkel-Mistral-PairRM-DPO": 7,
321
+ "togethercomputer/alpaca-7b": 7,
322
+ "teknium/OpenHermes-2-Mistral-7B": 7,
323
+ "teknium/OpenHermes-2p5-Mistral-7B": 7,
324
+ "togethercomputer/Llama-2-7B-32K-Instruct": 7,
325
+ "togethercomputer/RedPajama-INCITE-Chat-3B-v1": 3,
326
+ "togethercomputer/RedPajama-INCITE-7B-Chat": 7,
327
+ "togethercomputer/StripedHyena-Nous-7B": 7,
328
+ "Undi95/ReMM-SLERP-L2-13B": 13,
329
+ "Undi95/Toppy-M-7B": 7,
330
+ "WizardLM/WizardLM-13B-V1.2": 13,
331
+ "upstage/SOLAR-10.7B-Instruct-v1.0": 11,
332
+ }
333
+
334
+ # Cost per million tokens based on up to X Billion parameters, e.g. up 4B is $0.1/million
335
+ chat_lang_code_model_costs = {4: 0.1, 8: 0.2, 21: 0.3, 41: 0.8, 80: 0.9, 110: 1.8}
336
+
337
+ mixture_model_sizes = {
338
+ "cognitivecomputations/dolphin-2.5-mixtral-8x7b": 56,
339
+ "databricks/dbrx-instruct": 132,
340
+ "mistralai/Mixtral-8x7B-Instruct-v0.1": 47,
341
+ "mistralai/Mixtral-8x22B-Instruct-v0.1": 141,
342
+ "NousResearch/Nous-Hermes-2-Mistral-7B-DPO": 7,
343
+ "NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO": 47,
344
+ "NousResearch/Nous-Hermes-2-Mixtral-8x7B-SFT": 47,
345
+ "Snowflake/snowflake-arctic-instruct": 480,
346
+ }
347
+
348
+ # Cost per million tokens based on up to X Billion parameters, e.g. up 56B is $0.6/million
349
+ mixture_costs = {56: 0.6, 176: 1.2, 480: 2.4}
350
+
351
+
352
+ def calculate_together_cost(input_tokens: int, output_tokens: int, model_name: str) -> float:
353
+ """Cost calculation for inference"""
354
+ if model_name in chat_lang_code_model_sizes or model_name in mixture_model_sizes:
355
+ cost_per_mil = 0
356
+
357
+ # Chat, Language, Code models
358
+ if model_name in chat_lang_code_model_sizes:
359
+ size_in_b = chat_lang_code_model_sizes[model_name]
360
+
361
+ for top_size in chat_lang_code_model_costs:
362
+ if size_in_b <= top_size:
363
+ cost_per_mil = chat_lang_code_model_costs[top_size]
364
+ break
365
+
366
+ else:
367
+ # Mixture-of-experts
368
+ size_in_b = mixture_model_sizes[model_name]
369
+
370
+ for top_size in mixture_costs:
371
+ if size_in_b <= top_size:
372
+ cost_per_mil = mixture_costs[top_size]
373
+ break
374
+
375
+ if cost_per_mil == 0:
376
+ warnings.warn("Model size doesn't align with cost structure.", UserWarning)
377
+
378
+ return cost_per_mil * ((input_tokens + output_tokens) / 1e6)
379
+
380
+ else:
381
+ # Model is not in our list of models, can't determine the cost
382
+ warnings.warn(
383
+ "The model isn't catered for costing, to apply costs you can use the 'price' key on your config_list.",
384
+ UserWarning,
385
+ )
386
+
387
+ return 0
@@ -0,0 +1,18 @@
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
+ try:
6
+ import httpx # noqa: F401
7
+ except ImportError as e:
8
+ raise ImportError("httpx is not installed. Please install it with:\npip install httpx") from e
9
+
10
+ from .agent import HTTPRemoteAgent
11
+ from .httpx_client_factory import HttpxClientFactory
12
+ from .runtime import HTTPAgentBus
13
+
14
+ __all__ = (
15
+ "HTTPAgentBus",
16
+ "HTTPRemoteAgent",
17
+ "HttpxClientFactory",
18
+ )
@@ -0,0 +1,199 @@
1
+ # Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ from typing import Any
5
+
6
+ import httpx
7
+
8
+ from autogen import ConversableAgent
9
+ from autogen.agentchat.group import ContextVariables
10
+ from autogen.oai.client import OpenAIWrapper
11
+
12
+ from .errors import RemoteAgentError, RemoteAgentNotFoundError
13
+ from .httpx_client_factory import ClientFactory, EmptyClientFactory
14
+ from .protocol import RequestMessage, ResponseMessage
15
+ from .retry import NoRetryPolicy, RetryPolicy
16
+
17
+
18
+ class HTTPRemoteAgent(ConversableAgent):
19
+ """A remote agent that communicates with other agents via HTTP long-polling.
20
+
21
+ This agent forwards messages to a remote endpoint and handles the response
22
+ through HTTP requests. It supports both synchronous and asynchronous operations.
23
+
24
+ Example:
25
+ >>> remote_agent = HTTPRemoteAgent(url="http://api.example.com/agents", name="my_remote_agent")
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ url: str,
31
+ name: str,
32
+ *,
33
+ silent: bool = False,
34
+ client: ClientFactory | None = None,
35
+ retry_policy: RetryPolicy | None = None,
36
+ ) -> None:
37
+ """Initialize the HTTPRemoteAgent.
38
+
39
+ Args:
40
+ url (str): The base URL of the remote agent service.
41
+ name (str): The name of this agent.
42
+ silent (bool): If True, suppresses logging output.
43
+ client (ClientFactory | None): HTTP client factory. If None, uses EmptyClientFactory.
44
+ retry_policy (RetryPolicy | None): Retry policy for HTTP requests. If None, uses NoRetryPolicy.
45
+ """
46
+
47
+ self.url = url
48
+ self.retry_policy: RetryPolicy = retry_policy or NoRetryPolicy
49
+
50
+ self._httpx_client_factory = client or EmptyClientFactory()
51
+
52
+ super().__init__(name, silent=silent)
53
+
54
+ self.__llm_config: dict[str, Any] = {}
55
+
56
+ self.replace_reply_func(
57
+ ConversableAgent.generate_oai_reply,
58
+ HTTPRemoteAgent.generate_remote_reply,
59
+ )
60
+ self.replace_reply_func(
61
+ ConversableAgent.a_generate_oai_reply,
62
+ HTTPRemoteAgent.a_generate_remote_reply,
63
+ )
64
+
65
+ def generate_remote_reply(
66
+ self,
67
+ messages: list[dict[str, Any]] | None = None,
68
+ sender: ConversableAgent | None = None,
69
+ config: OpenAIWrapper | None = None,
70
+ ) -> tuple[bool, dict[str, Any] | None]:
71
+ if messages is None:
72
+ messages = self._oai_messages[sender]
73
+
74
+ retry_policy = self.retry_policy()
75
+
76
+ task_id: Any = None
77
+ with self._httpx_client_factory.make_sync() as client:
78
+ while True:
79
+ with retry_policy:
80
+ if task_id is None:
81
+ # initiate remote procedure
82
+ task_id = self._process_create_remote_task_response(
83
+ client.post(
84
+ f"{self.url}/{self.name}",
85
+ content=RequestMessage(
86
+ messages=messages,
87
+ context=self.context_variables.data,
88
+ client_tools=self.__llm_config.get("tools", []),
89
+ ).model_dump_json(),
90
+ )
91
+ )
92
+
93
+ reply_response = client.get(f"{self.url}/{self.name}/{task_id}")
94
+
95
+ if reply_response.status_code in (200, 204): # valid answer codes
96
+ break
97
+
98
+ if reply_response.status_code == 425: # task still in progress
99
+ continue
100
+
101
+ if reply_response.status_code == 404:
102
+ task_id = None # recreate task due remote agent lost it
103
+ continue
104
+
105
+ raise RemoteAgentError(f"Remote client error: {reply_response}, {reply_response.content!r}")
106
+
107
+ if reply := self._process_remote_reply(reply_response):
108
+ if sender:
109
+ context_variables = ContextVariables(reply.context)
110
+ sender.context_variables.update(context_variables.to_dict())
111
+ # TODO: support multiple messages response for remote chat history
112
+ return True, reply.messages[-1]
113
+
114
+ return True, None
115
+
116
+ async def a_generate_remote_reply(
117
+ self,
118
+ messages: list[dict[str, Any]] | None = None,
119
+ sender: ConversableAgent | None = None,
120
+ config: OpenAIWrapper | None = None,
121
+ ) -> tuple[bool, dict[str, Any] | None]:
122
+ if messages is None:
123
+ messages = self._oai_messages[sender]
124
+
125
+ retry_policy = self.retry_policy()
126
+
127
+ task_id: Any = None
128
+ async with self._httpx_client_factory() as client:
129
+ while True:
130
+ with retry_policy:
131
+ if task_id is None:
132
+ # initiate remote procedure
133
+ task_id = self._process_create_remote_task_response(
134
+ await client.post(
135
+ f"{self.url}/{self.name}",
136
+ content=RequestMessage(
137
+ messages=messages,
138
+ context=self.context_variables.data,
139
+ client_tools=self.__llm_config.get("tools", []),
140
+ ).model_dump_json(),
141
+ )
142
+ )
143
+
144
+ reply_response = await client.get(f"{self.url}/{self.name}/{task_id}")
145
+
146
+ if reply_response.status_code in (200, 204): # valid answer codes
147
+ break
148
+
149
+ if reply_response.status_code == 425: # task still in progress
150
+ continue
151
+
152
+ if reply_response.status_code == 404:
153
+ task_id = None # recreate task due remote agent lost it
154
+ continue
155
+
156
+ raise RemoteAgentError(f"Remote client error: {reply_response}, {reply_response.content!r}")
157
+
158
+ if reply := self._process_remote_reply(reply_response):
159
+ if sender:
160
+ context_variables = ContextVariables(reply.context)
161
+ sender.context_variables.update(context_variables.to_dict())
162
+ # TODO: support multiple messages response for remote chat history
163
+ return True, reply.messages[-1]
164
+
165
+ return True, None
166
+
167
+ def _process_create_remote_task_response(self, response: httpx.Response) -> Any:
168
+ if response.status_code == 404:
169
+ raise RemoteAgentNotFoundError(self.name)
170
+
171
+ if response.status_code != 202:
172
+ raise RemoteAgentError(f"Remote client error: {response}, {response.content!r}")
173
+
174
+ return response.json()
175
+
176
+ def _process_remote_reply(self, reply_response: httpx.Response) -> ResponseMessage | None:
177
+ if reply_response.status_code == 204:
178
+ return None
179
+
180
+ try:
181
+ serialized_message = ResponseMessage.model_validate_json(reply_response.content)
182
+
183
+ except Exception as e:
184
+ raise RemoteAgentError(f"Remote client error: {reply_response}, {reply_response.content!r}") from e
185
+
186
+ return serialized_message
187
+
188
+ def update_tool_signature(
189
+ self,
190
+ tool_sig: str | dict[str, Any],
191
+ is_remove: bool,
192
+ silent_override: bool = False,
193
+ ) -> None:
194
+ self.__llm_config = self._update_tool_config(
195
+ self.__llm_config,
196
+ tool_sig=tool_sig,
197
+ is_remove=is_remove,
198
+ silent_override=silent_override,
199
+ )