huggingface/smolagents · error · TypeError

Argument {key} has type '{actual_type}' but should be '{tool

Error message

Argument {key} has type '{actual_type}' but should be '{tool.inputs[key]['type']}'

What it means

Raised by smolagents' validate_tool_arguments when an argument passed to a tool does not match the JSON Schema type declared in the tool's inputs definition. It is the library's pre-execution guard so that tool forward() methods receive correctly typed values. Integer values are accepted where 'number' is expected, and 'any' or nullable schemas bypass the check.

Source

Thrown at src/smolagents/tools.py:1402

    """
    if isinstance(arguments, dict):
        for key, value in arguments.items():
            if key not in tool.inputs:
                raise ValueError(f"Argument {key} is not in the tool's input schema")

            actual_type = _get_json_schema_type(type(value))["type"]
            expected_type = tool.inputs[key]["type"]
            expected_type_is_nullable = tool.inputs[key].get("nullable", False)

            # Type is valid if it matches, is "any", or is null for nullable parameters
            if (
                (actual_type != expected_type if isinstance(expected_type, str) else actual_type not in expected_type)
                and expected_type != "any"
                and not (actual_type == "null" and expected_type_is_nullable)
            ):
                if actual_type == "integer" and expected_type == "number":
                    continue
                raise TypeError(f"Argument {key} has type '{actual_type}' but should be '{tool.inputs[key]['type']}'")

        for key, schema in tool.inputs.items():
            key_is_nullable = schema.get("nullable", False)
            if key not in arguments and not key_is_nullable:
                raise ValueError(f"Argument {key} is required")
        return None
    else:
        expected_type = list(tool.inputs.values())[0]["type"]
        if _get_json_schema_type(type(arguments))["type"] != expected_type and not expected_type == "any":
            raise TypeError(f"Argument has type '{type(arguments).__name__}' but should be '{expected_type}'")


__all__ = [
    "AUTHORIZED_TYPES",
    "Tool",
    "tool",
    "load_tool",
    "launch_gradio_demo",

View on GitHub (pinned to 30bb116109)

Solutions

  1. Fix the arguments to match the declared type (e.g., convert '5' to 5 before calling the tool)
  2. Adjust the tool's inputs declaration to the type actually received, or set 'type': 'any' / 'nullable': True where appropriate
  3. If a model keeps emitting wrong types, tighten the tool description or prompt so the model produces correctly typed JSON
  4. For integer-tolerant float inputs, note ints are allowed for 'number' but not vice versa; cast in your wrapper

Example fix

# before
tool = Tool(name='add', inputs={'a': {'type': 'integer'}}, ...)
tool(a='5')  # TypeError

# after
tool(a=int('5'))
# or declare: inputs={'a': {'type': 'any'}}
Defensive patterns

Strategy: validation

Validate before calling

import json
def validate_args(tool, arguments):
    type_map = {str: 'string', int: 'integer', float: 'number', bool: 'boolean', list: 'array', dict: 'object'}
    for key, schema in tool.inputs.items():
        if key in arguments and isinstance(schema.get('type'), str):
            expected = schema['type']
            if expected == 'any':
                continue
            actual = type_map.get(type(arguments[key]))
            if actual and actual != expected and not (actual == 'integer' and expected == 'number'):
                raise ValueError(f'{key}: expected {expected}, got {actual}')
    return arguments

Type guard

def args_match(tool, arguments: dict) -> bool:
    tm = {str: 'string', int: 'integer', float: 'number', bool: 'boolean', list: 'array', dict: 'object'}
    return all(
        s.get('type') == 'any' or tm.get(type(arguments.get(k))) == s.get('type')
        or (tm.get(type(arguments.get(k))) == 'integer' and s.get('type') == 'number')
        for k, s in tool.inputs.items() if k in arguments
    )

Try / catch

try:
    result = tool(**arguments)
except TypeError as e:
    if 'has type' in str(e):
        # coerce types from the message and retry, or log and surface to the model
        raise

Prevention

When it happens

Trigger: Calling a Tool (or an agent making a tool call) with, e.g., a string '5' where inputs declare {'type': 'integer'}, or a dict where 'array' is declared. Also triggered by argument keys not present in the tool's inputs whose type cannot be validated.

Common situations: LLM models returning numbers as strings, booleans as 'true', or lists as comma-separated strings; mismatch between the tool author's declared input types and what the model actually emits; custom tools with hand-written input schemas that don't match the Python signatures.

Related errors


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