import pytest from crewai import Agent, Crew, Task from crewai_arcade.structured import StructuredTool from pydantic import BaseModel class CalculatorInput(BaseModel): x: float y: float def add_numbers(x: float, y: float) -> float: """Add two numbers together.""" return x + y def unnamed_function(x: float, y: float) -> float: return x + y def test_structured_tool_basic(): # Test basic functionality with explicit name and description calculator_tool = StructuredTool.from_function( func=add_numbers, args_schema=CalculatorInput, name="Calculator", description="A tool that adds two numbers together", ) expected_description = ( "Tool Name: Calculator\n" "Tool Arguments: {'x': {'description': None, 'type': 'float'}, 'y': {'description': None, 'type': 'float'}}\n" "Tool Description: A tool that adds two numbers together" ) assert calculator_tool.description == expected_description assert calculator_tool.func(2, 3) == 5 def test_structured_tool_auto_name_description(): # Test automatic name and description generation from function calculator_tool = StructuredTool.from_function(func=add_numbers, args_schema=CalculatorInput) expected_description = ( "Tool Name: add_numbers\n" "Tool Arguments: {'x': {'description': None, 'type': 'float'}, 'y': {'description': None, 'type': 'float'}}\n" "Tool Description: Add two numbers together." ) assert calculator_tool.description == expected_description def test_structured_tool_validation_errors(): # Test missing docstring with pytest.raises( ValueError, match="Function must have a docstring if description not provided." ): StructuredTool.from_function(func=unnamed_function, args_schema=CalculatorInput) def test_structured_tool_in_crew(): calculator_tool = StructuredTool.from_function( func=add_numbers, args_schema=CalculatorInput, ) calculator_agent = Agent( role="Math Expert", goal="Perform mathematical calculations accurately", backstory="An expert mathematician who specializes in calculations", tools=[calculator_tool], verbose=True, cache=False, ) addition_task = Task( description="Add the numbers 5 and 3 together", expected_output="The sum of 5 and 3 is 8", agent=calculator_agent, ) crew = Crew( agents=[calculator_agent], tasks=[addition_task], ) # Assert crew structure assert len(crew.agents) == 1 assert len(crew.tasks) == 1 assert crew.agents[0] == calculator_agent assert crew.tasks[0] == addition_task assert crew.tasks[0].agent == calculator_agent assert len(crew.agents[0].tools) == 1 assert isinstance(crew.agents[0].tools[0], StructuredTool)