mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-14 18:48:29 +00:00
fix: address PR feedback with improved validation, documentation, and tests
Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from typing import Any, List, Optional, Dict, Callable, Union
|
||||
from typing import Any, List, Optional, Dict, Callable, Union, ClassVar
|
||||
|
||||
from pydantic import Field, model_validator
|
||||
from pydantic import Field, model_validator, field_validator, ConfigDict
|
||||
|
||||
from crewai.tools.base_tool import BaseTool
|
||||
from crewai.tools.structured_tool import CrewStructuredTool
|
||||
@@ -19,25 +19,90 @@ class ToolWithInstruction(BaseTool):
|
||||
description: Description of the tool (inherited from the wrapped tool with instructions)
|
||||
"""
|
||||
|
||||
MAX_INSTRUCTION_LENGTH: ClassVar[int] = 2000
|
||||
|
||||
name: str = Field(default="", description="Name of the tool")
|
||||
description: str = Field(default="", description="Description of the tool")
|
||||
tool: BaseTool = Field(description="The tool to wrap")
|
||||
instructions: str = Field(description="Instructions about when and how to use this tool")
|
||||
|
||||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||||
|
||||
@field_validator("instructions")
|
||||
@classmethod
|
||||
def validate_instructions(cls, value: str) -> str:
|
||||
"""Validate that instructions are not empty and not too long.
|
||||
|
||||
Args:
|
||||
value: The instructions string to validate
|
||||
|
||||
Returns:
|
||||
str: The validated and sanitized instructions
|
||||
|
||||
Raises:
|
||||
ValueError: If instructions are empty or exceed maximum length
|
||||
"""
|
||||
if not value or not value.strip():
|
||||
raise ValueError("Instructions cannot be empty")
|
||||
|
||||
if len(value) > cls.MAX_INSTRUCTION_LENGTH:
|
||||
raise ValueError(
|
||||
f"Instructions exceed maximum length of {cls.MAX_INSTRUCTION_LENGTH} characters"
|
||||
)
|
||||
|
||||
return value.strip()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def set_tool_attributes(self) -> "ToolWithInstruction":
|
||||
"""Set attributes from the wrapped tool."""
|
||||
"""Sets name, description, and args_schema from the wrapped tool.
|
||||
|
||||
Returns:
|
||||
ToolWithInstruction: The validated instance with updated attributes.
|
||||
"""
|
||||
self.name = self.tool.name
|
||||
self.description = f"{self.tool.description}\nInstructions: {self.instructions}"
|
||||
self.args_schema = self.tool.args_schema
|
||||
return self
|
||||
|
||||
def update_instructions(self, new_instructions: str) -> None:
|
||||
"""Updates the tool's usage instructions.
|
||||
|
||||
Args:
|
||||
new_instructions (str): New instructions for tool usage.
|
||||
|
||||
Raises:
|
||||
ValueError: If new instructions are empty or exceed maximum length
|
||||
"""
|
||||
if not new_instructions or not new_instructions.strip():
|
||||
raise ValueError("Instructions cannot be empty")
|
||||
|
||||
if len(new_instructions) > self.MAX_INSTRUCTION_LENGTH:
|
||||
raise ValueError(
|
||||
f"Instructions exceed maximum length of {self.MAX_INSTRUCTION_LENGTH} characters"
|
||||
)
|
||||
|
||||
self.instructions = new_instructions.strip()
|
||||
|
||||
self.description = f"{self.tool.description}\nInstructions: {self.instructions}"
|
||||
|
||||
def _run(self, *args: Any, **kwargs: Any) -> Any:
|
||||
"""Run the wrapped tool."""
|
||||
"""Run the wrapped tool.
|
||||
|
||||
Args:
|
||||
*args: Positional arguments to pass to the wrapped tool
|
||||
**kwargs: Keyword arguments to pass to the wrapped tool
|
||||
|
||||
Returns:
|
||||
Any: The result from the wrapped tool's _run method
|
||||
"""
|
||||
return self.tool._run(*args, **kwargs)
|
||||
|
||||
def to_structured_tool(self) -> CrewStructuredTool:
|
||||
"""Convert this tool to a CrewStructuredTool instance."""
|
||||
"""Convert this tool to a CrewStructuredTool instance.
|
||||
|
||||
Returns:
|
||||
CrewStructuredTool: A structured tool with instructions included in the description
|
||||
"""
|
||||
structured_tool = self.tool.to_structured_tool()
|
||||
|
||||
structured_tool.description = f"{structured_tool.description}\nInstructions: {self.instructions}"
|
||||
|
||||
Reference in New Issue
Block a user