diff --git a/src/crewai/tools/structured_tool.py b/src/crewai/tools/structured_tool.py index d4d4b03f9..bd6818605 100644 --- a/src/crewai/tools/structured_tool.py +++ b/src/crewai/tools/structured_tool.py @@ -152,7 +152,10 @@ class CrewStructuredTool: continue # Skip **kwargs parameters - if param.kind == inspect.Parameter.VAR_KEYWORD: + if param.kind in ( + inspect.Parameter.VAR_KEYWORD, + inspect.Parameter.VAR_POSITIONAL, + ): continue # Only validate required parameters without defaults @@ -214,22 +217,17 @@ class CrewStructuredTool: None, lambda: self.func(**parsed_args, **kwargs) ) + def _run(self, *args, **kwargs) -> Any: + """Legacy method for compatibility.""" + # Convert args/kwargs to our expected format + input_dict = dict(zip(self.args_schema.model_fields.keys(), args)) + input_dict.update(kwargs) + return self.invoke(input_dict) + def invoke( - self, - input: Union[str, dict], - config: Optional[dict] = None, - **kwargs: Any, + self, input: Union[str, dict], config: Optional[dict] = None, **kwargs: Any ) -> Any: - """Synchronously invoke the tool. - - Args: - input: The input arguments - config: Optional configuration - **kwargs: Additional keyword arguments - - Returns: - The result of the tool execution - """ + """Main method for tool execution.""" parsed_args = self._parse_args(input) return self.func(**parsed_args, **kwargs) diff --git a/tests/tools/test_base_tool.py b/tests/tools/test_base_tool.py index eca36739c..cd4b53caf 100644 --- a/tests/tools/test_base_tool.py +++ b/tests/tools/test_base_tool.py @@ -1,4 +1,5 @@ from typing import Callable + from crewai.tools import BaseTool, tool @@ -21,8 +22,7 @@ def test_creating_a_tool_using_annotation(): my_tool.func("What is the meaning of life?") == "What is the meaning of life?" ) - # Assert the langchain tool conversion worked as expected - converted_tool = my_tool.to_langchain() + converted_tool = my_tool.to_structured_tool() assert converted_tool.name == "Name of my tool" assert ( @@ -41,9 +41,7 @@ def test_creating_a_tool_using_annotation(): def test_creating_a_tool_using_baseclass(): class MyCustomTool(BaseTool): name: str = "Name of my tool" - description: str = ( - "Clear description for what this tool is useful for, you agent will need this information to use it." - ) + description: str = "Clear description for what this tool is useful for, you agent will need this information to use it." def _run(self, question: str) -> str: return question @@ -61,8 +59,7 @@ def test_creating_a_tool_using_baseclass(): } assert my_tool.run("What is the meaning of life?") == "What is the meaning of life?" - # Assert the langchain tool conversion worked as expected - converted_tool = my_tool.to_langchain() + converted_tool = my_tool.to_structured_tool() assert converted_tool.name == "Name of my tool" assert ( @@ -73,7 +70,7 @@ def test_creating_a_tool_using_baseclass(): "question": {"title": "Question", "type": "string"} } assert ( - converted_tool.run("What is the meaning of life?") + converted_tool._run("What is the meaning of life?") == "What is the meaning of life?" ) @@ -81,9 +78,7 @@ def test_creating_a_tool_using_baseclass(): def test_setting_cache_function(): class MyCustomTool(BaseTool): name: str = "Name of my tool" - description: str = ( - "Clear description for what this tool is useful for, you agent will need this information to use it." - ) + description: str = "Clear description for what this tool is useful for, you agent will need this information to use it." cache_function: Callable = lambda: False def _run(self, question: str) -> str: @@ -97,9 +92,7 @@ def test_setting_cache_function(): def test_default_cache_function_is_true(): class MyCustomTool(BaseTool): name: str = "Name of my tool" - description: str = ( - "Clear description for what this tool is useful for, you agent will need this information to use it." - ) + description: str = "Clear description for what this tool is useful for, you agent will need this information to use it." def _run(self, question: str) -> str: return question