Créer un agent IA de A à Z : tutoriel complet et sans compromis
Tutoriel complet pour créer un agent IA de A à Z : cadrage Use case, choix du framework, tools, memory et déploiement. Code Python prêt à copier.
Créer un agent IA de A à Z : tutoriel complet et sans compromis
Introduction
Créer un agent IA fonctionnel ne commence pas par du code — ça commence par un problème bien défini. La majorité des agents qui échouent ne sont pas victims d'une technologie insuffisante. Ils sont victims d'un use case mal cadré en amont. Résultat : un agent qui fait quelque chose de vague, mal, et qu'on finit par abandonner.
Ce tutoriel vous prend par la main, de la définition du problème jusqu'au déploiement sur un VPS. Chaque étape dispose de code Python fonctionnel, kopiable directement. On couvre CrewAI pour le prototypage rapide, et OpenClaw pour la production. À la fin, vous aurez un agent capable de poursuivre un objectif, d'utiliser des outils, de mémoriser du contexte, et de tourner en production avec monitoring.
Prérequis : Python 3.11+, bases en développement, un minimum de culture IA.
Résumé rapide
| Étape | Ce qu'on fait | Outil principal |
|---|---|---|
| 1 — Cadrage | Définir le problème, les KPIs, le périmètre | Template fourni |
| 2 — Framework | Choisir selon contexte | CrewAI / OpenClaw / LangGraph |
| 3 — Conception | Prompt system, tools, memory, goals | Prompt ingeniería |
| 4 — Core | Premier agent avec tool basique | Python + dépendances |
| 5 — Memory | Vector store, résumé conversation, persistance | ChromaDB / SQLite |
| 6 — Production | Logging, retry, human-in-the-loop, fallback | Structlog + tenacity |
| 7 — Déploiement | Docker + VPS + health checks + alerting | Docker Compose |
Définir et cadrer le use case
Pourquoi 90 % des agents échouent
Un agent IA, c'est un système qui poursuit un objectif de manière autonome en utilisant des outils et en s'adaptant à son environnement. Quand le use case est flou, l'agent n'a pas de boussole claire. Il dérive, produit des résultats inconsistants, et l'utilisateur perd confiance.
Les causes les plus fréquentes :
- Objectif trop vague — « je veux un agent intelligent » : chaque intervenant comprend quelque chose de différent
- KPIs absents — impossible de savoir si l'agent fonctionne
- Périmètre non délimité — l'agent finit par essayer de tout faire et rien faire correctement
- Boucle humaine manquante — pas de mécanisme pour un intervenant humain quand l'agent est incertain
Le template de cadrage
Avant d'écrire la moindre ligne de code, remplissez ce template :
PROBLÈME :
[Une phrase. Qui a le problème ? Quel est le problème concret ?]
KPI DE SUCCÈS :
[Métrique mesurable. Ex : « temps moyen de réponse < 30 s », « taux de précision > 92 % »]
PÉRIMÈTRE :
[Ce que l'agent FAIT — ce qu'il NE fait PAS]
OUTILS NÉCESSAIRES :
[Liste des tools dont l'agent a besoin]
BOUCLE HUMAINE :
[Quand l'agent appelle un humain ? Cas d'ambiguïté, seuil de confiance bas]
CONTRAINTES :
[Budget, latence, données disponibles, RGPD…]
Exemple de cadrage rempli :
PROBLÈME : Un analyste SEO passe 3 h/jour à extraire manuellement les positions
Google Search Console pour les 200 requêtes prioritaires.
KPI DE SUCCÈS : Rapport généré automatiquement chaque matin à 7 h, < 5 min de traitement.
PÉRIMÈTRE : Extrait les données GSC → produit un résumé Markdown.
Ne modifie pas les données source. N'envoie pas d'emails.
OUTILS NÉCESSAIRES : Accès API GSC, écriture fichier Markdown, potentiellement Slack.
BOUCLE HUMAINE : Si l'API GSC retourne une erreur, alerter sur Slack et attendre confirmation.
CONTRAINTES : RGPD — pas de données personnelles dans les rapports. Budget VPS < 10 €/mois.
Quand le template est rempli, on passe au choix du framework.
Choisir le bon framework
Tous les frameworks d'agents ne sont pas égaux. Le bon choix dépend de trois paramètres :
A. Complexité du workflow
├── Linéaire / few-shots → CrewAI
└── Graphes d'états complexes → LangGraph
B. Horizon temporel
├── Prototypage (< 2 semaines) → CrewAI
└── Production → OpenClaw
C. Nécessité de multi-agents
├── Non → CrewAI ou code custom
└── Oui → OpenClaw ou LangGraph
CrewAI — pour prototyper vite
CrewAI est le choix le plus pragmatique pour valider un use case rapidement. Configuration minimale, structure claire, bonnes abstractions pour les tools et la mémoire.
Quand choisir CrewAI :
- Validation de concept
- PoC pour un client ou une équipe
- Besoin d'un agent unique ou de quelques agents simples
- Timeline serrée
Limites : gestion limitées de l'état persistant, debugging fin parfois difficile, pas de built-in pour la supervision production.
OpenClaw — pour la production
OpenClaw est conçu pour les agents en production : orchestration robuste, skills, memory vectorielle intégrée, channels multiples (Discord, Telegram, WhatsApp), cron jobs, et monitoring.
Quand choisir OpenClaw :
- Agent en production avec monitoring requis
- Multi-canal (chat, email, Discord…)
- Besoin de skills réutilisables
- Équipe qui va maintenir l'agent sur le long terme
Limites : courbe d'apprentissage plus marquée que CrewAI.
LangGraph — pour les graphes d'états complexes
LangGraph (de LangChain) impose un modèle mental à base de graphes d'états. Chaque nœud est un état, chaque arête est une transition. Puissant pour les agents avec des chemins d'exécution complexes et des branchements logiques.
Quand choisir LangGraph :
- Agent avec workflows à embranchements multiples
- Besoin de persistance d'état fine (résumer avant chaque transition)
- Agents collaboratifs complexes
Pour un premier agent, LangGraph est souvent overkill. CrewAI ou OpenClaw couvrent 80 % des cas.
Concevoir l'agent : prompt system, tools, memory, goals
Un agent, c'est quatre piliers. Si l'un manque, l'agent fonctionne mal.
Le prompt system
Le prompt system définit qui est l'agent, ce qu'il sait faire, et comment il doit se comporter. C'est sa carte d'identité.
SYSTEM_PROMPT = """
Tu es un analyste SEO automatisé.
TA RÔLE : Tu extrais les métriques Google Search Console pour les requêtes
prioritaires et produis un résumé Markdown structuré.
TES PRINCIPES :
- Ne jamais inventer de données. Si une donnée manque, dis-le.
- Tu peux appeler un outil jusqu'à 3 fois maximum par tâche.
- Si un outil échoue, utilise un fallback et signale-le dans ta réponse.
TON TON : Clair, factuel, sans superflu. Pas de formules marketing.
"""
Le prompt system doit répondre à :
- Rôle — qui est l'agent ?
- Responsabilités — qu'est-ce qu'il fait ? Qu'est-ce qu'il ne fait pas ?
- Contraintes comportementales — quand est-ce qu'il refuse, quand est-ce qu'il escalate ?
- Ton — formel, décontracté, technique ?
Les tools — ce que l'agent peut faire
Une tool est une fonction que l'agent peut appeler. Elle a :
- Un nom unique
- Une description (servira au modèle pour décider quand l'utiliser)
- Des paramètres d'entrée typés
- Une sortie structurée
from typing import Literal
def fetch_gsc_data(queries: list[str], days: int = 30) -> dict:
"""
Extrait les métriques Google Search Console pour une liste de requêtes.
"""
# ... appel API
return {
"query": queries[0],
"clicks": 142,
"impressions": 3200,
"ctr": 0.044,
"position": 12.3
}
def save_report(content: str, filename: str) -> dict:
"""
Écrit le rapport généré dans un fichier Markdown.
"""
path = Path(f"/data/reports/{filename}")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding="utf-8")
return {"status": "ok", "path": str(path)}
Règle : chaque tool fait une seule chose, et le fait bien. Pas de tool « god » qui fait 10 opérations différentes.
La memory — ce que l'agent se souvient
Un agent sans mémoire traite chaque interaction comme la première. La memory lui donne de la continuité :
- Mémoire courte (short-term) — résumé de la conversation en cours
- Mémoire longue (long-term) — vecteurs检索 via une base vectorielle (ChromaDB, Qdrant…)
- Mémoire procédurale — facts ou preferences persistés (ex : « préfère les rapports le matin »)
# Résumé de conversation (short-term memory)
def summarize_conversation(messages: list[dict]) -> str:
"""Renvoie un résumé des messages, max 5 phrases."""
prompt = f"Résume cette conversation en 5 phrases maximum :\n{messages}"
response = llm.invoke([{"role": "user", "content": prompt}])
return response.content
# Stockage vectoriel (long-term memory)
import chromadb
chroma_client = chromadb.Client()
collection = chroma_client.get_or_create_collection("agent_memory")
def store_memory(text: str, metadata: dict):
embedding = embedding_model.encode(text)
collection.add(
ids=[str(hash(text))],
documents=[text],
embeddings=[embedding.tolist()],
metadatas=[metadata]
)
def retrieve_memory(query: str, top_k: int = 5) -> list[dict]:
embedding = embedding_model.encode(query)
results = collection.query(
query_embeddings=[embedding.tolist()],
n_results=top_k
)
return results
Les goals — ce que l'agent veut accomplir
Les goals sont les objectifs mesurables que l'agent doit atteindre. Contrairement à un simple prompt, un goal a des critères de succès explicites :
GOAL = {
"objective": "Produire un rapport quotidien des positions GSC",
"success_criteria": {
"rapport_genere": True,
"temps_traitement_max": 300, # secondes
"donnees_completes": True # toutes les requêtes traitées
},
"fallback": "Si l'API GSC échoue, produire un rapport partiel et alerter"
}
Implémenter l'agent — Partie 1 : Core
Setup projet et dépendances
mkdir mon-agent-seo && cd mon-agent-seo
python -m venv .venv && source .venv/bin/activate
pip install crewai crewai-tools chromadb openai python-dotenv
Fichier .env :
OPENAI_API_KEY=sk-...
GOOGLE_SEARCH_CONSOLE_CREDENTIALS=/path/to/credentials.json
Premier agent avec CrewAI
# agent_seo.py
import os
from crewai import Agent, Task, Crew
from crewai_tools import DirectoryReadTool, FileWriteTool
from dotenv import load_dotenv
load_dotenv()
# ─── Tools ───
directory_reader = DirectoryReadTool(
directory="./data/queries"
)
file_writer = FileWriteTool(
file_path="./data/reports/daily_report.md"
)
# ─── Agent ───
analyst = Agent(
role="Analyste SEO",
goal="Extraire les métriques GSC et produire un rapport Markdown",
backstory=(
"Tu es un analyste SEO senior. Tu maîtrises Google Search Console "
"et sais transformer des données brutes en insights actionnables."
),
tools=[directory_reader, file_writer],
verbose=True,
allow_delegation=False,
)
# ─── Task ───
extraction_task = Task(
description=(
"Lis la liste de requêtes dans ./data/queries/priority_queries.txt. "
"Pour chaque requête, extrais les métriques GSC (clicks, impressions, CTR, position) "
"sur les 30 derniers jours. Génère un rapport Markdown structuré."
),
agent=analyst,
expected_output="Un fichier Markdown avec un tableau des métriques par requête."
)
# ─── Crew ───
crew = Crew(
agents=[analyst],
tasks=[extraction_task],
process="sequential",
verbose=True,
)
# ─── Exécution ───
result = crew.kickoff()
print(result)
Exécutez le script :
python agent_seo.py
# Output : Rapport généré dans ./data/reports/daily_report.md
Validation checklist :
- L'agent s'exécute sans erreur
- Le rapport est généré avec des données
- Les tools sont appelées correctement (
verbose=Truepermet de suivre) - Le comportement est cohérent avec le prompt system
Implémenter l'agent — Partie 2 : Memory
Mémoire conversationnelle
CrewAI intègre nativement un système de memory. Configurez-le simplement :
from crewai import Agent, Memory
memory = Memory(
type="short_term", # ou "vector" pour la mémoire à long terme
embedder={
"provider": "openai",
"model": "text-embedding-3-small"
}
)
analyst = Agent(
role="Analyste SEO",
goal="Extraire les métriques GSC et produire un rapport Markdown",
backstory="...",
tools=[directory_reader, file_writer],
verbose=True,
memory=memory, # ← activée ici
allow_delegation=False,
)
Vector store avec ChromaDB
Pour un agent qui doit retenir des informations d'un jour sur l'autre :
# memory_store.py
import chromadb
from chromadb.config import Settings
from crewai.memory.storage.chromadb_storage import ChromadbStorage
chroma_settings = Settings(anonymized_telemetry=False)
chroma_storage = ChromadbStorage(
collection_name="seo_agent_memory",
persist_directory="./data/chroma",
embedding_model="openai",
settings=chroma_settings,
)
# L'agent peut maintenant chercher dans ses souvenirs
memory_results = chroma_storage.search(
query="rapport précédent succès",
top_n=3
)
# → Renvoie les 3 souvenirs les plus pertinents
Résumé automatique de conversation
# conversation_summarizer.py
from openai import OpenAI
client = OpenAI()
def summarize_if_long(messages: list[dict], threshold: int = 10) -> str:
"""
Résume la conversation si elle dépasse `threshold` messages.
"""
if len(messages) < threshold:
return ""
conversation_text = "\n".join(
f"{m['role']}: {m['content']}" for m in messages[-threshold:]
)
summary_prompt = (
"Résume cette conversation en 5 phrases maximum. "
"Identifie les décisions clés et les informations à retenir.\n\n"
f"{conversation_text}"
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": summary_prompt}]
)
return response.choices[0].message.content
Validation checklist :
- La mémoire vectorielle stocke les rapports passés
- Une requête sur « succès du dernier rapport » retourne des résultats pertinents
- Le résumé automatique fonctionne quand la conversation dépasse 10 messages
Implémenter l'agent — Partie 3 : Production
Logging structuré
# structured_logging.py
import structlog
import logging
import sys
logging.basicConfig(
format="%(message)s",
stream=sys.stdout,
level=logging.INFO,
)
structlog.configure(
processors=[
structlog.stdlib.filter_by_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog.processors.JSONRenderer(),
],
wrapper_class=structlog.stdlib.BoundLogger,
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
cache_logger_on_first_use=True,
)
log = structlog.get_logger()
# Usage
log.info("agent_started", agent="seo_analyst", run_id="run_123")
log.warning("tool_failed", tool="fetch_gsc", error="rate_limit_exceeded")
log.error("agent_failed", run_id="run_123", error="unhandled_exception")
Retry automatique avec backoff
# retry_handler.py
import tenacity
from openai import RateLimitError, APIError
@tenacity.retry(
wait=tenacity.wait_exponential(multiplier=1, min=2, max=60),
stop=tenacity.stop_after_attempt(5),
retry=tenacity.retry_if_exception_type((RateLimitError, APIError)),
before_sleep=lambda retry_state: log.warning(
"retrying",
attempt=retry_state.attempt_number,
wait_seconds=retry_state.kwargs.get("wait", "N/A")
),
)
def call_openai_with_retry(messages: list[dict]) -> str:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages
)
return response.choices[0].message.content
Human-in-the-loop
# human_in_the_loop.py
def human_review_step(task_output: str, context: dict) -> str:
"""
Pause l'agent et demande confirmation humaine.
Retourne 'approved', 'rejected', ou 'modified' avec le contenu modifié.
"""
print("=" * 60)
print("📋 DEMANDE DE CONFIRMATION HUMAINE")
print("=" * 60)
print(f"\nContexte : {context.get('description', 'N/A')}")
print(f"\nRésultat proposé :\n{task_output[:500]}...")
print("\n" + "=" * 60)
response = input("Approuver (a) / Rejeter (r) / Modifier (m) : ").strip().lower()
if response == "a":
return "approved"
elif response == "r":
return "rejected"
elif response == "m":
print("Entrez la version modifiée :")
return f"modified: {input()}"
return "rejected"
Fallback sur erreur
# fallback_handler.py
from typing import Optional
import traceback
def execute_with_fallback(agent, task, fallback_action: Optional[str] = None):
try:
result = agent.execute_task(task)
return {"status": "success", "result": result}
except Exception as e:
log.error(
"agent_execution_failed",
task=task.description,
error=str(e),
trace=traceback.format_exc()
)
if fallback_action == "partial_report":
return {
"status": "fallback",
"result": "Rapport partiel : les données GSC n'ont pas pu être "
"complètement extraites. Un alert a été envoyé."
}
return {
"status": "error",
"result": None,
"error": str(e)
}
Validation checklist :
- Les logs sortent en JSON structuré (pas de print brut)
- Un appel réseau raté déclenche un retry avec backoff
- L'agent s'arrête et demande une confirmation humaine quand
human_review_stepest appelé - En cas d'erreur fatale non gérée, un rapport de fallback est produit
Déployer et superviser
Docker Compose pour un VPS
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "agent_seo.py"]
# docker-compose.yml
version: '3.8'
services:
seo-agent:
build: .
container_name: seo-agent
restart: unless-stopped
env_file:
- .env
volumes:
- ./data:/data
- ./logs:/logs
healthcheck:
test: ["CMD", "python", "-c", "print('ok')"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
deploy:
resources:
limits:
cpus: '1'
memory: 1G
# Déploiement sur VPS
docker compose build
docker compose up -d
# Vérifier le status
docker compose ps
# Voir les logs
docker compose logs -f seo-agent
Health checks et alerting
# health_monitor.py
import requests
import structlog
from datetime import datetime
log = structlog.get_logger()
def health_check() -> dict:
"""Vérifie que l'agent et ses dépendances sont opérationnels."""
checks = {
"timestamp": datetime.utcnow().isoformat(),
"agent_alive": True,
"vector_store_reachable": False,
"openai_api_reachable": False,
}
# Vérifier ChromaDB
try:
chroma_client.get_collection("seo_agent_memory")
checks["vector_store_reachable"] = True
except Exception as e:
log.error("health_check_chroma_failed", error=str(e))
# Vérifier OpenAI API
try:
requests.get("https://api.openai.com/v1/models", timeout=5)
checks["openai_api_reachable"] = True
except Exception as e:
log.error("health_check_openai_failed", error=str(e))
failed_checks = [k for k, v in checks.items() if v is False and k != "timestamp"]
if failed_checks:
log.critical(
"health_check_failed",
failed_checks=failed_checks,
checks=checks
)
# Intégrer ici l'alerte Slack / email / PagerDuty
return checks
Coût approximatif (VPS)
| Composant | Coût mensuel approx. |
|---|---|
| VPS Hetzner (CPX21, 4 vCPU, 8 Go RAM) | ~7 €/mois |
| ChromaDB (storage local) | Inclus |
| OpenAI API (rapport quotidien, ~100 req.) | ~0,5 €/mois |
| Backup journalier (optionnel) | ~2 €/mois |
| Total | ~10 €/mois |
Un agent SEO basique tourne confortablement sur un VPS à 10-15 €/mois. Si le volume de requêtes explose, verticaliser (plus de RAM) avant d'horizontalscaler.
Questions fréquentes
Qu'est-ce qu'un agent IA exactement ?
Un agent IA est un système qui utilise un modèle de langage pour poursuivre un objectif de manière autonome : il décide quelles actions prendre, appelle des outils, et s'adapte au feedback. Contrairement à un simple chatbot qui répond à une question, un agent planifie une séquence d'actions, utilise des tools, et maintient un état entre les interactions.
Comment créer un agent IA avec Python ?
Le processus en 4 étapes :
- Définir le use case et les KPIs
- Choisir un framework (CrewAI pour prototyper, OpenClaw pour production)
- Définir le prompt system et les tools
- Implémenter le cœur, ajouter la mémoire, puis le logging et le déploiement
Voir les sections 3 à 7 pour le détail code.
Quel framework choisir pour créer un agent IA en 2026 ?
| Besoin | Framework |
|---|---|
| Prototype rapide | CrewAI |
| Production multi-canal avec monitoring | OpenClaw |
| Workflows à états complexes | LangGraph |
CrewAI et OpenClaw couvrent 80 % des cas d'usage. LangGraph devient pertinent quand le graphe de décisions est trop complexe pour les abstractions linéaires.
Comment ajouter de la mémoire à un agent IA ?
La mémoire se décompose en trois types :
- Mémoire courte — résumé de la conversation en cours (appel LLM avec prompt de synthèse)
- Mémoire longue — stockage vectoriel (ChromaDB, Qdrant) avec retrieval sémantique
- Mémoire procédurale — facts ou preferences persistés dans une base clé-valeur
CrewAI intègre nativement un système de memory activable en une ligne. OpenClaw propose une layer de vector memory via ses skills.
Comment déployer un agent IA sur un VPS ?
Les étapes :
- Containeriser l'agent avec Docker
- Écrire un
docker-compose.ymlavec health check - Déployer sur un VPS (Hetzner, OVH…)
- Configurer un cron pour l'exécution planifiée
- Mettre en place un monitoring (logs structurés JSON + alerting)
Voir la section 7 pour le code complet Docker et health monitoring.
Articles liés
Vous avez désormais un cadre complet pour créer un agent IA de qualité production. Si vous voulez approfondir un aspect précis, ces ressources vous interesseront :
- Créer un agent IA avec Python — Setup complet, environment Python, premières dépendances
- Guide CrewAI — Agents, tasks, tools, process : tout ce qu'il faut savoir
- Guide OpenClaw — OpenClaw pour la production multi-canal
- Mémoire des agents IA — Vector stores, résumés, persistance : les différentes approches
- Outils pour agents IA — Comment concevoir des tools robustes et testables
- Déployer un agent IA — VPS, Docker, monitoring et alerting : le guide complet
Cet article fait partie du cluster Tutoriels sur FrameworksAgents.com. Pour suivre la production d'articles sur les frameworks d'agents IA, voir TOPICS_QUEUE.md.
Restez informé sur les agents IA
Nouveaux tutoriels, comparatifs et guides pratiques directement dans votre boîte mail.