{"record":{"id":"8f65024ccfaf85d2","repo":"huggingface/smolagents","slug":"in-tool-self-name-forward-method-parameters","errorCode":null,"errorMessage":"In tool '{self.name}', 'forward' method parameters were {actual_keys}, but expected {expected_keys}. It should take 'self' as its first argument, then its next arguments should match the keys of tool attribute 'inputs'.","messagePattern":"In tool '(.+?)', 'forward' method parameters were (.+?), but expected (.+?)\\. It should take 'self' as its first argument, then its next arguments should match the keys of tool attribute 'inputs'\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/smolagents/tools.py","lineNumber":207,"sourceCode":"                    f\"Input '{input_name}': type must be a string or list of strings, got {type(input_content['type']).__name__}\"\n                )\n            # Check all types are authorized\n            invalid_types = [t for t in input_types if t not in AUTHORIZED_TYPES]\n            if invalid_types:\n                raise ValueError(f\"Input '{input_name}': types {invalid_types} must be one of {AUTHORIZED_TYPES}\")\n        # Validate output type\n        assert getattr(self, \"output_type\", None) in AUTHORIZED_TYPES\n\n        # Validate forward function signature, except for Tools that use a \"generic\" signature (PipelineTool, SpaceToolWrapper, LangChainToolWrapper)\n        if not (\n            hasattr(self, \"skip_forward_signature_validation\")\n            and getattr(self, \"skip_forward_signature_validation\") is True\n        ):\n            signature = inspect.signature(self.forward)\n            actual_keys = set(key for key in signature.parameters.keys() if key != \"self\")\n            expected_keys = set(self.inputs.keys())\n            if actual_keys != expected_keys:\n                raise Exception(\n                    f\"In tool '{self.name}', 'forward' method parameters were {actual_keys}, but expected {expected_keys}. \"\n                    f\"It should take 'self' as its first argument, then its next arguments should match the keys of tool attribute 'inputs'.\"\n                )\n\n            json_schema = _convert_type_hints_to_json_schema(self.forward, error_on_missing_type_hints=False)[\n                \"properties\"\n            ]  # This function will not raise an error on missing docstrings, contrary to get_json_schema\n            for key, value in self.inputs.items():\n                assert key in json_schema, (\n                    f\"Input '{key}' should be present in function signature, found only {json_schema.keys()}\"\n                )\n                if \"nullable\" in value:\n                    assert \"nullable\" in json_schema[key], (\n                        f\"Nullable argument '{key}' in inputs should have key 'nullable' set to True in function signature.\"\n                    )\n                if key in json_schema and \"nullable\" in json_schema[key]:\n                    assert \"nullable\" in value, (\n                        f\"Nullable argument '{key}' in function signature should have key 'nullable' set to True in inputs.\"","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/tools.py#L189-L225","documentation":"Tool.forward's parameter names (after self) must exactly match the keys of the tool's inputs dict, because smolagents forwards arguments to forward by keyword. A mismatch raises an exception listing actual vs expected keys.","triggerScenarios":"Defining forward(self, text, temperature) while self.inputs keys are {\"text\", \"temp\"}, or renaming an inputs key without updating forward, or adding an extra parameter not declared in inputs (no **kwargs allowed).","commonSituations":"Refactoring tool code and renaming arguments in one place only; copy-pasting a Tool subclass and editing inputs but not forward; adding a new input entry but forgetting the function parameter.","solutions":["Make forward's parameters exactly the keys of self.inputs, in any order but with identical names","If the tool uses a generic signature (PipelineTool, SpaceToolWrapper, LangChainToolWrapper), set skip_forward_signature_validation = True","Add the missing key to self.inputs or the missing parameter to forward"],"exampleFix":"# before\nclass MyTool(Tool):\n    inputs = {\"query\": {\"type\": \"string\", \"description\": \"...\"}}\n    def forward(self, text): ...\n# after\nclass MyTool(Tool):\n    inputs = {\"query\": {\"type\": \"string\", \"description\": \"...\"}}\n    def forward(self, query): ...","handlingStrategy":"validation","validationCode":"import inspect\ndef signature_matches(tool):\n    params = {k for k in inspect.signature(tool.forward).parameters if k != \"self\"}\n    return params == set(tool.inputs.keys())\n\nassert signature_matches(MyTool())","typeGuard":"import inspect\ndef tool_signature_valid(tool) -> bool:\n    params = {k for k in inspect.signature(tool.forward).parameters if k not in (\"self\", \"args\", \"kwargs\")}\n    return params == set(tool.inputs.keys())","tryCatchPattern":null,"preventionTips":["Write inputs and forward together, deriving one from the other","Add a smoke test that instantiates every Tool subclass (validation runs in __init__)","Rename inputs keys and forward params in the same commit"],"tags":["smolagents","tool","forward","signature-mismatch"],"backgroundTag":"function-signature-mismatch","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}