Skip to content

Spec-driven development : écrire des contrats pour les agents IA

SigmaJunction · Ingénierie10 min de lecture

Quelque chose s’est discrètement inversé dans l’ingénierie logicielle ces deux dernières années. Pendant l’essentiel de l’histoire du métier, le code était l’artefact et la spécification l’échafaudage jetable qui l’entourait - un document écrit une fois, parcouru deux fois, abandonné au troisième sprint. Aujourd’hui, les agents IA écrivent une part croissante du code, et l’économie s’est retournée. Le code est devenu bon marché à produire et bon marché à régénérer. Ce qui est rare, c’est un énoncé précis de ce que le code doit faire. La spécification n’est plus un échafaudage. C’est l’artefact d’ingénierie.

Les équipes qui la traitent ainsi obtiennent des agents un levier qui capitalise : elles délèguent un travail bien défini, vérifient le résultat mécaniquement et fusionnent en confiance. Les autres récoltent une nouvelle sorte de dette technique : du code d’apparence plausible que personne n’a demandé, généré plus vite que quiconque ne peut le relire. La différence entre les deux ne tient ni au modèle ni à l’outillage. Elle tient à ce que la spécification soit, ou non, un contrat.

Un prompt n’est pas une spécification

L’erreur la plus fréquente consiste à prendre la zone de chat pour la spécification. Un prompt est une entrée en conversation : il décrit une intention en prose, laisse les cas limites à la bonne volonté du lecteur, et disparaît dans un historique de défilement à la seconde où il est envoyé. Personne ne peut le relire, le comparer, ni le désigner trois semaines plus tard quand le comportement est contesté. Un agent à qui l’on donne un prompt fait ce que fait un artisan à qui l’on a expliqué le chantier dans un couloir : il comble chaque vide avec ses propres hypothèses, avec assurance.

Une spécification est un objet différent. Elle vit dans le dépôt, à côté du code qu’elle gouverne. Elle est versionnée, on voit donc ce qui a été convenu et quand cela a changé. Elle est relisible, un collègue peut donc contester l’exigence plutôt que l’implémentation. Et elle est vérifiable - la propriété cruciale - c’est-à-dire que pour tout travail livré il existe une façon mécanique de demander : est-ce que cela satisfait la spécification, oui ou non ? À la seconde où cette question demande un jugement, vous avez de la prose, pas un contrat.

Ce qui fait d’une spécification un contrat

Quatre ingrédients séparent un contrat d’un vœu. Les critères d’acceptation viennent en premier : des énoncés observables et binaires sur le comportement. « Rapide » est un vœu ; « p95 sous 200 ms à 50 requêtes par seconde » est un critère. « Gère les entrées invalides » est un vœu ; « rejette les charges utiles malformées avec un 422 et un code d’erreur exploitable par une machine » est un critère. Si vous ne pouvez pas trancher conforme ou non conforme depuis l’extérieur de l’implémentation, réécrivez jusqu’à le pouvoir.

Les exemples travaillésviennent en deuxième, et ils abattent plus de travail que toute autre section. Des paires entrée-sortie concrètes - y compris les moches : la liste vide, la soumission en double, le cas limite de fuseau horaire, l’utilisateur qui colle un émoji dans le champ montant. C’est dans les exemples que remontent les hypothèses cachées. Ce sont aussi, et ce n’est pas un hasard, des cas de test qui n’attendent que d’être transcrits.

Les invariantsviennent en troisième : des propriétés qui doivent tenir quel que soit le chemin pris par l’implémentation. Les soldes ne passent jamais en négatif. Chaque transition d’état est journalisée. Les suppressions sont logiques. Aucun appel au prestataire de paiement sans clé d’idempotence. Les invariants sont les garde-fous qui survivent au refactoring - ce qui compte doublement quand le refactoring est fait par un agent qui n’a jamais assisté à la réunion où la règle a été expliquée.

Les non-objectifsviennent en dernier et sont les plus négligés. Le mode de défaillance d’un agent est rarement d’en faire trop peu ; c’est d’en faire trop - inventer des options de configuration, ajouter un cache que personne n’a demandé, « améliorer » le code voisin. Une courte liste de ce que ce changement ne doit pas toucher et des problèmes qu’il ne doit pas résoudre est le contrôle de périmètre le moins cher que vous écrirez jamais.

Un agent comble chaque vide de la spécification avec ses propres hypothèses - avec assurance. Le contrat existe pour qu’il ne reste aucun vide à combler.

Un contrat doit être appliqué

Un contrat que personne n’applique est une décoration. La couche d’application est ce qui fait du développement piloté par la spécification une pratique d’ingénierie plutôt qu’une habitude documentaire, et elle a trois parties. D’abord, les tests comme forme exécutable du contrat.Les critères d’acceptation et les exemples travaillés sont transcrits en suite de tests avant que l’agent n’écrive le code d’implémentation. La suite, c’est la spécification compilée en quelque chose qu’une machine peut vérifier ; le travail de l’agent est de la faire passer sans l’affaiblir. Protégez les tests eux-mêmes en revue - un agent qui modifie une assertion pour la faire passer a renégocié le contrat unilatéralement.

Ensuite, les frontières typées.Schémas, types et contrats d’API verrouillent chaque interface que touche le code de l’agent. Un schéma strict à la frontière transforme toute une classe de sorties plausibles mais fausses en erreurs de compilation et en échecs de validation - un retour que l’agent reçoit en quelques secondes, dans la boucle, plutôt qu’un retour livré par un relecteur des jours plus tard. Plus la frontière est stricte, moins il reste de place pour laisser passer du n’importe quoi assuré.

Enfin, des points de contrôle en revue qui comparent le diff au contrat.La revue humaine ne disparaît pas ; elle change de cible. Relire la sortie d’un agent ligne à ligne, à la vitesse d’un agent, est un combat perdu : il y a simplement plus de code que d’attention. Comparer le diff au contrat est faisable : le changement satisfait-il chaque critère d’acceptation, respecte-t-il chaque invariant, reste-t-il à l’intérieur des non-objectifs ? Tout ce que le contrat n’explique pas dans le diff est la première question de la revue, pas un bonus.

Les trois façons dont cela dérape

Spécification vague, n’importe quoi assuré.L’équipe écrit trois puces, l’agent produit huit cents lignes, et l’écart entre l’intention et le comportement se découvre en production. L’indice, ce sont les revues qui commencent par « ce n’est pas ce que je voulais dire » - une phrase qui accuse la spécification, pas l’agent. Le remède est ennuyeux : plus d’exemples, des critères plus nets, écrits avant la génération et non après.

Sur-spécification, aucun levier.Le fossé d’en face. Si la spécification dicte l’implémentation - fichier par fichier, fonction par fonction - vous avez écrit le code deux fois, une fois en français et une fois dans le langage où il s’exécute, et l’agent est réduit à un dactylographe. Spécifiez le comportement à la frontière et les invariants à l’intérieur ; laissez l’implémentation à la partie qui l’écrit. Si spécifier une tâche prend plus de temps que de la faire, cette tâche n’avait pas besoin d’un agent.

La dérive de spécification.La défaillance la plus silencieuse. Le contrat disait une chose, la production a évolué vers une autre, et après trois mois de petites renégociations au passage, la spécification décrit un système qui n’existe plus. La dérive est inévitable ; la dérive non consignée est un choix. La règle qui l’empêche tient en une phrase : les changements de comportement atterrissent d’abord comme changements de spécification, dans la même pull request, ou ils n’atterrissent pas.

La boucle, de bout en bout

En pratique, cela ressemble à une boucle courte. Écrire le contrat- critères, exemples, invariants, non-objectifs - et le faire relire par les personnes qui vivront avec le comportement ; c’est là que le désaccord coûte le moins cher. Transcrire en tests les parties vérifiables, des tests qui échouent. Confier le contrat à l’agentet le laisser produire face à la suite en échec, en itérant jusqu’à ce que les contrôles mécaniques - tests, types, schémas, linters - passent sans qu’on ait touché aux contrôles eux-mêmes. Puis comparer le diff au contrat, et non à votre patience : critères remplis, invariants tenus, rien en dehors des non-objectifs. La fusion enregistre le contrat et son exécution en une seule unité atomique, et la tâche suivante démarre d’une base honnête.

La boucle a un bénéfice de second ordre qui surprend les équipes : les contrats rendent le travail des agents parallélisable. Deux agents sur un même brief flou se percutent ; cinq agents sur cinq contrats aux frontières typées fusionnent proprement, parce que chaque contrat énonce ce que sa pièce doit faire et où elle s’arrête. La propriété qui rend une spécification vérifiable la rend composable - et c’est ainsi qu’une petite équipe senior supervise un volume d’implémentation simultanée qui aurait exigé un service entier il y a cinq ans.

Une dernière règle mécanique garde la boucle honnête : les contrôles tournent en CI, pas sur parole d’agent. Un agent qui rapporte « tous les tests passent » émet une affirmation ; un pipeline vert sur une suite de tests non modifiée est un fait. Le contrat, ses tests et le pipeline forment ensemble un arbitre neutre qui se moque de savoir si le code a été écrit par une personne en mauvais jour ou par un modèle en jour d’assurance - et c’est exactement cette indifférence qui rend le résultat digne de confiance.

Les équipes qui adoptent cette pratique découvrent que le goulot d’étranglement a bougé. La compétence rare n’est plus de produire du code : c’est de décider précisément ce que le code doit faire et de l’exprimer de façon vérifiable. C’était depuis toujours la partie difficile du logiciel ; les agents n’ont pas créé le problème, ils ont supprimé l’endroit où il se cachait.

Quand cela paie - et quand c’est de la charge inutile

Le développement piloté par la spécification n’est pas gratuit, et prétendre le contraire tue l’adoption. Le contrat se rentabilise quand le travail porte à conséquence et que le coût de l’erreur est réel : des systèmes qui déplacent de l’argent, touchent des données clients, se tiennent aux frontières entre équipes, ou seront maintenus par des personnes - et des agents - qui n’étaient pas là quand les décisions ont été prises. Il paie le plus vite exactement là où la sortie des agents est la plus difficile à relire à l’œil.

C’est de la charge inutile pour les explorations, les prototypes et les scripts jetables - du code dont toute la raison d’être est d’être supprimé une fois qu’il a répondu à une question. Écrivez une phrase d’intention, laissez l’agent tourner, gardez l’enseignement et effacez le code. La discipline consiste à savoir dans quel mode vous êtes, et à être honnête à la seconde où un prototype commence discrètement à devenir un système. C’est ce moment-là - et non la réécriture six mois plus tard - qui appelle l’écriture du contrat.

L’industrie a mis deux décennies à comprendre que les tests ne sont pas de la bureaucratie mais ce qui permet d’aller vite sans casser ce qui compte. Les spécifications font aujourd’hui le même trajet, pour la même raison. Quand le coût marginal d’écrire du code tend vers zéro, la valeur se concentre dans l’énoncé de ce que le code doit faire - et les équipes qui écrivent cet énoncé comme un contrat sont celles chez qui les agents capitalisent vraiment.

À lire ensuite

Recevez le prochain essai par e-mail

Le logiciel comme investissement, l'IA appliquée et la pratique de l'ingénierie - écrit pour ceux qui signent les factures.

Un à deux essais par mois, sans bruit. Confirmation par e-mail, désabonnement en un clic.

Vous mettez des agents au travail sur un système qui compte ?

Nous construisons les contrats, leur application et le logiciel. L'appel de diagnostic est gratuit.