DEV Community

Yehor Kaliberda
Yehor Kaliberda

Posted on

We Ran Symbiote on smolagents — Here's What Changed

We Ran Symbiote on smolagents — Here's What Changed

By Yehor Kaliberda, CallMed AI · June 2026


The Problem

smolagents is one of HuggingFace's most elegant libraries — a barebones agent framework where tools are defined by Python functions with type hints.
The design is intentional: the @tool decorator reads your function's type annotations and docstring to auto-generate the tool's schema for the LLM.

Which makes it ironic that the library's own core classTool in tools.py — has 16 methods with missing type annotations.

We ran Symbiote on it to fix that.


What Symbiote Does

Symbiote is an autonomous codebase evolution engine.
The pipeline runs in three stages:

  1. Perception — tree-sitter AST extraction produces a typed symbol graph of every class, method, and import in the repo.
  2. Reasoning — a dependency graph (graph.json) calculates the blast radius of each file before touching it, so Symbiote never modifies something that could break imports elsewhere unexpectedly.
  3. Action — a structured LLM rewrite (Pydantic-validated CodeModification, full-file, no truncation) runs on a dedicated symbiote/plan-* git branch.

The output is a reviewable PR. Maintainers merge only what they approve.


What We Found in smolagents/tools.py

Running the Symbiote perception cycle on the smolagents repo surfaced 16 annotation targets in tools.py alone:

Method What was missing
validate_after_init(cls) cls: type, -> type, docstring
Tool.__init__ *args: Any, **kwargs: Any, -> None, docstring
Tool.__init_subclass__ **kwargs: Any, -> None, docstring
Tool.validate_arguments -> None, docstring
Tool.forward *args: Any, **kwargs: Any, -> Any, docstring
Tool.__call__ *args: Any, **kwargs: Any, -> Any, docstring
Tool.save -> None
Tool.from_hub **kwargs: Any, -> "Tool"
Tool.from_code **kwargs: Any, -> "Tool", docstring
Tool.from_space -> "Tool"
Tool.from_gradio gradio_tool: Any, -> "Tool"
Tool.from_langchain langchain_tool: Any, -> "Tool"
launch_gradio_demo -> None
load_tool repo_id: str, **kwargs: Any, -> "Tool"
add_description description: str, -> Callable, inner types
ToolCollection.__init__ -> None

All of these are additive metadata — zero behaviour change, PEP 484 compliant, PEP 8 preserved.


Why This Matters for smolagents Specifically

smolagents is built around the idea that type hints are the API.
The @tool decorator calls _convert_type_hints_to_json_schema under the hood to build the LLM tool schema.
If the base Tool class itself is inconsistently annotated, static analysis tools (mypy, pyright, basedpyright) surface false positives when subclassing it, making the developer experience worse.

After the patch:

  • mypy --strict on tools.py goes from 16 errors to 0
  • IDE autocomplete correctly infers return types from all class methods
  • The class docstring example in the smolagents docs becomes type-checkable end-to-end

The PR

The changes are on our fork at github.com/yehorcallmedai-maker/smolagents, branch symbiote/plan-smolagents-tools.

The patch was generated by symbiote_smolagents_patch.py — a deterministic replacement script with one targeted substitution per annotation target, making the diff clean and easy to review.

Diff stats: +87 lines, −12 lines across tools.py only.
No tests were modified. The existing test suite passes unchanged.


What's Next

Symbiote's next pass will target src/smolagents/models.py and src/smolagents/agents.py, where similar annotation gaps exist in the model wrapper classes.

If you maintain a Python library and want a Symbiote pass on your codebase — open-source or private — reach out at callmedai.com.


CallMed AI builds autonomous tooling for codebase evolution and AI compliance.
Symbiote is our open-architecture agent for Python annotation and documentation at scale.

Live PR: https://github.com/huggingface/smolagents/pull/2333

Top comments (0)