Boucle d’agent
Cette page décrit de bout en bout comment Copilot CLI traite un message utilisateur (depuis l’envoi du prompt jusqu’àsession.idle).
Architecture
Le SDK est la couche de transport. Il envoie les prompts en JSON-RPC au Copilot CLI et relaie les événements vers votre application. C’est le CLI qui exécute la boucle agentique d’utilisation d’outils et qui orchestre un ou plusieurs appels à l’API LLM jusqu’à l’achèvement de la tâche.Boucle d’utilisation d’outils
Lorsque vous appelezsession.send({ prompt }), le CLI entre dans la boucle suivante :
À chaque appel, le modèle consulte tout l’historique de la conversation (system prompt / message utilisateur / l’ensemble des appels d’outils et de leurs résultats jusqu’ici).
Important : une itération de cette boucle correspond exactement à un appel à l’API LLM, et se traduit dans le journal d’événements par une paire assistant.turn_start / assistant.turn_end. Il n’y a pas d’appels cachés.
Qu’est-ce qu’un Turn (tour) ?
Un turn correspond à un appel à l’API LLM et à son résultat.- Le CLI envoie l’historique de la conversation au LLM
- Le LLM répond (avec potentiellement des requêtes d’outils)
- En cas de requête d’outil, le CLI l’exécute
assistant.turn_endest émis
| Turn | Action du modèle | toolRequests ? |
|---|---|---|
| 1 | Recherche dans la codebase avec grep et glob | ✅ Oui |
| 2 | Lecture de fichiers spécifiques d’après les résultats | ✅ Oui |
| 3 | Lectures supplémentaires pour approfondir le contexte | ✅ Oui |
| 4 | Génération de la réponse textuelle finale | ❌ Non → fin de boucle |
Flux d’événements sur plusieurs tours
Qui déclenche chaque tour
| Acteur | Responsabilité |
|---|---|
| Votre application | Envoie le prompt initial via session.send() |
| Copilot CLI | Exécute la boucle d’outils et renvoie les résultats d’outils comme entrée du tour suivant au LLM |
| LLM | Décide de demander des outils et de continuer, ou de renvoyer une réponse finale et de terminer |
| SDK | Se contente de relayer les événements. Ne contrôle pas la boucle |
Différence entre session.idle et session.task_complete
Ces deux événements signalent l’achèvement, mais leurs garanties sont très différentes.
session.idle
- Toujours émis à la fin de la boucle d’utilisation d’outils
- Éphémère : non persisté sur disque, non rejoué lors de la reprise d’une session
- Signification : « l’agent a cessé de traiter et peut recevoir le prochain message »
- À utiliser comme signal fiable de « terminé »
sendAndWait() du SDK attend cet événement.
session.task_complete
- Émission optionnelle (uniquement si le modèle le signale explicitement)
- Persisté (sauvegardé dans le journal d’événements de la session)
- Signification : « l’agent estime avoir accompli la tâche globale »
- Peut inclure un
summaryoptionnel
Mode Autopilot : le CLI incite au task_complete
En mode autopilot (headless / autonome), le CLI garde trace de l’appel éventuel de task_complete par le modèle. Si la boucle d’outils se termine sans task_complete, le CLI insère le message utilisateur synthétique suivant pour inciter le modèle :
“You have not yet marked the task as complete using the task_complete tool. If you were planning, stop planning and start implementing. You aren’t done until you have fully completed the task.”Cela relance de fait la boucle d’utilisation d’outils. Le modèle reçoit cette incitation comme un nouveau message utilisateur et poursuit le travail. L’incitation inclut aussi la consigne « ne pas appeler
task_complete trop tôt ».
- Ne pas appeler s’il reste des questions en suspens. Décidez et continuez.
- Ne pas appeler si vous ne faites que rencontrer une erreur. Essayez de la résoudre.
- Ne pas appeler s’il reste des tâches. Terminez-les d’abord.
- Le modèle appelle
task_completeavec un résumé → le CLI émetsession.task_complete→ terminé - Le modèle s’arrête sans l’appeler → le CLI incite → le modèle continue ou appelle
task_complete
Pourquoi task_complete n’est parfois pas émis
En mode interactif (chat classique), le CLI n’incite pas à task_complete. Le modèle peut donc l’omettre. Les principales raisons sont :
- Q&A conversationnelle : le modèle répond à la question et s’arrête, sans « tâche accomplie » discrète
- Décision du modèle : il renvoie le texte final sans appeler
task_complete - Session interrompue : la session se termine avant que le modèle n’atteigne le point d’achèvement
session.idle. C’est un signal mécanique (fin de boucle) et non un signal sémantique (le modèle juge que c’est fini).
Lequel utiliser ?
| Cas d’usage | Signal |
|---|---|
| « Attendre la fin du traitement de l’agent » | session.idle ✅ |
| « Savoir que la tâche de codage est terminée » | session.task_complete (best-effort) |
| « Timeout / gestion d’erreurs » | session.idle + session.error ✅ |
Compter les appels au LLM
Le nombre de pairesassistant.turn_start / assistant.turn_end dans le journal d’événements correspond au nombre total d’appels à l’API LLM. Il n’y a pas d’appels cachés pour la planification, l’évaluation ou la vérification d’achèvement.
Exemple pour compter le nombre de tours d’une session :
Documents associés
- Événements de streaming — Référence au niveau des champs pour chaque type d’événement
- Reprise de session — Sauvegarde et reprise d’une session
- Hooks de session — Intercepter les événements dans la boucle (permissions, outils)