huggingface/smolagents · error · InterpreterError

Forbidden function evaluation: '{call.func.id}' is not among

Error message

Forbidden function evaluation: '{call.func.id}' is not among the explicitly allowed tools or defined/imported in the preceding code

What it means

For a bare-name call f(...), evaluate_call looks the name up in state (code-defined variables/imports), static_tools, custom_tools, and the built-in ERRORS dict; if it is found nowhere, the interpreter treats it as an unauthorized call and raises InterpreterError. This is the sandbox's NameError equivalent with a security rationale: only explicitly provided tools and code-defined/imported names may be called.

Source

Thrown at src/smolagents/local_python_executor.py:858

        func = evaluate_ast(call.func, state, static_tools, custom_tools, authorized_imports)
    elif isinstance(call.func, ast.Attribute):
        obj = evaluate_ast(call.func.value, state, static_tools, custom_tools, authorized_imports)
        func_name = call.func.attr
        if not hasattr(obj, func_name):
            raise InterpreterError(f"Object {obj} has no attribute {func_name}")
        func = getattr(obj, func_name)
    elif isinstance(call.func, ast.Name):
        func_name = call.func.id
        if func_name in state:
            func = state[func_name]
        elif func_name in static_tools:
            func = static_tools[func_name]
        elif func_name in custom_tools:
            func = custom_tools[func_name]
        elif func_name in ERRORS:
            func = ERRORS[func_name]
        else:
            raise InterpreterError(
                f"Forbidden function evaluation: '{call.func.id}' is not among the explicitly allowed tools or defined/imported in the preceding code"
            )
    elif isinstance(call.func, ast.Subscript):
        func = evaluate_ast(call.func, state, static_tools, custom_tools, authorized_imports)
        if not callable(func):
            raise InterpreterError(f"This is not a correct function: {call.func}).")
        func_name = None

    args = []
    for arg in call.args:
        if isinstance(arg, ast.Starred):
            args.extend(evaluate_ast(arg.value, state, static_tools, custom_tools, authorized_imports))
        else:
            args.append(evaluate_ast(arg, state, static_tools, custom_tools, authorized_imports))

    kwargs = {}
    for keyword in call.keywords:
        if keyword.arg is None:

View on GitHub (pinned to 30bb116109)

Solutions

  1. Add the missing import inside the executed code (`import pandas as pd` before `pd.read_csv`)
  2. Define the helper inside the snippet, or pass it as a static/custom tool when constructing the agent
  3. Check for typos and ensure the name was assigned earlier in the same snippet (state does not persist across separate evaluate_python calls unless you reuse the interpreter state)

Example fix

# before
code = "df = pd.read_csv('data.csv')"

# after
code = "import pandas as pd\ndf = pd.read_csv('data.csv')"
Defensive patterns

Strategy: validation

Validate before calling

import ast
code_tree = ast.parse(code)
defined = {n.id for n in ast.walk(code_tree) if isinstance(n, ast.Name) and isinstance(n.ctx, ast.Store)}
defined |= {n.names[0].asname or n.names[0].name.split('.')[0] for n in ast.walk(code_tree) if isinstance(n, ast.Import)}
defined |= {(n.module or '').split('.')[0] for n in ast.walk(code_tree) if isinstance(n, ast.ImportFrom)}
called = {n.func.id for n in ast.walk(code_tree) if isinstance(n, ast.Call) and isinstance(n.func, ast.Name)}
missing = called - defined - set(static_tools) - set(custom_tools)
if missing:
    raise ValueError(f'undefined names called: {missing}')

Try / catch

from smolagents.local_python_executor import InterpreterError
try:
    evaluate_python(code, static_tools=static_tools)
except InterpreterError as e:
    if 'Forbidden function evaluation' in str(e):
        code = add_missing_imports(code)
        evaluate_python(code, static_tools=static_tools)

Prevention

When it happens

Trigger: Executed code calls a function never defined or imported in the snippet and not among the tools: `print(x)` is fine (builtins) but e.g. `pd.read_csv(...)` without `import pandas as pd`, calling `len` is fine but `search(...)` with no such tool registered, or calling a name defined only in another cell/before a state reset.

Common situations: LLM forgets the import line (very common: using np/pd without importing); calling a tool that was not attached to the agent; relying on variables from a previous evaluation after the interpreter state was reset; typo'd function names.

Understand the failure class

Related errors


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