Les appels d'outils MCP en double ont besoin d'une identité d'exécution
Les appels d'outils MCP en double exigent plus que des tentatives répétées. Utilisez des empreintes de requête et des relevés d'activité pour distinguer les reconnexions des véritables secondes actions.

Une reconnexion est un problème de transport. Une seconde action est un problème d'exécution. Les équipes en subissent les conséquences lorsqu'elles confondent les deux et laissent un client réessayer chaque requête sans réponse visible.
MCP permet facilement de passer à côté de ce problème, car un appel d'outil peut franchir plusieurs frontières : un processus agent, un transport MCP, une passerelle d'action et une API HTTP ou une cible SSH. Une connexion peut disparaître après que la cible a accepté le travail, mais avant que l'agent ne reçoive le résultat. Si votre système renvoie alors l'appel, la cible voit deux requêtes valides. Elle n'a aucune raison de deviner que la seconde était accidentelle.
La solution n'est pas d'augmenter le budget de tentatives. Donnez à chaque action demandée une identité d'exécution, enregistrez son cycle de vie et prenez les décisions de nouvelle tentative à partir de cet enregistrement. Une empreinte de requête indique ce que l'appelant cherchait à faire. Un relevé d'activité indique si le système a déjà commencé ou terminé l'action. Vous avez besoin des deux.
Une reconnexion n'autorise pas une nouvelle exécution
Lorsqu'un client se reconnecte après la rupture d'un flux, il sait que la communication a échoué. Il ne sait pas que l'appel d'outil initial a échoué.
La distinction paraît évidente jusqu'à ce qu'un middleware générique de nouvelle tentative soit ajouté sous un client MCP. Le middleware voit un délai d'attente, une réinitialisation de connexion ou l'absence de réponse. Il ne sait pas si le POST concernait une lecture, une écriture, une commande distante ou une opération irréversible. Il renvoie les octets, parce que c'est souvent ainsi que fonctionne le code de nouvelle tentative HTTP.
Pour une lecture comme GET /repos/acme/api/branches, cela peut être acceptable. Pour POST /payments, DELETE /projects/atlas ou une commande SSH qui modifie un hôte de production, cela peut créer un second effet de bord. La couche d'outils ne peut pas réparer la situation après coup en renvoyant simplement un seul résultat au modèle.
La spécification du transport MCP Streamable HTTP autorise explicitement les clients à reprendre la livraison des événements du serveur vers le client avec Last-Event-ID lorsqu'un flux est interrompu. C'est un mécanisme de récupération des messages d'un flux. Il ne transforme pas une seconde requête JSON-RPC tools/call en la même exécution. La documentation du SDK TypeScript sépare également les jetons de reprise du chemin de requête et autorise un middleware client autour de fetch. C'est précisément pourquoi les équipes doivent définir leur règle de nouvelle tentative dans le code, au lieu de supposer que le transport les protégera.
Utilisez cette règle :
Reprenez un flux de réponse lorsque le protocole le permet. Renvoyez une action ayant un effet de bord uniquement lorsque la couche d'action peut l'identifier comme la même exécution.
Les cas difficiles ne sont pas les échecs nets. Ce sont ceux où le serveur commence le travail, où la réponse disparaît et où le client ne sait pas s'il doit attendre, reprendre le flux, consulter l'état ou réessayer. Votre conception doit rendre cette incertitude visible.
Les identifiants JSON-RPC identifient des messages, pas des actions durables
L'identifiant d'une requête JSON-RPC sert à associer une requête à sa réponse. Il ne suffit pas à dédupliquer une action après une reconnexion, un redémarrage de processus ou une nouvelle exécution d'agent.
Considérez ces deux appels :
{"jsonrpc":"2.0","id":41,"method":"tools/call","params":{"name":"deploy_release","arguments":{"service":"catalog","version":"2026.07.22"}}}
{"jsonrpc":"2.0","id":41,"method":"tools/call","params":{"name":"deploy_release","arguments":{"service":"catalog","version":"2026.07.22"}}}
Il peut s'agir de la même requête envoyée deux fois après une perte de connexion. Ils peuvent aussi provenir de deux processus clients distincts qui commencent tous deux leur numérotation à 1 ou 41. Même au sein d'un seul processus, un bug d'implémentation peut réutiliser des identifiants. Cette valeur ne vous apprend presque rien si vous ne l'associez pas à un appelant authentifié et à une session de protocole précise.
Considérez maintenant deux appels avec des identifiants différents :
{"jsonrpc":"2.0","id":41,"method":"tools/call","params":{"name":"deploy_release","arguments":{"service":"catalog","version":"2026.07.22"}}}
{"jsonrpc":"2.0","id":42,"method":"tools/call","params":{"name":"deploy_release","arguments":{"service":"catalog","version":"2026.07.22"}}}
Il peut s'agir d'une nouvelle tentative de transport dont le client a généré un nouvel identifiant. L'agent peut aussi avoir demandé volontairement un second déploiement après avoir reçu un résultat incertain. Les identifiants de message sont des indices, pas la décision.
Ne commettez pas l'erreur inverse en dédupliquant pour toujours chaque appel d'outil correspondant. Déployer deux fois la même version peut être sans conséquence, voire intentionnel. Créer deux fois le même ticket externe peut être incorrect. Renouveler deux fois un identifiant peut bloquer un service. La classe d'action détermine la durée pendant laquelle une identité d'exécution reste pertinente.
Un modèle pratique sépare trois identifiants :
- Identifiant de corrélation du protocole : l'identifiant JSON-RPC et, le cas échéant, le contexte de session ou de flux MCP.
- Identifiant d'exécution : un identifiant créé par le serveur pour une tentative acceptée d'exécuter une action d'outil.
- Empreinte d'intention : un condensat stable de l'effet demandé, utilisé pour retrouver une exécution précédente lorsque la corrélation du protocole change.
Une fois ces éléments séparés, les journaux cessent de prétendre répondre à une question à laquelle ils ne peuvent pas répondre.
Une empreinte utile décrit l'effet
Une empreinte de requête doit rester identique lorsque la livraison change et changer lorsque l'effet demandé change. Ne hachez pas les octets JSON bruts en appelant le résultat une empreinte. Le JSON brut varie selon l'ordre des propriétés, les espaces, les valeurs par défaut facultatives, les identifiants de requête et les changements de mise en forme sans conséquence.
Commencez par construire un enregistrement d'action canonique. Pour une action HTTP, il peut avoir cette forme :
{
"actor": "signed-process:com.example.agent",
"tool": "deploy_release",
"channel": "http",
"target": "deploy-api.internal.example/releases",
"credential_ref": "deploy-service",
"method": "POST",
"arguments": {
"service": "catalog",
"version": "2026.07.22",
"region": "us-east-1"
},
"intent_scope": "run:5f8097"
}
Canonisez l'ordre des champs, supprimez ceux qui n'ont aucune signification sémantique et normalisez les équivalents connus avant de calculer un condensat. Si region vaut par défaut us-east-1, matérialisez-la toujours ou omettez-la toujours lorsque la cible fournit cette valeur. Mélanger les deux crée de faux écarts.
Le champ actor est important. Deux processus agents autorisés qui envoient des arguments identiques peuvent représenter des actions intentionnelles distinctes. credential_ref compte également. Une requête effectuée avec une identité de service n'est pas nécessairement équivalente à la même requête, sur le même chemin et avec le même corps, effectuée avec une autre identité. Pour SSH, incluez l'identité de l'hôte, le compte, la commande, le répertoire de travail s'il modifie le comportement et, lorsque cela est possible, une représentation normalisée de la commande.
Ne mettez pas de secrets dans l'enregistrement canonique. Ne placez jamais de jetons bearer, de clés privées ou d'en-têtes d'autorisation bruts dans les données d'entrée d'une empreinte. Si un argument contient lui-même un secret, remplacez-le par une référence interne protégée ou calculez l'empreinte avec une construction à clé comme HMAC. Un hachage simple et non salé d'un secret à faible entropie transforme votre espace d'audit en oracle permettant de tester des suppositions.
La recommandation familière « hachez simplement la requête » est populaire parce qu'elle est courte. Elle est incorrecte pour le contrôle des actions. Un hachage prouve seulement que certains octets ont été transmis à une fonction. Il n'indique pas si ces octets représentent le même acteur, le même effet sur la cible ou la même fenêtre de nouvelle tentative.
Le relevé d'activité doit contenir des états, pas une seule ligne de journal
Un relevé d'activité utile indique à quel endroit l'action s'est arrêtée. S'il ne contient que les états réussite et échec, une reconnexion vous laissera dans le doute au moment où vous avez le plus besoin d'une réponse claire.
Enregistrez au moins ces transitions pour chaque identifiant d'exécution :
- Acceptée : la passerelle a validé la requête et attribué un identifiant d'exécution.
- Autorisée : l'approbation ou l'autorisation de session requise a permis l'action.
- Envoyée : la passerelle a transmis l'action au client HTTP ou à l'assistant SSH.
- Résultat observé : la réponse de la cible, le code de sortie ou un échec explicite de livraison est arrivé.
- Résultat livré : l'agent a reçu le résultat de l'outil, si le transport permet de l'établir.
Les quatrième et cinquième états doivent rester séparés. Une cible peut renvoyer HTTP 201 alors que la connexion au client MCP se rompt avant qu'il ne voie la réponse. Marquer cette exécution comme échouée parce que la livraison du résultat a échoué serait un mensonge. La marquer comme terminée donne au code de récupération quelque chose d'utile : il peut renvoyer ou reconstituer le résultat connu sans envoyer une nouvelle requête.
Voici le format d'enregistrement que je veux voir pendant un incident :
{
"execution_id": "act_01J4K8J7DX7V",
"fingerprint": "hmac-sha256:4a1e...d90c",
"tool": "deploy_release",
"actor": "signed-process:com.example.agent",
"target": "deploy-api.internal.example/releases",
"state": "completed_result_not_delivered",
"accepted_at": "2026-07-22T14:03:18Z",
"dispatched_at": "2026-07-22T14:03:19Z",
"completed_at": "2026-07-22T14:03:25Z",
"target_status": 201,
"result_reference": "result_01J4K8JFM2"
}
L'enregistrement n'a pas besoin d'exposer la réponse complète de la cible à chaque opérateur. Il doit fournir suffisamment de détails protégés pour que la passerelle prenne une décision de récupération, ainsi que suffisamment d'informations lisibles pour qu'une personne comprenne ce qui s'est passé.
Le journal Activity de Sallyport enregistre les appels individuels, tandis que son journal Sessions enregistre les exécutions des agents. Cette séparation est utile pour l'analyse : l'exécution indique quel processus agent existait et l'enregistrement de l'appel indique si une action particulière vers l'extérieur a franchi la frontière d'envoi. Sa chaîne d'audit peut également être vérifiée hors ligne avec sp audit verify, ce qui aide à établir que l'enregistrement n'a pas été discrètement réécrit après un incident.
Traitez les résultats inconnus séparément
La plupart des actions en double commencent avec un système qui ne connaît que deux résultats : réussite et échec. Les actions réseau en nécessitent un troisième : inconnu.
Inconnu ne signifie pas que le système n'a rien fait. Cela signifie qu'il ne peut pas prouver si la cible a accepté l'action. Un délai d'attente avant la sortie des premiers octets de votre processus peut souvent être retenté sans risque. Un délai d'attente après la remise du corps d'une requête HTTP au système d'exploitation est un événement différent. Une connexion SSH interrompue après le démarrage d'une commande sur le shell distant est plus grave encore, car la commande peut continuer après la fin du processus local.
Classez chaque action d'outil avant de décider de sa récupération :
| Type d'action | Exemple | Comportement par défaut après un résultat inconnu |
|---|---|---|
| Lecture seule | Récupérer l'état d'une compilation | Réessayer avec des limites ordinaires |
| Écriture idempotente | Mettre une ressource nommée dans un état déclaré | Réessayer avec la même identité d'idempotence |
| Écriture conditionnelle | Mettre à jour uniquement si la version correspond | Consulter l'état, puis réessayer seulement si la condition tient toujours |
| Action irréversible | Envoyer un paiement, révoquer un accès, renouveler un identifiant | Arrêter et demander une vérification explicite |
| Commande distante | Exécuter une migration via SSH | Consulter un marqueur durable ou demander une vérification |
Le verbe HTTP de l'API ne suffit pas à remplir ce tableau. PUT est souvent décrit comme idempotent, mais une extrémité mal conçue peut envoyer une notification, déclencher une compilation ou ajouter un événement d'audit à chaque réception. POST peut être répétable sans danger lorsque l'API respecte une clé d'idempotence. Examinez le contrat réel de la cible.
Pour les commandes distantes longues, ajoutez un marqueur durable avant de lancer le travail. Une commande de migration peut créer un enregistrement avec un identifiant d'exécution, le mettre à jour au début du travail et le marquer comme terminé uniquement après validation. À la reconnexion, consultez ce marqueur avant de renvoyer la commande. Sans marqueur, « cela n'a probablement pas été exécuté » n'est pas une stratégie de récupération.
Faites correspondre les tentatives dans une portée d'intention limitée
Une empreinte seule fera correspondre trop d'actions légitimes. Limitez-la à la période et au contexte dans lesquels une nouvelle tentative est raisonnablement possible.
La portée la plus simple est une exécution d'agent. Si le même processus signé envoie la même action alors que son premier résultat n'est pas résolu, considérez la seconde requête comme une tentative potentielle. Si un autre processus l'envoie plusieurs heures plus tard, considérez-la comme une nouvelle intention, sauf si l'action possède elle-même une clé d'idempotence durable.
Une bonne règle de correspondance ressemble à ceci :
if prior.fingerprint == incoming.fingerprint
and prior.actor == incoming.actor
and prior.intent_scope == incoming.intent_scope
and prior.state in {accepted, authorized, dispatched, completed_result_not_delivered}:
recover_or_attach_to(prior.execution_id)
else:
create_new_execution()
recover_or_attach_to ne doit pas renvoyer aveuglément une réussite. Son comportement dépend de l'état précédent.
Si l'exécution précédente est acceptée mais pas envoyée, la passerelle peut poursuivre cette exécution. Si elle a été envoyée avec un résultat inconnu, la passerelle doit consulter l'extrémité d'état de la cible, son mécanisme d'idempotence ou son marqueur durable. Si elle est terminée mais que la livraison du résultat a échoué, elle doit renvoyer la référence du résultat enregistré. Si elle a été rejetée par l'autorisation, elle doit renvoyer ce rejet plutôt que créer un nouveau processus d'approbation à partir de la même nouvelle tentative ambiguë.
La portée doit correspondre à l'action. Une fenêtre de cinq minutes peut convenir à une requête d'API qui expire. Elle ne suffit pas pour un déploiement logiciel qui dure une heure. Un renouvellement d'identifiant peut nécessiter une empreinte durable jusqu'à la vérification de l'identifiant actif. N'utilisez pas une durée de vie globale simplement parce qu'elle est facile à configurer. Définissez des règles de conservation et de récupération propres à chaque action.
L'approbation est un indice, pas un mécanisme d'idempotence
Une approbation humaine peut établir qu'un processus était autorisé à tenter une action. Elle ne peut pas prouver qu'une tentative précédente a déjà eu lieu.
Cela compte pour les systèmes qui demandent une confirmation à chaque appel sensible. Supposons qu'un agent demande le renouvellement d'un identifiant de production. Une personne approuve. La passerelle envoie la requête, puis le client se déconnecte. L'agent se reconnecte et génère le même appel d'outil. Demander une seconde approbation crée un choix trompeur. L'opérateur voit une requête familière et peut l'approuver, mais la question à résoudre est de savoir si le premier renouvellement a abouti.
L'approbation à chaque appel conserve son utilité. Elle contrôle l'autorisation au moment de l'utilisation. Séparez-la de la gestion des doublons :
- L'autorisation décide si l'appelant actuel peut lancer une exécution.
- L'empreinte décide si une requête entrante correspond à une exécution existante.
- Les relevés d'activité décident si cette exécution peut être reprise, récupérée ou doit être examinée.
Lorsqu'une nouvelle tentative correspond à une exécution en attente, affichez le relevé d'activité d'origine au lieu de présenter une nouvelle approbation comme si rien ne s'était passé. Le réviseur doit voir la cible, l'heure du premier envoi, le résultat connu et la raison pour laquelle la passerelle n'a pas renvoyé l'action.
Sallyport utilise une échelle de décision fixe : un coffre verrouillé refuse les actions, un nouveau processus agent reçoit par défaut une autorisation par session et certains identifiants peuvent exiger une approbation à chaque utilisation. Ces contrôles répondent à la question de savoir qui peut agir. L'enregistrement d'exécution doit encore répondre à celle de savoir si l'action a déjà franchi la frontière.
Les clés d'idempotence HTTP ne résolvent qu'une partie du problème
Si une API en amont accepte les clés d'idempotence, utilisez-les. Envoyez une valeur stable pendant toute la durée d'une exécution, conservez la réponse de la cible et réutilisez cette valeur uniquement pour récupérer la même exécution.
Par exemple, la passerelle peut créer un identifiant d'exécution avant l'envoi et l'associer à l'en-tête attendu par l'API :
POST /v1/releases HTTP/1.1
Host: deploy-api.internal.example
Idempotency-Key: act_01J4K8J7DX7V
Content-Type: application/json
{"service":"catalog","version":"2026.07.22","region":"us-east-1"}
L'API doit définir ce qu'elle fait lorsque cet en-tête se répète. Le meilleur comportement consiste à renvoyer le résultat d'origine pour la même requête sémantique et à rejeter une requête différente qui tente de réutiliser la même valeur. Si elle accepte silencieusement un corps modifié avec la même clé, votre passerelle ne peut rien déduire de fiable d'une répétition.
N'utilisez pas l'empreinte comme clé d'idempotence externe si elle peut persister entre des actions intentionnelles. Un identifiant d'exécution est unique pour une tentative acceptée. L'empreinte localise une tentative potentiellement liée. Ces deux éléments ont des rôles différents.
L'idempotence HTTP ne fait rien pour SSH à elle seule. Il vous faut un protocole distant. Une méthode sûre consiste à transmettre un identifiant d'exécution généré à un script qui écrit un état durable sur l'hôte ou dans un espace partagé, puis refuse de démarrer deux fois la même opération. Si vous ne pouvez pas modifier la commande ni vérifier un marqueur externe, classez-la parmi les actions irréversibles et exigez une vérification après une déconnexion incertaine.
Analysez la séquence, pas le nombre final
Deux lignes d'activité contenant les mêmes arguments ne prouvent pas un doublon. Commencez par la séquence des événements et suivez le premier appel jusqu'à sa frontière d'envoi.
Une véritable analyse doit répondre aux questions suivantes dans cet ordre :
- Un seul processus agent ou deux processus distincts ont-ils envoyé les appels ?
- Le premier appel a-t-il reçu l'autorisation et atteint l'étape d'envoi ?
- La passerelle a-t-elle reçu une réponse ou un code de sortie de la cible ?
- La livraison du résultat a-t-elle échoué après la fin de l'action sur la cible ?
- Le second appel a-t-il réutilisé l'identifiant d'exécution d'origine, porté une clé d'idempotence ou créé une nouvelle tentative ?
Cet ordre évite une conclusion fréquente et erronée : « Les journaux montrent deux appels, donc l'agent a agi deux fois. » Vous pouvez découvrir que la passerelle a enregistré une exécution terminée et une nouvelle tentative du client qui s'y est rattachée. Vous pouvez aussi découvrir deux processus autorisés distincts, chacun avec son propre contexte de planification, qui ont tous deux envoyé l'action. Les corrections à apporter ne sont pas les mêmes.
Conservez l'espace d'activité en ajout uniquement ou rendez-le infalsifiable d'une autre manière. Les analyses de doublons surviennent souvent après un incident coûteux, lorsque quelqu'un souhaite une histoire plus nette que celle que le système peut réellement étayer. Un enregistrement chaîné par hachage ne rend pas la décision initiale correcte, mais il rend sa reconstitution ultérieure plus difficile à manipuler.
Ne cachez pas non plus l'ambiguïté à l'agent. Renvoyez un résultat indiquant que l'exécution précédente attend une vérification ou qu'elle est terminée mais que la livraison du résultat a été interrompue. Un modèle qui voit un échec fabriqué essaiera à nouveau. Un modèle qui voit un état incertain explicite peut consulter l'état, demander une vérification ou choisir une voie plus sûre.
Intégrez le comportement en cas de répétition dans chaque contrat d'outil
Chaque outil ayant un effet de bord doit répondre explicitement à une question : que se passe-t-il lorsque l'appelant perd la réponse après l'envoi ?
Écrivez la réponse à côté de la définition de l'outil. Indiquez si l'action est en lecture seule, répétable avec une identité d'idempotence, récupérable par une consultation d'état ou bloquée après un résultat inconnu. Précisez ce qui doit entrer dans son empreinte et pendant combien de temps une exécution inachevée peut encore être rattachée. Si personne ne peut l'écrire, l'outil n'est pas prêt pour une utilisation autonome.
Le travail d'ingénierie reste généralement modeste par rapport au nettoyage nécessaire après un double déploiement, un double compte, un double paiement ou un second renouvellement d'identifiant. Ajoutez l'identifiant d'exécution avant l'appel à la cible. Enregistrez les changements d'état avant et après l'envoi. Conservez une référence du résultat. Puis faites en sorte que le code de reconnexion consulte cet enregistrement avant de toucher à nouveau au monde extérieur.
C'est la règle à retenir : un transport interrompu peut interrompre une conversation, mais il ne doit jamais transformer silencieusement l'incertitude en seconde action.
FAQ
Qu'est-ce qui constitue un appel d'outil MCP en double ?
Il s'agit d'un effet de bord répété lorsque deux exécutions atteignent la cible, et non de deux messages apparaissant simplement dans un journal. Répéter une requête HTTP qui lit uniquement des données peut être gênant. En revanche, une requête répétée qui envoie de l'argent, supprime une branche, renouvelle un identifiant ou crée un compte nécessite une réponse différente. Commencez par identifier l'effet en aval avant de débattre de l'intention du client de « réessayer ».
Une reconnexion MCP peut-elle exécuter deux fois le même appel d'outil ?
Parfois. Le client peut perdre la réponse alors que le serveur a déjà terminé l'appel, puis se reconnecter et envoyer à nouveau la même requête. Mais des appels identiques en apparence peuvent aussi provenir d'un agent qui a revu son plan, d'un superviseur qui a redémarré un processus ou d'une personne qui a donné deux fois la même instruction.
L'identifiant de requête JSON-RPC suffit-il pour dédupliquer les appels ?
Non. L'identifiant d'une requête JSON-RPC identifie un message au sein d'une conversation de protocole, mais ne constitue pas une identité d'exécution durable après le redémarrage du client ou l'ouverture d'une nouvelle connexion. Considérez-le comme un indice utile, puis associez-le à une empreinte de requête et à un relevé d'activité.
Que doit contenir une empreinte de requête MCP ?
Incluez le processus ou le principal autorisé, le nom de l'outil, les arguments normalisés, l'identité de la cible, l'identité de l'identifiant utilisé et une portée temporelle ou d'intention limitée. N'incluez pas les éléments propres au transport, comme le numéro de socket, un identifiant d'événement SSE temporaire ou un identifiant de requête généré aléatoirement. L'empreinte doit décrire l'effet demandé, pas le chemin utilisé pour le transmettre.
Dois-je réessayer automatiquement un appel d'outil échoué ?
Évitez de réexécuter automatiquement toute action ayant un effet externe, sauf si la cible accepte une clé d'idempotence ou si vous pouvez prouver que la première tentative n'a pas commencé. Reconnecter un flux de réponse n'est pas la même chose que renvoyer une invocation d'outil. La récupération sûre consiste généralement à retrouver le résultat ou à consulter d'abord le relevé d'activité.
Que doit montrer un relevé d'activité pendant l'analyse d'une tentative ?
Un relevé d'activité doit contenir l'empreinte de la requête, la tentative d'exécution, le contexte d'autorisation, les horodatages, la cible et l'état du résultat. Il doit distinguer « reçu », « démarré », « terminé » et « échec de livraison du résultat ». Si ces états sont réduits à une seule ligne de journal, l'opérateur ne peut pas déterminer si une seconde action a eu lieu.
Quand un agent doit-il envoyer une clé d'idempotence ?
Utilisez une clé d'idempotence lorsque l'API destinataire en prend une en charge et conservez-la lors d'une nouvelle tentative de transport pour la même action. Ne la réutilisez pas pour une action volontaire ultérieure, même si les arguments sont identiques. Si l'API ne possède aucun mécanisme d'idempotence, votre passerelle doit conserver ses propres enregistrements d'exécutions en attente et terminées.
Comment distinguer une tentative d'une seconde action volontaire ?
Une reconnexion modifie généralement les indices de connexion : heure de démarrage du processus, session de transport, identifiant de requête ou état du flux. Une répétition volontaire s'accompagne souvent d'un nouveau contexte de planification, d'une nouvelle décision d'autorisation, d'arguments modifiés ou d'un délai significatif après le résultat précédent. Aucun de ces signaux ne suffit à lui seul, d'où la nécessité d'une règle de décision enregistrée.
Puis-je stocker uniquement le hachage de chaque requête d'outil ?
Non. Une empreinte n'est qu'un index. Conservez une représentation canonique protégée ou suffisamment de champs structurés pour expliquer pourquoi deux appels correspondent, tout en limitant les valeurs sensibles visibles par les opérateurs. Si les empreintes couvrent des secrets, dérivez-les avec une clé secrète afin qu'un lecteur des journaux ne puisse pas tester des suppositions contre le condensat.
Que faire lorsque le résultat du premier appel est inconnu ?
Traitez-la comme une exécution ambiguë et arrêtez la répétition automatique pour cette catégorie d'action. Présentez le relevé d'activité précédent, le résultat connu et l'effet exact sur la cible à la personne chargée de l'approbation. Une répétition rapide coûte moins cher qu'une répétition irréversible, mais elle reste un défaut de conception à corriger.