Aller au contenu
Développement medium

smolagents : quand l'agent IA écrit du code

10 min de lecture

logo python

Les agents des guides précédents appellent leurs outils en JSON : un nom de fonction, des arguments. smolagents, la bibliothèque de Hugging Face, prend le parti inverse — son CodeAgent fait écrire au modèle du code Python, qu'il exécute. Enchaîner des actions, boucler, stocker un résultat intermédiaire : tout cela s'exprime naturellement en code, laborieusement en JSON. Vous construirez un agent d'analyse de données qui charge un CSV, calcule des agrégats et produit un graphique — en une poignée de lignes. Au passage : l'interpréteur restreint de smolagents, ses limites de sécurité, et le critère pour choisir entre un agent-code et un agent-JSON. Public visé : développeur ayant lu les guides sur le function calling et les frameworks d'agents.

  • Pourquoi faire écrire du code à un agent plutôt que du JSON.
  • La différence entre CodeAgent et ToolCallingAgent.
  • Brancher smolagents sur un modèle Ollama local.
  • Construire un agent d'analyse de données avec pandas et matplotlib.
  • Les garde-fous de l'interpréteur restreint — et ce qu'il ne protège pas.

Ce guide prolonge Function calling et outils : la notion d'outil y est posée. Il vous faut :

  • Une instance Ollama avec le modèle qwen2.5.
  • Les bases de pandas et de Python.
  • Python 3.10+.

Code plutôt que JSON : la philosophie de smolagents

Section intitulée « Code plutôt que JSON : la philosophie de smolagents »

Quand un agent veut enchaîner deux actions — récupérer une liste, puis filtrer ses éléments —, le format JSON l'oblige à un aller-retour : un appel d'outil, le résultat renvoyé au modèle, un second appel. Chaque étape repasse par le modèle. Et stocker un résultat intermédiaire, le réutiliser, boucler dessus : le JSON n'a pas de variables, pas de boucles.

Le code, lui, a tout cela. Faire écrire au modèle lignes = charger(); total = sum(l["montant"] for l in lignes) exprime en une expression ce que le JSON étalerait sur plusieurs tours. C'est l'idée de smolagents : le code est le bon langage pour décrire des actions — composable, doté de variables, de boucles, d'appels imbriqués. Des travaux de recherche montrent qu'un modèle qui agit en code se trompe moins qu'un modèle qui agit en JSON.

La contrepartie est sérieuse, et le guide y revient : un agent qui écrit du code est un agent qui exécute du code. Du code généré par un modèle, donc potentiellement faux ou dangereux.

smolagents propose deux types d'agents, et le choix n'est pas anodin.

Le CodeAgent est le cœur de la bibliothèque : à chaque étape, le modèle écrit un bloc de code Python que l'agent exécute. C'est l'approche « code » décrite ci-dessus, recommandée par défaut.

Le ToolCallingAgent suit le paradigme classique : le modèle émet des appels d'outils en JSON, comme dans les guides PydanticAI et LangGraph. smolagents le fournit pour les cas où ce format est imposé — un fournisseur de modèle qui ne gère bien que le JSON, par exemple.

Ce guide utilise le CodeAgent : c'est lui qui porte la singularité de smolagents.

smolagents est agnostique au modèle. Pour viser un Ollama local, on passe par LiteLLMModel, qui s'appuie sur LiteLLM — la couche d'unification déjà rencontrée dans le guide sur le function calling.

from smolagents import LiteLLMModel
MODELE = LiteLLMModel(
model_id="ollama_chat/qwen2.5", api_base="http://localhost:11434"
)

Le préfixe ollama_chat/ n'est pas un détail : il indique à LiteLLM d'utiliser le format de requête de conversation d'Ollama, plus fiable pour un agent que le format générique. Un modèle solide en génération de code — qwen2.5 ici — est un bon choix : le CodeAgent lui demande, à chaque étape, du Python correct.

L'agent va répondre à une question d'analyse sur un fichier ventes.csv (colonnes region, produit, montant). On le crée avec CodeAgent.

from smolagents import CodeAgent
IMPORTS_AUTORISES = ["pandas", "numpy", "matplotlib", "matplotlib.*"]
def construire_agent() -> CodeAgent:
return CodeAgent(
tools=[],
model=MODELE,
additional_authorized_imports=IMPORTS_AUTORISES,
max_steps=6,
)

Trois paramètres méritent l'attention. tools=[] : l'agent n'a aucun outil sur mesure — il n'en a pas besoin, il écrit lui-même le code pandas. additional_authorized_imports autorise les bibliothèques dont le code généré aura besoin ; on y revient plus bas. max_steps borne le nombre d'allers-retours avec le modèle — un garde-fou contre une boucle qui n'aboutit pas.

L'agent se lance avec run, en lui passant la tâche en langage naturel :

TACHE = (
"Charge le fichier ventes.csv (colonnes region, produit, montant). "
"Calcule le chiffre d'affaires total par région. Enregistre un "
"graphique en barres dans le fichier ventes.png. Conclus en nommant "
"la région qui réalise le meilleur chiffre d'affaires."
)
agent = construire_agent()
conclusion = agent.run(TACHE)

Le modèle traduit cette consigne en Python. Sur l'exécution du lab, il écrit, en un seul bloc, le chargement, l'agrégation, le graphique et la réponse :

plt.bar(sales_by_region['region'], sales_by_region['montant'])
plt.savefig('ventes.png')
best_region = sales_by_region.loc[sales_by_region['montant'].idxmax(), 'region']
final_answer(best_region)

Tout est là : un agrégat pandas, un graphique matplotlib, une réponse finale via final_answer — la fonction par laquelle le CodeAgent clôt sa tâche. Aucun outil JSON n'aurait enchaîné ces quatre opérations dans un seul appel. C'est la composabilité du code en action.

Un agent qui exécute du code généré par un modèle est un risque. smolagents n'exécute donc pas ce code dans l'interpréteur Python normal : il le passe à un interpréteur restreint maison, le LocalPythonExecutor.

Cet interpréteur lit le code instruction par instruction et applique des règles strictes. Les imports sont interdits par défaut : seules passent les bibliothèques explicitement listées dans additional_authorized_imports — d'où la liste pandas, numpy, matplotlib de notre agent. Un import os ou import subprocess est refusé. L'accès aux sous-modules est lui aussi bloqué sauf autorisation — d'où le matplotlib.*. Enfin, le nombre d'opérations est plafonné, ce qui neutralise les boucles infinies.

# Refusé : os n'est pas dans la liste d'imports autorisés.
import os; os.system("rm -rf /tmp/data")
# >>> InterpreterError: Import of os is not allowed.

smolagents ne remplace pas PydanticAI ou LangGraph — il répond à un besoin différent.

Le CodeAgent brille sur les tâches calculatoires et exploratoires : analyser des données, transformer des fichiers, enchaîner des opérations dont on ne connaît pas la séquence d'avance. Là où le travail est du code, faire écrire du code à l'agent est direct et naturel.

Un agent JSON typé — PydanticAI — reste préférable quand on veut une sortie structurée garantie et un périmètre d'outils fermé et contrôlé. Un graphe LangGraph s'impose quand le parcours doit être explicite et débogable étape par étape. Et dans tous les cas où le code généré toucherait à des ressources sensibles, le coût d'isolation d'un CodeAgent peut dépasser son bénéfice.

Le critère tient en une question : la tâche est-elle, par nature, du code ? Si oui, smolagents est taillé pour elle. Sinon, un agent à outils JSON est plus sûr et plus prévisible.

SymptômeCause probableSolution
InterpreterError: Import of ... is not allowedBibliothèque non autoriséeL'ajouter à additional_authorized_imports
Accès à un sous-module refuséSous-module non autoriséAutoriser paquet.* dans la liste d'imports
L'agent s'arrête sans réponsemax_steps atteintAugmenter max_steps ou simplifier la tâche
matplotlib échoue sur une machine sans écranBackend interactif par défautForcer MPLBACKEND=Agg avant l'exécution
Le code généré est souvent incorrectModèle faible en génération de codeChoisir un modèle solide en code (qwen2.5)
  • smolagents fait écrire du code Python à l'agent, là où les autres frameworks font émettre du JSON.
  • Le code compose : boucles, variables, appels imbriqués — un format JSON ne le permet pas.
  • CodeAgent est l'approche code ; ToolCallingAgent garde le paradigme JSON classique.
  • LiteLLMModel avec le préfixe ollama_chat/ branche smolagents sur un Ollama local.
  • L'interpréteur restreint bloque les imports non autorisés — mais ne remplace pas une vraie isolation.
  • Choisir smolagents quand la tâche est du code ; un agent JSON typé sinon.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn