huggingface/smolagents · error · ValueError

Multiple @tool decorators found on function '{func_node.name

Error message

Multiple @tool decorators found on function '{func_node.name}'. Only one @tool decorator is allowed.

What it means

While parsing the decorated function's AST, smolagents found more than one plain `@tool` decorator (ast.Name nodes named 'tool') applied to the same function. Duplicate decoration would wrap the tool twice and corrupt schema generation, so it raises ValueError.

Source

Thrown at src/smolagents/tools.py:1130

    # Create and attach the source code of the dynamically created tool class and forward method
    # - Get the source code of tool_function
    tool_source = textwrap.dedent(inspect.getsource(tool_function))
    # - Remove the tool decorator and function definition line
    lines = tool_source.splitlines()
    tree = ast.parse(tool_source)
    #   - Find function definition
    func_node = next((node for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)), None)
    if not func_node:
        raise ValueError(
            f"No function definition found in the provided source of {tool_function.__name__}. "
            "Ensure the input is a standard function."
        )
    #   - Extract decorator lines
    decorator_lines = ""
    if func_node.decorator_list:
        tool_decorators = [d for d in func_node.decorator_list if isinstance(d, ast.Name) and d.id == "tool"]
        if len(tool_decorators) > 1:
            raise ValueError(
                f"Multiple @tool decorators found on function '{func_node.name}'. Only one @tool decorator is allowed."
            )
        if len(tool_decorators) < len(func_node.decorator_list):
            warnings.warn(
                f"Function '{func_node.name}' has decorators other than @tool. "
                "This may cause issues with serialization in the remote executor. See issue #1626."
            )
        decorator_start = tool_decorators[0].end_lineno if tool_decorators else 0
        decorator_end = func_node.decorator_list[-1].end_lineno
        decorator_lines = "\n".join(lines[decorator_start:decorator_end])
    #   - Extract tool source body
    body_start = func_node.body[0].lineno - 1  # AST lineno starts at 1
    tool_source_body = "\n".join(lines[body_start:])
    # - Create the forward method source, including def line and indentation
    forward_method_source = f"def forward{new_sig}:\n{tool_source_body}"
    # - Create the class source
    indent = " " * 4  # for class method
    class_source = (

View on GitHub (pinned to 30bb116109)

Solutions

  1. Remove the duplicate @tool decorator, leaving exactly one
  2. If decorating programmatically, ensure the input is a raw function, not an already-wrapped Tool
  3. Check imports to confirm you're not decorating an already-processed function from another module

Example fix

# before
@tool
@tool
def add(a: int, b: int) -> int:
    return a + b
# after
@tool
def add(a: int, b: int) -> int:
    return a + b
Defensive patterns

Strategy: validation

Validate before calling

import ast, inspect
src = inspect.getsource(my_func)
fn = next(n for n in ast.walk(ast.parse(src)) if isinstance(n, ast.FunctionDef))
names = [d.id for d in fn.decorator_list if isinstance(d, ast.Name)]
assert names.count("tool") <= 1, "remove duplicate @tool"

Try / catch

try:
    my_tool = tool(my_func)
except ValueError as e:
    if "Multiple @tool decorators" in str(e):
        raise  # fix the source; do not retry programmatically
    raise

Prevention

When it happens

Trigger: Stacking @tool twice, e.g. `@tool\n@tool\ndef f(...)`, or applying @tool to a function that was already converted to a Tool by another @tool call. Calling `tool(tool(func))` programmatically can produce the same result.

Common situations: Copy-paste accidents during refactoring; migration code that applies @tool on top of already-decorated imports; lint-disabled duplicates after merges.

Related errors


AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28). Data as JSON: /api/errors/26c065d6fa6ca3fb. Report an issue: GitHub.