Notes pratiques : Utilisation d’agents IA d’entreprise en ingénierie
Guide pas à pas des notes pratiques : Utilisation d’agents IA d’entreprise en ingénierie : contrats, vérifications et emplacements de code prêts à l’emploi pour les équipes qui mettent en œuvre ce modèle.
Les notes suivantes reconstituent une approche pratique pour aborder le sujet « Engineering Enterprise AI Agent Harnesses ». L’accent est mis sur les contrats, les vérifications et les placeholders de code à insérer, plutôt que sur une présentation motivante. Lors de la phase d’aperçu, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système.
1. Le modèle, l’agent et le harness sont des éléments distincts
L’agent modèle 1 et les étapes fonctionnent le mieux lorsqu’ils sont considérés comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours optimal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Fixez un budget de tokens par tour et par session : les outils agents élargissent lourdement le contexte ; des plafonds stricts empêchent que les démonstrations ne se transforment en factures inattendues.
Observe → Reason → Validate → Act → Observe
2. Pourquoi les systèmes d’entreprise ont besoin d’un cadre de gestion
La méthode en deux étapes des systèmes d’entreprise fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
3. L’architecture de mise à profit des agents d’entreprise
La phase de l’agent d’entreprise fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Recueillez un transcript exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des critères de succès et refusez toute mise en œuvre partielle silencieuse. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Bordure entre utilisateur et application
La phase de délimitation entre l’utilisateur et l’application fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Mettez à disposition des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Planificateur et gestionnaire d’état
Les étapes du planificateur et de la gestionnaire d’état fonctionnent le mieux lorsqu’elles sont considérées comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de les valider automatiquement.
Réseau de exécution du modèle
La phase d’exécution du modèle fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez en même temps le parcours optimal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Fixez un budget de tokens par tour et par session : les outils agents élargissent lourdement le contexte ; des plafonds stricts empêchent que les démos ne se transforment en factures inattendues.
Registre des outils
La phase d’enregistrement des outils fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé. Exposez les outils avec des schémas restreints et des étiquettes explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Moteur de politiques
L’étape du moteur de politiques fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et des notes de réversion avant d’élargir le périmètre. Traitez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez toute complétion partielle silencieuse. Exposez des outils dotés de schémas restreints et de labels explicites indiquant leurs effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de valider automatiquement. L’étape du moteur de politiques fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et des notes de réversion avant d’élargir le périmètre. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
Règles de conduite
Pour l’étape Guardrails, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure. Authentifiez au niveau du gateway et réautorisez au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.
Contrôle d’approbation humaine
Pour l’étape d’approbation par les humains, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Authentifiez à l’entrée du système et réautorisez au niveau du plan de données. Un jeton porteur seul ne constitue pas une frontière entre les tenants.
Exécuteur d’outils et environnement isolé
Pour l’exécuteur d’outils et l’étape de sandbox, définissez les entrées, le responsable de l’étape ainsi que les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute exécution partielle silencieuse. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un simple token porteur ne constitue pas une frontière entre les tenants. Pour l’exécuteur d’outils et l’étape de sandbox, définissez les entrées, le responsable de l’étape ainsi que les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
Mémoire et données
Lors de l’étape relative à la mémoire et aux données, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, les boucles d’agent de débogage gaspillent des heures.
Observabilité et traces
Lors de la phase d’Observabilité et de suivi des traces, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, le débogage des boucles d’agent prend des heures.
Évaluations et retours
Lors de l’étape d’évaluation et de retour d’information, écrivez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès, et refusez toute exécution partielle silencieuse. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans ces traces, les boucles d’analyse des erreurs perdent des heures. Lors de l’étape d’évaluation et de retour d’information, écrivez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système.
4. Exécution étape par étape d’un exécution d’agent
L’exécution en 4 étapes peut être optimisée en la considérant comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et des notes de réversion avant d’élargir le périmètre. Documentez ensemble le parcours réussi et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de valider automatiquement.
Étape 1 — Recevoir et classer l’objectif
La étape 1 « Recevoir et préparer » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit pointer vers une seule responsabilité plutôt qu’un processus embrouillé. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Étape 2 — Construire un contexte délimité
La phase de construction limitée de l’Étape 2 fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des vérifications de succès et refusez toute mise en œuvre partielle silencieuse. Exposez des outils dotés de schémas restreints et de labels explicites indiquant leurs effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement. La phase de construction limitée de l’Étape 2 fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les stocks de secrets et les indicateurs fonctionnels doivent se trouver en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
Étape 3 — Demandez au modèle quelle action effectuer ensuite
Pour l’étape 3 « Demander », définissez les entrées, le responsable de l’étape ainsi que les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours idéal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure. Préférez des sorties structurées avec validation de schéma plutôt que du texte libre lorsque l’étape suivante consiste en du code ou une appel à outil.
Étape 4 — Valider en dehors du modèle
Pour l’étape 4 « Valider en dehors » , définissez les entrées, le responsable de l’étape ainsi que les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Préférez des sorties structurées avec validation de schéma à du texte libre lorsque l’étape suivante consiste en du code ou une appel d’outil.
Étape 5 — Obtenir l’approbation si nécessaire
Pour l’étape 5 « Obtenir l’approbation », définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminations partielles silencieuses. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un simple token porteur ne constitue pas une frontière entre les tenants. Pour l’étape 5 « Obtenir l’approbation », définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
Étape 6 — Exécuter dans un environnement contrôlé
Lors de l’exécution de l’étape 6, notez d’abord les paramètres requis, le signal de succès ainsi que la réaction en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez à la fois le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans ces traces, le débogage prend des heures inutilement.
Étape 7 — Normaliser l’observation
Lors de l’exécution de l’étape 7 « Normaliser », notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, le débogage de boucles d’agent prend des heures.
Étape 8 — Continuer ou arrêter
Lors de l’exécution de l’étape 8 Continue, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez toute exécution partielle silencieuse. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans ces traces, les boucles d’analyse des erreurs perdent des heures. Lors de l’exécution de l’étape 8 Continue, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système.
Étape 9 — Produire la réponse finale et les traces
La étape 9 « Produire la phase » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de rollback avant d’élargir le périmètre. Documentez ensemble le parcours idéal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure. Fournissez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de valider automatiquement.
5. Exemple : un agent de comptes clients
Les 5 exemples montrent que l’étape des comptes clients fonctionne le mieux lorsqu’elle est considérée comme une entité mesurable. Recueillez un exemple réussi, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité et non un processus embrouillé. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
6. Modes de défaillance que le système doit empêcher
Les 6 modes de défaillance : cette étape fonctionne le mieux lorsque la surface est traitée comme une entité mesurable. Capturez un transcript idéal, un cas de défaillance et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des vérifications de succès et refusez toute mise à jour partielle silencieuse. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Sécurité basée uniquement sur les prompts
La phase de sécurité basée uniquement sur les prompts fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût en tokens ou en requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Fixez un budget en tokens par tour et par session : les outils agents élargissent de manière importante le contexte ; des plafonds stricts empêchent que les démonstrations ne se transforment en factures inattendues.
Connexion directe du modèle à l’outil
La phase de connexion directe du modèle à l’outil fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du schéma. Fixez des limites de tokens par tour et par session. Les outils agents élargissent l’étendue du contexte de manière importante ; des plafonds stricts empêchent que les démonstrations se transforment en factures inattendues.
Credenciaux partagés surpuissants
La phase de partage de crédentielles surdimensionnées fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez en même temps le parcours optimal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Fournissez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Le contenu non fiable devient des instructions
La phase où le contenu non fiable devient des instructions fonctionne le mieux lorsqu’il est traité comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Boucles illimitées
La phase des boucles illimitées fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez toute mise en œuvre partielle silencieuse. Exposez des outils dotés de schémas restreints et de labels explicites indiquant leurs effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement. La phase des boucles illimitées fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
Journaliser tout
Pour l’étape de journalisation, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une amélioration ultérieure. Authentifiez au niveau du gateway et réautorisez au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.
Mesurer uniquement les réponses fluides
Pour l’étape de mesure uniquement des réponses fluides, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Authentifiez au niveau du gateway et réautorisez au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.
7. Mettre en place un environnement local pour l’exploitation de l’IA
Pour le point 7, créez une étape, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute complétion partielle silencieuse. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un simple token porteur ne constitue pas une frontière entre les tenants. Pour le point 7, créez une étape, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
Prérequis
Lors de la phase des Prérequis, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, les boucles d’agent de débogage gaspillent des heures.
mkdir enterprise-agent-harness
cd enterprise-agent-harness
python -m venv .venv
source .venv/bin/activate
.venv\Scripts\Activate.ps1
python -m pip install openai pydantic fastapi uvicorn python-dotenv
Conservez la configuration séparément des secrets
Lorsque vous configurez Keep de manière indépendante de l’étape, notez d’abord les exigences : entrées requises, signal de succès et conséquences en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans ces traces, le débogage de boucles d’agent prend des heures.
AI_PROVIDER=openai
AI_MODEL=<approved-model-id>
OPENAI_API_KEY=<set-locally-never-commit>
HARNESS_ENV=development
HARNESS_MAX_STEPS=8
HARNESS_RUN_TIMEOUT_SECONDS=120
HARNESS_MAX_TOOL_RETRIES=2
HARNESS_REQUIRE_APPROVAL_FOR_WRITES=true
Utilisez une structure de projet en couches
Lors de la phase « Utiliser un projet en couches », écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez les terminations partielles silencieuses. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, les boucles d’agent de débogage gaspillent des heures.
enterprise-agent-harness/
├── app/
│ ├── api.py # authenticated HTTP entry point
│ ├── harness.py # observe/reason/validate/act loop
│ ├── model_adapter.py # provider-specific model calls
│ ├── schemas.py # typed proposals and observations
│ ├── tools/
│ │ ├── registry.py # available capabilities
│ │ ├── invoices.py # example read-only tool
│ │ └── email.py # example external-write tool
│ ├── policy/
│ │ ├── engine.py # allow/deny/require-approval
│ │ └── rules.yaml # reviewed declarative policy
│ ├── approvals.py # exact-action approval records
│ ├── sandbox.py # isolated execution adapter
│ ├── state.py # run and conversation state
│ ├── telemetry.py # sanitized events and traces
│ └── redaction.py # secret and sensitive-data filtering
├── evals/
│ ├── cases.jsonl # representative tasks and attacks
│ └── run_evals.py
├── tests/
│ ├── test_policy.py
│ ├── test_tools.py
│ └── test_harness.py
├── Dockerfile
├── compose.yaml
├── .env
.example
└── pyproject.toml
Lors de la phase « Utiliser un projet en couches », écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système.
Définissez d’abord la limite de l’autonomie
La phase de définition de la limite d’autonomie fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Recueillez un transcript exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours idéal et le parcours de récupération. Les tentatives répétées, les contrôles humains et le traitement des messages non livrés font partie du produit, et non d’une mise en forme ultérieure. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de valider automatiquement.
8. Créez un ensemble de référence exécutable
La méthode « 8 Build a runnable stage » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de rollback avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
Définir des contrats typés
La phase de définition des contrats typés fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemplaire idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des vérifications de succès et refusez toute mise en œuvre partielle silencieuse. Exposez des outils dotés de schémas restreints et de labels explicites indiquant leurs effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant d’approuver automatiquement.
from enum import Enum
from typing import Any, Literal
from pydantic import BaseModel, Field
class Risk(str, Enum):
READ_ONLY = "read_only"
SENSITIVE_READ = "sensitive_read"
EXTERNAL_WRITE = "external_write"
DESTRUCTIVE = "destructive"
class ToolProposal(BaseModel):
tool: str
arguments: dict[str, Any]
reason: str
class PolicyDecision(BaseModel):
outcome: Literal["allow", "deny", "require_approval"]
reason_code: str
explanation: str
class Observation(BaseModel):
tool: str
ok: bool
data: dict[str, Any] = Field(default_factory=dict)
error_code: str | None = None
class RunState(BaseModel):
run_id: str
user_id: str
tenant_id: str
goal: str
step: int = 0
observations: list[Observation] = Field(default_factory=list)
finished: bool = False
La phase de définition des contrats typés fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemplaire idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système.
Enregistrez les outils avec des métadonnées de sécurité
Pour les outils Register en phase de sécurité, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une amélioration ultérieure. Authentifiez au niveau du gateway et réautorisez au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.
from dataclasses import dataclass
from typing import Callable
@dataclass(frozen=True)
class ToolDefinition:
name: str
risk: Risk
handler: Callable[..., dict]
timeout_seconds: int
idempotent: bool
TOOLS = {
"list_overdue_invoices": ToolDefinition(
name="list_overdue_invoices",
risk=Risk.SENSITIVE_READ,
handler=list_overdue_invoices,
timeout_seconds=10,
idempotent=True,
),
"send_email": ToolDefinition(
name="send_email",
risk=Risk.EXTERNAL_WRITE,
handler=send_email,
timeout_seconds=15,
idempotent=False,
),
}
Mettre en œuvre une politique déterministe
Pour la phase de mise en œuvre d’une politique déterministe, il convient de définir les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu, sans avoir à deviner l’état caché. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.
def authorize(state: RunState, proposal: ToolProposal) -> PolicyDecision:
definition = TOOLS.get(proposal.tool)
if definition is None:
return PolicyDecision(
outcome="deny",
reason_code="UNKNOWN_TOOL",
explanation="The requested capability is not registered.",
)
if not identity_can_use_tool(
user_id=state.user_id,
tenant_id=state.tenant_id,
tool=definition.name,
arguments=proposal.arguments,
):
return PolicyDecision(
outcome="deny",
reason_code="NOT_AUTHORIZED",
explanation="The caller lacks permission for this resource.",
)if definition.risk in {Risk.EXTERNAL_WRITE, Risk.DESTRUCTIVE}:
return PolicyDecision(
outcome="require_approval",
reason_code="CONSEQUENTIAL_ACTION",
explanation="The exact action must be approved before execution.",
)return PolicyDecision(
outcome="allow",
reason_code="POLICY_ALLOWED",
explanation="The action is permitted within the caller's scope.",
)
Lier l’approbation à l’action précise
Pour obtenir l’approbation de la phase Bind, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute finalisation partielle silencieuse. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un simple token porteur ne constitue pas une frontière entre les tenants. Pour obtenir l’approbation de la phase Bind, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
import hashlib
import json
def action_digest(state: RunState, proposal: ToolProposal) -> str:
value = {
"user_id": state.user_id,
"tenant_id": state.tenant_id,
"tool": proposal.tool,
"arguments": proposal.arguments,
}
canonical = json.dumps(value, sort_keys=True, separators=(",", ":"))
return hashlib.sha256(canonical.encode("utf-8")).hexdigest()
Mettre en œuvre la boucle contrôlée
Lors de l’étape de mise en œuvre de la boucle contrôlée, écrivez d’abord le cahier des charges : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, le débogage des boucles d’agent prend des heures inutilement.
async def run_harness(state: RunState, model, approvals, executor):
max_steps = 8
while not state.finished and state.step < max_steps:
state.step += 1context = build_bounded_context(state, TOOLS)
response = await model.next_action(context)if response.final_answer is not None:
state.finished = True
return complete_run(state, response.final_answer)proposal = ToolProposal.model_validate(response.tool_proposal)
decision = authorize(state, proposal)
trace_policy_decision(state, proposal, decision)if decision.outcome == "deny":
state.observations.append(Observation(
tool=proposal.tool,
ok=False,
error_code=decision.reason_code,
))
continueif decision.outcome == "require_approval":
digest = action_digest(state, proposal)
if not approvals.has_valid_approval(digest):
return pause_for_approval(state, proposal, digest)observation = await executor.execute(
definition=TOOLS[proposal.tool],
arguments=proposal.arguments,
identity={
"user_id": state.user_id,
"tenant_id": state.tenant_id,
},
)
state.observations.append(redact_observation(observation))return stop_run(state, reason="STEP_LIMIT_REACHED")
Connecter le modèle via un adaptateur
Lorsque vous travaillez sur l’étape de connexion du modèle, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de maintenir l’honnêteté des modifications ultérieures du code. Préférez des unités petites et testables à des scripts volumineux. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus complexe et embrouillé. Cachez les instructions du système stables ainsi que les schémas des outils. Envoyer à nouveau un préambule identique est une cause fréquente de gaspillage de ressources.
class ModelAdapter:
async def next_action(self, context) -> "ModelTurn":
raise NotImplementedError
Exposer une API authentifiée
Lors de la phase d’Exposition d’une API authentifiée, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès, et refusez les terminations partielles silencieuses. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, les boucles d’analyse des erreurs perdent des heures précieuses.
from fastapi import Depends, FastAPI
app = FastAPI()
@app.post("/runs")
async def create_run(request: RunRequest, identity=Depends(require_identity)):
state = RunState(
run_id=new_run_id(),
user_id=identity.user_id,
tenant_id=identity.tenant_id,
goal=request.goal,
)
return await run_harness(state, model, approvals, executor)
@app.post("/runs/{run_id}/approvals")
async def approve_run_action(
run_id: str,
request: ApprovalRequest,
identity=Depends(require_identity),
):
return approve_exact_action(run_id, request.action_digest, identity)
Lors de la phase d’Exposition d’une API authentifiée, notez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système.
Exécuter localement
La phase d’Exécution localement fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple de fonctionnement idéal, un cas d’échec et des notes de rollback avant d’élargir le périmètre. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives de réexécution, les contrôles manuels et la gestion des messages non traités font partie intégrante du produit, et non d’améliorations ultérieures. Exposez des outils dotés de schémas restreints et de labels explicites indiquant leurs effets secondaires. Les hôtes doivent savoir quels appels modifient l’état du système avant de valider automatiquement ces appels.
uvicorn app.api:app --host 127.0.0.1 --port 8000 --reload
9. Tester et évaluer le harnais
La phase de test et d’évaluation 9 fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement réussi, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de valider automatiquement.
Tests unitaires et d’intégration déterministes
La phase d’unité et d’intégration déterministe fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des vérifications de succès et refusez toute mise en œuvre partielle silencieuse. Exposez des outils dotés de schémas restreints et de labels explicites indiquant leurs effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de valider automatiquement. La phase d’unité et d’intégration déterministe fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système.
def test_external_write_requires_approval():
proposal = ToolProposal(
tool="send_email",
arguments={"to": "customer@example.test", "body": "Reminder"},
reason="Send the approved reminder",
)
decision = authorize(make_finance_run(), proposal)assert decision.outcome == "require_approval"
assert decision.reason_code == "CONSEQUENTIAL_ACTION"
Évaluations des modèles et des flux de travail
Pendant l’étape d’évaluation des modèles et des flux de travail, définissez les entrées, le responsable de chaque étape ainsi que les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez conjointement le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’améliorations ultérieures. Préférez des sorties structurées avec validation de schéma plutôt que du texte libre lorsque l’étape suivante consiste en du code ou une appel à outil.
10. Déployer le système à l’échelle enterprise
Pour l’étape 10 « Déployer le harnais », définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un pipeline embrouillé. Authentifiez au niveau du gateway et réautorisez au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.
Topologie de production
Pour l’étape de topologie de production, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute exécution partielle silencieuse. Authentifiez-vous au niveau du gateway et réautorisez-vous au niveau du plan de données. Un token porteur seul ne constitue pas une frontière entre les tenants.
Client
│
▼
API Gateway / WAF
│ authentication, rate limits, request ID
▼
Harness API
├── Policy Service
├── Approval Service
├── Model Gateway ─────► Model Provider
├── State Store
├── Trace / Audit Pipeline
└── Tool Executor Queue
│
▼
Isolated Workers
├── MCP / SaaS APIs
├── Browser Sandbox
├── Code Sandbox
└── Enterprise Data
Pour l’étape de topologie de production, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du schéma.
Containeriser le plan de contrôle
Lors de la phase de containerisation du plan de contrôle, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, le débogage des boucles d’agent prend des heures inutilement.
FROM python:3.12-slim
WORKDIR /app
COPY pyproject.toml ./
RUN pip install --no-cache-dir .COPY app ./appRUN useradd --create-home --uid 10001 harness
USER harnessENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1CMD ["uvicorn", "app.api:app", "--host", "0.0.0.0", "--port", "8000"]
Contrôles en production
Lors de la phase de contrôle de production, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans cette trace, les boucles d’agent de débogage gaspillent des heures.
Itinéraire du développement vers la production
Lors de la phase de transition du développement à la production, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez toute exécution partielle silencieuse. Enregistrez le nom de l’outil, le hash des arguments, la latence et le résultat de chaque appel. Sans ces traces, les tentatives de débogage s’éternisent inutilement. Lors de la phase de transition du développement à la production, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans avoir à lire l’ensemble du système.
11. Liste de vérification de la prêté à l’entreprise
La phase 11 de la liste de vérification de la prêté à l’entreprise fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Recueillez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours optimal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure. Exposez des outils dotés de schémas restreints et de labels explicites indiquant les effets secondaires. Les hôtes doivent savoir quels appels modifient l’état avant de valider automatiquement.
Conclusion
La phase de conclusion fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Recueillez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre.