Idée en 30 secondes
Single-Step Agents devient un anti-pattern quand une seule étape est utilisée pour des tâches avec tools, side effects ou ambiguïté.
Résultat : il n'y a pas d'espace pour la validation, le recovery et l'arrêt contrôlé. Pour les tâches avec tools ou side effects (changements d'état), cela devient vite fragile en production.
Pour des cas read-only sûrs, le single-step peut convenir, mais pour les tâches avec tools ou side effects il faut une bounded loop avec stop_reason explicite.
Exemple d'anti-pattern
L'équipe construit un agent de support qui doit rechercher des données et exécuter des actions dans des systèmes externes.
Mais l'implémentation ne fait qu'une étape : une décision d'action et une exécution.
decision = agent.decide(user_message)
result = run_tool(decision.tool, decision.args)
return result
Dans ce schéma, il n'y a pas de réévaluation après le tool-result :
# pas de validate_output(...)
# pas de no_progress(...)
# pas de stop_reason
Pour ce cas, il faut une boucle contrôlée avec des limites :
for step in range(MAX_STEPS):
decision = agent.next_step(state)
...
Ici, l'approche single-step ajoute :
- risque précoce d'action erronée
- absence de recovery après erreur d'outil
- contrôle faible de la qualité de la réponse finale
Pourquoi ça apparaît et ce qui se passe mal
Cet anti-pattern apparaît souvent quand l'équipe optimise "pour faire plus simple" et réduit le système d'agent à un seul appel modèle.
Causes typiques :
- volonté de réduire la latency à tout prix
- confusion entre "single LLM call" et "agent complet"
- absence d'exigences sur stop reasons et validation d'output
- espoir que le prompt couvre à lui seul les scénarios de recovery
Résultats :
- pas de recovery-loop - après une erreur tool, l'agent n'a plus de suite
- risque de write prématuré - un side effect peut arriver avant validation
- output fragile - pas d'étape pour vérifier "la tâche est-elle vraiment résolue"
- debug difficile - le run se termine sans raison transparente
- instabilité en production - une seule étape ratée devient immédiatement un incident
Contrairement à No Stop Conditions, ici il n'y a même pas de boucle contrôlée : le problème commence plus tôt, dans le design "une étape puis terminé".
Signaux de production typiques que le single-step est déjà dangereux :
- des tâches avec tools et side effects tournent sans
max_steps/stop_reason - un tool-call échoué termine immédiatement le run sans tentative de recovery sûre
- une erreur de routing déclenche une action externe sans validation supplémentaire
- l'équipe ne peut pas expliquer pourquoi cette action a été choisie pour ce run
Point important : chaque étape agent fait partie de l'LLM inference. Dans un design single-step, vous laissez en pratique une seule inference prendre une décision critique sans vérification.
Bonne approche
Commencez par une bounded loop minimale pour tous les scénarios avec tools ou side effects. Gardez le single-step uniquement pour les cas read-only vraiment sûrs, low-risk, sans tool-call.
Cadre pratique :
- séparez les routes :
read_only_single_stepetloop_required - pour la route loop, définissez
max_steps,timeout,stop_reason - ajoutez les vérifications
validate_outputetno_progress - exécutez les actions write uniquement après des vérifications policy explicites
MAX_STEPS = 6
def run_support_flow(user_message: str):
route = classify_intent(user_message) # simple classifier or rules
if route == "read_only_faq":
return run_single_step_answer(user_message) # no tools, no side effects
state = init_state(user_message)
for step in range(MAX_STEPS): # hard limit for unsafe loops
decision = agent.next_step(state)
if decision.type == "final_answer":
if validate_output(decision.output): # format and required fields
return decision.output
return stop("invalid_output")
result = run_tool(decision.tool, decision.args)
if no_progress(state, result): # repeated pattern or no meaningful state change
return stop("no_progress")
state.append(result)
return stop("max_steps_exceeded")
Avec ce schéma, les risques deviennent maîtrisables : le système clôt la tâche ou s'arrête avec une raison transparente.
Test rapide
Si la réponse à ces questions est "oui", vous avez un risque d'anti-pattern Single-Step Agents :
- Les tâches avec tools et side effects sont-elles exécutées via un seul model call ?
- Après un tool-result échoué, le run se termine-t-il sans étape de recovery ?
- N'y a-t-il pas de
stop_reasonexplicite quand le scénario n'est pas correctement clôturé ?
Différence avec les autres anti-patterns
Agent Everywhere Problem vs Single-Step Agents
| Agent Everywhere Problem | Single-Step Agents |
|---|---|
| Problème principal : l'agent est utilisé même pour des tâches déterministes. | Problème principal : même quand un agent est nécessaire, il est exécuté en une étape sans boucle. |
| Quand il apparaît : quand un workflow simple est remplacé par du agent reasoning. | Quand il apparaît : quand des tâches avec tools/write tournent sans recovery ni logique d'arrêt. |
En bref : Agent Everywhere Problem concerne le choix inutile de l'agent, alors que Single-Step Agents concerne une façon dangereuse d'exécuter l'agent.
No Stop Conditions vs Single-Step Agents
| No Stop Conditions | Single-Step Agents |
|---|---|
| Problème principal : il y a une boucle, mais sans conditions de fin claires. | Problème principal : il n'y a pas de boucle, donc pas d'espace pour un recovery contrôlé. |
| Quand il apparaît : quand un run tombe dans des répétitions infinies ou longues. | Quand il apparaît : quand une seule mauvaise étape termine le scénario ou déclenche une action indésirable. |
En bref : No Stop Conditions concerne une boucle non contrôlée, tandis que Single-Step Agents concerne l'absence de boucle là où elle est nécessaire.
Tool Calling for Everything vs Single-Step Agents
| Tool Calling for Everything | Single-Step Agents |
|---|---|
| Problème principal : des tool-calls inutiles même dans des scénarios simples. | Problème principal : un tool-call critique est exécuté en une étape sans validation du résultat. |
| Quand il apparaît : quand le tool-call devient la route par défaut. | Quand il apparaît : quand il n'y a aucune boucle après tool-result pour valider ou corriger. |
En bref : Tool Calling for Everything augmente le nombre d'appels inutiles, tandis que Single-Step Agents augmente le risque d'un appel critique non contrôlé.
Auto-vérification : avez-vous cet anti-pattern ?
Vérification rapide de l'anti-pattern Single-Step Agents.
Cochez les points pour votre système et consultez le statut ci-dessous.
Vérifiez votre système :
Progression: 0/8
⚠ Il y a des signes de cet anti-pattern
Essayez de déplacer les étapes simples dans un workflow et de garder l'agent uniquement pour les décisions complexes.
FAQ
Q : L'approche single-step est-elle toujours mauvaise ?
R : Non. Elle convient aux scénarios read-only sûrs sans tools ni side effects. Le problème apparaît quand elle est appliquée à des tâches qui demandent recovery et contrôle.
Q : Comment savoir qu'il faut passer à une boucle ?
R : S'il y a des tool-calls, des actions externes, un output ambigu ou un risque d'erreur à fort impact, il faut une bounded loop avec stop_reason explicite.
Q : La latency augmente-t-elle fortement après passage à une boucle ?
R : Elle peut augmenter, mais cela se pilote avec des budget limits. En production, un résultat contrôlé et sûr est généralement plus important que "rapide mais fragile".
Et ensuite
Anti-patterns proches :
- Agent Everywhere Problem - quand un agent est ajouté là où un workflow suffit.
- No Stop Conditions - quand une boucle existe mais sans arrêt contrôlé.
- Tool Calling for Everything - quand les tools sont appelés sans besoin explicite.
Ce qu'il faut construire à la place :
- Stop Conditions - comment définir les conditions de fin pour un run contrôlé.
- Routing Agent - comment séparer les routes read-only et side-effecting.
- Tool Execution Layer - comment exécuter les tool-calls en sécurité via policy et limites.