Sans boucles, il n'y a pas d'agent
Tout le secret de Claude Code peut être écrit sur une seule ligne : while stop_reason == "tool_use"
Que fait exactement un agent ?
Lorsque vous exécutez Claude Code dans le terminal et le laissez "organiser tous les commentaires TODO dans une liste", ce que vous voyez est : il décide de lui-même de d'abord grep, puis de cat quelques fichiers, puis de sortir Markdown. Le modèle n'exécute pas le code lui-même - il demande à être exécuté. Ce qui lui donne vraiment l'air "avec les mains et les pieds", ce sont les quelque 30 lignes de code de colle qui l'entourent.
Cette leçon consiste à démonter le cercle de colle et à voir clairement. C'est ce qu'on appelle la boucle d'agent (boucle d'agent) et sa structure est :
while réponse.stop_reason == "tool_use" : réponse = LLM(messages, outils) # 1. demander au modèle execute_tools(response.tool_calls) # 2. exécutez ce qu'il a demandé messages.append(tool_results) # 3. renvoyer les résultats
C'est tout. Pas plus. Le code de production Claude comporte des autorisations, des hooks, des sous-agents, une isolation de l'arbre de travail et une compression de mémoire empilés en plus - mais le noyau est toujours ces quatre lignes.
Intuition clé : Chaque fois que le modèle répond, c'est soit "Je veux ajuster l'outil", soit "J'ai terminé". La boucle continue tant qu'elle est dans l'état précédent ; une fois qu'elle entre dans ce dernier état, la boucle sort. Le critère est le champ stop_reason dans la réponse.
Voir les messages[] grandir étape par étape
La tâche de la simulation de boucle suivante est : "Quels fichiers se trouvent dans le répertoire actuel ? Ensuite, lisez package.json". Cliquez sur Étape. Chaque fois que vous appuyez dessus, vous avancez d'une action dans le cycle. À gauche se trouve la bulle de dialogue vue par l'homme, à droite se trouve le véritable tableau messages[] intégré au modèle - remarquez comment il grandit.
Les résultats de l'outil doivent être réinscrits dans l'historique des messages
Le piège le plus simple pour les novices est de considérer « l'outil d'exécution » comme un effet secondaire : une fois exécuté, c'est fait. Cependant, le modèle ne peut voir les messages[] que lors du prochain cycle d'inférence, et il ne sait pas que des choses qui n'y figurent pas se sont produites. Sans l’étape d’ajout, la boucle entière serait fausse.
Toutes les erreurs ne sont pas identiques. Deux types courants :
- Oubliez l'ajout : le modèle ne verra pas les résultats la prochaine fois, il demandera à nouveau au même outil - et vous obtiendrez une boucle infinie.
- Ajouter mais perdre
tool_use_id: l'API Anthropic signalera directement une erreurtool_result doit avoir tool_use_id, et la boucle s'effondrera à l'étape d'appel de l'API.
La même tâche : "Compter le nombre de fichiers Python dans le projet". Exécutez les deux versions côte à côte pour voir la différence dans les fins.
Comprendre stop_reason
Chaque fois que le modèle revient, il apportera un stop_reason. Pour décider de continuer la boucle, il suffit de regarder ce champ :
tool_use— Le modèle souhaite ajuster l'outil, continuer le bouclage.end_turn— Le modèle sent qu'il est terminé et quitte la boucle.max_tokens— Lorsque la limite supérieure de jetons est générée, elle est tronquée et quitte la boucle (généralement traitée comme une exception pour avertir l'utilisateur que la sortie est incomplète).stop_sequence— Lorsqu'une séquence d'arrêt personnalisée est rencontrée, quittez la boucle.
Écrire incorrectement "continuer tant qu'il n'y a pas de tool_use", ou ignorer max_tokens et le traiter directement comme une fin normale, sont des bugs courants.
Agissez et courez
Clone local shareAI-lab/learn-claude-code :
clone de git https://github.com/shareAI-lab/learn-claude-code cd apprendre-claude-code pip install -r exigences.txt cp .env.example .env # remplir ANTHROPIC_API_KEY agents python/s01_agent_loop.py
Alors laissez-le faire quelque chose de réel : Aidez-moi à compter combien de fichiers .py se trouvent dans ce référentiel. Vous le verrez envoyer un ls -R, voir la sortie, envoyer un autre find . -nom "*.py" | wc -l, puis vous indique la réponse. L'ensemble du processus est cette boucle.