Smolagents: Lightweight AI Agent Framework by HuggingFace
Introduction
Smolagents is a lightweight and minimalist AI agent framework from HuggingFace, designed for building AI agents with a code-first approach. Unlike other agent frameworks that tend to be complex and heavy, Smolagents focuses on simplicity while still providing powerful features such as multi-step reasoning, custom tool creation, and multi-agent orchestration.
This framework is ideal for developers who want to build AI agents without excessive overhead. Smolagents uses a unique approach where the agent generates Python code as its "actions" instead of rigid JSON formats, making agents more flexible and expressive.
In this tutorial, we will learn how to use Smolagents from installation, understanding agent types, creating custom tools, to building a research agent that can search the web, process data, and generate reports.
Prerequisites
Before getting started, make sure you have:
- Python 3.10 or later
- pip package manager
- API key from HuggingFace, OpenAI, or Anthropic
- Basic understanding of Python and AI/LLM concepts
Installation
Basic Installation
# Install smolagents
pip install smolagents
Install with additional dependencies for all features
pip install smolagents[all]
Or install specific dependencies
pip install smolagents[openai] # For OpenAI
pip install smolagents[anthropic] # For Anthropic
pip install smolagents[gradio] # For Gradio UI
pip install smolagents[telemetry] # For monitoring
Verify Installation
import smolagents
print(f"Smolagents version: {smolagents.version}")
Test basic import
from smolagents import CodeAgent, HfApiModel
print("Import successful!")
Setup Environment Variables
# For HuggingFace
export HFTOKEN="hfyourtokenhere"
For OpenAI
export OPENAIAPIKEY="sk-your-key-here"
For Anthropic
export ANTHROPICAPIKEY="sk-ant-your-key-here"
CodeAgent vs ToolCallingAgent
Smolagents provides two main agent types that take different approaches to completing tasks.
CodeAgent
CodeAgent generates and executes Python code as its actions. This is the recommended agent type because it is more flexible and efficient.
from smolagents import CodeAgent, HfApiModel
Initialize model
model = HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct")
Create CodeAgent
agent = CodeAgent(
tools=[], # No additional tools
model=model,
maxsteps=5
)
Run agent
result = agent.run("Calculate the average of the following numbers: 15, 28, 42, 37, 56")
print(result)
Advantages of CodeAgent:
- Generates Python code that can perform complex computations
- More efficient as it can combine multiple operations in a single step
- Supports variables and logic flow
- Output is easier to debug
ToolCallingAgent
ToolCallingAgent uses the standard tool calling format (similar to function calling in OpenAI). This agent calls tools one by one in JSON format.
from smolagents import ToolCallingAgent, HfApiModel
Initialize model
model = HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct")
Create ToolCallingAgent
agent = ToolCallingAgent(
tools=[],
model=model,
maxsteps=5
)
Run agent
result = agent.run("What is the result of 25 48?")
print(result)
When to use ToolCallingAgent:
- When the model performs better at tool calling than code generation
- When you need stricter control over the actions the agent takes
- When integrating with existing systems that use tool calling format
Built-in Tools
Smolagents provides several built-in tools that are ready to use.
Web Search Tool
from smolagents import CodeAgent, HfApiModel, DuckDuckGoSearchTool
Initialize search tool
searchtool = DuckDuckGoSearchTool()
Create agent with search tool
agent = CodeAgent(
tools=[searchtool],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=5
)
Search for information
result = agent.run("Search for the latest developments in AI agents in 2025")
print(result)
Python Interpreter Tool
CodeAgent inherently has the ability to execute Python code. However, you can configure the execution environment:
from smolagents import CodeAgent, HfApiModel
agent = CodeAgent(
tools=[],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
additionalauthorizedimports=["numpy", "pandas", "matplotlib"],
maxsteps=5
)
Agent can use authorized libraries
result = agent.run("""
Create a numpy array with 100 random numbers,
calculate the mean, median, and standard deviation
""")
print(result)
Visit Webpage Tool
from smolagents import CodeAgent, HfApiModel, VisitWebpageTool
Tool for visiting and reading web pages
visittool = VisitWebpageTool()
agent = CodeAgent(
tools=[visittool],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=5
)
result = agent.run("Read the page at https://huggingface.co/blog and summarize the latest article")
print(result)
Custom Tool Creation
Using the @tool Decorator
The easiest way to create a custom tool is using the @tool decorator:
from smolagents import tool, CodeAgent, HfApiModel
@tool
def getweather(city: str) -> str:
"""
Gets weather information for a specific city.
Args:
city: Name of the city to check weather for
Returns:
String containing weather information
"""
import requests
apikey = "yourweatherapikey"
url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={apikey}&units=metric"
response = requests.get(url)
data = response.json()
if response.statuscode == 200:
temp = data['main']['temp']
desc = data['weather'][0]['description']
humidity = data['main']['humidity']
return f"Weather in {city}: {desc}, Temperature: {temp}C, Humidity: {humidity}%"
else:
return f"Could not get weather data for {city}"
Use tool in agent
agent = CodeAgent(
tools=[getweather],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=5
)
result = agent.run("What is the weather like in Jakarta today?")
print(result)
Tool with Multiple Parameters
@tool
def searchdatabase(query: str, table: str, limit: int = 10) -> str:
"""
Searches a database based on a query.
Args:
query: Search keyword
table: Name of the table to search
limit: Maximum number of results to return
Returns:
Search results as a formatted string
"""
import sqlite3
conn = sqlite3.connect("app.db")
cursor = conn.cursor()
cursor.execute(
f"SELECT FROM {table} WHERE content LIKE ? LIMIT ?",
(f"%{query}%", limit)
)
results = cursor.fetchall()
conn.close()
if results:
return f"Found {len(results)} results:\n" + "\n".join(str(r) for r in results)
else:
return "No matching results found"
Custom Tool Class
For more complex tools, you can create a class:
from smolagents import Tool
class EmailSenderTool(Tool):
name = "sendemail"
description = "Sends an email to a specified address with the given subject and body"
inputs = {
"to": {
"type": "string",
"description": "Recipient email address"
},
"subject": {
"type": "string",
"description": "Email subject"
},
"body": {
"type": "string",
"description": "Email body content"
}
}
outputtype = "string"
def forward(self, to: str, subject: str, body: str) -> str:
import smtplib
from email.mime.text import MIMEText
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = "agent@example.com"
msg['To'] = to
try:
with smtplib.SMTP('smtp.example.com', 587) as server:
server.starttls()
server.login("agent@example.com", "password")
server.sendmessage(msg)
return f"Email successfully sent to {to}"
except Exception as e:
return f"Failed to send email: {str(e)}"
Use the tool
emailtool = EmailSenderTool()
Multi-Step Reasoning
Smolagents supports multi-step reasoning where the agent can break down complex tasks into smaller steps.
from smolagents import CodeAgent, HfApiModel, DuckDuckGoSearchTool
agent = CodeAgent(
tools=[DuckDuckGoSearchTool()],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=10, # Allow more steps
verbose=True # Show reasoning process
)
result = agent.run("""
Perform the following analysis:
Find the 3 largest AI companies in Southeast Asia
For each company, find information about their main products
Compare and create a comparison summary
""")
print(result)
The agent will perform several steps:
- Step 1: Search for AI companies in Southeast Asia
- Step 2: Search for details about each company
- Step 3: Compile and compare information
- Step 4: Create a summary
Configuring Planning
agent = CodeAgent(
tools=[DuckDuckGoSearchTool()],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=10,
planninginterval=3 # Agent creates a plan every 3 steps
)
Model Integration
HuggingFace Inference API
from smolagents import CodeAgent, HfApiModel
Using a model from HF Hub
model = HfApiModel(
modelid="Qwen/Qwen2.5-Coder-32B-Instruct",
token="hfyourtoken"
)
agent = CodeAgent(tools=[], model=model)
OpenAI
from smolagents import CodeAgent, OpenAIServerModel
Using OpenAI
model = OpenAIServerModel(
modelid="gpt-4o",
apikey="sk-your-key"
)
agent = CodeAgent(tools=[], model=model)
Anthropic
from smolagents import CodeAgent, AnthropicServerModel
Using Anthropic Claude
model = AnthropicServerModel(
modelid="claude-sonnet-4-20250514",
apikey="sk-ant-your-key"
)
agent = CodeAgent(tools=[], model=model)
Local Models (via Ollama)
from smolagents import CodeAgent, OpenAIServerModel
Using local model via Ollama
model = OpenAIServerModel(
modelid="llama3.1:8b",
apibase="http://localhost:11434/v1",
apikey="ollama" # Ollama does not require a key
)
agent = CodeAgent(tools=[], model=model)
Agent with Memory
Smolagents supports memory to maintain context between interactions.
from smolagents import CodeAgent, HfApiModel
Create agent
agent = CodeAgent(
tools=[],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=5
)
First interaction
result1 = agent.run("My name is Alice and I am a data scientist")
print(result1)
Second interaction - agent remembers previous context
result2 = agent.run("What is my name and what is my profession?")
print(result2)
Persistent Memory with File Storage
import json
from smolagents import tool
@tool
def savememory(key: str, value: str) -> str:
"""
Saves information to persistent memory.
Args:
key: Key to store the information under
value: Value to store
Returns:
Storage confirmation message
"""
try:
with open("agentmemory.json", "r") as f:
memory = json.load(f)
except FileNotFoundError:
memory = {}
memory[key] = value
with open("agentmemory.json", "w") as f:
json.dump(memory, f, indent=2)
return f"Successfully saved: {key} = {value}"
@tool
def recallmemory(key: str) -> str:
"""
Retrieves information from persistent memory.
Args:
key: Key of the information to retrieve
Returns:
Stored value or not found message
"""
try:
with open("agentmemory.json", "r") as f:
memory = json.load(f)
return memory.get(key, f"No information found for key: {key}")
except FileNotFoundError:
return "Memory is empty"
Multi-Agent Orchestration with ManagedAgent
ManagedAgent allows you to create multi-agent systems where a manager agent delegates tasks to specialist agents.
from smolagents import CodeAgent, HfApiModel, DuckDuckGoSearchTool, ManagedAgent
model = HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct")
Specialist agent for web research
webresearcher = CodeAgent(
tools=[DuckDuckGoSearchTool()],
model=model,
maxsteps=5
)
Wrap as ManagedAgent
managedresearcher = ManagedAgent(
agent=webresearcher,
name="webresearcher",
description="Agent specialized in searching and analyzing information from the internet. Use this agent when you need to find facts, data, or the latest information."
)
Specialist agent for data analysis
dataanalyst = CodeAgent(
tools=[],
model=model,
additionalauthorizedimports=["numpy", "pandas"],
maxsteps=5
)
managedanalyst = ManagedAgent(
agent=dataanalyst,
name="dataanalyst",
description="Agent specialized in data analysis using Python. Use this agent for statistical computation, dataset analysis, and data visualization."
)
Manager agent (orchestrator)
manageragent = CodeAgent(
tools=[],
model=model,
managedagents=[managedresearcher, managedanalyst],
maxsteps=10
)
Run complex task
result = manageragent.run("""
Conduct research on digital economy growth in Southeast Asia:
Find the latest data and statistics
Analyze growth trends
Create a summary with key insights
""")
print(result)
Common Multi-Agent Patterns
# Pattern: Researcher + Writer
researcher = ManagedAgent(
agent=CodeAgent(
tools=[DuckDuckGoSearchTool()],
model=model,
maxsteps=5
),
name="researcher",
description="Searches and collects information from the internet"
)
writer = ManagedAgent(
agent=CodeAgent(
tools=[],
model=model,
maxsteps=5
),
name="writer",
description="Writes content based on provided information"
)
Manager coordinates researcher and writer
manager = CodeAgent(
tools=[],
model=model,
managedagents=[researcher, writer],
maxsteps=10
)
Gradio UI Integration
Smolagents can be integrated with Gradio to create an interactive chat interface.
from smolagents import CodeAgent, HfApiModel, DuckDuckGoSearchTool, GradioUI
Create agent
agent = CodeAgent(
tools=[DuckDuckGoSearchTool()],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=5
)
Launch Gradio UI
ui = GradioUI(agent)
ui.launch(
servername="0.0.0.0",
serverport=7860,
share=False
)
After running, open your browser at http://localhost:7860 to access the chat interface.
Customizing Gradio UI
ui = GradioUI(
agent,
fileuploadfolder="./uploads", # Folder for uploaded files
)
ui.launch(
servername="0.0.0.0",
serverport=7860,
share=True # Create a public URL via Gradio
)
Practical Example: Research Agent
Now we will build a complete research agent that can search the web, process data, and generate structured reports.
Project Setup
mkdir research-agent && cd research-agent
pip install smolagents[all] python-dotenv
Creating Custom Tools
# tools.py
import json
from datetime import datetime
from smolagents import tool
@tool
def savereport(title: str, content: str, format: str = "md") -> str:
"""
Saves a report to a file.
Args:
title: Report title
content: Report content
format: File format (md or txt)
Returns:
Confirmation with file path
"""
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
filename = f"reports/{title.lower().replace(' ', '')}{timestamp}.{format}"
import os
os.makedirs("reports", existok=True)
with open(filename, "w") as f:
f.write(content)
return f"Report saved successfully at: {filename}"
@tool
def analyzetext(text: str, analysistype: str) -> str:
"""
Analyzes text with various methods.
Args:
text: Text to analyze
analysistype: Type of analysis (wordcount, sentiment, summarystats)
Returns:
Analysis results as a formatted string
"""
if analysistype == "wordcount":
words = text.split()
sentences = text.split('.')
paragraphs = text.split('\n\n')
return json.dumps({
"words": len(words),
"sentences": len(sentences),
"paragraphs": len(paragraphs),
"avgwordspersentence": len(words) / max(len(sentences), 1)
}, indent=2)
elif analysistype == "summarystats":
words = text.split()
uniquewords = set(w.lower() for w in words)
return json.dumps({
"totalwords": len(words),
"uniquewords": len(uniquewords),
"vocabularyrichness": len(uniquewords) / max(len(words), 1),
"mostcommon": max(set(words), key=words.count) if words else ""
}, indent=2)
else:
return f"Analysis type '{analysistype}' is not recognized"
@tool
def formatreport(title: str, sections: str) -> str:
"""
Formats a research report with a standard template.
Args:
title: Report title
sections: Section content as a JSON string
Returns:
Formatted report in markdown
"""
try:
sectiondata = json.loads(sections)
except json.JSONDecodeError:
return "Error: sections must be a valid JSON string"
report = f"# {title}\n\n"
report += f"Date: {datetime.now().strftime('%B %d, %Y')}\n"
report += f"Generated by: Research Agent (Smolagents)\n\n"
for section in sectiondata:
report += f"## {section.get('heading', 'Untitled')}\n\n"
report += f"{section.get('content', '')}\n\n"
report += "## Disclaimer\n\n"
report += "This report was automatically generated by an AI Research Agent. "
report += "Verification of data and facts is required before official use.\n"
return report
Building the Research Agent
# researchagent.py
from smolagents import (
CodeAgent, HfApiModel, OpenAIServerModel,
DuckDuckGoSearchTool, VisitWebpageTool, ManagedAgent
)
from tools import save
report, analyzetext, formatreport
Choose model
model = OpenAIServerModel(modelid="gpt-4o")
Web research specialist agent
webagent = CodeAgent(
tools=[DuckDuckGoSearchTool(), VisitWebpageTool()],
model=model,
maxsteps=8,
name="webresearcher",
description="Searches for information on the internet"
)
managedweb = ManagedAgent(
agent=webagent,
name="webresearcher",
description="Agent that searches and collects information from the internet. Provide a specific topic to search for."
)
Analysis and writing specialist agent
analysisagent = CodeAgent(
tools=[analyzetext, formatreport, savereport],
model=model,
additionalauthorizedimports=["json", "datetime"],
maxsteps=5,
name="analystwriter",
description="Analyzes data and writes reports"
)
managedanalyst = ManagedAgent(
agent=analysisagent,
name="analystwriter",
description="Agent that analyzes text data and writes formatted reports. Provide raw data to be analyzed and written into a report."
)
Manager agent (orchestrator)
researchmanager = CodeAgent(
tools=[],
model=model,
managedagents=[managedweb, managedanalyst],
maxsteps=12,
verbose=True
)
Run research
result = researchmanager.run("""
Conduct in-depth research on the development of open-source
Large Language Models (LLMs) in 2025-2026. Focus on:
Latest open-source models and their performance
Comparison with proprietary models
Industry and startup adoption trends
Predictions for future development
Generate a comprehensive research report and save it to a file.
""")
print("Research complete!")
print(result)
Running the Research Agent
# Run the research agent
python researchagent.py
Adding a Gradio Interface
# app.py
from smolagents import CodeAgent, OpenAIServerModel, DuckDuckGoSearchTool, VisitWebpageTool, GradioUI
from tools import savereport, analyzetext, formatreport
model = OpenAIServerModel(modelid="gpt-4o")
agent = CodeAgent(
tools=[
DuckDuckGoSearchTool(),
VisitWebpageTool(),
analyzetext,
formatreport,
savereport
],
model=model,
additionalauthorizedimports=["json", "datetime"],
maxsteps=10,
verbose=True
)
Launch UI
ui = GradioUI(agent)
ui.launch(servername="0.0.0.0", serverport=7860)
Tips and Best Practices
Security
# Limit authorized imports
agent = CodeAgent(
tools=[],
model=model,
additionalauthorizedimports=["numpy", "pandas"],
# Do not allow os, subprocess, etc. for security
maxsteps=5
)
Error Handling
from smolagents import CodeAgent, HfApiModel
try:
agent = CodeAgent(
tools=[],
model=HfApiModel(modelid="Qwen/Qwen2.5-Coder-32B-Instruct"),
maxsteps=5
)
result = agent.run("Analyze this data")
except Exception as e:
print(f"Agent error: {e}")
# Fallback logic
Performance Optimization
# Limit the number of steps to save tokens
agent = CodeAgent(
tools=[],
model=model,
maxsteps=5, # Do not set too many
)
Use a specific system prompt
agent = CodeAgent(
tools=[DuckDuckGoSearchTool()],
model=model,
systemprompt="""You are an efficient research assistant.
Always:
Plan your steps before acting
Only use tools when necessary
Provide concise and structured answers
"""
)
Logging and Debugging
import logging
logging.basicConfig(level=logging.INFO)
Enable verbose mode
agent = CodeAgent(
tools=[],
model=model,
max_steps=5,
verbose=True # Show each reasoning step
)
Conclusion
Smolagents from HuggingFace offers a fresh approach to building AI agents. With its code-first philosophy and minimalist design, this framework enables developers to:
- Build agents quickly using CodeAgent that generates Python code
- Create custom tools easily using the
@tooldecorator - Integrate various LLM models (HuggingFace, OpenAI, Anthropic, local)
- Orchestrate multi-agent systems with ManagedAgent
- Create interactive UIs with Gradio
Compared to other agent frameworks, Smolagents stands out for its simplicity. There are no excessive abstractions, no complicated boilerplate. Just define tools, choose a model, and run the agent.
This framework is ideal for rapid prototyping, research projects, and applications that need lightweight AI agents without heavy infrastructure overhead. With the active HuggingFace community support, Smolagents continues to evolve with exciting new features.