Sitemap

Smolagents Cheat Sheet

5 min readJun 26, 2026

--

Hugging Face’s minimal library for agents that think in code.

Core idea: the LLM writes Python snippets to call your tools instead of emitting JSON tool calls. (~1,000 lines of core code, model-agnostic.)

Install

pip install smolagents                  # core
pip install 'smolagents[toolkit]' # + default tools (web search, etc.)
pip install 'smolagents[litellm]' # OpenAI / Anthropic / 100+ via LiteLLM
pip install 'smolagents[transformers]' # local HF models
pip install 'smolagents[mcp]' # MCP server integration
pip install 'smolagents[openai]' # OpenAI-compatible servers
pip install 'smolagents[telemetry]' # OpenTelemetry tracing
pip install 'smolagents[gradio]' # GradioUI

Hello, agent

from smolagents import CodeAgent, InferenceClientModel
model = InferenceClientModel() # default HF Inference model
agent = CodeAgent(tools=[], model=model)
print(agent.run("Sum the numbers from 1 to 10"))

Agent types

Press enter or click to view image in full size
Difference between CodeAgent an ToolCallingAgent
from smolagents import ToolCallingAgent, WebSearchTool
agent = ToolCallingAgent(tools=[WebSearchTool()], model=model)

Common constructor args

agent = CodeAgent(
tools=[...], # list of Tool INSTANCES (not classes)
model=model,
add_base_tools=True, # include the default toolbox
max_steps=10, # cap reasoning steps
verbosity_level=1, # 0 silent, 1 steps, 2 detailed
planning_interval=3, # re-plan every N steps (None = off)
stream_outputs=True,
additional_authorized_imports=["numpy", "pandas"], # CodeAgent only
executor_type="local", # "local" | "e2b" | "docker" | "blaxel" | "modal" | "wasm"
step_callbacks=[my_callback],
name="...", description="...", # only needed if used as a managed sub-agent
)

Running

agent.run("task")                                  # returns final answer
agent.run("task", reset=False) # keep memory (follow-up)
agent.run("task", additional_args={"key": value}) # inject objects/state
agent.run("Describe this", images=[pil_image]) # vision input
for chunk in agent.run("task", stream=True): ... # stream steps

Models

# HF Inference providers (Cerebras, Together, Novita, SambaNova, Fireworks, ...)
from smolagents import InferenceClientModel
model = InferenceClientModel(model_id="deepseek-ai/DeepSeek-R1", provider="together")

# LiteLLM -> OpenAI, Anthropic, Gemini, etc.
from smolagents import LiteLLMModel
model = LiteLLMModel(model_id="anthropic/claude-sonnet-4-5", api_key=os.environ["ANTHROPIC_API_KEY"], temperature=0.2)
# Any OpenAI-compatible endpoint (OpenAI, OpenRouter, Together, vLLM, Ollama...)
from smolagents import OpenAIServerModel # newer alias: OpenAIModel
model = OpenAIServerModel(model_id="gpt-4o", api_base="https://api.openai.com/v1", api_key=os.environ["OPENAI_API_KEY"])
# Local transformers pipeline
from smolagents import TransformersModel
model = TransformersModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct")

Also available: AzureOpenAIModel, AmazonBedrockModel, MLXModel (Apple Silicon).

Tools

Default toolbox ([toolkit] extra)

WebSearchTool · DuckDuckGoSearchTool · GoogleSearchTool · VisitWebpageTool · PythonInterpreterTool · FinalAnswerTool · UserInputTool · SpeechToTextTool

Add them all with add_base_tools=True.

Custom tool — decorator (quick)

The function needs type hints + a docstring with an Args: section (these become the schema the LLM sees).

from smolagents import tool
@tool
def get_product_price(product_name: str) -> float:
"""Gets the price of a product.
Args:
product_name: The name of the product to look up.
"""
return PRICES[product_name]
agent = CodeAgent(tools=[get_product_price], model=model)

Custom tool — class (full control)

from smolagents import Tool
class QueryTool(Tool):
name = "qdrant_query"
description = "Semantic search over the movie collection."
inputs = {
"query": {"type": "string", "description": "Text query, semantically close to targets."}
}
output_type = "string"
def forward(self, query: str) -> str:
... # your logic
return result

Import existing tools

# A Hugging Face Space as a tool
from smolagents import Tool
image_gen = Tool.from_space("black-forest-labs/FLUX.1-schnell", name="image_generator", description="Generate an image")

# Hub-shared tool
from smolagents import load_tool
t = load_tool("m-ric/text-to-image", trust_remote_code=True)

# LangChain tool
from smolagents import Tool
lc_tool = Tool.from_langchain(some_langchain_tool)

Tool collections & MCP

# From a Hub collection (pulls tools from all Spaces in it)
from smolagents import ToolCollection, CodeAgent
coll = ToolCollection.from_hub("huggingface-tools/diffusion-tools-...", trust_remote_code=True)
agent = CodeAgent(tools=[*coll.tools], add_base_tools=True, model=model)

---

# From an MCP server (stdio)
from mcp import StdioServerParameters
params = StdioServerParameters(command="uvx", args=["mcp-server-fetch"])
with ToolCollection.from_mcp(params, trust_remote_code=True) as tc:
agent = CodeAgent(tools=[*tc.tools], model=model)
agent.run("Fetch the homepage of huggingface.co")

# From an MCP server (HTTP)
with ToolCollection.from_mcp(
{"url": "http://127.0.0.1:8000/mcp", "transport": "streamable-http"},
trust_remote_code=True,
) as tc:
agent = ToolCallingAgent(tools=[*tc.tools], model=model)

---Multi-agent (orchestration)

Give a sub-agent a name + description, then pass it via managed_agents. The manager calls it like any other tool.

from smolagents import CodeAgent, ToolCallingAgent, WebSearchTool, VisitWebpageTool

web_agent = ToolCallingAgent(
tools=[WebSearchTool(), VisitWebpageTool()],
model=model,
name="web_search_agent",
description="Runs web searches. Give it your query as an argument.",
)

manager = CodeAgent(
tools=[],
model=model,
managed_agents=[web_agent],
additional_authorized_imports=["time", "numpy", "pandas"],
)
manager.run("Who is the CEO of Hugging Face, and what year were they born?"Secure code execution

Secure code execution

Get Deeptij’s stories in your inbox

Join Medium for free to get updates from this writer.

CodeAgent runs locally by default (restricted interpreter: only your tools + a safe builtins/imports list). Authorize more withadditional_authorized_imports. For untrusted workloads, sandbox it:

agent = CodeAgent(tools=[...], model=model, executor_type="e2b")     # needs E2B_API_KEY
agent = CodeAgent(tools=[...], model=model, executor_type="docker")
agent = CodeAgent(tools=[...], model=model, executor_type="blaxel") # BL_API_KEY + BL_WORKSPACE

⚠️ The LLM can generate arbitrary code. Never authorize unsafe imports on untrusted input; prefer a sandbox in production.

Inspect, debug, replay

agent.memory.steps          # full step-by-step record (task, thoughts, tool calls, observations, timings, tokens)
agent.replay() # pretty re-print of the whole run
agent.logs # raw logs

Step callback (runs after each step — handy for logging or trimming memory):

from smolagents import ActionStep, CodeAgent
def log_step(step: ActionStep, agent: CodeAgent) -> None:
print(f"Done step {step.step_number}")
if step.step_number > 5:
step.observations_images = None # drop images to save tokens
agent = CodeAgent(tools=[...], model=model, step_callbacks=[log_step])

Drive the loop manually:

from smolagents import TaskStep, ActionStep
agent.memory.steps.append(TaskStep(task="...", task_images=[]))
final = None; n = 1
while final is None and n <= 10:
s = ActionStep(step_number=n, observations_images=[])
final = agent.step(s)
agent.memory.steps.append(s); n += 1

Share & serve

# Push / pull agents and tools to the Hub
agent.push_to_hub("username/my-agent")
agent = CodeAgent.from_hub("username/my-agent", trust_remote_code=True)
my_tool.push_to_hub("username/my-tool")

# Web UI
from smolagents import GradioUI
GradioUI(agent).launch()

CLI

# generalist multi-step CodeAgent
smolagent "Plan a trip to Tokyo, Kyoto and Osaka" \
--model-type InferenceClientModel \
--model-id "Qwen/Qwen2.5-Coder-32B-Instruct" \
--imports pandas numpy \
--tools web_search
smolagent # interactive setup wizard (no prompt)

# vision web-browsing agent (uses helium)
webagent "Go to example.com and find the pricing page" \
--model-type LiteLLMModel --model-id gpt-4o

Quick decisions

  • CodeAgent vs ToolCallingAgent → composition/reasoning vs reliable atomic calls.
  • Which model class → HF Inference: InferenceClientModel · OpenAI/Anthropic/etc.: LiteLLMModel · any OpenAI-compatible URL: OpenAIServerModel · local: TransformersModel.
  • Custom tool → simple fn: @tool · stateful/complex: subclass Tool.
  • Production → set a low max_steps, use a sandbox (e2b/docker), never trust raw imports, keep a human in the loop for tool calls.

Resources

Docs: huggingface.co/docs/smolagents

Repo: github.com/huggingface/smolagents

--

--