langchain-ai/langchain · error · ValueError

Too many arguments for tool decorator. A decorator

Error message

Too many arguments for tool decorator. A decorator 

What it means

The @tool decorator accepts at most one positional argument (a name string or the function itself). This error means extra positional arguments were passed, i.e. the decorator was used with a signature the API does not support — everything besides the first positional must be keyword-only.

Source

Thrown at libs/core/langchain_core/tools/convert.py:357

            return Tool(
                name=tool_name,
                func=func,
                description=tool_description,
                return_direct=return_direct,
                coroutine=coroutine,
                response_format=response_format,
                extras=extras,
            )

        return _tool_factory

    if len(args) != 0:
        # Triggered if a user attempts to use positional arguments that
        # do not exist in the function signature
        # e.g., @tool("name", runnable, "extra_arg")
        # Here, "extra_arg" is not a valid argument
        msg = "Too many arguments for tool decorator. A decorator "
        raise ValueError(msg)

    if runnable is not None:
        # tool is used as a function
        # for instance tool_from_runnable = tool("name", runnable)
        if not name_or_callable:
            msg = "Runnable without name for tool constructor"
            raise ValueError(msg)
        if not isinstance(name_or_callable, str):
            msg = "Name must be a string for tool constructor"
            raise ValueError(msg)
        return _create_tool_factory(name_or_callable)(runnable)
    if name_or_callable is not None:
        if callable(name_or_callable) and hasattr(name_or_callable, "__name__"):
            # Used as a decorator without parameters
            # @tool
            # def my_tool():
            #    pass
            return _create_tool_factory(name_or_callable.__name__)(name_or_callable)

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Pass only the name positionally and everything else by keyword: @tool('search', return_direct=True)
  2. To convert a Runnable, use tool('name', runnable=runnable)
  3. To decorate a function, apply @tool directly or @tool('name') — never pass the function positionally to tool()

Example fix

# before
my_tool = tool("search", my_func, True)

# after
my_tool = tool("search", return_direct=True)(my_func)
# or
@tool("search", return_direct=True)
def my_func(query: str) -> str: ...
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def safe_tool_call(*args, **kwargs):
    """Enforce @tool's one-positional-argument contract."""
    if len(args) > 1:
        msg = "tool() takes at most 1 positional argument; pass the rest by keyword"
        raise TypeError(msg)
    return tool(*args, **kwargs)

Try / catch

try:
    t = tool("name", func, True)
except ValueError as e:
    if "Too many arguments" in str(e):
        t = tool("name", return_direct=True)(func)
    else:
        raise

Prevention

When it happens

Trigger: @tool('name', runnable, 'extra') or tool('name', func, True); any call to tool(...) with len(args) > 1 positionally.

Common situations: Assuming @tool supports positional (name, func) style like older or different APIs; copy-pasting decorator usage from another library; typos adding stray positional args.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/d7ff684ab295c057. Report an issue: GitHub.