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.
- ag2-0.10.2.dist-info/METADATA +819 -0
- ag2-0.10.2.dist-info/RECORD +423 -0
- ag2-0.10.2.dist-info/WHEEL +4 -0
- ag2-0.10.2.dist-info/licenses/LICENSE +201 -0
- ag2-0.10.2.dist-info/licenses/NOTICE.md +19 -0
- autogen/__init__.py +88 -0
- autogen/_website/__init__.py +3 -0
- autogen/_website/generate_api_references.py +426 -0
- autogen/_website/generate_mkdocs.py +1216 -0
- autogen/_website/notebook_processor.py +475 -0
- autogen/_website/process_notebooks.py +656 -0
- autogen/_website/utils.py +413 -0
- autogen/a2a/__init__.py +36 -0
- autogen/a2a/agent_executor.py +86 -0
- autogen/a2a/client.py +357 -0
- autogen/a2a/errors.py +18 -0
- autogen/a2a/httpx_client_factory.py +79 -0
- autogen/a2a/server.py +221 -0
- autogen/a2a/utils.py +207 -0
- autogen/agentchat/__init__.py +47 -0
- autogen/agentchat/agent.py +180 -0
- autogen/agentchat/assistant_agent.py +86 -0
- autogen/agentchat/chat.py +325 -0
- autogen/agentchat/contrib/__init__.py +5 -0
- autogen/agentchat/contrib/agent_eval/README.md +7 -0
- autogen/agentchat/contrib/agent_eval/agent_eval.py +108 -0
- autogen/agentchat/contrib/agent_eval/criterion.py +43 -0
- autogen/agentchat/contrib/agent_eval/critic_agent.py +44 -0
- autogen/agentchat/contrib/agent_eval/quantifier_agent.py +39 -0
- autogen/agentchat/contrib/agent_eval/subcritic_agent.py +45 -0
- autogen/agentchat/contrib/agent_eval/task.py +42 -0
- autogen/agentchat/contrib/agent_optimizer.py +432 -0
- autogen/agentchat/contrib/capabilities/__init__.py +5 -0
- autogen/agentchat/contrib/capabilities/agent_capability.py +20 -0
- autogen/agentchat/contrib/capabilities/generate_images.py +301 -0
- autogen/agentchat/contrib/capabilities/teachability.py +393 -0
- autogen/agentchat/contrib/capabilities/text_compressors.py +66 -0
- autogen/agentchat/contrib/capabilities/tools_capability.py +22 -0
- autogen/agentchat/contrib/capabilities/transform_messages.py +93 -0
- autogen/agentchat/contrib/capabilities/transforms.py +578 -0
- autogen/agentchat/contrib/capabilities/transforms_util.py +122 -0
- autogen/agentchat/contrib/capabilities/vision_capability.py +215 -0
- autogen/agentchat/contrib/captainagent/__init__.py +9 -0
- autogen/agentchat/contrib/captainagent/agent_builder.py +790 -0
- autogen/agentchat/contrib/captainagent/captainagent.py +514 -0
- autogen/agentchat/contrib/captainagent/tool_retriever.py +334 -0
- autogen/agentchat/contrib/captainagent/tools/README.md +44 -0
- autogen/agentchat/contrib/captainagent/tools/__init__.py +5 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_correlation.py +40 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/calculate_skewness_and_kurtosis.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_iqr.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/detect_outlier_zscore.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/explore_csv.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/data_analysis/shapiro_wilk_test.py +30 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_download.py +27 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/arxiv_search.py +53 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_image.py +53 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/extract_pdf_text.py +38 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_wikipedia_text.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/get_youtube_caption.py +34 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/image_qa.py +60 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/optical_character_recognition.py +61 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/perform_web_search.py +47 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/scrape_wikipedia_tables.py +33 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/transcribe_audio_file.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/information_retrieval/youtube_download.py +35 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_circle_area_from_diameter.py +21 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_day_of_the_week.py +18 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_fraction_sum.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_matrix_power.py +31 -0
- autogen/agentchat/contrib/captainagent/tools/math/calculate_reflected_point.py +16 -0
- autogen/agentchat/contrib/captainagent/tools/math/complex_numbers_product.py +25 -0
- autogen/agentchat/contrib/captainagent/tools/math/compute_currency_conversion.py +23 -0
- autogen/agentchat/contrib/captainagent/tools/math/count_distinct_permutations.py +27 -0
- autogen/agentchat/contrib/captainagent/tools/math/evaluate_expression.py +28 -0
- autogen/agentchat/contrib/captainagent/tools/math/find_continuity_point.py +34 -0
- autogen/agentchat/contrib/captainagent/tools/math/fraction_to_mixed_numbers.py +39 -0
- autogen/agentchat/contrib/captainagent/tools/math/modular_inverse_sum.py +23 -0
- autogen/agentchat/contrib/captainagent/tools/math/simplify_mixed_numbers.py +36 -0
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_digit_factorials.py +15 -0
- autogen/agentchat/contrib/captainagent/tools/math/sum_of_primes_below.py +15 -0
- autogen/agentchat/contrib/captainagent/tools/requirements.txt +10 -0
- autogen/agentchat/contrib/captainagent/tools/tool_description.tsv +34 -0
- autogen/agentchat/contrib/gpt_assistant_agent.py +526 -0
- autogen/agentchat/contrib/graph_rag/__init__.py +9 -0
- autogen/agentchat/contrib/graph_rag/document.py +29 -0
- autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +167 -0
- autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +103 -0
- autogen/agentchat/contrib/graph_rag/graph_query_engine.py +53 -0
- autogen/agentchat/contrib/graph_rag/graph_rag_capability.py +63 -0
- autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +263 -0
- autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +83 -0
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +210 -0
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +93 -0
- autogen/agentchat/contrib/img_utils.py +397 -0
- autogen/agentchat/contrib/llamaindex_conversable_agent.py +117 -0
- autogen/agentchat/contrib/llava_agent.py +189 -0
- autogen/agentchat/contrib/math_user_proxy_agent.py +464 -0
- autogen/agentchat/contrib/multimodal_conversable_agent.py +125 -0
- autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +325 -0
- autogen/agentchat/contrib/rag/__init__.py +10 -0
- autogen/agentchat/contrib/rag/chromadb_query_engine.py +268 -0
- autogen/agentchat/contrib/rag/llamaindex_query_engine.py +195 -0
- autogen/agentchat/contrib/rag/mongodb_query_engine.py +319 -0
- autogen/agentchat/contrib/rag/query_engine.py +76 -0
- autogen/agentchat/contrib/retrieve_assistant_agent.py +59 -0
- autogen/agentchat/contrib/retrieve_user_proxy_agent.py +704 -0
- autogen/agentchat/contrib/society_of_mind_agent.py +200 -0
- autogen/agentchat/contrib/swarm_agent.py +1404 -0
- autogen/agentchat/contrib/text_analyzer_agent.py +79 -0
- autogen/agentchat/contrib/vectordb/__init__.py +5 -0
- autogen/agentchat/contrib/vectordb/base.py +224 -0
- autogen/agentchat/contrib/vectordb/chromadb.py +316 -0
- autogen/agentchat/contrib/vectordb/couchbase.py +405 -0
- autogen/agentchat/contrib/vectordb/mongodb.py +551 -0
- autogen/agentchat/contrib/vectordb/pgvectordb.py +927 -0
- autogen/agentchat/contrib/vectordb/qdrant.py +320 -0
- autogen/agentchat/contrib/vectordb/utils.py +126 -0
- autogen/agentchat/contrib/web_surfer.py +304 -0
- autogen/agentchat/conversable_agent.py +4307 -0
- autogen/agentchat/group/__init__.py +67 -0
- autogen/agentchat/group/available_condition.py +91 -0
- autogen/agentchat/group/context_condition.py +77 -0
- autogen/agentchat/group/context_expression.py +238 -0
- autogen/agentchat/group/context_str.py +39 -0
- autogen/agentchat/group/context_variables.py +182 -0
- autogen/agentchat/group/events/transition_events.py +111 -0
- autogen/agentchat/group/group_tool_executor.py +324 -0
- autogen/agentchat/group/group_utils.py +659 -0
- autogen/agentchat/group/guardrails.py +179 -0
- autogen/agentchat/group/handoffs.py +303 -0
- autogen/agentchat/group/llm_condition.py +93 -0
- autogen/agentchat/group/multi_agent_chat.py +291 -0
- autogen/agentchat/group/on_condition.py +55 -0
- autogen/agentchat/group/on_context_condition.py +51 -0
- autogen/agentchat/group/patterns/__init__.py +18 -0
- autogen/agentchat/group/patterns/auto.py +160 -0
- autogen/agentchat/group/patterns/manual.py +177 -0
- autogen/agentchat/group/patterns/pattern.py +295 -0
- autogen/agentchat/group/patterns/random.py +106 -0
- autogen/agentchat/group/patterns/round_robin.py +117 -0
- autogen/agentchat/group/reply_result.py +24 -0
- autogen/agentchat/group/safeguards/__init__.py +21 -0
- autogen/agentchat/group/safeguards/api.py +241 -0
- autogen/agentchat/group/safeguards/enforcer.py +1158 -0
- autogen/agentchat/group/safeguards/events.py +140 -0
- autogen/agentchat/group/safeguards/validator.py +435 -0
- autogen/agentchat/group/speaker_selection_result.py +41 -0
- autogen/agentchat/group/targets/__init__.py +4 -0
- autogen/agentchat/group/targets/function_target.py +245 -0
- autogen/agentchat/group/targets/group_chat_target.py +133 -0
- autogen/agentchat/group/targets/group_manager_target.py +151 -0
- autogen/agentchat/group/targets/transition_target.py +424 -0
- autogen/agentchat/group/targets/transition_utils.py +6 -0
- autogen/agentchat/groupchat.py +1832 -0
- autogen/agentchat/realtime/__init__.py +3 -0
- autogen/agentchat/realtime/experimental/__init__.py +20 -0
- autogen/agentchat/realtime/experimental/audio_adapters/__init__.py +8 -0
- autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +148 -0
- autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +139 -0
- autogen/agentchat/realtime/experimental/audio_observer.py +42 -0
- autogen/agentchat/realtime/experimental/clients/__init__.py +15 -0
- autogen/agentchat/realtime/experimental/clients/gemini/__init__.py +7 -0
- autogen/agentchat/realtime/experimental/clients/gemini/client.py +274 -0
- autogen/agentchat/realtime/experimental/clients/oai/__init__.py +8 -0
- autogen/agentchat/realtime/experimental/clients/oai/base_client.py +220 -0
- autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +243 -0
- autogen/agentchat/realtime/experimental/clients/oai/utils.py +48 -0
- autogen/agentchat/realtime/experimental/clients/realtime_client.py +191 -0
- autogen/agentchat/realtime/experimental/function_observer.py +84 -0
- autogen/agentchat/realtime/experimental/realtime_agent.py +158 -0
- autogen/agentchat/realtime/experimental/realtime_events.py +42 -0
- autogen/agentchat/realtime/experimental/realtime_observer.py +100 -0
- autogen/agentchat/realtime/experimental/realtime_swarm.py +533 -0
- autogen/agentchat/realtime/experimental/websockets.py +21 -0
- autogen/agentchat/realtime_agent/__init__.py +21 -0
- autogen/agentchat/user_proxy_agent.py +114 -0
- autogen/agentchat/utils.py +206 -0
- autogen/agents/__init__.py +3 -0
- autogen/agents/contrib/__init__.py +10 -0
- autogen/agents/contrib/time/__init__.py +8 -0
- autogen/agents/contrib/time/time_reply_agent.py +74 -0
- autogen/agents/contrib/time/time_tool_agent.py +52 -0
- autogen/agents/experimental/__init__.py +27 -0
- autogen/agents/experimental/deep_research/__init__.py +7 -0
- autogen/agents/experimental/deep_research/deep_research.py +52 -0
- autogen/agents/experimental/discord/__init__.py +7 -0
- autogen/agents/experimental/discord/discord.py +66 -0
- autogen/agents/experimental/document_agent/__init__.py +19 -0
- autogen/agents/experimental/document_agent/chroma_query_engine.py +301 -0
- autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +113 -0
- autogen/agents/experimental/document_agent/document_agent.py +643 -0
- autogen/agents/experimental/document_agent/document_conditions.py +50 -0
- autogen/agents/experimental/document_agent/document_utils.py +376 -0
- autogen/agents/experimental/document_agent/inmemory_query_engine.py +214 -0
- autogen/agents/experimental/document_agent/parser_utils.py +134 -0
- autogen/agents/experimental/document_agent/url_utils.py +417 -0
- autogen/agents/experimental/reasoning/__init__.py +7 -0
- autogen/agents/experimental/reasoning/reasoning_agent.py +1178 -0
- autogen/agents/experimental/slack/__init__.py +7 -0
- autogen/agents/experimental/slack/slack.py +73 -0
- autogen/agents/experimental/telegram/__init__.py +7 -0
- autogen/agents/experimental/telegram/telegram.py +76 -0
- autogen/agents/experimental/websurfer/__init__.py +7 -0
- autogen/agents/experimental/websurfer/websurfer.py +70 -0
- autogen/agents/experimental/wikipedia/__init__.py +7 -0
- autogen/agents/experimental/wikipedia/wikipedia.py +88 -0
- autogen/browser_utils.py +309 -0
- autogen/cache/__init__.py +10 -0
- autogen/cache/abstract_cache_base.py +71 -0
- autogen/cache/cache.py +203 -0
- autogen/cache/cache_factory.py +88 -0
- autogen/cache/cosmos_db_cache.py +144 -0
- autogen/cache/disk_cache.py +97 -0
- autogen/cache/in_memory_cache.py +54 -0
- autogen/cache/redis_cache.py +119 -0
- autogen/code_utils.py +598 -0
- autogen/coding/__init__.py +30 -0
- autogen/coding/base.py +120 -0
- autogen/coding/docker_commandline_code_executor.py +283 -0
- autogen/coding/factory.py +56 -0
- autogen/coding/func_with_reqs.py +203 -0
- autogen/coding/jupyter/__init__.py +23 -0
- autogen/coding/jupyter/base.py +36 -0
- autogen/coding/jupyter/docker_jupyter_server.py +160 -0
- autogen/coding/jupyter/embedded_ipython_code_executor.py +182 -0
- autogen/coding/jupyter/import_utils.py +82 -0
- autogen/coding/jupyter/jupyter_client.py +224 -0
- autogen/coding/jupyter/jupyter_code_executor.py +154 -0
- autogen/coding/jupyter/local_jupyter_server.py +164 -0
- autogen/coding/local_commandline_code_executor.py +341 -0
- autogen/coding/markdown_code_extractor.py +44 -0
- autogen/coding/utils.py +55 -0
- autogen/coding/yepcode_code_executor.py +197 -0
- autogen/doc_utils.py +35 -0
- autogen/environments/__init__.py +10 -0
- autogen/environments/docker_python_environment.py +365 -0
- autogen/environments/python_environment.py +125 -0
- autogen/environments/system_python_environment.py +85 -0
- autogen/environments/venv_python_environment.py +220 -0
- autogen/environments/working_directory.py +74 -0
- autogen/events/__init__.py +7 -0
- autogen/events/agent_events.py +1016 -0
- autogen/events/base_event.py +100 -0
- autogen/events/client_events.py +168 -0
- autogen/events/helpers.py +44 -0
- autogen/events/print_event.py +45 -0
- autogen/exception_utils.py +73 -0
- autogen/extensions/__init__.py +5 -0
- autogen/fast_depends/__init__.py +16 -0
- autogen/fast_depends/_compat.py +75 -0
- autogen/fast_depends/core/__init__.py +14 -0
- autogen/fast_depends/core/build.py +206 -0
- autogen/fast_depends/core/model.py +527 -0
- autogen/fast_depends/dependencies/__init__.py +15 -0
- autogen/fast_depends/dependencies/model.py +30 -0
- autogen/fast_depends/dependencies/provider.py +40 -0
- autogen/fast_depends/library/__init__.py +10 -0
- autogen/fast_depends/library/model.py +46 -0
- autogen/fast_depends/py.typed +6 -0
- autogen/fast_depends/schema.py +66 -0
- autogen/fast_depends/use.py +272 -0
- autogen/fast_depends/utils.py +177 -0
- autogen/formatting_utils.py +83 -0
- autogen/function_utils.py +13 -0
- autogen/graph_utils.py +173 -0
- autogen/import_utils.py +539 -0
- autogen/interop/__init__.py +22 -0
- autogen/interop/crewai/__init__.py +7 -0
- autogen/interop/crewai/crewai.py +88 -0
- autogen/interop/interoperability.py +71 -0
- autogen/interop/interoperable.py +46 -0
- autogen/interop/langchain/__init__.py +8 -0
- autogen/interop/langchain/langchain_chat_model_factory.py +156 -0
- autogen/interop/langchain/langchain_tool.py +78 -0
- autogen/interop/litellm/__init__.py +7 -0
- autogen/interop/litellm/litellm_config_factory.py +178 -0
- autogen/interop/pydantic_ai/__init__.py +7 -0
- autogen/interop/pydantic_ai/pydantic_ai.py +172 -0
- autogen/interop/registry.py +70 -0
- autogen/io/__init__.py +15 -0
- autogen/io/base.py +151 -0
- autogen/io/console.py +56 -0
- autogen/io/processors/__init__.py +12 -0
- autogen/io/processors/base.py +21 -0
- autogen/io/processors/console_event_processor.py +61 -0
- autogen/io/run_response.py +294 -0
- autogen/io/thread_io_stream.py +63 -0
- autogen/io/websockets.py +214 -0
- autogen/json_utils.py +42 -0
- autogen/llm_clients/MIGRATION_TO_V2.md +782 -0
- autogen/llm_clients/__init__.py +77 -0
- autogen/llm_clients/client_v2.py +122 -0
- autogen/llm_clients/models/__init__.py +55 -0
- autogen/llm_clients/models/content_blocks.py +389 -0
- autogen/llm_clients/models/unified_message.py +145 -0
- autogen/llm_clients/models/unified_response.py +83 -0
- autogen/llm_clients/openai_completions_client.py +444 -0
- autogen/llm_config/__init__.py +11 -0
- autogen/llm_config/client.py +59 -0
- autogen/llm_config/config.py +461 -0
- autogen/llm_config/entry.py +169 -0
- autogen/llm_config/types.py +37 -0
- autogen/llm_config/utils.py +223 -0
- autogen/logger/__init__.py +11 -0
- autogen/logger/base_logger.py +129 -0
- autogen/logger/file_logger.py +262 -0
- autogen/logger/logger_factory.py +42 -0
- autogen/logger/logger_utils.py +57 -0
- autogen/logger/sqlite_logger.py +524 -0
- autogen/math_utils.py +338 -0
- autogen/mcp/__init__.py +7 -0
- autogen/mcp/__main__.py +78 -0
- autogen/mcp/helpers.py +45 -0
- autogen/mcp/mcp_client.py +349 -0
- autogen/mcp/mcp_proxy/__init__.py +19 -0
- autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +62 -0
- autogen/mcp/mcp_proxy/mcp_proxy.py +577 -0
- autogen/mcp/mcp_proxy/operation_grouping.py +166 -0
- autogen/mcp/mcp_proxy/operation_renaming.py +110 -0
- autogen/mcp/mcp_proxy/patch_fastapi_code_generator.py +98 -0
- autogen/mcp/mcp_proxy/security.py +399 -0
- autogen/mcp/mcp_proxy/security_schema_visitor.py +37 -0
- autogen/messages/__init__.py +7 -0
- autogen/messages/agent_messages.py +946 -0
- autogen/messages/base_message.py +108 -0
- autogen/messages/client_messages.py +172 -0
- autogen/messages/print_message.py +48 -0
- autogen/oai/__init__.py +61 -0
- autogen/oai/anthropic.py +1516 -0
- autogen/oai/bedrock.py +800 -0
- autogen/oai/cerebras.py +302 -0
- autogen/oai/client.py +1658 -0
- autogen/oai/client_utils.py +196 -0
- autogen/oai/cohere.py +494 -0
- autogen/oai/gemini.py +1045 -0
- autogen/oai/gemini_types.py +156 -0
- autogen/oai/groq.py +319 -0
- autogen/oai/mistral.py +311 -0
- autogen/oai/oai_models/__init__.py +23 -0
- autogen/oai/oai_models/_models.py +16 -0
- autogen/oai/oai_models/chat_completion.py +86 -0
- autogen/oai/oai_models/chat_completion_audio.py +32 -0
- autogen/oai/oai_models/chat_completion_message.py +97 -0
- autogen/oai/oai_models/chat_completion_message_tool_call.py +60 -0
- autogen/oai/oai_models/chat_completion_token_logprob.py +62 -0
- autogen/oai/oai_models/completion_usage.py +59 -0
- autogen/oai/ollama.py +657 -0
- autogen/oai/openai_responses.py +451 -0
- autogen/oai/openai_utils.py +897 -0
- autogen/oai/together.py +387 -0
- autogen/remote/__init__.py +18 -0
- autogen/remote/agent.py +199 -0
- autogen/remote/agent_service.py +197 -0
- autogen/remote/errors.py +17 -0
- autogen/remote/httpx_client_factory.py +131 -0
- autogen/remote/protocol.py +37 -0
- autogen/remote/retry.py +102 -0
- autogen/remote/runtime.py +96 -0
- autogen/retrieve_utils.py +490 -0
- autogen/runtime_logging.py +161 -0
- autogen/testing/__init__.py +12 -0
- autogen/testing/messages.py +45 -0
- autogen/testing/test_agent.py +111 -0
- autogen/token_count_utils.py +280 -0
- autogen/tools/__init__.py +20 -0
- autogen/tools/contrib/__init__.py +9 -0
- autogen/tools/contrib/time/__init__.py +7 -0
- autogen/tools/contrib/time/time.py +40 -0
- autogen/tools/dependency_injection.py +249 -0
- autogen/tools/experimental/__init__.py +54 -0
- autogen/tools/experimental/browser_use/__init__.py +7 -0
- autogen/tools/experimental/browser_use/browser_use.py +154 -0
- autogen/tools/experimental/code_execution/__init__.py +7 -0
- autogen/tools/experimental/code_execution/python_code_execution.py +86 -0
- autogen/tools/experimental/crawl4ai/__init__.py +7 -0
- autogen/tools/experimental/crawl4ai/crawl4ai.py +150 -0
- autogen/tools/experimental/deep_research/__init__.py +7 -0
- autogen/tools/experimental/deep_research/deep_research.py +329 -0
- autogen/tools/experimental/duckduckgo/__init__.py +7 -0
- autogen/tools/experimental/duckduckgo/duckduckgo_search.py +103 -0
- autogen/tools/experimental/firecrawl/__init__.py +7 -0
- autogen/tools/experimental/firecrawl/firecrawl_tool.py +836 -0
- autogen/tools/experimental/google/__init__.py +14 -0
- autogen/tools/experimental/google/authentication/__init__.py +11 -0
- autogen/tools/experimental/google/authentication/credentials_hosted_provider.py +43 -0
- autogen/tools/experimental/google/authentication/credentials_local_provider.py +91 -0
- autogen/tools/experimental/google/authentication/credentials_provider.py +35 -0
- autogen/tools/experimental/google/drive/__init__.py +9 -0
- autogen/tools/experimental/google/drive/drive_functions.py +124 -0
- autogen/tools/experimental/google/drive/toolkit.py +88 -0
- autogen/tools/experimental/google/model.py +17 -0
- autogen/tools/experimental/google/toolkit_protocol.py +19 -0
- autogen/tools/experimental/google_search/__init__.py +8 -0
- autogen/tools/experimental/google_search/google_search.py +93 -0
- autogen/tools/experimental/google_search/youtube_search.py +181 -0
- autogen/tools/experimental/messageplatform/__init__.py +17 -0
- autogen/tools/experimental/messageplatform/discord/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/discord/discord.py +284 -0
- autogen/tools/experimental/messageplatform/slack/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/slack/slack.py +385 -0
- autogen/tools/experimental/messageplatform/telegram/__init__.py +7 -0
- autogen/tools/experimental/messageplatform/telegram/telegram.py +271 -0
- autogen/tools/experimental/perplexity/__init__.py +7 -0
- autogen/tools/experimental/perplexity/perplexity_search.py +249 -0
- autogen/tools/experimental/reliable/__init__.py +10 -0
- autogen/tools/experimental/reliable/reliable.py +1311 -0
- autogen/tools/experimental/searxng/__init__.py +7 -0
- autogen/tools/experimental/searxng/searxng_search.py +142 -0
- autogen/tools/experimental/tavily/__init__.py +7 -0
- autogen/tools/experimental/tavily/tavily_search.py +176 -0
- autogen/tools/experimental/web_search_preview/__init__.py +7 -0
- autogen/tools/experimental/web_search_preview/web_search_preview.py +120 -0
- autogen/tools/experimental/wikipedia/__init__.py +7 -0
- autogen/tools/experimental/wikipedia/wikipedia.py +284 -0
- autogen/tools/function_utils.py +412 -0
- autogen/tools/tool.py +188 -0
- autogen/tools/toolkit.py +86 -0
- autogen/types.py +29 -0
- autogen/version.py +7 -0
- templates/client_template/main.jinja2 +72 -0
- templates/config_template/config.jinja2 +7 -0
- templates/main.jinja2 +61 -0
|
@@ -0,0 +1,111 @@
|
|
|
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
|
+
from collections.abc import Callable
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from autogen.agentchat.agent import Agent
|
|
9
|
+
from autogen.agentchat.group.targets.transition_target import TransitionTarget
|
|
10
|
+
from autogen.events.base_event import BaseEvent, wrap_event
|
|
11
|
+
from autogen.formatting_utils import colored
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@wrap_event
|
|
15
|
+
class AfterWorksTransitionEvent(BaseEvent):
|
|
16
|
+
"""Event for after works handoffs"""
|
|
17
|
+
|
|
18
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
19
|
+
|
|
20
|
+
source_agent: Agent
|
|
21
|
+
transition_target: TransitionTarget
|
|
22
|
+
|
|
23
|
+
def __init__(self, source_agent: Agent, transition_target: TransitionTarget):
|
|
24
|
+
super().__init__(source_agent=source_agent, transition_target=transition_target)
|
|
25
|
+
|
|
26
|
+
def print(self, f: Callable[..., Any] | None = None) -> None:
|
|
27
|
+
f = f or print
|
|
28
|
+
super().print(f)
|
|
29
|
+
|
|
30
|
+
f(
|
|
31
|
+
colored(
|
|
32
|
+
f"***** AfterWork handoff ({self.source_agent.name if hasattr(self.source_agent, 'name') else self.source_agent}): {self.transition_target.display_name()} *****",
|
|
33
|
+
"blue",
|
|
34
|
+
),
|
|
35
|
+
flush=True,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@wrap_event
|
|
40
|
+
class OnContextConditionTransitionEvent(BaseEvent):
|
|
41
|
+
"""Event for OnContextCondition handoffs"""
|
|
42
|
+
|
|
43
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
44
|
+
|
|
45
|
+
source_agent: Agent
|
|
46
|
+
transition_target: TransitionTarget
|
|
47
|
+
|
|
48
|
+
def __init__(self, source_agent: Agent, transition_target: TransitionTarget):
|
|
49
|
+
super().__init__(source_agent=source_agent, transition_target=transition_target)
|
|
50
|
+
|
|
51
|
+
def print(self, f: Callable[..., Any] | None = None) -> None:
|
|
52
|
+
f = f or print
|
|
53
|
+
super().print(f)
|
|
54
|
+
|
|
55
|
+
f(
|
|
56
|
+
colored(
|
|
57
|
+
f"***** OnContextCondition handoff ({self.source_agent.name if hasattr(self.source_agent, 'name') else self.source_agent}): {self.transition_target.display_name()} *****",
|
|
58
|
+
"blue",
|
|
59
|
+
),
|
|
60
|
+
flush=True,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@wrap_event
|
|
65
|
+
class OnConditionLLMTransitionEvent(BaseEvent):
|
|
66
|
+
"""Event for LLM-based OnCondition handoffs"""
|
|
67
|
+
|
|
68
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
69
|
+
|
|
70
|
+
source_agent: Agent
|
|
71
|
+
transition_target: TransitionTarget
|
|
72
|
+
|
|
73
|
+
def __init__(self, source_agent: Agent, transition_target: TransitionTarget):
|
|
74
|
+
super().__init__(source_agent=source_agent, transition_target=transition_target)
|
|
75
|
+
|
|
76
|
+
def print(self, f: Callable[..., Any] | None = None) -> None:
|
|
77
|
+
f = f or print
|
|
78
|
+
super().print(f)
|
|
79
|
+
|
|
80
|
+
f(
|
|
81
|
+
colored(
|
|
82
|
+
f"***** LLM-based OnCondition handoff ({self.source_agent.name if hasattr(self.source_agent, 'name') else self.source_agent}): {self.transition_target.display_name()} *****",
|
|
83
|
+
"blue",
|
|
84
|
+
),
|
|
85
|
+
flush=True,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@wrap_event
|
|
90
|
+
class ReplyResultTransitionEvent(BaseEvent):
|
|
91
|
+
"""Event for reply result transitions"""
|
|
92
|
+
|
|
93
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
94
|
+
|
|
95
|
+
source_agent: Agent
|
|
96
|
+
transition_target: TransitionTarget
|
|
97
|
+
|
|
98
|
+
def __init__(self, source_agent: Agent, transition_target: TransitionTarget):
|
|
99
|
+
super().__init__(source_agent=source_agent, transition_target=transition_target)
|
|
100
|
+
|
|
101
|
+
def print(self, f: Callable[..., Any] | None = None) -> None:
|
|
102
|
+
f = f or print
|
|
103
|
+
super().print(f)
|
|
104
|
+
|
|
105
|
+
f(
|
|
106
|
+
colored(
|
|
107
|
+
f"***** ReplyResult transition ({self.source_agent.name if hasattr(self.source_agent, 'name') else self.source_agent}): {self.transition_target.display_name()} *****",
|
|
108
|
+
"blue",
|
|
109
|
+
),
|
|
110
|
+
flush=True,
|
|
111
|
+
)
|
|
@@ -0,0 +1,324 @@
|
|
|
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 inspect
|
|
6
|
+
from collections.abc import Callable
|
|
7
|
+
from copy import deepcopy
|
|
8
|
+
from typing import Annotated, Any
|
|
9
|
+
|
|
10
|
+
from autogen.agentchat.group.events.transition_events import OnConditionLLMTransitionEvent, ReplyResultTransitionEvent
|
|
11
|
+
from autogen.code_utils import content_str
|
|
12
|
+
from autogen.io.base import IOStream
|
|
13
|
+
|
|
14
|
+
from ...oai import OpenAIWrapper
|
|
15
|
+
from ...tools import Depends, Tool
|
|
16
|
+
from ...tools.dependency_injection import inject_params, on
|
|
17
|
+
from ..agent import Agent
|
|
18
|
+
from ..conversable_agent import ConversableAgent
|
|
19
|
+
from .context_variables import __CONTEXT_VARIABLES_PARAM_NAME__, ContextVariables
|
|
20
|
+
from .reply_result import ReplyResult
|
|
21
|
+
from .targets.transition_target import TransitionTarget
|
|
22
|
+
|
|
23
|
+
__TOOL_EXECUTOR_NAME__ = "_Group_Tool_Executor"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class GroupToolExecutor(ConversableAgent):
|
|
27
|
+
"""Tool executor for the group chat initiated with initiate_group_chat"""
|
|
28
|
+
|
|
29
|
+
def __init__(self) -> None:
|
|
30
|
+
super().__init__(
|
|
31
|
+
name=__TOOL_EXECUTOR_NAME__,
|
|
32
|
+
system_message="Tool Execution, do not use this agent directly.",
|
|
33
|
+
human_input_mode="NEVER",
|
|
34
|
+
code_execution_config=False,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Store the next target from a tool call
|
|
38
|
+
self._group_next_target: TransitionTarget | None = None
|
|
39
|
+
|
|
40
|
+
# Track the original agent that initiated the tool call (for safeguards)
|
|
41
|
+
self._tool_call_originator: str | None = None
|
|
42
|
+
# Group manager will be set by link_agents_to_group_manager
|
|
43
|
+
self._group_manager: Any = None
|
|
44
|
+
|
|
45
|
+
# Primary tool reply function for handling the tool reply and the ReplyResult and TransitionTarget returns
|
|
46
|
+
self.register_reply([Agent, None], self._generate_group_tool_reply, remove_other_reply_funcs=True)
|
|
47
|
+
|
|
48
|
+
def set_next_target(self, next_target: TransitionTarget) -> None:
|
|
49
|
+
"""Sets the next target to transition to, used in the determine_next_agent function."""
|
|
50
|
+
self._group_next_target = next_target
|
|
51
|
+
|
|
52
|
+
def get_next_target(self) -> TransitionTarget:
|
|
53
|
+
"""Gets the next target to transition to."""
|
|
54
|
+
"""Returns the next target to transition to, if it exists."""
|
|
55
|
+
if self._group_next_target is None:
|
|
56
|
+
raise ValueError(
|
|
57
|
+
"No next target set. Please set a next target before calling this method. Use has_next_target() to check if a next target exists."
|
|
58
|
+
)
|
|
59
|
+
return self._group_next_target
|
|
60
|
+
|
|
61
|
+
def has_next_target(self) -> bool:
|
|
62
|
+
"""Checks if there is a next target to transition to."""
|
|
63
|
+
return self._group_next_target is not None
|
|
64
|
+
|
|
65
|
+
def clear_next_target(self) -> None:
|
|
66
|
+
"""Clears the next target to transition to."""
|
|
67
|
+
self._group_next_target = None
|
|
68
|
+
|
|
69
|
+
def set_tool_call_originator(self, agent_name: str) -> None:
|
|
70
|
+
"""Sets the original agent that initiated the tool call (for safeguard transparency)."""
|
|
71
|
+
self._tool_call_originator = agent_name
|
|
72
|
+
|
|
73
|
+
def get_tool_call_originator(self) -> str | None:
|
|
74
|
+
"""Gets the original agent that initiated the tool call."""
|
|
75
|
+
return self._tool_call_originator
|
|
76
|
+
|
|
77
|
+
def clear_tool_call_originator(self) -> None:
|
|
78
|
+
"""Clears the tool call originator."""
|
|
79
|
+
self._tool_call_originator = None
|
|
80
|
+
|
|
81
|
+
def _modify_context_variables_param(
|
|
82
|
+
self, f: Callable[..., Any], context_variables: ContextVariables
|
|
83
|
+
) -> Callable[..., Any]:
|
|
84
|
+
"""Modifies the context_variables parameter to use dependency injection and link it to the group context variables.
|
|
85
|
+
|
|
86
|
+
This essentially changes:
|
|
87
|
+
def some_function(some_variable: int, context_variables: ContextVariables) -> str:
|
|
88
|
+
|
|
89
|
+
to:
|
|
90
|
+
|
|
91
|
+
def some_function(some_variable: int, context_variables: Annotated[ContextVariables, Depends(on(self.context_variables))]) -> str:
|
|
92
|
+
"""
|
|
93
|
+
sig = inspect.signature(f)
|
|
94
|
+
|
|
95
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
96
|
+
return f(*args, **kwargs)
|
|
97
|
+
|
|
98
|
+
# Check if context_variables parameter exists and update it if so
|
|
99
|
+
if __CONTEXT_VARIABLES_PARAM_NAME__ in sig.parameters:
|
|
100
|
+
new_params = []
|
|
101
|
+
for name, param in sig.parameters.items():
|
|
102
|
+
if name == __CONTEXT_VARIABLES_PARAM_NAME__:
|
|
103
|
+
# Replace with new annotation using Depends
|
|
104
|
+
new_param = param.replace(annotation=Annotated[ContextVariables, Depends(on(context_variables))])
|
|
105
|
+
new_params.append(new_param)
|
|
106
|
+
else:
|
|
107
|
+
new_params.append(param)
|
|
108
|
+
|
|
109
|
+
# Update signature
|
|
110
|
+
new_sig = sig.replace(parameters=new_params)
|
|
111
|
+
wrapper.__signature__ = new_sig # type: ignore[attr-defined]
|
|
112
|
+
|
|
113
|
+
return wrapper
|
|
114
|
+
|
|
115
|
+
def make_tool_copy_with_context_variables(
|
|
116
|
+
self, current_tool: Tool, context_variables: ContextVariables
|
|
117
|
+
) -> Tool | None:
|
|
118
|
+
"""Checks for the context_variables parameter in the tool and updates it to use dependency injection."""
|
|
119
|
+
# If the tool has a context_variables parameter, remove the tool and reregister it without the parameter
|
|
120
|
+
if __CONTEXT_VARIABLES_PARAM_NAME__ in current_tool.tool_schema["function"]["parameters"]["properties"]:
|
|
121
|
+
# We'll replace the tool, so start with getting the underlying function
|
|
122
|
+
tool_func = current_tool._func
|
|
123
|
+
|
|
124
|
+
# Remove the Tool from the agent
|
|
125
|
+
name = current_tool._name
|
|
126
|
+
description = current_tool._description
|
|
127
|
+
|
|
128
|
+
# Recreate the tool without the context_variables parameter
|
|
129
|
+
tool_func = self._modify_context_variables_param(tool_func, context_variables)
|
|
130
|
+
tool_func = inject_params(tool_func)
|
|
131
|
+
return ConversableAgent._create_tool_if_needed(func_or_tool=tool_func, name=name, description=description)
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
def _change_tool_context_variables_to_depends(
|
|
135
|
+
self, agent: ConversableAgent, current_tool: Tool, context_variables: ContextVariables
|
|
136
|
+
) -> None:
|
|
137
|
+
"""Checks for the context_variables parameter in the tool and updates it to use dependency injection."""
|
|
138
|
+
if new_tool := self.make_tool_copy_with_context_variables(current_tool, context_variables):
|
|
139
|
+
agent.remove_tool_for_llm(current_tool)
|
|
140
|
+
agent.register_for_llm()(new_tool)
|
|
141
|
+
|
|
142
|
+
def register_agents_functions(self, agents: list[ConversableAgent], context_variables: ContextVariables) -> None:
|
|
143
|
+
"""Adds the functions of the agents to the group tool executor."""
|
|
144
|
+
for agent in agents:
|
|
145
|
+
# As we're moving towards tools and away from function maps, this may not be used
|
|
146
|
+
self._function_map.update(agent._function_map)
|
|
147
|
+
|
|
148
|
+
# Update any agent tools that have context_variables parameters to use Dependency Injection
|
|
149
|
+
for tool in agent.tools:
|
|
150
|
+
self._change_tool_context_variables_to_depends(agent, tool, context_variables)
|
|
151
|
+
|
|
152
|
+
# Add all tools to the Tool Executor agent
|
|
153
|
+
for tool in agent.tools:
|
|
154
|
+
self.register_for_execution(serialize=False, silent_override=True)(tool)
|
|
155
|
+
|
|
156
|
+
def function_is_agent_llm_handoff(self, agent_name: str, function_name: str) -> bool:
|
|
157
|
+
"""Determines if a function name is an LLM handoff.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
agent_name (str): The name of the agent the conditions against
|
|
161
|
+
function_name (str): The function name to check.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
bool: True if the function is an LLM handoff, False otherwise.
|
|
165
|
+
"""
|
|
166
|
+
agent = self._group_manager.groupchat.agent_by_name(agent_name)
|
|
167
|
+
if agent is None:
|
|
168
|
+
return False
|
|
169
|
+
# Check if agent is a ConversableAgent with handoffs
|
|
170
|
+
if not isinstance(agent, ConversableAgent) or not hasattr(agent, "handoffs"):
|
|
171
|
+
return False
|
|
172
|
+
return any(on_condition.llm_function_name == function_name for on_condition in agent.handoffs.llm_conditions)
|
|
173
|
+
|
|
174
|
+
def get_sender_agent_for_message(self, message: dict[str, Any]) -> Agent | None:
|
|
175
|
+
"""Gets the sender agent from the message.
|
|
176
|
+
|
|
177
|
+
Args:
|
|
178
|
+
message: The message containing the tool call and source agent
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
The sender agent, or None if not found
|
|
182
|
+
"""
|
|
183
|
+
if "name" in message and self._group_manager:
|
|
184
|
+
agent = self._group_manager.groupchat.agent_by_name(message.get("name"))
|
|
185
|
+
return agent # type: ignore[no-any-return]
|
|
186
|
+
return None
|
|
187
|
+
|
|
188
|
+
def is_handoff_function(self, message: dict[str, Any]) -> bool:
|
|
189
|
+
"""Checks if the tool call is a handoff function.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
message: The message containing the tool call and source agent
|
|
193
|
+
"""
|
|
194
|
+
if "name" in message:
|
|
195
|
+
agent_name = message.get("name")
|
|
196
|
+
|
|
197
|
+
if agent_name and "tool_calls" in message and self._group_manager:
|
|
198
|
+
for tool_call in message["tool_calls"]:
|
|
199
|
+
if "function" in tool_call and "name" in tool_call["function"]:
|
|
200
|
+
function_name = tool_call["function"]["name"]
|
|
201
|
+
if self.function_is_agent_llm_handoff(agent_name, function_name):
|
|
202
|
+
return True
|
|
203
|
+
return False
|
|
204
|
+
|
|
205
|
+
def _send_llm_handoff_event(self, message: dict[str, Any], transition_target: TransitionTarget) -> None:
|
|
206
|
+
"""Send an LLM OnCondition handoff event.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
message: The message containing the tool call and source agent
|
|
210
|
+
transition_target: The target to transition to
|
|
211
|
+
"""
|
|
212
|
+
if self.is_handoff_function(message):
|
|
213
|
+
source_agent = self.get_sender_agent_for_message(message)
|
|
214
|
+
if source_agent:
|
|
215
|
+
iostream = IOStream.get_default()
|
|
216
|
+
iostream.send(
|
|
217
|
+
OnConditionLLMTransitionEvent(
|
|
218
|
+
source_agent=source_agent,
|
|
219
|
+
transition_target=transition_target,
|
|
220
|
+
)
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
def _send_reply_result_handoff_event(self, message: dict[str, Any], transition_target: TransitionTarget) -> None:
|
|
224
|
+
"""Send a ReplyResult handoff event.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
message: The message containing the tool call and source agent
|
|
228
|
+
transition_target: The target to transition to
|
|
229
|
+
"""
|
|
230
|
+
source_agent = self.get_sender_agent_for_message(message)
|
|
231
|
+
if source_agent:
|
|
232
|
+
iostream = IOStream.get_default()
|
|
233
|
+
iostream.send(
|
|
234
|
+
ReplyResultTransitionEvent(
|
|
235
|
+
source_agent=source_agent,
|
|
236
|
+
transition_target=transition_target,
|
|
237
|
+
)
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def _generate_group_tool_reply(
|
|
241
|
+
self,
|
|
242
|
+
agent: ConversableAgent,
|
|
243
|
+
messages: list[dict[str, Any]] | None = None,
|
|
244
|
+
sender: Agent | None = None,
|
|
245
|
+
config: OpenAIWrapper | None = None,
|
|
246
|
+
) -> tuple[bool, dict[str, Any] | None]:
|
|
247
|
+
"""Pre-processes and generates tool call replies.
|
|
248
|
+
|
|
249
|
+
This function:
|
|
250
|
+
1. Adds context_variables back to the tool call for the function, if necessary.
|
|
251
|
+
2. Generates the tool calls reply.
|
|
252
|
+
3. Updates context_variables and next_agent based on the tool call response.
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
if config is None:
|
|
256
|
+
config = agent # type: ignore[assignment]
|
|
257
|
+
if messages is None:
|
|
258
|
+
messages = agent._oai_messages[sender]
|
|
259
|
+
|
|
260
|
+
message = messages[-1]
|
|
261
|
+
# Track the original agent that initiated this tool call (for safeguard transparency)
|
|
262
|
+
# Use sender.name as fallback when message doesn't have a name field (e.g., for tool_calls messages)
|
|
263
|
+
agent_name = message.get("name", sender.name if sender else "unknown")
|
|
264
|
+
self.set_tool_call_originator(agent_name)
|
|
265
|
+
|
|
266
|
+
if message.get("tool_calls"):
|
|
267
|
+
tool_call_count = len(message["tool_calls"])
|
|
268
|
+
|
|
269
|
+
tool_message = None
|
|
270
|
+
# Loop through tool calls individually (so context can be updated after each function call)
|
|
271
|
+
next_target: TransitionTarget | None = None
|
|
272
|
+
tool_responses_inner = []
|
|
273
|
+
contents = []
|
|
274
|
+
for index in range(tool_call_count):
|
|
275
|
+
message_copy = deepcopy(message)
|
|
276
|
+
|
|
277
|
+
# 1. add context_variables to the tool call arguments
|
|
278
|
+
tool_call = message_copy["tool_calls"][index]
|
|
279
|
+
|
|
280
|
+
# Ensure we are only executing the one tool at a time
|
|
281
|
+
message_copy["tool_calls"] = [tool_call]
|
|
282
|
+
|
|
283
|
+
# 2. generate tool calls reply
|
|
284
|
+
_, tool_message = agent.generate_tool_calls_reply([message_copy])
|
|
285
|
+
|
|
286
|
+
if tool_message is None:
|
|
287
|
+
raise ValueError("Tool call did not return a message")
|
|
288
|
+
|
|
289
|
+
# 3. update context_variables and next_agent, convert content to string
|
|
290
|
+
for tool_response in tool_message["tool_responses"]:
|
|
291
|
+
content = tool_response.get("content")
|
|
292
|
+
|
|
293
|
+
# Tool Call returns that are a target are either a ReplyResult or a TransitionTarget
|
|
294
|
+
if isinstance(content, ReplyResult):
|
|
295
|
+
if content.context_variables and content.context_variables.to_dict() != {}:
|
|
296
|
+
agent.context_variables.update(content.context_variables.to_dict())
|
|
297
|
+
if content.target is not None:
|
|
298
|
+
self._send_reply_result_handoff_event(message_copy, content.target)
|
|
299
|
+
next_target = content.target
|
|
300
|
+
elif isinstance(content, TransitionTarget):
|
|
301
|
+
self._send_llm_handoff_event(message_copy, content)
|
|
302
|
+
next_target = content
|
|
303
|
+
|
|
304
|
+
# Serialize the content to a string
|
|
305
|
+
normalized_content = (
|
|
306
|
+
content_str(content) if isinstance(content, (str, list)) or content is None else str(content)
|
|
307
|
+
)
|
|
308
|
+
tool_response["content"] = normalized_content
|
|
309
|
+
|
|
310
|
+
tool_responses_inner.append(tool_response)
|
|
311
|
+
contents.append(normalized_content)
|
|
312
|
+
|
|
313
|
+
self._group_next_target = next_target # type: ignore[attr-defined]
|
|
314
|
+
|
|
315
|
+
# Put the tool responses and content strings back into the response message
|
|
316
|
+
# Caters for multiple tool calls
|
|
317
|
+
if tool_message is None:
|
|
318
|
+
raise ValueError("Tool call did not return a message")
|
|
319
|
+
|
|
320
|
+
tool_message["tool_responses"] = tool_responses_inner
|
|
321
|
+
tool_message["content"] = "\n".join(contents)
|
|
322
|
+
|
|
323
|
+
return True, tool_message
|
|
324
|
+
return False, None
|