mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-10 00:28:31 +00:00
fix: allow CrewStructuredTool to be used with Task's tools parameter
Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
@@ -40,6 +40,7 @@ from crewai.tasks.guardrail_result import GuardrailResult
|
|||||||
from crewai.tasks.output_format import OutputFormat
|
from crewai.tasks.output_format import OutputFormat
|
||||||
from crewai.tasks.task_output import TaskOutput
|
from crewai.tasks.task_output import TaskOutput
|
||||||
from crewai.tools.base_tool import BaseTool
|
from crewai.tools.base_tool import BaseTool
|
||||||
|
from crewai.tools.structured_tool import CrewStructuredTool
|
||||||
from crewai.utilities.config import process_config
|
from crewai.utilities.config import process_config
|
||||||
from crewai.utilities.converter import Converter, convert_to_model
|
from crewai.utilities.converter import Converter, convert_to_model
|
||||||
from crewai.utilities.events import (
|
from crewai.utilities.events import (
|
||||||
@@ -73,6 +74,10 @@ class Task(BaseModel):
|
|||||||
tools: List of tools/resources limited for task execution.
|
tools: List of tools/resources limited for task execution.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
model_config = {
|
||||||
|
"arbitrary_types_allowed": True,
|
||||||
|
}
|
||||||
|
|
||||||
__hash__ = object.__hash__ # type: ignore
|
__hash__ = object.__hash__ # type: ignore
|
||||||
logger: ClassVar[logging.Logger] = logging.getLogger(__name__)
|
logger: ClassVar[logging.Logger] = logging.getLogger(__name__)
|
||||||
used_tools: int = 0
|
used_tools: int = 0
|
||||||
@@ -118,7 +123,7 @@ class Task(BaseModel):
|
|||||||
output: Optional[TaskOutput] = Field(
|
output: Optional[TaskOutput] = Field(
|
||||||
description="Task output, it's final result after being executed", default=None
|
description="Task output, it's final result after being executed", default=None
|
||||||
)
|
)
|
||||||
tools: Optional[List[BaseTool]] = Field(
|
tools: Optional[List[Union[BaseTool, CrewStructuredTool]]] = Field(
|
||||||
default_factory=list,
|
default_factory=list,
|
||||||
description="Tools the agent is limited to use for this task.",
|
description="Tools the agent is limited to use for this task.",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,15 +21,17 @@ from crewai.utilities.exceptions.context_window_exceeding_exception import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_tools(tools: List[BaseTool]) -> List[CrewStructuredTool]:
|
def parse_tools(tools: List[Union[BaseTool, CrewStructuredTool]]) -> List[CrewStructuredTool]:
|
||||||
"""Parse tools to be used for the task."""
|
"""Parse tools to be used for the task."""
|
||||||
tools_list = []
|
tools_list = []
|
||||||
|
|
||||||
for tool in tools:
|
for tool in tools:
|
||||||
if isinstance(tool, CrewAITool):
|
if isinstance(tool, CrewAITool):
|
||||||
tools_list.append(tool.to_structured_tool())
|
tools_list.append(tool.to_structured_tool())
|
||||||
|
elif isinstance(tool, CrewStructuredTool):
|
||||||
|
tools_list.append(tool)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Tool is not a CrewStructuredTool or BaseTool")
|
raise ValueError("Tool must be an instance of BaseTool or CrewStructuredTool")
|
||||||
|
|
||||||
return tools_list
|
return tools_list
|
||||||
|
|
||||||
|
|||||||
62
tests/tools/test_task_with_structured_tool.py
Normal file
62
tests/tools/test_task_with_structured_tool.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import pytest
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from crewai.task import Task
|
||||||
|
from crewai.tools.structured_tool import CrewStructuredTool
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def simple_tool_function():
|
||||||
|
def test_func(param1: str, param2: int = 0) -> str:
|
||||||
|
"""Test function with basic params."""
|
||||||
|
return f"{param1} {param2}"
|
||||||
|
|
||||||
|
return test_func
|
||||||
|
|
||||||
|
|
||||||
|
def test_task_with_structured_tool(simple_tool_function):
|
||||||
|
"""Test that CrewStructuredTool can be used directly with Task."""
|
||||||
|
tool = CrewStructuredTool.from_function(
|
||||||
|
func=simple_tool_function,
|
||||||
|
name="test_tool",
|
||||||
|
description="Test tool description"
|
||||||
|
)
|
||||||
|
|
||||||
|
task = Task(
|
||||||
|
description="Test task description",
|
||||||
|
expected_output="Expected output",
|
||||||
|
tools=[tool]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(task.tools) == 1
|
||||||
|
assert task.tools[0] == tool
|
||||||
|
|
||||||
|
|
||||||
|
def test_mixed_tool_types(simple_tool_function):
|
||||||
|
"""Test that both BaseTool and CrewStructuredTool can be used together with Task."""
|
||||||
|
from crewai.tools import BaseTool
|
||||||
|
|
||||||
|
structured_tool = CrewStructuredTool.from_function(
|
||||||
|
func=simple_tool_function,
|
||||||
|
name="structured_tool",
|
||||||
|
description="Structured tool description"
|
||||||
|
)
|
||||||
|
|
||||||
|
class TestBaseTool(BaseTool):
|
||||||
|
name: str = "base_tool"
|
||||||
|
description: str = "Base tool description"
|
||||||
|
|
||||||
|
def _run(self, query: str) -> str:
|
||||||
|
return f"Result for {query}"
|
||||||
|
|
||||||
|
base_tool = TestBaseTool()
|
||||||
|
|
||||||
|
task = Task(
|
||||||
|
description="Test task description",
|
||||||
|
expected_output="Expected output",
|
||||||
|
tools=[structured_tool, base_tool]
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(task.tools) == 2
|
||||||
|
assert task.tools[0] == structured_tool
|
||||||
|
assert isinstance(task.tools[1], BaseTool)
|
||||||
Reference in New Issue
Block a user