Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/main/smolagents_doc/en/tools.ipynb
Views: 2935
Tools
Here, we're going to see advanced tool usage.
[!TIP] If you're new to building agents, make sure to first read the intro to agents and the guided tour of smolagents.
What is a tool, and how to build one?
A tool is mostly a function that an LLM can use in an agentic system.
But to use it, the LLM will need to be given an API: name, tool description, input types and descriptions, output type.
So it cannot be only a function. It should be a class.
So at core, the tool is a class that wraps a function with metadata that helps the LLM understand how to use it.
Here's how it looks:
The custom tool subclasses Tool to inherit useful methods. The child class also defines:
An attribute
name
, which corresponds to the name of the tool itself. The name usually describes what the tool does. Since the code returns the model with the most downloads for a task, let's name itmodel_download_counter
.An attribute
description
is used to populate the agent's system prompt.An
inputs
attribute, which is a dictionary with keys"type"
and"description"
. It contains information that helps the Python interpreter make educated choices about the input.An
output_type
attribute, which specifies the output type. The types for bothinputs
andoutput_type
should be Pydantic formats, they can be either of these:~AUTHORIZED_TYPES()
.A
forward
method which contains the inference code to be executed.
And that's all it needs to be used in an agent!
There's another way to build a tool. In the guided_tour, we implemented a tool using the @tool
decorator. The tool() decorator is the recommended way to define simple tools, but sometimes you need more than this: using several methods in a class for more clarity, or using additional class attributes.
In this case, you can build your tool by subclassing Tool as described above.
Share your tool to the Hub
You can share your custom tool to the Hub by calling push_to_hub() on the tool. Make sure you've created a repository for it on the Hub and are using a token with read access.
For the push to Hub to work, your tool will need to respect some rules:
All methods are self-contained, e.g. use variables that come either from their args.
As per the above point, all imports should be defined directly within the tool's functions, else you will get an error when trying to call save() or push_to_hub() with your custom tool.
If you subclass the
__init__
method, you can give it no other argument thanself
. This is because arguments set during a specific tool instance's initialization are hard to track, which prevents from sharing them properly to the hub. And anyway, the idea of making a specific class is that you can already set class attributes for anything you need to hard-code (just setyour_variable=(...)
directly under theclass YourTool(Tool):
line). And of course you can still create a class attribute anywhere in your code by assigning stuff toself.your_variable
.
Once your tool is pushed to Hub, you can visualize it. Here is the model_downloads_tool
that I've pushed. It has a nice gradio interface.
When diving into the tool files, you can find that all the tool's logic is under tool.py. That is where you can inspect a tool shared by someone else.
Then you can load the tool with load_tool() or create it with from_hub() and pass it to the tools
parameter in your agent. Since running tools means running custom code, you need to make sure you trust the repository, thus we require to pass trust_remote_code=True
to load a tool from the Hub.
Import a Space as a tool
You can directly import a Space from the Hub as a tool using the Tool.from_space() method!
You only need to provide the id of the Space on the Hub, its name, and a description that will help you agent understand what the tool does. Under the hood, this will use gradio-client
library to call the Space.
For instance, let's import the FLUX.1-dev Space from the Hub and use it to generate an image.
And voilà, here's your image! 🏖️
Then you can use this tool just like any other tool. For example, let's improve the prompt a rabbit wearing a space suit
and generate an image of it. This example also shows how you can pass additional arguments to the agent.
How cool is this? 🤩
Use LangChain tools
We love Langchain and think it has a very compelling suite of tools. To import a tool from LangChain, use the from_langchain()
method.
Here is how you can use it to recreate the intro's search result using a LangChain web search tool. This tool will need pip install langchain google-search-results -q
to work properly.
Manage your agent's toolbox
You can manage an agent's toolbox by adding or replacing a tool in attribute agent.tools
, since it is a standard dictionary.
Let's add the model_download_tool
to an existing agent initialized with only the default toolbox.
Now we can leverage the new tool:
[!TIP] Beware of not adding too many tools to an agent: this can overwhelm weaker LLM engines.
Use a collection of tools
You can leverage tool collections by using the ToolCollection
object. It supports loading either a collection from the Hub or an MCP server tools.
Tool Collection from a collection in the Hub
You can leverage it with the slug of the collection you want to use. Then pass them as a list to initialize your agent, and start using them!
To speed up the start, tools are loaded only if called by the agent.
Tool Collection from any MCP server
Leverage tools from the hundreds of MCP servers available on glama.ai or smithery.ai.
The MCP servers tools can be loaded in a ToolCollection
object as follow: