From 95af240974e353c861520c4f4beb6afa1f1f7caf Mon Sep 17 00:00:00 2001 From: lorenzejay Date: Wed, 16 Apr 2025 12:25:17 -0700 Subject: [PATCH] feat: Enhance tool adapters to support asynchronous execution - Updated LangGraphToolAdapter and OpenAIAgentToolAdapter to handle asynchronous tool execution by checking if the output is awaitable. - Introduced `inspect` import to facilitate the awaitability check. - Refactored tool wrapper functions to ensure proper handling of both synchronous and asynchronous tool results. --- .../langgraph/langgraph_tool_adapter.py | 27 ++++++++++++------- .../openai_agent_tool_adapter.py | 9 ++++++- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/crewai/agents/agent_adapters/langgraph/langgraph_tool_adapter.py b/src/crewai/agents/agent_adapters/langgraph/langgraph_tool_adapter.py index 02a229c51..e1bdd42e8 100644 --- a/src/crewai/agents/agent_adapters/langgraph/langgraph_tool_adapter.py +++ b/src/crewai/agents/agent_adapters/langgraph/langgraph_tool_adapter.py @@ -1,3 +1,5 @@ +import inspect +import asyncio from typing import Any, List, Optional from crewai.agents.agent_adapters.base_tool_adapter import BaseToolAdapter @@ -28,18 +30,25 @@ class LangGraphToolAdapter(BaseToolAdapter): converted_tools.append(tool) continue - def tool_wrapper(*args, tool=tool, **kwargs): - if len(args) > 0 and isinstance(args[0], str): - return tool.run(args[0]) - elif "input" in kwargs: - return tool.run(kwargs["input"]) - else: - return tool.run(**kwargs) + sanitized_name = self.sanitize_tool_name(tool.name) - sanitized_tool_name = self.sanitize_tool_name(tool.name) + async def tool_wrapper(*args, tool=tool, **kwargs): + output = None + if len(args) > 0 and isinstance(args[0], str): + output = tool.run(args[0]) + elif "input" in kwargs: + output = tool.run(kwargs["input"]) + else: + output = tool.run(**kwargs) + + if inspect.isawaitable(output): + result = await output + else: + result = output + return result converted_tool = StructuredTool( - name=sanitized_tool_name, + name=sanitized_name, description=tool.description, func=tool_wrapper, args_schema=tool.args_schema, diff --git a/src/crewai/agents/agent_adapters/openai_agents/openai_agent_tool_adapter.py b/src/crewai/agents/agent_adapters/openai_agents/openai_agent_tool_adapter.py index 0c7a56c6b..92eeb7b00 100644 --- a/src/crewai/agents/agent_adapters/openai_agents/openai_agent_tool_adapter.py +++ b/src/crewai/agents/agent_adapters/openai_agents/openai_agent_tool_adapter.py @@ -1,3 +1,4 @@ +import inspect from typing import Any, List, Optional from agents import FunctionTool, Tool @@ -58,7 +59,13 @@ class OpenAIAgentToolAdapter(BaseToolAdapter): args_dict = {param_name: str(arguments)} # Run the tool with the processed arguments - result = tool._run(**args_dict) + output = tool._run(**args_dict) + + # Await if the tool returned a coroutine + if inspect.isawaitable(output): + result = await output + else: + result = output # Ensure the result is JSON serializable if isinstance(result, (dict, list, str, int, float, bool, type(None))):