Prompts encadrés : empêcher les assistants IA d’inventer une pile parallèle
Pourquoi les demandes de fonctionnalités vagues amènent les assistants de codage à ajouter des bibliothèques et des enveloppes dupliquées, et comment une instruction bien définie avec des chemins, des invariants et des limites strictes résout ce problème.
Sources: AI Doesn’t Need Better Prompts. It Needs Boundaries.
Si vous demandez à un assistant de codage de « créer une page de paramètres utilisateur », vous obtiendrez généralement quelque chose qui se compile, s’affiche et a l’air terminé. En y regardant de plus près, on constate souvent qu’il contient son propre stockage d’état, ses propres outils de récupération de données et une bibliothèque de validation que votre répertoire n’a jamais utilisée. Rien ne tombe en panne, et c’est précisément pour cette raison que le problème échappe à la vérification. Cet article explique pourquoi les demandes vagues échouent de cette manière, pourquoi ajouter des adjectifs ne sert à rien, et comment rédiger une instruction précise, ainsi qu’un tableau de contrôle reutilisable pour garantir que le code généré reste intégré à votre architecture existante.
Comment une demande vague échoue discrètement
Imaginez une équipe travaillant sur une application d’administration pour les clients développée avec React et TypeScript. Le code existant comprend déjà des primitives de formulaire, un client API partagé ainsi qu’un hook de notification. Quelqu’un demande à l’assistant, en une seule phrase courte, la création d’une page de paramètres. Le résultat inclut des onglets, des formulaires, des messages toast, des chargements en squelette ainsi qu’un petit stockage d’état. En réalité, ces modifications entrent en conflit silencieux avec le code existant :
- L’état des formulaires est géré par une bibliothèque que le projet n’utilise pas.
- De nouveaux enveloppeurs fetch sont ajoutés à côté du client API partagé.
- Les messages toast sont générés directement plutôt que d’utiliser le hook de notification du projet.
- Les schémas de validation ignorent les structures déjà définies dans
types/. - Un « stockage de paramètres » côté client contient trois champs qui devraient en réalité se trouver sur le serveur.
- Les chargements en squelette ne correspondent pas au reste du tableau de bord.
Rien de tout cela ne provoque d’erreur, et cela pourrait passer inaperçu lors d’un examen rapide à moins que quelqu’un n’ouvre package.json. C’est là le danger : des instructions vagues entraînent des échecs discrets. Elles introduisent une deuxième façon de faire quelque chose que l’équipe a déjà résolu, et chaque futur mainteneur doit gérer les deux approches. L’assistant est efficace avec le code qu’il peut voir ; ce sont les fichiers qu’il n’a jamais ouverts qui déterminent si cette fonctionnalité appartient réellement à votre application.
Pourquoi une instruction plus longue n’est pas la solution
Le conseil habituel est d’être plus précis. Une deuxième tentative naturelle consiste à demander une page de configuration « affinée, prête pour la production » avec « une UX propre, un bon TypeScript et une gestion solide des erreurs. »
Cela produit la même architecture parallèle, mais avec une plus grande assurance. Les mots décrivent le goût, et le goût laisse le modèle entièrement libre d’inventer une structure. Ce qui manquait, ce n’était jamais l’éloquence ; c’étaient des limites : des indications claires sur ce que le modèle peut utiliser, ce qu’il ne doit pas ajouter, et ce qui constitue une tâche terminée.
Rédiger la version limitée
Le prompt limité ci-dessous demande la même fonctionnalité, mais ressemble à une description de poste. Il indique les composants exacts, le hook, le client API et le fichier de schéma à réutiliser, énumère le comportement des onglets et de soumission, définit les tests, et se termine par des interdictions explicites.
Build a user settings page in React and TypeScript.
Use ONLY these existing pieces:
- `src/components/FormField.tsx`
- `src/components/Button.tsx`
- `src/hooks/useNotify.ts`
- `src/api/client.ts` (no new fetch wrappers)
- validation schemas from `src/types/userSettings.ts`
Behavior:
- Tabs: Profile, Notifications, Security
- Preserve unsaved edits when switching tabs
- Show server field errors beside the matching inputs
- Disable submit while in flight
- Ignore duplicate submits
Tests:
- loading, success, server error, duplicate click
- empty required fields
Do NOT:
- add a state-management library
- add a toast library
- create a new API client
- invent types that duplicate `src/types/userSettings.ts`
Ce n’est pas tant un prompt plus élégant qu’une note d’architecture que le modèle doit suivre. Par rapport à la version concise, il communique sept éléments qui étaient auparavant laissés au hasard :
- Quels composants existants réutiliser.
Avec ces contraintes, la différence résultante devient agréablement ennuyeuse. Elle utilise le même FormField, le même useNotify, le même api/client. Les onglets conservent leur état non enregistré sans nécessiter un nouveau stockage, et les soumissions dupliquées sont gérées par un bouton désactivé ainsi que par des tests, plutôt qu’avec un commentaire du type « gérer plus tard ». Les bases de code existantes contiennent déjà des modèles ; la tâche du prompt est de les indiquer de manière si claire que le modèle ne puisse pas les manquer.
Cela explique également pourquoi les développeurs expérimentés obtiennent généralement de meilleurs résultats avec des assistants. Leur avantage réside non pas dans la formulation, mais dans leur capacité à savoir à l’avance quels détails sont importants. Ce qui compte, c’est de communiquer l’architecture, et non de simplement décorer le prompt.
Un test rapide pour vérifier la bornéité
Si votre prompt a du sens lorsqu’il est collé dans n’importe quel répertoire au monde, il n’est pas encore borné. Un bon prompt devrait être légèrement inutile en dehors de votre propre arborescence de sources, car il fait référence à vos chemins, à vos types et à vos conventions.
Une liste de contrôle réutilisable avant le lancement
Le fait de conserver un modèle au-dessus de chaque demande de fonctionnalité permet d’instaurer cet état d’esprit structuré. Celui ci-dessous regroupe les questions par contexte, invariants, comportement, contraintes et définition de l’état final. La section des invariants est celle qui est le plus souvent ignorée : décider si les données se trouvent sur le serveur, dans l’URL ou dans l’état de l’interface locale permet d’éviter le problème du « stockage de trois champs » avant même qu’il ne survienne.
CONTEXT
- Stack: React + TypeScript
- Relevant paths: ...
- Patterns to copy: ...
INVARIANTS
- Where does data live (server / URL / local UI state)?
- What must survive refresh?
- What is the source of truth for types/validation?
BEHAVIOR
- Happy path
- Empty / invalid input
- Server errors (field-level + form-level)
- Slow network / double submit
- Permission failure
CONSTRAINTS
- Do not add: ...
- Do not invent parallel: API client / store / toast / form lib
- Prefer editing: [files]
DONE
- Tests for: ...
- Manual checks: ...
Utilisez le modèle comme critère d’aptitude à générer du code. Si vous ne pouvez pas remplir les sections relatives aux contraintes et aux chemins concernés, vous n’êtes pas prêt à générer de code ; vous êtes encore en phase de conception. Générer du code alors que la conception n’est pas finalisée est précisément ce qui permet à une seconde architecture de voir le jour. Les parties stables de cette liste de contrôle peuvent être conservées dans un fichier d’instructions projet ; consultez notre guide sur la rédaction d’un fichier CLAUDE.md efficace.
Quoi encore qui nécessite une révision humaine
Les prompts délimités éliminent la plupart des éléments perturbateurs, mais ils ne remplacent pas le jugement. Lors de la révision des différences, vérifiez toujours :
- Un nouveau paquet que personne n’a approuvé.
- Une autre manière d’appeler l’API.
- Des types s’éloignant du contrat défini par le serveur.
- Un état côté client pour des données qui devraient être gérées par le serveur.
- Des tests ne couvrant que les scénarios positifs prévus par le modèle.
Rédiger le prompt est la partie simple ; savoir quels critères sont importants dans cette base de code est la partie complexe, et ces connaissances appartiennent à l’équipe.
La plus petite modification à effectuer aujourd’hui
Si une liste complète de vérifications vous semble trop lourde, ajoutez simplement trois lignes à votre prochaine demande de fonctionnalité : quels chemins utiliser, quelles bibliothèques ne pas ajouter, et à quoi ressemble un résultat « terminé », y compris au moins un scénario d’échec.
Use only: [paths]
Do not add: [libs]
Done when: [2–3 behaviors + one failure path]
Conclusion
- Les prompts vagues provoquent rarement des pannes ; ils créent une infrastructure redondante qui semble terminée mais vous coûtera plus tard.
- Plus d’adjectifs modifient le ton du résultat, mais pas sa structure. Les contraintes, elles, modifient la structure.
- Un prompt bien défini permet de nommer les fichiers à réutiliser, d’indiquer la source fiable des données et des types, de décrire le comportement en cas d’extrêmes, les tests à effectuer, ainsi que les dépendances interdites.
- Lorsque le modèle invente quelque chose en dehors des limites prévues, considérez cela comme un manque de délimitation : corrigez le prompt et régénérer plutôt que de simplement affiner la formulation.