huggingface/smolagents · error · ValueError

Tool dictionary must contain 'code' key with the tool source

Error message

Tool dictionary must contain 'code' key with the tool source code

What it means

Tool.from_dict requires the dictionary to contain a 'code' key holding the tool's Python source, since reconstruction works by exec-ing that code via from_code. Missing 'code' raises ValueError.

Source

Thrown at src/smolagents/tools.py:380

        if hasattr(self, "output_schema") and self.output_schema is not None:
            tool_dict["output_schema"] = self.output_schema

        return tool_dict

    @classmethod
    def from_dict(cls, tool_dict: dict[str, Any], **kwargs) -> "Tool":
        """
        Create tool from a dictionary representation.

        Args:
            tool_dict (`dict[str, Any]`): Dictionary representation of the tool.
            **kwargs: Additional keyword arguments to pass to the tool's constructor.

        Returns:
            `Tool`: Tool object.
        """
        if "code" not in tool_dict:
            raise ValueError("Tool dictionary must contain 'code' key with the tool source code")

        tool = cls.from_code(tool_dict["code"], **kwargs)

        # Set output_schema if it exists in the dictionary
        if "output_schema" in tool_dict:
            tool.output_schema = tool_dict["output_schema"]

        return tool

    def save(self, output_dir: str | Path, tool_file_name: str = "tool", make_gradio_app: bool = True):
        """
        Saves the relevant code files for your tool so it can be pushed to the Hub. This will copy the code of your
        tool in `output_dir` as well as autogenerate:

        - a `{tool_file_name}.py` file containing the logic for your tool.
        If you pass `make_gradio_app=True`, this will also write:
        - an `app.py` file providing a UI for your tool when it is exported to a Space with `tool.push_to_hub()`
        - a `requirements.txt` containing the names of the modules used by your tool (as detected when inspecting its

View on GitHub (pinned to 30bb116109)

Solutions

  1. Use tool.to_dict() output as the canonical format and load it back unmodified
  2. If constructing the dict manually, include 'code': the full tool source string (what to_dict produces)
  3. Alternatively load via Tool.from_hub(repo_id) if the tool lives on the Hub

Example fix

# before
d = {"name": "my_tool", "description": "..."}
Tool.from_dict(d)
# after
d = my_tool.to_dict()  # includes 'code'
Tool.from_dict(d)
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_tool_dict(d: dict) -> bool:
    return isinstance(d, dict) and "code" in d and isinstance(d["code"], str)

Type guard

from typing import TypedDict
class ToolDict(TypedDict):
    code: str
    class_name: str
    name: str
    description: NotRequired[str]

Prevention

When it happens

Trigger: Calling Tool.from_dict(d) where d was built manually, or a dict produced by a different serializer, that lacks the 'code' key; passing a dict with only 'class_name'/'name'/'description' metadata.

Common situations: Hand-editing a saved agent's tools JSON and dropping keys; loading a dict produced by an older/newer smolagents version whose save format differs; constructing tool dicts from YAML configs without embedding source.

Related errors


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