huggingface/smolagents · error · NotImplementedError
Write this method in your subclass of `Tool`.
Error message
Write this method in your subclass of `Tool`.
What it means
The base Tool.forward is abstract and raises NotImplementedError; every usable tool must override it. __call__ delegates to forward, so calling an un-subclassed or partially implemented Tool fails here.
Source
Thrown at src/smolagents/tools.py:229
json_schema = _convert_type_hints_to_json_schema(self.forward, error_on_missing_type_hints=False)[
"properties"
] # This function will not raise an error on missing docstrings, contrary to get_json_schema
for key, value in self.inputs.items():
assert key in json_schema, (
f"Input '{key}' should be present in function signature, found only {json_schema.keys()}"
)
if "nullable" in value:
assert "nullable" in json_schema[key], (
f"Nullable argument '{key}' in inputs should have key 'nullable' set to True in function signature."
)
if key in json_schema and "nullable" in json_schema[key]:
assert "nullable" in value, (
f"Nullable argument '{key}' in function signature should have key 'nullable' set to True in inputs."
)
def forward(self, *args, **kwargs):
raise NotImplementedError("Write this method in your subclass of `Tool`.")
def __call__(self, *args, sanitize_inputs_outputs: bool = False, **kwargs):
if not self.is_initialized:
self.setup()
# Handle the arguments might be passed as a single dictionary
if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], dict):
potential_kwargs = args[0]
# If the dictionary keys match our input parameters, convert it to kwargs
if all(key in self.inputs for key in potential_kwargs):
args = ()
kwargs = potential_kwargs
if sanitize_inputs_outputs:
args, kwargs = handle_agent_input_types(*args, **kwargs)
outputs = self.forward(*args, **kwargs)
if sanitize_inputs_outputs:View on GitHub (pinned to 30bb116109)
Solutions
- Implement def forward(self, ...) in your Tool subclass with parameters matching self.inputs
- Subclass a more specific base (PipelineTool) which splits work into setup/forward_inputs/forward_output, or use the @tool decorator
- Check for typos in the method name (it must be exactly 'forward')
Example fix
# before
class MyTool(Tool):
def run(self, query): return query
# after
class MyTool(Tool):
def forward(self, query: str) -> str: return query Defensive patterns
Strategy: type-guard
Validate before calling
import inspect
def forward_implemented(cls) -> bool:
return cls.forward is not Tool.forward Type guard
def is_callable_tool(tool) -> bool:
return type(tool).forward is not Tool.forward Try / catch
try:
result = tool("input")
except NotImplementedError:
logger.error("%s is incomplete: implement forward()", type(tool).__name__) Prevention
- Always implement forward in Tool subclasses; the method name must be exactly 'forward'
- Consider the @tool decorator for simple function tools so no abstract method remains
- Run a tiny call in unit tests to catch unimplemented tools early
When it happens
Trigger: Instantiating Tool directly and calling it; subclassing Tool but naming the method 'run', '_forward', or misspelling 'forward'; forgetting to implement forward in a custom tool class.
Common situations: Following a tutorial and skipping the forward implementation; renaming methods during refactor; creating a Tool subclass skeleton to test setup() only.
Related errors
- This method should be implemented in child classes
- Binary operation {type(binop.op).__name__} is not implemente
- You must set an attribute {attr}.
- Attribute {attr} should have type {expected_type.__name__},
- Attribute output_schema should have type dict, got {type(out
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/a7db978aa65f37fb.
Report an issue: GitHub.