C'est l'implémentation complète de l'exemple de l'article Construisons ton premier agent IA.
Si tu ne l'as pas encore lu, commence par là. Ici, on se concentre sur le code.
Ce que cet exemple démontre
- Objectif de l'agent : obtenir du modèle un nombre supérieur à 10
- Boucle : Act -> Check -> Retry (au maximum
MAX_STEPSfois) - Validation : le modèle peut retourner du texte, une chaîne vide ou une valeur non numérique - l'agent gère ces cas
- Stop condition : l'agent s'arrête soit en cas de succès, soit quand les étapes sont épuisées
Structure du projet
examples/
└── start-here/
└── write-your-first-agent/
└── python/
├── main.py # boucle d'agent
├── llm.py # appel LLM (isolation de l'intégration)
├── evaluator.py # vérification du résultat
└── requirements.txt
Pourquoi trois fichiers et pas un seul ? Parce que dans un agent réel, génération et évaluation sont presque toujours séparées. Si tu veux changer le modèle ou la logique de vérification, tu changes un fichier sans toucher au reste.
Comment lancer
1. Clone le dépôt et va dans le dossier :
git clone https://github.com/AgentPatterns-tech/agentpatterns.git
cd examples/start-here/write-your-first-agent/python
2. Installe les dépendances :
pip install -r requirements.txt
3. Définis la clé API :
export OPENAI_API_KEY="sk-..."
4. Lance :
python main.py
Code
main.py - boucle d'agent
from llm import generate_number
from evaluator import parse_int, is_goal_reached
GOAL = 10
MAX_STEPS = 5
def run():
for step in range(1, MAX_STEPS + 1):
print(f"\n🤖 Step {step}: Agent is trying...")
output = generate_number()
print(f"💬 Model generated: {output}")
number = parse_int(output)
if number is None:
print("❌ Not a number. Trying again...")
continue
if is_goal_reached(number, GOAL):
print(f"✅ Goal reached! {number} > {GOAL}")
return
print(f"❌ Not enough. {number} ≤ {GOAL}. Trying again...")
print("\n⚠️ Max steps reached without success")
if __name__ == "__main__":
run()
main.py ne sait rien d'OpenAI. Il ne sait pas parser des nombres. Il pilote uniquement la boucle - c'est le rôle de l'agent.
llm.py - appel du modèle
import os
from openai import OpenAI
api_key = os.environ.get("OPENAI_API_KEY")
client = OpenAI(api_key=api_key)
PROMPT = "Write ONLY a random number between 1 and 20. No text, no explanation."
def generate_number() -> str:
resp = client.responses.create(
model="gpt-4.1-mini",
input=PROMPT,
)
return resp.output_text.strip()
Le modèle reçoit une tâche et renvoie du texte. Il ne sait pas qu'il existe un agent, un objectif ou une limite d'étapes. Il génère simplement.
evaluator.py - vérification du résultat
def parse_int(text: str) -> int | None:
"""Retourne int ou None si le texte n'est pas un entier."""
try:
return int(text.strip())
except (ValueError, AttributeError):
return None
def is_goal_reached(number: int, goal: int) -> bool:
"""Retourne True si le nombre satisfait la condition."""
return number > goal
Deux petites questions avec des réponses claires : "est-ce un nombre ?" et "objectif atteint ?". C'est tout.
requirements.txt
openai>=1.0.0
Exemple de sortie
🤖 Step 1: Agent is trying...
💬 Model generated: 7
❌ Not enough. 7 ≤ 10. Trying again...
🤖 Step 2: Agent is trying...
💬 Model generated: 3
❌ Not enough. 3 ≤ 10. Trying again...
🤖 Step 3: Agent is trying...
💬 Model generated: 14
✅ Goal reached! 14 > 10
Pourquoi c'est un "agent" et pas juste une fonction
| Fonction | Agent | |
|---|---|---|
| Nombre de tentatives | 1 | jusqu'à MAX_STEPS |
| Vérifie le résultat | ❌ | ✅ |
| Décide de continuer ou de s'arrêter | ❌ | ✅ |
| Nécessite une intervention humaine entre les étapes | — | ❌ |
Un appel modèle n'est pas un agent.
Une boucle avec vérification et décision "réessayer ou s'arrêter" est un agent.
Où creuser ensuite
Essaie de modifier l'exemple toi-même :
- Change
GOAL = 10enGOAL = 19- à quelle fréquence l'agent atteindra-t-il l'objectif dansMAX_STEPS? - Supprime
MAX_STEPSet metswhile True- que va-t-il se passer ? - Change le prompt pour que le modèle génère des nombres de 1 à 100 - quel impact sur le comportement de l'agent ?
- Ajoute un compteur du nombre total d'appels API et affiche-le à la fin