Construire un Agent IA avec Python
Apprenez à créer un agent IA fonctionnel en Python : tool calling avec l'API OpenAI/Anthropic, framework Agno, gestion de la mémoire et déploiement.
Prérequis
Avant de commencer, assurez-vous d''avoir :
- Des bases en Python
- Une clé API OpenAI ou Anthropic
- Compréhension des LLMs (voir notre cours sur les LLMs)
L''API de Tool Calling : la Brique de Base
Tous les grands LLMs proposent aujourd''hui une API de tool calling (ou function calling). Le principe : vous décrivez les outils disponibles au modèle, et il décide quand les utiliser.
Avec l''API OpenAI
import openai
# 1. Définir les outils disponibles
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obtenir la météo actuelle d''une ville",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Nom de la ville"
}
},
"required": ["city"]
}
}
}
]
# 2. Envoyer la requête avec les outils
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Quel temps fait-il à Paris ?"}],
tools=tools,
)
# 3. Le modèle décide d''appeler l''outil
tool_call = response.choices[0].message.tool_calls[0]
print(tool_call.function.name) # "get_weather"
print(tool_call.function.arguments) # {"city": "Paris"}
Avec l''API Anthropic (Claude)
Anthropic propose deux approches : la méthode classique avec un schéma JSON, et le nouveau décorateur @beta_tool qui simplifie tout.
Méthode classique :
import anthropic
client = anthropic.Anthropic()
# Définir l''outil avec un schéma JSON
tools = [
{
"name": "get_weather",
"description": "Obtenir la météo d''une ville",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "Nom de la ville"}
},
"required": ["city"]
}
}
]
response = client.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "Météo à Lyon ?"}]
)
Méthode moderne avec @beta_tool (recommandée) :
import json
from anthropic import Anthropic, beta_tool
client = Anthropic()
@beta_tool
def get_weather(city: str) -> str:
"""Obtenir la météo d''une ville.
Args:
city: Nom de la ville
Returns:
Les données météo au format JSON.
"""
return json.dumps({"city": city, "temp": 18, "condition": "nuageux"})
# tool_runner gère automatiquement la boucle agent !
runner = client.beta.messages.tool_runner(
model="claude-sonnet-4-5-20250929",
max_tokens=1024,
tools=[get_weather],
messages=[{"role": "user", "content": "Météo à Lyon ?"}],
)
for message in runner:
print(message)
Le décorateur @beta_tool génère automatiquement le schéma JSON à partir des type hints Python. Et tool_runner gère toute la boucle agent pour vous — plus besoin de coder la boucle while manuellement !
Tool calling vs Function calling : C''est la même chose. OpenAI a d''abord utilisé le terme "function calling" avant de le renommer "tool calling". Anthropic utilise directement "tool use".
La Boucle Agent en Code
Voici la boucle agent complète, étape par étape :
Implémentation Python
import json
def run_agent(user_message: str, tools: list, tool_functions: dict):
"""Boucle agent complète avec tool calling."""
messages = [{"role": "user", "content": user_message}]
while True:
# Appel au LLM
response = openai.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
)
choice = response.choices[0]
# Si le LLM veut utiliser un outil
if choice.finish_reason == "tool_calls":
# Ajouter la réponse du LLM à l''historique
messages.append(choice.message)
# Exécuter chaque outil demandé
for tool_call in choice.message.tool_calls:
fn_name = tool_call.function.name
fn_args = json.loads(tool_call.function.arguments)
# Appeler la vraie fonction Python
result = tool_functions[fn_name](**fn_args)
# Renvoyer le résultat au LLM
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
})
# Sinon, c''est la réponse finale
else:
return choice.message.content
Utilisation
# Définir les fonctions réelles
def get_weather(city: str) -> dict:
# Ici on appellerait une vraie API météo
return {"city": city, "temp": 18, "condition": "nuageux"}
def search_restaurants(city: str, cuisine: str = "") -> dict:
return {"results": [f"Le Bon {cuisine} à {city}", f"Chez Marcel - {city}"]}
# Mapper les noms aux fonctions
tool_functions = {
"get_weather": get_weather,
"search_restaurants": search_restaurants,
}
# Lancer l''agent
answer = run_agent(
"Quel temps fait-il à Paris et recommande-moi un restaurant italien ?",
tools=tools_definition,
tool_functions=tool_functions,
)
print(answer)
# "Il fait 18°C à Paris (nuageux). Je vous recommande Le Bon italien à Paris !"
Ajouter de la Mémoire
Un agent sans mémoire oublie tout entre chaque conversation. Il existe plusieurs stratégies :
Mémoire conversationnelle simple
class ConversationMemory:
def __init__(self, max_messages: int = 50):
self.messages: list[dict] = []
self.max_messages = max_messages
def add(self, role: str, content: str):
self.messages.append({"role": role, "content": content})
# Garder seulement les N derniers messages
if len(self.messages) > self.max_messages:
self.messages = self.messages[-self.max_messages:]
def get_context(self) -> list[dict]:
return self.messages.copy()
Mémoire avec résumé
Pour les conversations longues, on peut résumer les anciens messages :
class SummarizedMemory:
def __init__(self):
self.summary = ""
self.recent_messages: list[dict] = []
def add(self, role: str, content: str):
self.recent_messages.append({"role": role, "content": content})
# Tous les 20 messages, résumer
if len(self.recent_messages) > 20:
self.summary = self._summarize()
self.recent_messages = self.recent_messages[-5:]
def _summarize(self) -> str:
# Demander au LLM de résumer la conversation
prompt = f"Résume cette conversation en 3-4 phrases :\n{self.recent_messages}"
# ... appel LLM ...
return summary
def get_context(self) -> list[dict]:
messages = []
if self.summary:
messages.append({
"role": "system",
"content": f"Résumé de la conversation précédente : {self.summary}"
})
messages.extend(self.recent_messages)
return messages
Framework : Agno
Agno est un framework Python open source conçu pour construire des agents IA. Sa philosophie : des fonctions Python simples comme outils, pas de schéma JSON, pas de décorateurs spéciaux.
Installation
Agent avec Agno
from agno.agent import Agent
from agno.models.anthropic import Claude
# 1. Définir des outils = simples fonctions Python
def get_weather(city: str) -> str:
"""Obtenir la météo actuelle d''une ville.
Args:
city: Nom de la ville.
Returns:
str: Les données météo de la ville.
"""
# Ici on appellerait une vraie API météo
return f"Il fait 18°C à {city}, ciel partiellement nuageux."
def search_restaurants(city: str, cuisine: str = "") -> str:
"""Chercher des restaurants dans une ville.
Args:
city: Nom de la ville.
cuisine: Type de cuisine (optionnel).
Returns:
str: Liste de restaurants trouvés.
"""
return f"Restaurants {cuisine} à {city} : Le Bon Goût, Chez Marcel"
# 2. Créer l''agent (une seule ligne !)
agent = Agent(
model=Claude(id="claude-sonnet-4-5"),
tools=[get_weather, search_restaurants],
instructions=["Réponds toujours en français."],
markdown=True,
)
# 3. Lancer l''agent
agent.print_response(
"Quel temps fait-il à Paris et recommande-moi un restaurant italien ?",
stream=True,
)
Pas besoin de décorateur @tool ni de schéma JSON manuel. Agno lit les type hints et la docstring de vos fonctions Python pour générer automatiquement la description des outils pour le LLM.
Agno avec différents modèles
Agno supporte tous les grands LLMs — changer de modèle = changer une ligne :
from agno.models.openai import OpenAIChat
from agno.models.anthropic import Claude
from agno.models.google import Gemini
# OpenAI
agent_gpt = Agent(model=OpenAIChat(id="gpt-4o"), tools=[get_weather])
# Anthropic
agent_claude = Agent(model=Claude(id="claude-sonnet-4-5"), tools=[get_weather])
# Google
agent_gemini = Agent(model=Gemini(id="gemini-2.5-flash"), tools=[get_weather])
Mémoire intégrée avec Agno
Agno fournit une gestion de mémoire native, bien plus puissante que notre implémentation manuelle :
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.memory import MemoryManager
from agno.models.anthropic import Claude
# Base de données pour la persistance
db = SqliteDb(db_file="tmp/agents.db")
# Le MemoryManager extrait automatiquement les faits importants
memory_manager = MemoryManager(
model=Claude(id="claude-sonnet-4-5"),
db=db,
)
agent = Agent(
model=Claude(id="claude-sonnet-4-5"),
db=db,
memory_manager=memory_manager,
enable_agentic_memory=True, # L''agent gère sa propre mémoire
add_history_to_context=True, # Historique dans le contexte
num_history_runs=5, # 5 dernières conversations
markdown=True,
)
# Première conversation
agent.print_response("Je m''appelle Alice et je travaille chez Acme", stream=True)
# Plus tard... l''agent se souvient !
agent.print_response("Quel est mon nom ?", stream=True)
# → "Vous vous appelez Alice et vous travaillez chez Acme."
Avec enable_agentic_memory, l''agent extrait automatiquement les informations importantes de chaque conversation (noms, préférences, faits clés) et les stocke dans SQLite. Plus besoin de gérer la mémoire manuellement !
Agno simplifie énormément la création d''agents : définissez vos outils comme de simples fonctions Python, créez un Agent, et Agno gère toute la boucle ReAct, la mémoire et le streaming automatiquement.
Gestion des Erreurs et Garde-fous
Un agent en production doit être robuste :
Limiter les itérations
MAX_ITERATIONS = 10
def run_agent_safe(user_message: str, tools: list, tool_functions: dict):
"""Boucle agent avec limite d''itérations."""
messages = [{"role": "user", "content": user_message}]
for iteration in range(MAX_ITERATIONS):
response = call_llm(messages, tools)
if response.has_tool_calls():
execute_tools(response, tool_functions, messages)
else:
return response.content
# Si on arrive ici, l''agent tourne en boucle
return "Désolé, je n''ai pas pu résoudre cette tâche dans le temps imparti."
Valider les appels d''outils
def delete_file(path: str) -> str:
"""Supprime un fichier (DANGEREUX)."""
# Garde-fou : ne jamais supprimer en dehors du dossier autorisé
allowed_dir = "/tmp/agent-workspace/"
if not path.startswith(allowed_dir):
return "ERREUR : Suppression interdite en dehors du workspace"
os.remove(path)
return f"Fichier {path} supprimé"
Supervision humaine (Human-in-the-loop)
def send_email(to: str, subject: str, body: str) -> str:
"""Envoie un email (nécessite validation humaine)."""
print(f"\n--- VALIDATION REQUISE ---")
print(f"À : {to}")
print(f"Sujet : {subject}")
print(f"Corps : {body}")
confirm = input("Envoyer ? (oui/non) : ")
if confirm.lower() == "oui":
# Envoyer réellement l''email
return "Email envoyé avec succès"
return "Envoi annulé par l''utilisateur"
En production, ne faites JAMAIS confiance à un agent pour des actions irréversibles sans validation. Un LLM peut mal interpréter une instruction et supprimer les mauvais fichiers, envoyer un email au mauvais destinataire, etc.
Architecture d''un Agent Complet
Résumé
| Concept | Description |
|---|---|
| Tool Calling | API qui permet au LLM de choisir et appeler des fonctions |
| Boucle Agent | While loop qui exécute les outils jusqu''à la réponse finale |
| Mémoire | Stockage du contexte (court/long terme) entre les tours |
| Agno | Framework Python pour créer des agents avec de simples fonctions |
| Garde-fous | Limites d''itérations, validation humaine, sandboxing |
Prochaine étape : Dans le cours avancé, nous verrons les architectures multi-agents avec Agno Team, où plusieurs agents collaborent pour résoudre des tâches complexes, et le déploiement en production avec AgentOS.
Specialiste IA — Master Intelligence Artificielle
Diplome d'un Master en Intelligence Artificielle, je travaille au quotidien sur des projets IA en entreprise. J'ai cree IwanttolearnAI pour rendre l'apprentissage de l'IA accessible a tous, gratuitement.
Continuer a apprendre
Mémoire des Agents IA : Short-Term et Long-Term avec Agno
Apprenez à donner une mémoire persistante à vos agents Agno : short-term dans le contexte, long-term avec SQLite et PostgreSQL, et partage de mémoire entre plusieurs agents.
MCP : Le Protocole qui Connecte les Agents aux Outils
Découvrez MCP (Model Context Protocol) créé par Anthropic : architecture client-serveur, transports stdio et HTTP, utilisation avec Agno, et création de votre propre serveur MCP.
Tool Use et Function Calling avec Agno
Donnez des "mains" à vos agents IA : apprenez à utiliser les outils intégrés d'Agno (recherche web, fichiers, finance) et à créer vos propres outils custom avec le décorateur @tool.