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 itsView on GitHub (pinned to 30bb116109)
Solutions
- Use tool.to_dict() output as the canonical format and load it back unmodified
- If constructing the dict manually, include 'code': the full tool source string (what to_dict produces)
- 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
- Only load dicts produced by Tool.to_dict(); don't hand-craft them
- Round-trip test: assert Tool.from_dict(t.to_dict()).name == t.name
- Version-pin smolagents so the save format stays stable
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
- Unknown model class '{model_info['class']}'. Supported model
- Unknown agent class '{managed_agent_dict['class']}'. Support
- Deserializing pickle data. This is a security risk if the da
- Error during jinja template rendering: {type(e).__name__}: {
- Cannot specify both 'messages' and 'steps' parameters. Use '
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/474a96226e6309ff.
Report an issue: GitHub.