A tool that wraps a user-defined Python function. Attributes: func: The function to wrap.
| 40 | |
| 41 | |
| 42 | class FunctionTool(BaseTool): |
| 43 | """A tool that wraps a user-defined Python function. |
| 44 | |
| 45 | Attributes: |
| 46 | func: The function to wrap. |
| 47 | """ |
| 48 | |
| 49 | def __init__( |
| 50 | self, |
| 51 | func: Callable[..., Any], |
| 52 | *, |
| 53 | require_confirmation: Union[bool, Callable[..., bool]] = False, |
| 54 | ): |
| 55 | """Initializes the FunctionTool. Extracts metadata from a callable object. |
| 56 | |
| 57 | Args: |
| 58 | func: The function to wrap. |
| 59 | require_confirmation: Whether this tool requires confirmation. A boolean or |
| 60 | a callable that takes the function's arguments and returns a boolean. If |
| 61 | the callable returns True, the tool will require confirmation from the |
| 62 | user. |
| 63 | """ |
| 64 | name = '' |
| 65 | doc = '' |
| 66 | # Handle different types of callables |
| 67 | if hasattr(func, '__name__'): |
| 68 | # Regular functions, unbound methods, etc. |
| 69 | name = func.__name__ |
| 70 | elif hasattr(func, '__class__'): |
| 71 | # Callable objects, bound methods, etc. |
| 72 | name = func.__class__.__name__ |
| 73 | |
| 74 | # Get documentation (prioritize direct __doc__ if available) |
| 75 | if hasattr(func, '__doc__') and func.__doc__: |
| 76 | doc = inspect.cleandoc(func.__doc__) |
| 77 | elif ( |
| 78 | hasattr(func, '__call__') |
| 79 | and hasattr(func.__call__, '__doc__') |
| 80 | and func.__call__.__doc__ |
| 81 | ): |
| 82 | # For callable objects, try to get docstring from __call__ method |
| 83 | doc = inspect.cleandoc(func.__call__.__doc__) |
| 84 | |
| 85 | super().__init__(name=name, description=doc) |
| 86 | self.func = func |
| 87 | # Detect context parameter by type annotation, fallback to 'tool_context' name |
| 88 | self._context_param_name = find_context_parameter(func) or 'tool_context' |
| 89 | self._ignore_params = [self._context_param_name, 'input_stream'] |
| 90 | self._require_confirmation = require_confirmation |
| 91 | |
| 92 | @override |
| 93 | def _get_declaration(self) -> Optional[types.FunctionDeclaration]: |
| 94 | function_decl = types.FunctionDeclaration.model_validate( |
| 95 | build_function_declaration( |
| 96 | func=self.func, |
| 97 | # The model doesn't understand the function context. |
| 98 | # input_stream is for streaming tool |
| 99 | ignore_params=self._ignore_params, |
no outgoing calls