huggingface/smolagents · error · ValueError
No function definition found in the provided source of {tool
Error message
No function definition found in the provided source of {tool_function.__name__}. Ensure the input is a standard function. What it means
The @tool decorator inspects the function's source via inspect/ast to strip its definition and decorators for serialization. If no ast.FunctionDef node can be found in the retrieved source, it raises ValueError because it cannot process the callable as a standard function.
Source
Thrown at src/smolagents/tools.py:1121
# Get the signature parameters of the tool function
sig = inspect.signature(tool_function)
# - Add "self" as first parameter to tool_function signature
new_sig = sig.replace(
parameters=[inspect.Parameter("self", inspect.Parameter.POSITIONAL_OR_KEYWORD)] + list(sig.parameters.values())
)
# - Set the signature of the forward method
SimpleTool.forward.__signature__ = new_sig
# 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_linenoView on GitHub (pinned to 30bb116109)
Solutions
- Convert the callable to a standard `def` function at module level and decorate that
- Define tools in real .py files (not notebooks/exec/dynamic strings) so inspect.getsource works
- Avoid wrapping lambdas, partials, or builtins with @tool; write an explicit wrapper function
Example fix
# before
get_weather = tool(lambda city: fetch(city))
# after
@tool
def get_weather(city: str) -> str:
return fetch(city) Defensive patterns
Strategy: type-guard
Validate before calling
import inspect, ast
def has_function_def_source(func) -> bool:
try:
tree = ast.parse(inspect.getsource(func))
except (TypeError, OSError):
return False
return any(isinstance(n, ast.FunctionDef) for n in ast.walk(tree))
assert has_function_def_source(candidate), "define tool as a plain def in a .py file" Type guard
def is_wrappable_as_tool(func) -> bool:
return inspect.isfunction(func) and not inspect.isbuiltin(func) and has_function_def_source(func) Try / catch
try:
my_tool = tool(candidate)
except ValueError as e:
if "No function definition" in str(e):
def wrapper(arg: str) -> str:
return candidate(arg)
wrapper.__name__ = getattr(candidate, '__name__', 'tool_fn')
my_tool = tool(wrapper)
else:
raise Prevention
- Define tools as plain module-level def functions in real files
- Avoid decorating lambdas, partials, builtins, or notebook-defined callables
When it happens
Trigger: Applying @tool to objects whose source contains no plain function definition: lambdas, builtins, C extensions, functools.partial results, callables defined in exec'd/REPL code, or decorated functions where inspect.getsource returns unexpected source.
Common situations: Wrapping lambdas or imported native functions as tools; defining tools in Jupyter cells or dynamically generated code where source retrieval misbehaves; double-decorating with wrappers that hide the original function.
Related errors
- Multiple @tool decorators found on function '{func_node.name
- Unsupported comparison operator: {op}
- {expression.__class__.__name__} is not supported.
- Source code must define a class
- Tool return type not found: make sure your function has a re
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/d089a2b45c3f135e.
Report an issue: GitHub.