A Coding Implementation to Build Multi-Agent AI Systems with SmolAgents Using Code Execution, Tool Calling, and Dynamic Orchestration
In this tutorial, we construct a sophisticated, production-ready agentic system utilizing SmolAgents and reveal how trendy, light-weight AI brokers can motive, execute code, dynamically handle instruments, and collaborate throughout a number of brokers. We begin by putting in dependencies and configuring a strong but environment friendly LLM backend, and then progressively design customized instruments, together with mathematical utilities, reminiscence storage, and net search capabilities. We discover each CodeAgent and ToolCallingAgent paradigms, perceive how instruments are managed dynamically by the agent.instruments dictionary, and implement multi-agent orchestration.
import subprocess, sys
def pip(*args):
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", *args])
pip("smolagents[all]", "duckduckgo-search", "wikipedia", "wealthy")
import os, math, textwrap
from wealthy.console import Console
from wealthy.panel import Panel
from wealthy.desk import Table
from wealthy import print as rprint
console = Console()
def part(title: str, shade: str = "daring cyan"):
console.rule(f"[{color}]{title}[/{color}]")
def present(label: str, worth):
console.print(Panel(str(worth), title=f"[bold yellow]{label}[/bold yellow]", increase=False))
import getpass
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
if not OPENAI_API_KEY:
OPENAI_API_KEY = getpass.getpass("
Enter your OpenAI API key: ")
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
console.print("[green]✓ OpenAI API key loaded.[/green]")
part("SECTION 1 · SmolAgents Architecture")
console.print(Panel("""
SmolAgents (HuggingFace) is a minimalist agent framework.
Current secure launch: 1.24.0 | Using: OpenAI gpt-4o-mini
CORE ABSTRACTIONS
Tool
agent.instruments (dict)
ToolAssortment
LiteLLMModel
CodeAgent
ToolCallingAgent
MULTI-AGENT (v1.8+ API)
Pass sub-agents instantly through managed_agents=[sub_agent]
Sub-agents want identify= and description= set at init.
ManagedAgent wrapper class was eliminated in v1.8.0.
EXECUTION LOOP (CodeAgent)
Task ──► LLM writes Python ──► sandbox executes it
◄── commentary (device output / exception) ◄──
Repeats up to max_steps, then calls final_answer(...)
""", title="[bold green]Architecture[/bold green]"))
We set up all required dependencies and arrange the execution setting. We configure safe API key loading and initialize the wealthy console utilities for structured output formatting. We additionally introduce the architectural overview of SmolAgents to set up a robust conceptual basis earlier than constructing brokers.
part("SECTION 2 · Building Custom Tools")
from smolagents import Tool, device
@device
def celsius_to_fahrenheit(celsius: float) -> str:
return f"{celsius}°C = {celsius * 9/5 + 32:.2f}°F"
class PrimeTool(Tool):
identify = "prime_checker"
description = (
"If composite, returns the smallest prime issue."
)
inputs = {
"n": {"sort": "integer", "description": "Positive integer to take a look at."}
}
output_type = "string"
def ahead(self, n: int) -> str:
if n < 2:
return f"{n} isn't prime (have to be >= 2)."
for i in vary(2, int(math.isqrt(n)) + 1):
if n % i == 0:
return f"{n} is NOT prime. Smallest issue: {i}."
return f"{n} IS prime!"
class MemoTool(Tool):
identify = "memory_store"
description = (
"Stores or retrieves key-value pairs. "
"motion='set' shops key+worth; "
"motion='get' retrieves by key; "
"motion='record' reveals all keys."
)
inputs = {
"motion": get ,
"key": {"sort": "string", "description": "Memory key (skip for record)", "nullable": True},
"worth": {"sort": "string", "description": "Value to retailer (set solely)", "nullable": True},
}
output_type = "string"
def __init__(self, *args, **kwargs):
tremendous().__init__(*args, **kwargs)
self._store: dict[str, str] = {}
def ahead(self, motion: str, key: str = None, worth: str = None) -> str:
if motion == "set":
self._store[key] = worth
return f"Stored '{key}' = '{worth}'"
elif motion == "get":
return self._store.get(key, f"Key '{key}' not discovered.")
elif motion == "record":
return "Keys: " + ", ".be part of(self._store.keys()) if self._store else "Memory empty."
return "Unknown motion. Use: set | get | record"
We outline customized instruments utilizing each decorator-based and class-based approaches to reveal flexibility in device creation. We implement mathematical reasoning and a stateful reminiscence device to allow persistent interactions throughout agent steps. We construction the instruments with clear schemas so the brokers can interpret and invoke them accurately.
class DuckDuckGoTool(Tool):
identify = "web_search"
description = "Performs an internet search and returns prime outcomes as plain textual content."
inputs = {
"question": {"sort": "string", "description": "The search question."},
"max_results": {"sort": "integer", "description": "Results to return (1-10).", "nullable": True},
}
output_type = "string"
def ahead(self, question: str, max_results: int = 3) -> str:
strive:
from duckduckgo_search import DDGS
with DDGS() as ddgs:
outcomes = [
f"* {r['title']}n {r['href']}n {r['body'][:200]}"
for r in ddgs.textual content(question, max_results=max_results)
]
return "nn".be part of(outcomes) if outcomes else "No outcomes discovered."
besides Exception as e:
return f"Search failed: {e}"
@device
def factorial(n: int) -> str:
return f"{n}! = {math.factorial(n)}"
present("celsius_to_fahrenheit(100)", celsius_to_fahrenheit(100))
present("PrimeTool — 97", PrimeTool().ahead(97))
present("PrimeTool — 100", PrimeTool().ahead(100))
m = MemoTool()
m.ahead("set", "creator", "Ada Lovelace")
present("MemoTool get 'creator'", m.ahead("get", "creator"))
part("SECTION 3 · Managing Tools (agent.instruments dict)")
console.print(Panel("""
The Toolbox class was eliminated in v1.x.
Tools reside in agent.instruments, a plain Python dict keyed by device identify.
""", title="[bold green]Tools Dict[/bold green]"))
part("SECTION 4 · LLM Engines")
console.print(Panel("""
SmolAgents helps a number of LLM backends through LiteLLMModel.
We use gpt-4o-mini.
""", title="[bold green]Engine Options[/bold green]"))
from smolagents import LiteLLMModel
MODEL_ID = "openai/gpt-4o-mini"
engine = LiteLLMModel(model_id=MODEL_ID, api_key=OPENAI_API_KEY)
console.print(f"[green]Engine prepared:[/green] {MODEL_ID}")
We lengthen the system with an internet search device and a factorial utility to broaden the agent’s capabilities. We take a look at the instruments independently to confirm correctness earlier than integrating them into brokers. We additionally initialize the LLM engine utilizing LiteLLMModel, getting ready the core reasoning backend for execution.
part("SECTION 5 · CodeAgent")
from smolagents import CodeAgent
code_agent = CodeAgent(
instruments = [celsius_to_fahrenheit, PrimeTool(), MemoTool(), DuckDuckGoTool()],
mannequin = engine,
max_steps = 6,
verbosity_level = 1,
)
console.print("n[bold]Initial agent.instruments keys:[/bold]", record(code_agent.instruments.keys()))
code_agent.instruments["factorial"] = factorial
console.print("[dim]After including factorial:[/dim]", record(code_agent.instruments.keys()))
console.print("n[bold yellow]Task 1:[/bold yellow]")
result1 = code_agent.run(
"Convert boiling level (100C) and physique temperature (37C) to Fahrenheit. "
"Which is increased and by how a lot?"
)
present("CodeAgent — Task 1", result1)
console.print("n[bold yellow]Task 2:[/bold yellow]")
result2 = code_agent.run("What is 17 instances 19? Is that outcome prime? Also examine 7919.")
present("CodeAgent — Task 2", result2)
console.print("n[bold yellow]Task 3:[/bold yellow]")
result3 = code_agent.run("Compute 10! utilizing the factorial device.")
present("CodeAgent — Task 3", result3)
We assemble a CodeAgent that may write and execute Python dynamically to clear up multi-step issues. We reveal runtime device injection by including a brand new device with out rebuilding the agent. We then execute progressively complicated reasoning duties to validate chaining, arithmetic computation, and device coordination.
part("SECTION 6 · ToolCallingAgent (ReAct)")
from smolagents import ToolCallingAgent
react_agent = ToolCallingAgent(
instruments = [celsius_to_fahrenheit, PrimeTool(), MemoTool()],
mannequin = engine,
max_steps = 5,
verbosity_level = 1,
)
console.print("n[bold yellow]Task 4:[/bold yellow]")
result4 = react_agent.run(
"Then retrieve each details and summarise them."
)
present("ToolCallingAgent — Task 4", result4)
part("SECTION 7 · Multi-Agent Orchestration (v1.8+ API)")
math_agent = CodeAgent(
instruments = [PrimeTool()],
mannequin = engine,
max_steps = 4,
identify = "math_specialist",
description = "Handles mathematical questions and primality checks.",
verbosity_level = 0,
)
research_agent = ToolCallingAgent(
instruments = [DuckDuckGoTool(), MemoTool()],
mannequin = engine,
max_steps = 4,
identify = "research_specialist",
description = "Searches the online and shops or retrieves details from reminiscence.",
verbosity_level = 0,
)
manager_agent = CodeAgent(
instruments = [],
mannequin = engine,
managed_agents = [math_agent, research_agent],
max_steps = 8,
verbosity_level = 1,
)
console.print("n[bold yellow]Task 5:[/bold yellow]")
result5 = manager_agent.run(
"Find out what 12 months Python was first launched (use research_specialist), "
"then examine whether or not that 12 months is a chief quantity (use math_specialist)."
)
present("Manager Agent — Task 5", result5)
We construct a ToolCallingAgent to showcase structured ReAct-style reasoning with managed device invocation. We then implement a multi-agent orchestration system the place specialised brokers collaborate beneath a supervisor agent. We reveal delegation, coordination, and cross-agent reasoning to clear up compound duties effectively.
In conclusion, we constructed a completely practical multi-agent system able to reasoning, looking, calculating, storing reminiscence, and delegating duties between specialised brokers. We demonstrated how SmolAgents allows versatile device integration, runtime extensibility, and structured collaboration with out pointless architectural complexity. We confirmed how CodeAgent executes actual Python logic for superior chaining, whereas ToolCallingAgent ensures structured, auditable reasoning loops. Finally, we carried out a supervisor agent that coordinates specialised sub-agents, proving how scalable orchestration might be achieved with minimal overhead.
Check out the Full Implementation Code and Notebook. Also, be happy to observe us on Twitter and don’t overlook to be part of our 130k+ ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to companion with us for selling your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar and so on.? Connect with us
The put up A Coding Implementation to Build Multi-Agent AI Systems with SmolAgents Using Code Execution, Tool Calling, and Dynamic Orchestration appeared first on MarkTechPost.
