Accueil / Articles

Conception de l’outil d’agent : politique, sandboxing, mémoire et vérification

Découvrez quels niveaux de fonctionnement transforment un LLM appelant des outils en un agent fiable : politique d’exécution, sandboxing du système d’exploitation, état persistant, vérification, contrôle du contexte et coûts.

Éditeur : REACTAPP.TOP19 min de lecture4372 mots

Sources: Agent Harness Engineering: The Missing Layer Between an LLM and a Real AI Agent

Les équipes qui se lancent dans la création d’un agent IA commencent généralement par comparer les modèles : taille de la fenêtre de contexte, scores d’évaluation, qualité du raisonnement, prix par token. Une fois un modèle choisi, quelques outils sont intégrés, et le résultat est appelé agent. Ce qui existe réellement à ce stade, c’est un modèle capable d’appeler des fonctions, et l’écart entre celui-ci et un agent opérationnel est comblé par une couche de exécution aujourd’hui communément désignée sous le nom de agent harness. Ce guide présente les différentes couches de cet agent harness, ce à quoi chacune vous protège, ainsi que la manière d’en développer progressivement les fonctionnalités sans être submergé par les abstractions du framework.

Un modèle capable d’appeler des outils n’est pas encore un agent

L’ensemble de départ typique se présente sous forme d’une courte liste des capacités mises à disposition du modèle.

search()
read_file()
write_file()
run_command()

Avec ces quatre fonctions, le modèle peut rechercher, lire, écrire et exécuter des commandes. Cela donne l’impression d’autonomie, mais rien dans cette configuration ne décide de ce que le modèle est autorisé à manipuler, quelles opérations nécessitent l’approbation d’un humain, quelles informations survivent à une panne ou à un redémarrage, comment les résultats sont vérifiés, ou quelle partie des résultats de chaque outil est réutilisée dans la requête. Toutes ces responsabilités incombent au système de gestion.

Le système de gestion s’avère également être une variable mesurable. Au moment où cet article est écrit, une étude de 2026 comparant les systèmes de gestion pour des agents de codage a révélé des différences allant jusqu’à 40 fois dans le nombre de tokens consommés par tâche résolue, tandis que les écarts dans le taux de réussite entre ces mêmes systèmes étaient bien plus faibles. La conclusion n’est pas qu’un environnement d’exécution ingénieux peut transformer un modèle faible en un modèle brillant. Elle est plutôt que l’environnement d’exécution influence fortement l’efficacité, la sécurité et la prévisibilité avec lesquelles un modèle compétent accomplit sa tâche.

La boucle au centre et les questions qui l’entourent

En résumé, un agent est une boucle : on demande au modèle ce qu’il doit faire, on exécute l’outil demandé, on ajoute le résultat au contexte, et on répète jusqu’à ce que le modèle indique avoir terminé.

while True:
    response = model(context)

    if response.is_final:
        break

    result = execute_tool(response.tool_call)

    context.append(result)

De nombreux agents réels ont quelque chose de très proche de cela à leur cœur. Le modèle prend une décision, l’environnement d’exécution la met en œuvre, les observations reviennent, et le modèle choisit l’étape suivante. La boucle elle-même est simple ; l’effort d’ingénierie réside dans tout ce qui l’entoure. Un système utilisable doit répondre à une longue liste de questions opérationnelles à chaque tour.

Can the agent execute this command?

Can it access this directory?

Does it need human approval?

What happens if the command fails?

What information should return to the model?

What should survive the session?

Should another agent review the result?

How much context should we send?

How much will this turn cost?

What happens if the model loops forever?

Tout ensemble, ces éléments forment le « harness ». Un article conceptuel récent le décrit comme l’environnement de exécution qui relie un modèle de langage au monde extérieur grâce à des outils, à une gestion du contexte, à des contrôles de sécurité, à des mécanismes d’orchestration et à des points d’extension. Une représentation mentale pratique consiste à diviser l’agent en deux parties.

                  AI Agent
                       │
              ┌────────┴────────┐
              │                 │
           Model             Harness
              │                 │
        reasoning        ┌──────┼───────┐
        planning         │      │       │
        generation     Tools  Memory  Safety
                        │      │       │
                     Sandbox Context Verification

D’un côté, le modèle assure la réflexion, la planification et la génération. De l’autre côté, le « harness » fournit des outils, de la mémoire et des mesures de sécurité, soutenu par un environnement isolé, une gestion du contexte et des vérifications. Le modèle apporte l’intelligence ; le « harness » régule la manière dont cette intelligence interagit avec les systèmes réels.

Pourquoi un prompt ne peut pas être votre mécanisme de sécurité

Supposons que le prompt du système contienne une règle claire :

N’effacez jamais un fichier en production sans m’en demander d’abord l’autorisation.

Il n’y a rien d’ambigu dans cette phrase, pourtant il s’agit toujours d’une demande. Le modèle peut la mal interpréter, en perdre le souvenir au cours d’une session longue, la confronter à des instructions contradictoires ailleurs dans le contexte, se convaincre que le cas actuel est une exception, ou obtenir le même résultat destructeur grâce à un outil différent que la règle ne couvrait pas explicitement. Demander à un agent d’éviter quelque chose est fondamentalement différent de rendre cette action impossible sans autorisation. Un prompt exprime un souhait :

Please don't do X.

Un harnais peut exprimer une règle qui est évaluée dans le code :

if dangerous_action and not approved:
    deny()

La deuxième version fonctionne que le modèle se souvienne ou non de l’instruction. Cela illustre le premier principe de l’ingénierie des outils : chaque fois qu’une règle est déterministe, il faut l’implémenter en code déterministe. Claude Code suit la même logique dans sa conception. Les hooks s’exécutent lors d’événements de cycle de vie et d’appels d’outils, et peuvent par exemple rejeter un appel d’outil avant qu’il ne soit exécuté, tandis que des fichiers tels que CLAUDE.md fournissent des directives que le modèle lit comme contexte. Si vous écrivez un tel fichier, conservez-le à des fins de référence et déplacez les mécanismes de contrôle dans des hooks ; notre guide pour un CLAUDE.md efficace explique ce qui doit y figurer.

Niveau 1 : une frontière d’exécution entre la demande et l’action

La première question que le système doit résoudre concerne les actions que l’agent peut effectuer. Prenons un outil qui supprime un fichier.

def delete_file(path):
    os.remove(path)

Le modèle peut l’appeler avec n’importe quel argument de son choix.

delete_file("important.md")

Si cette appel s’exécute immédiatement, le modèle dispose d’une autorité illimitée sur tout ce que la fonction peut atteindre. La solution consiste à faire passer chaque appel par un contrôleur qui vérifie la politique avant de l’exécuter.

def execute(call):

    if call.name == "delete_file":
        if not call.args.get("human_approved"):
            return "DENIED: human approval required"

    return dispatch(call)

Désormais, le modèle peut toujours demander une suppression, mais demander ne signifie plus agir. Le flux devient alors une décision basée sur une politique ayant deux issues possibles.

Model decision
      ↓
Policy check
      ↓
Permission?
   ↙       ↘
 No         Yes
 ↓           ↓
Deny       Execute

Cela reflète une conception de sécurité conventionnelle : le modèle propose, l’exécution met en œuvre. Un détail à renforcer dans du code réel concerne l’origine de l’approbation. Dans le schéma ci-dessus, le drapeau d’approbation est lu dans les arguments mêmes de l’appel, générés par le modèle. Un outil de production devrait obtenir l’approbation de manière externe, via une étape de confirmation humaine ou un jeton signé que le modèle ne peut pas fabriquer, sinon le modèle pourrait simplement définir lui-même ce drapeau.

Pourquoi les vérifications au niveau de l’outil laissent passer des risques

Les politiques d’outil sont nécessaires mais insuffisantes. Imaginez que l’outil refuse cet appel :

delete_file("secrets/api_key")

Cela semble être une protection, jusqu’à ce que l’agent exécute plutôt la commande shell équivalente :

rm secrets/api_key

La politique delete_file ne voit jamais cette opération. Ou bien l’outil bloque la lecture du chemin secret :

read("secrets/api_key")

Mais un chemin relatif parvient à passer car personne ne l’a normalisé :

read("../secrets/api_key")

Les liens symboliques, les programmes d’aide qui ouvrent des fichiers au nom de l’agent, ainsi que les interpréteurs qui acceptent du code arbitraire créent tous des accès indirects similaires. Une politique exprimée en termes de noms d’outils et d’arguments de chaîne ne peut pas énumérer tous les chemins menant à une ressource, ce qui en fait une barrière de sécurité incomplète. Les directives d’OpenAI concernant l’exécution des agents de codage recommandent plutôt de combiner le sandboxing, des politiques d’approbation, une exécution restreinte, des contrôles réseau et de la télémétrie plutôt que de compter sur les prompts. Le principe à retenir : le système de gestion applique la politique, tandis que le système d’exploitation assure la barrière finale.

Niveau 2 : sandboxing de ce à quoi l’agent peut physiquement accéder

La politique définit ce que l’agent est autorisé à faire ; un environnement de test détermine d’abord ce à quoi il peut accéder. L’approche faible consiste en une liste de refus qui tente d’énumérer chaque emplacement sensible.

Don't access:
- /etc
- ~/.ssh
- secrets/
- production/
- credentials/
- ...

De telles listes ne sont jamais complètes. L’approche plus solide inverse la logique par défaut : accorder presque rien, puis ajouter précisément ce dont la tâche a besoin, comme un seul espace de travail de projet.

Agent workspace:

/workspace
    ├── src/
    ├── tests/
    ├── pyproject.toml
    └── README.md

L’agent reçoit /workspace et rien d’autre sur l’hôte. Expressé en termes de politique, cela correspond à une liste d’autorisation.

Allowed:
    /workspace

Everything else:
    unavailable

Puisque le reste du système de fichiers n’existe tout simplement pas du point de vue de l’agent, les astuces liées aux chemins, les symboles de lien et les processus d’aide perdent une grande partie de leur efficacité. Les conteneurs, les machines virtuelles dédiées et les comptes d’utilisateurs restreints sont des moyens courants pour mettre en œuvre cela. Le SDK Agents d’OpenAI a ajouté une exécution dans un environnement sandbox natif précisément à cette fin, permettant ainsi aux agents d’installer des dépendances, d’éditer des fichiers et d’exécuter des commandes dans un environnement contrôlé.

Les limites réseau et de ressources doivent être gérées dans le sandbox

L’isolation du système de fichiers ne suffit pas. Un agent capable d’exécuter des actions aussi simples présente un profil de menace très différent :

curl https://example.com

Avec un accès réseau sortant, l’agent peut :

  • télécharger et exécuter du logiciel arbitraire
  • extraire des données vers un hôte externe
  • appeler des API de tiers
  • Accéder à des services internes qui font confiance au réseau local
  • Ingérer du contenu provenant de sites web non fiables, ce qui constitue également la voie classique pour l’injection de code
  • Un environnement isolé digne de ce nom couvre donc plusieurs dimensions, et pas seulement les fichiers.

    Filesystem
    Network
    Processes
    Environment variables
    Secrets
    CPU
    Memory
    Time
    

    Les processus héritent silencieusement des variables d’environnement et des secrets, tandis que les limites de CPU, de mémoire et de temps empêchent les exécutions débridées. C’est cette polyvalence qui pousse les environnements d’exécution modernes à concevoir l’environnement isolé comme un véritable environnement d’exécution complet, et non simplement un enveloppe légère.

    Niveau 3 : état persistant survivant à la session

    Un autre type de problème apparaît avec les tâches longues. Un agent passe une heure à explorer un répertoire et découvre alors une règle architecturale importante.

    The authentication service must never directly access the database.
    All database operations go through Repository classes.
    

    Alors la fenêtre de contexte se remplit, la session est redémarrée, et ces connaissances disparaissent. La session suivante ne comprend pas pourquoi le design est conçu de cette manière et peut enfreindre volontiers ses règles. L’historique des conversations n’est pas l’endroit approprié pour ce type d’informations. Un système organisé permet de séparer au moins trois catégories d’informations ayant des durées de vie différentes.

    Conversation state
        ↓
    temporary
    
    Project state
        ↓
    persistent
    
    Harness configuration
        ↓
    persistent + globally enforced
    

    Un exemple concret pour chacune :

    Conversation:
    "Let's investigate the login bug."
    
    Project:
    "Authentication uses OAuth."
    
    Harness:
    "Never modify generated migrations."
    

    L’élément de conversation peut disparaître en toute sécurité lorsque la tâche se termine. Les informations relatives au projet doivent persister entre les sessions, par exemple dans un fichier de notes versionné ou dans un stockage mémoire. La règle de gestion doit être appliquée à chaque exécution, quel que soit ce que le modèle se souvient actuellement, ce qui signifie généralement qu’elle doit figurer dans le code de configuration et d’application plutôt que dans du texte. À mesure que les sessions s’allongent, cette séparation devient d’autant plus importante. L’API Agents d’OpenAI, par exemple, inclut des fonctionnalités de gestion du contexte destinées aux agents à long terme, dont une compression automatique lorsque la session approche de sa limite de contexte. C’est précisément au moment de cette compression que les informations sur le projet non enregistrées sont perdues, il est donc utile de les conserver délibérément avant ce stade. Pour en savoir plus sur les niveaux de mémoire, consultez la mémoire d’agent à quatre niveaux avec LangGraph et Amazon Bedrock.

    LangGraph et Bedrock.

    Niveau 4 : vérification que l’agent ne possède pas

    Les agents peuvent se tromper avec une certitude absolue, donc l’agent qui a provoqué un changement ne devrait pas être le seul juge de sa correction. Prenons cet exemple :

    def calculate_total(items):
        return sum(item.price for item in items) + 1
    

    Le + 1 isolé peut sembler intentionnel pour le modèle qui l’a écrit. Une étape de vérification indépendante peut évaluer ce changement en fonction de plusieurs indicateurs.

    Code
    Tests
    Type checking
    Linting
    Security rules
    Expected behavior
    

    Ce qui rend cela précieux, c’est la séparation entre la production et le jugement.

                     Agent
                       │
                       ↓
                    Changes
                       │
                       ↓
                  Verification
                   ↙        ↘
                PASS         FAIL
                 ↓             ↓
              Continue      Investigate
    

    Un succès permet à la boucle de continuer ; un échec renvoie l’agent pour qu’il enquête à nouveau. Une amélioration facile à négliger : l’examinateur doit signaler les problèmes plutôt que de les corriger en silence. Si le vérificateur répare discrètement la faille, on perd l’indication que l’agent initial a échoué, et vos métriques de succès deviennent fictives.

    Les essais en mode simulation comme par défaut pour les modifications risquées

    Pour les opérations à plus haut risque, la visualisation du comportement par défaut est recommandée. Au lieu d’une fonction d’application qui agit immédiatement :

    apply_change()
    

    présenter une option dont le mode par défaut sécurisé est l’essai en simulation :

    apply_change(dry_run=True)
    

    L’agent reçoit d’abord une description de l’effet attendu.

    Would modify:
        src/auth.py
        tests/test_auth.py
    

    Seul un pas explicite et distinct, de préférence nécessitant une approbation, permet de passer de la visualisation à l’exécution. Cela offre au vérificateur ainsi qu’à tout examinateur humain quelque chose de concret à examiner avant que quoi que ce soit ne change.

    Niveau 5 : ingénierie du contexte

    Chaque token placé dans le contexte coûte de l’argent, concurrence pour attirer l’attention du modèle, et dans les tâches longues a tendance à s’accumuler plus rapidement qu’il n’est éliminé. Supposons que l’agent ait besoin d’une fonction parmi celles contenues dans un fichier de 5 000 lignes. Un système naïf envoie tout le fichier, puis le résultat complet de la recherche suivante, puis celui de l’outil suivant, et ainsi de suite. Très vite, le contexte contient tout cela :

    Task
    + entire repository
    + previous searches
    + tool output
    + logs
    + previous reasoning
    + repeated instructions
    

    Le modèle peut techniquement voir chaque token, mais la visibilité ne signifie pas la compréhension. Une meilleure conception considère le contexte comme un pipeline qui condense les informations avant qu’elles n’atteignent l’agent principal.

    Main Agent
         │
         ├── Search Agent
         │      │
         │      └── 50,000 tokens
         │
         │      ↓
         │
         └── 1,000-token summary
    

    Ici, un agent de recherche peut consommer 50 000 tokens lors de ses recherches, mais la session principale ne reçoit qu’un résumé de 1 000 tokens contenant uniquement les informations essentielles. C’est un argument fort en faveur des sous-agents. Claude Code, par exemple, décrit les sous-agents comme des entités fonctionnant dans leurs propres fenêtres de contexte isolées, ne renvoyant au dialogue principal que leur résultat final, ce qui empêche les investigations secondaires volumineuses de surcharger le contexte principal. L’inconvénient est qu’un résumé peut omettre des détails dont l’agent principal aura besoin plus tard ; par conséquent, les résumés devraient inclure des indications (chemins de fichiers, plages de lignes) permettant à l’agent de récupérer des informations précises sur demande.

    L’économie : le prix par token n’est pas le coût par tâche

    La gestion du contexte relève également d’une question budgétaire. Rappelons l’étude qui a révélé des différences allant jusqu’à 40 fois entre le nombre de tokens par tâche résolue selon les frameworks, alors que les écarts dans le taux de réussite étaient bien plus faibles. Cela change la question qui mérite d’être posée. Au lieu de demander « quel modèle est le moins cher ? », interrogez-vous sur le nombre de tokens nécessaires à l’ensemble du système d’agent pour terminer une tâche. Comparez deux configurations.

    Agent A : modèle moins cher, framework gourmand

    Model:
    $X / million tokens
    
    Task:
    500k tokens
    

    Agent B : modèle plus cher, framework économe

    Model:
    2X / million tokens
    
    Task:
    100k tokens
    

    L’agent B paie deux fois plus par token mais en utilise un cinquième, de sorte que chaque tâche accomplie coûte environ 40 % de ce que dépense l’agent A, sans même prendre en compte toute différence dans le taux de réussite. La tarification du modèle est un paramètre d’entrée ; l’économie des agents dépend de la quantité de travail que le système fait effectuer au modèle. Notre modèle de coûts basé sur l’architecture pour l’IA agente explore ce sujet plus en détail.

    Tours inutiles et politiques de terminaison

    I should inspect the repository.
    

    et à nouveau au tour suivant :

    I should inspect the repository.
    

    et encore une fois :

    I should inspect the repository.
    

    Rien ne change, pourtant chaque tour consomme des tokens, de la latence, des ressources de calcul, de l’espace de contexte et éventuellement de l’argent. La même étude sur les outils d’automatisation qualifie ces coûts supplémentaires de taxe d’attente par tâche, et non simplement de taxe sur les tokens : les utilisateurs attendent des tours qui ne produisent aucun résultat. Ces outils ont besoin de règles de terminaison, et la plus simple consiste à imposer une limite stricte au nombre de tours.

    MAX_TURNS = 30
    
    if agent.turns >= MAX_TURNS:
        stop()
    

    Une limite est un filet de sécurité, pas une stratégie. Les outils d’automatisation les plus utiles détectent les signaux indiquant qu’une exécution est bloquée.

    No progress
    Repeated tool calls
    Repeated identical observations
    No state change
    Test suite unchanged
    Agent oscillation
    Budget exhausted
    

    Des appels répétés à des outils identiques, des observations inchangées, aucune modification du système de fichiers, un ensemble de tests qui échoue toujours de la même manière, des oscillations entre deux états ou un budget épuisé signifient tous que poursuivre est peu probablement utile. À ce stade, le système de gestion doit s’arrêter, faire un résumé et transmettre l’information en haut de la hiérarchie. Notre guide sur les boucles d’agentie bornées en TypeScript montre ces modèles dans du code.

    De l’encapsuleur d’outil à la plateforme

    La conception des outils de programmation émerge comme une discipline à part entière. Une étude récente du code source de onze systèmes d’agents de codage en production a mis en évidence des schémas architecturaux récurrents chez eux : exécution d’outils, gestion du contexte, contrôles de sécurité, orchestration et mécanismes d’extension. Ses auteurs concluent que ces outils de codage sont passés de simples outils à des plateformes. Les premiers agents se présentaient comme suit :

    LLM + tools
    

    Les systèmes actuels ressemblent à une pile.

    LLM
     ↓
    Agent loop
     ↓
    Tool router
     ↓
    Policy engine
     ↓
    Sandbox
     ↓
    Context manager
     ↓
    Memory
     ↓
    Verification
     ↓
    Observability
     ↓
    Orchestration
    

    Le modèle reste au cœur, mais l’environnement de exécution qui l’entoure – allant du routage des outils et du moteur de politiques jusqu’à l’environnement isolé, au gestionnaire de contexte, à la mémoire, aux vérifications, à l’observabilité et à l’orchestration – est devenu un produit à part entière.

    Un schéma de référence pour un agent de codage

    Une architecture de départ judicieuse pour un agent de codage place la boucle de l’agent directement sous le modèle et se divise en trois composants : un routage d’outils, un gestionnaire de contexte et une mémoire. Les appels aux outils passent par un moteur de politiques vers le sandbox, les résultats sont soumis à une vérification, et tout est enregistré grâce aux mécanismes d’observabilité.

                        ┌──────────────┐
                        │    Model     │
                        └──────┬───────┘
                               │
                               ↓
                      ┌─────────────────┐
                      │   Agent Loop    │
                      └────────┬────────┘
                               │
                 ┌─────────────┼─────────────┐
                 ↓             ↓             ↓
            Tool Router     Context       Memory
                 │          Manager          │
                 ↓             │             ↓
           Policy Engine       │        Persistent State
                 │             │
                 ↓             ↓
              Sandbox ←────── Tools
                 │
                 ↓
            Verification
                 │
                 ↓
           Observability
    

    Assurez que chaque composant puisse être testé indépendamment : effectuez des tests unitaires sur le moteur de politiques à l’aide d’appels synthétiques, testez la gestion des chemins de manière aléatoire, et évaluez le vérificateur sur des fichiers corrompus connus, sans jamais faire appel au modèle.

    Développez l’infrastructure à partir des échecs, pas à partir d’un framework

    Vous n’avez pas besoin d’un framework d’agent massif pour bénéficier de ces avantages. La boucle centrale peut rester simple, même après l’ajout de mécanismes de politiques, de sandboxing et de vérification.

    while turns < MAX_TURNS:
    
        action = model.next_action(context)
    
        if action.is_final:
            return action.answer
    
        if not policy.allows(action):
            context.append("Action denied")
            continue
    
        result = sandbox.execute(action)
    
        verification = verifier.check(result)
    
        context.append(
            summarize(result, verification)
        )
    

    Prêtez attention à l’ordre des opérations : la vérification de la politique a lieu avant l’exécution, une action refusée est renvoyée au modèle plutôt que de faire planter la boucle, l’exécution passe toujours par le sandbox, et ce qui reentre dans le contexte est un résumé du résultat et de sa vérification, et non la sortie brute. À partir de là, n’ajoutez de complexité qu’en réponse à une défaillance observée.

    Agent deleted something?
        → add execution policy
    
    Agent accessed the wrong file?
        → strengthen sandbox
    
    Agent forgets architecture?
        → add persistent project memory
    
    Agent produces bad code?
        → add verification
    
    Agent becomes expensive?
        → optimize context
    
    Agent loops?
        → add termination detection
    

    Chaque symptôme correspond à une seule couche. C’est bien plus judicieux que d’introduire cinquante abstractions avant même de savoir quel est le problème. Pour une discussion plus approfondie sur la question de savoir s’il faut construire cette boucle soi-même ou en adopter une, consultez runtime harnesses vs composed frameworks.

    Le répertoire en tant que base de connaissances de l’agent

    Dans le développement piloté par des agents, un répertoire est bien plus qu’un simple code source. Il peut contenir tout ce dont un agent a besoin pour travailler sur le projet : décisions architecturales, commandes de développement et de test, vocabulaire du domaine, schémas, plans, manuels opérationnels ainsi que des instructions spécifiques aux agents, le tout versionné à côté du code qu’ils décrivent. Les écrits d’OpenAI sur l’ingénierie des outils de pilotage soulignent ce point, considérant les artefacts versionnés stockés dans le répertoire comme le système de référence de ce que l’agent doit connaître pour comprendre et modifier un projet, et recommandant l’utilisation d’une carte indiquant des documents ciblés plutôt que de un seul et énorme fichier d’instructions. La conclusion est sans équivoque : une décision de conception qui n’existe que dans l’esprit de quelqu’un ou dans un thread de discussion n’a pas d’existence pour l’agent. Rendre les connaissances découvrables fait désormais partie de l’architecture logicielle.

    Hooks : un comportement que le modèle n’a pas besoin de mémoriser

    Les crochets comptent parmi les primitives de harnais les plus utiles. Un crochet permet au temps d’exécution de réagir à un événement de cycle de vie grâce à du code déterministe. Le plus évident sert à contrôler les appels d’outils.

    Before tool call
            ↓
    Check policy
            ↓
    Allow / deny
    

    Un autre maintient une qualité de code constante après chaque modification.

    After file edit
            ↓
    Run formatter
            ↓
    Run type checker
    

    Un troisième protège les connaissances avant que le contexte ne soit compressé.

    Before context compaction
            ↓
    Persist important state
    

    Un quatrième crée une trace d’audit.

    After task completion
            ↓
    Generate audit record
    

    Claude Code décrit les crochets comme des commandes déclenchées par le cycle de vie qui s’exécutent de manière déterministe et peuvent, entre autres, bloquer un appel d’outil avant son exécution. Leur force réside dans le fait de déplacer le comportement complètement en dehors du raisonnement du modèle. Au lieu d’écrire « n’oubliez pas d’exécuter le formateur » dans une instruction en espérant que cela soit fait, le temps d’exécution exécute simplement le formateur à chaque fois.

    N’ayez jamais confiance au modèle pour gérer les limites

    Les modèles sont probabilistes ; les limites de sécurité ne le doivent pas. Cet anti-modèle délègue la décision au modèle :

    if model_says_safe:
        execute()
    

    Ce modèle délègue cette tâche à l’infrastructure, qui ne peut pas être convaincue de changer sa réponse :

    if operating_system_allows:
        execute()
    

    Utilisez le modèle pour les décisions qui bénéficient du jugement humain, et une infrastructure déterministe pour celles qui nécessitent des garanties. En pratique, chaque couche répond à sa propre question.

    Model:
    Should I modify this file?
    
    Harness:
    Is this file inside the workspace?
    
    OS:
    Can this process write to the file?
    
    Human:
    Should this high-risk action proceed?
    

    Le modèle décide si un changement est une bonne idée, le mécanisme de contrôle vérifie que la cible se trouve dans l’espace de travail, le système d’exploitation décide si le processus peut écrire le fichier, et un être humain décide si une action à haut risque doit être exécutée. De telles réponses par couches sont bien plus robustes que d’attendre de n’importe quel composant qu’il ait tout raison.

    Les mécanismes de contrôle amplifient les modèles ; ils ne les remplacent pas

    Il est tentant de conclure que les systèmes de gestion sont plus importants que les modèles. Les preuves ne le confirment pas. Dans la configuration étudiée, le choix du système de gestion avait un impact important sur l’efficacité des ressources utilisées, mais un impact bien moindre sur le succès de la tâche ; en outre, aucune optimisation du temps d’exécution ne peut transformer un modèle faible en un ingénieur logiciel compétent. Une façon claire de distinguer les deux :

    Model capability
        =
    What the agent can reason about
    
    Harness quality
        =
    How effectively that capability is deployed
    

    Un modèle brillant utilisé avec un système de gestion médiocre entraîne une perte énorme de ressources et d’argent. Un système de gestion soigneusement conçu autour d’un modèle faible produit toujours des décisions faibles, mais de manière plus sûre et efficace. Les deux sont nécessaires.

    Cinq questions à se poser avant de déployer un agent

    1. Que peut-il faire ?

    Faites la liste de tous les outils et identifiez toutes les opérations dangereuses.

    read
    write
    delete
    execute
    network
    deploy
    send_message
    

    2. Jusqu’où peut-il atteindre ?

    Les définitions des outils ne révèlent qu’une partie de l’histoire. Vérifiez ce à quoi le processus peut réellement accéder :

    filesystem
    network
    environment
    secrets
    processes
    credentials
    

    3. Que reste-t-il après un redémarrage ?

    Redémarrez l’agent et découvrez :

    What does it remember?
    
    What does it forget?
    
    Where is important state stored?
    

    4. Qui vérifie le résultat ?

    Pour les opérations à conséquences importantes, un flux de travail en deux étapes ne suffit pas :

    generate → approve
    

    Insérez des vérifications indépendantes entre la génération et l’approbation :

    generate
       ↓
    test
       ↓
    review
       ↓
    approve
    

    5. Quel est le véritable coût de chaque tâche ?

    Le nombre de tokens par requête est trompeur en soi :

    tokens per request
    

    Mesurez plutôt les résultats obtenus :

    tokens per successful task
    latency per successful task
    tool calls per task
    retries per task
    human interventions
    

    Les tokens, la latence, les appels d’outils, les tentatives de réessai et les interventions humaines par tâche réussie sont les indicateurs qui montrent si le système vaut la peine d’être mis en œuvre.

    Une définition fonctionnelle d’un agent de production

    En combinant ces différents éléments, on obtient une définition plus fidèle.

    Agent =
        Model
      + Tools
      + Execution Environment
      + Policy
      + Memory
      + Context Management
      + Verification
      + Observability
    

    Chaque élément a sa place. Sans modèle, il n’y a pas d’intelligence ; sans outils, il n’y a pas d’action ; sans environnement d’exécution et de politique définie, l’agent peut être dangereux ; sans mémoire, les tâches longues deviennent fragiles ; sans gestion du contexte, les coûts augmentent de façon exponentielle ; sans vérification, les erreurs se propagent sans être détectées ; et sans capacité d’observation, il est impossible de reconstituer ce qui s’est passé en cas de problème.

    Conclusion

    Le débat dans le secteur évolue : on ne se demande plus quel modèle excelle selon un benchmark, mais plutôt quel environnement de exécution permet à un modèle d’accomplir des tâches utiles de manière fiable. Les fournisseurs convergent vers les mêmes composants de base : OpenAI propose désormais une infrastructure d’agents gérés intégrant des environnements de test isolés, un traitement du contexte, une recherche d’outils, des appels à des outils depuis du code ainsi que des exécutions de longue durée, tandis qu’Anthropic met à disposition des instructions persistantes, des compétences, des sous-agents et des mécanismes déterministes. La recherche commence à considérer cet environnement d’exécution comme une variable expérimentale plutôt que de traiter le modèle comme l’ensemble du système. Ces fonctionnalités évoluent rapidement, il est donc conseillé de consulter la documentation à jour.

    La recette naïve pour créer un agent est courte :

    Pick LLM
    +
    Add tools
    =
    Agent
    

    Celle qui correspond à la réalité se présente comme suit :

                  Model
                    ↓
              Agent Runtime
                    ↓
          ┌─────────┼─────────┐
          ↓         ↓         ↓
       Policy    Context    Memory
          ↓         ↓         ↓
       Sandbox   Tools    Persistence
          └─────────┼─────────┘
                    ↓
              Verification
                    ↓
              Observability
    

    Le modèle prend des décisions ; le framework définit les conditions dans lesquelles ces décisions se transforment en actions. Avant de choisir un framework, demandez-vous ce qui se passe lorsque le modèle se trompe, puis construisez le framework en fonction de cette réponse.

    • Imposez des règles déterministes dans le code et les hooks, et non à travers des prompts.
    • Considérez les politiques des outils comme une première ligne de défense, et le sandbox du système d’exploitation, y compris les limites réseau et de ressources, comme la véritable barrière.
    • Séparez l’état de la conversation, du projet et du framework en fonction de leur durée de vie, et persistez les données du projet avant toute compression.
    • Gardez la vérification indépendante et faites en sorte que les reviewers rapportent plutôt qu’ils corrigent.
    • Optimisez le nombre de tokens par tâche réussie et arrêtez les exécutions qui ne progressent plus.

    L’objectif n’est pas un agent qui ne commet jamais d’erreurs, mais un système dans lequel une erreur du modèle ne devient pas automatiquement un incident en production.