{"record":{"id":"08dd9ff4a5b8e928","repo":"huggingface/smolagents","slug":"no-tool-subclass-found-in-the-code","errorCode":null,"errorMessage":"No Tool subclass found in the code.","messagePattern":"No Tool subclass found in the code\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/smolagents/tools.py","lineNumber":588,"sourceCode":"\n    @classmethod\n    def from_code(cls, tool_code: str, **kwargs):\n        module = types.ModuleType(\"dynamic_tool\")\n\n        exec(tool_code, module.__dict__)\n\n        # Find the Tool subclass\n        tool_class = next(\n            (\n                obj\n                for _, obj in inspect.getmembers(module, inspect.isclass)\n                if issubclass(obj, Tool) and obj is not Tool\n            ),\n            None,\n        )\n\n        if tool_class is None:\n            raise ValueError(\"No Tool subclass found in the code.\")\n\n        if not isinstance(tool_class.inputs, dict):\n            tool_class.inputs = ast.literal_eval(tool_class.inputs)\n\n        # Handle output_schema if it exists and is a string representation\n        if hasattr(tool_class, \"output_schema\") and isinstance(tool_class.output_schema, str):\n            tool_class.output_schema = ast.literal_eval(tool_class.output_schema)\n\n        return tool_class(**kwargs)\n\n    @staticmethod\n    def from_space(\n        space_id: str,\n        name: str,\n        description: str = \"\",\n        api_name: str | None = None,\n        token: str | None = None,\n    ):","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/huggingface/smolagents/blob/30bb1161095dbae2271e6bc3cc4c219cc3897a57/src/smolagents/tools.py#L570-L606","documentation":"Tool.from_code execs the provided source and scans the resulting namespace for exactly one class subclassing Tool. If none is found, it raises ValueError. This happens when the code defines a function (e.g. via @tool) instead of a class, or defines nothing Tool-like.","triggerScenarios":"Calling Tool.from_code with source that only contains a @tool-decorated function, an plain function, or unrelated code with no Tool subclass.","commonSituations":"Feeding code produced by the @tool decorator into from_code (the decorator path yields a Tool instance/class differently); hand-writing a tool.py for the Hub without subclassing Tool; truncated or wrong file passed as the code string.","solutions":["Ensure the source defines a class inheriting from smolagents.Tool (class MyTool(Tool): ...) with name, description, inputs, output_type, and forward","For @tool-decorated function tools, re-create them with the decorator or use the appropriate loading path rather than from_code","Verify the code string isn't truncated or empty before passing it"],"exampleFix":"# before\ncode = '''\nfrom smolagents import tool\n@tool\ndef greet(name: str) -> str:\n    \"\"\"Greets.\"\"\"\n    return f\"hi {name}\"\n'''\nTool.from_code(code)\n# after\ncode = '''\nfrom smolagents import Tool\nclass GreetTool(Tool):\n    name = \"greet\"\n    description = \"Greets someone.\"\n    inputs = {\"name\": {\"type\": \"string\", \"description\": \"Who\"}}\n    output_type = \"string\"\n    def forward(self, name): return f\"hi {name}\"\n'''\nTool.from_code(code)","handlingStrategy":"validation","validationCode":"import ast\ndef code_defines_tool_subclass(code: str) -> bool:\n    for node in ast.walk(ast.parse(code)):\n        if isinstance(node, ast.ClassDef):\n            for base in node.bases:\n                if getattr(base, \"id\", \"\") == \"Tool\" or getattr(base, \"attr\", \"\") == \"Tool\":\n                    return True\n    return False","typeGuard":"import ast\ndef has_tool_subclass(code: str) -> bool:\n    try:\n        return code_defines_tool_subclass(code)\n    except SyntaxError:\n        return False","tryCatchPattern":"try:\n    tool = Tool.from_code(code)\nexcept ValueError as e:\n    if \"No Tool subclass\" in str(e):\n        raise ValueError(f\"{path} does not define a Tool subclass\") from e\n    raise","preventionTips":["from_code expects class-based tools; use the decorator for function tools","Validate/parse code strings before loading, especially user- or LLM-generated code","Test Hub tool.py files locally with from_code before publishing"],"tags":["smolagents","from-code","tool-subclass","dynamic-import"],"backgroundTag":"no-tool-subclass-in-code","analyzedSha":"30bb1161095dbae2271e6bc3cc4c219cc3897a57","analyzedAt":"2026-08-28T18:52:54.169Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}