8 min de lecture

Des erreurs d'outils d'agents qui aident sans exposer les secrets

Concevez des erreurs d'outils d'agents qui orientent les nouvelles tentatives et les approbations sans exposer les jetons, les en-têtes, les échecs bruts de connexion ni les diagnostics sensibles.

Des erreurs d'outils d'agents qui aident sans exposer les secrets

Les erreurs d'outils d'agents doivent contenir suffisamment de structure pour permettre à l'agent de récupérer, mais elles ne doivent pas transformer chaque requête échouée en export d'identifiants. La limite est facile à décrire et régulièrement franchie en pratique : un wrapper intercepte une exception, renvoie le message de la bibliothèque et transmet discrètement au modèle une URL, un en-tête Authorization, le sujet d'un certificat, une cible SSH ou un fragment de jeton.

J'ai vu les dégâts commencer par un champ de débogage ajouté avec de bonnes intentions. Quelqu'un ajoute request_headers parce qu'un agent recevait sans cesse des réponses 401. L'agent copie l'erreur dans ses notes de travail. Ces notes sont ensuite collées dans une pull request, envoyées à un système d'assistance ou conservées dans une trace d'évaluation. L'échec initial est passé. Le secret, lui, ne l'est pas.

La bonne conception donne à l'agent une explication limitée de ce qui s'est produit, de ce qu'il peut faire ensuite sans danger et un identifiant de corrélation pour un opérateur humain. Elle garde les preuves brutes derrière la frontière d'action. Il ne s'agit pas de choisir entre des erreurs utiles et des erreurs qui protègent les secrets. C'est un travail de conception d'interface.

Une réponse d'erreur fait partie de la frontière de sécurité

Un agent traite la sortie d'un outil comme une mémoire de travail. Il peut citer cette sortie à un utilisateur, la placer dans un fichier, l'envoyer à un autre outil ou s'en servir pour choisir une nouvelle tentative. Tout champ renvoyé par une passerelle d'action doit donc être considéré comme divulgué à un appelant non fiable, même lorsque cet appelant est un agent lancé par un développeur qui possède la machine.

Un appel d'outil a deux publics. L'agent a besoin de faits opérationnels : l'action a-t-elle été exécutée, peut-il réessayer, faut-il un consentement et quelle entrée doit-il modifier ? L'opérateur a besoin de faits médico-légaux : quel identifiant a été sélectionné, quelle route exacte a été appelée, quel résolveur DNS a échoué et qu'a répondu le pair distant ? Ne répondez pas aux besoins du second public en déversant ses preuves devant le premier.

Cette distinction compte surtout lorsqu'un agent peut appeler des outils à répétition. Un humain qui voit une erreur très détaillée une seule fois remarquera peut-être un jeton bearer. Un agent peut la conserver pendant des dizaines de tours, puis l'inclure dans du code généré ou un scénario de test. Il n'a pas besoin d'intention malveillante pour que cela se produise.

Construisez l'interface autour d'une règle explicite : l'appelant ne reçoit que les champs qui resteraient sûrs s'ils étaient copiés dans un ticket public. Si un champ échoue à ce test, stockez-le dans des diagnostics protégés ou supprimez-le.

Donnez des décisions aux agents, pas des chaînes d'exception

Une réponse utile indique à l'agent le type de décision auquel il est confronté. Les exceptions brutes ne le font ni de manière fiable ni sûre. Leur formulation change selon les versions du système d'exploitation et des bibliothèques clientes, et elles mélangent souvent une cause technique avec des éléments qui doivent rester privés.

Utilisez un petit vocabulaire documenté de codes. Chaque code doit correspondre à un comportement précis de l'appelant. Ne rendez pas les codes si détaillés que vous finissiez par recréer chaque défaillance possible de l'amont.

Une forme de réponse pratique ressemble à ceci :

{
  "ok": false,
  "code": "AUTH_FAILED",
  "message": "The remote service rejected the stored credential.",
  "action": "stop_and_report",
  "retryable": false,
  "request_id": "act_7f3c2a91",
  "http_status": 401
}

L'agent peut s'arrêter, dire à l'utilisateur que l'authentification doit être vérifiée et inclure l'identifiant de requête. Il n'a pas besoin du jeton bearer, du schéma d'autorisation, de l'adresse e-mail du compte ni d'une copie du corps de la réponse pour prendre cette décision.

action est plus utile qu'un simple booléen vague. Un booléen indique si le temps pourrait résoudre le problème. Une action dit à l'agent ce qu'il doit faire. Gardez une liste de valeurs autorisées réduite :

  • retry_after_delay pour les opérations temporaires qui peuvent être répétées sans danger.
  • repair_input pour une requête que l'agent peut corriger sans nouvelle autorité.
  • request_approval lorsqu'une personne doit autoriser l'action.
  • stop_and_report pour les échecs qui nécessitent l'intervention d'un opérateur.
  • inspect_outcome lorsqu'une écriture a peut-être atteint le service distant.

La dernière valeur mérite une attention particulière. Un délai d'attente après l'envoi d'une écriture n'est pas équivalent à un délai d'attente avant son envoi. Si vous aplatissez les deux situations en NETWORK_ERROR, l'agent réessaiera une action peut-être déjà terminée. C'est ainsi que surviennent les doublons de tickets, de déploiements et d'enregistrements, ainsi que les commandes destructrices répétées.

N'exposez http_status que lorsqu'il est pertinent et sûr. Il fournit souvent un contexte utile pour les appels HTTP, mais ne prétendez pas qu'il donne la réponse complète. Un 403 peut signifier un échec d'autorisation en amont, une restriction au niveau d'une ressource ou une décision de la passerelle. Votre code d'outil doit nommer le comportement attendu de l'agent.

Gardez une taxonomie de codes assez petite pour être testée

Une taxonomie de codes doit décrire la responsabilité et la récupération, pas chaque couche de la pile réseau. Si votre liste contient cinquante codes après la première semaine, vous exportez probablement des détails d'implémentation sous un autre nom.

Commencez par des catégories qui permettent à l'appelant d'adopter un comportement différent :

CodeSignificationComportement de l'agent
INVALID_INPUTL'outil a rejeté les champs fournis avant toute action externe.Corriger l'entrée.
VAULT_LOCKEDLa passerelle ne peut utiliser aucun secret enregistré.Demander à une personne de le déverrouiller.
USER_DENIEDUne personne a refusé cette action.S'arrêter. Ne pas reformuler ni soumettre à nouveau.
AUTH_FAILEDLe service distant a rejeté l'identifiant sélectionné.S'arrêter et signaler le problème.
REMOTE_FORBIDDENLa requête a été authentifiée, mais ne dispose pas des droits distants nécessaires.S'arrêter et signaler le problème.
RATE_LIMITEDLe service distant a demandé aux appelants de ralentir.Attendre si un délai sûr existe.
TEMPORARY_FAILUREUne requête répétable a échoué temporairement.Réessayer dans une limite définie.
OUTCOME_UNKNOWNUne écriture a peut-être été achevée avant l'échec.Vérifier avant toute nouvelle tentative.
NETWORK_UNREACHABLELa passerelle n'a pas pu atteindre un point de terminaison distant.Réessayer uniquement si l'action peut être répétée sans danger.
INTERNAL_FAILURELa passerelle a échoué sans solution sûre pour l'appelant.S'arrêter et signaler l'identifiant de requête.

N'utilisez pas ERROR, FAILED ou EXCEPTION comme contrat principal. Ces libellés transfèrent à l'agent la charge de l'interprétation, qui déduira une solution à partir de la prose. Il peut se tromper.

Gardez la signification des codes stable. Vous pouvez améliorer le message destiné aux humains, ajouter un champ retry_after_seconds ou inclure une nouvelle valeur d'état sûre. Ne faites pas signifier à AUTH_FAILED à la fois des identifiants incorrects et un refus d'approbation local. Les agents et l'orchestration qui les entoure finiront par utiliser ce code pour choisir une branche.

La RFC 9457, « Problem Details for HTTP APIs », fournit une base utile : les réponses peuvent contenir un type de problème stable, un titre, un statut, un détail et une référence d'instance. C'est l'avertissement que les équipes négligent. La RFC indique que detail doit aider à corriger le problème et que les détails peuvent exposer des informations sensibles. Pour les outils d'agents, faites du type ou du code stable le contrat, gardez le détail court et utilisez l'instance ou l'identifiant de requête pour relier un opérateur aux preuves protégées.

Les en-têtes de requête et les erreurs de connexion sont des preuves, pas du contexte

Les équipes qualifient souvent les en-têtes bruts et les messages de transport de « contexte ». Ce sont des preuves. Les preuves appartiennent à un enregistrement d'audit soumis à des contrôles d'accès, pas à une réponse destinée à un agent.

Prenons une requête d'API échouée. Une exception typique d'une bibliothèque HTTP peut inclure l'URL complète demandée, la destination d'une redirection, l'adresse du proxy, les en-têtes de réponse et une partie du corps de la réponse. Chacun de ces éléments peut contenir des secrets. Les paramètres de requête contiennent encore des clés API dans les anciennes API. Les en-têtes Location contiennent souvent des URL de téléchargement signées. Les cookies et les en-têtes d'authentification personnalisés sont des fuites évidentes. Des champs moins visibles comme X-Request-Id peuvent être acceptables, tandis que X-Forwarded-Host ou un en-tête de service interne peut révéler une infrastructure dont l'agent n'avait jamais besoin de connaître l'existence.

Les erreurs SSH exigent la même discipline. Ne renvoyez pas une ligne de commande contenant une cible privée, un chemin vers known-hosts, un fichier d'identité proposé ou le texte brut d'une discordance de clé d'hôte. Une telle discordance a une signification utile pour l'appelant : la connexion est bloquée parce que l'identité distante ne peut pas être vérifiée. Renvoyez cette signification. Conservez la comparaison des empreintes, les chemins et les diagnostics de la bibliothèque pour l'opérateur.

OAuth 2.0 rend ce point particulièrement clair. La RFC 6750 indique qu'un jeton bearer donne accès à quiconque le possède et demande aux clients de protéger les jetons contre la divulgation lors du stockage et du transport. Un gestionnaire d'erreur qui copie un jeton bearer dans une trace contourne cette exigence, même si la requête d'origine utilisait correctement TLS.

Nettoyez avant la sérialisation, et non après la propagation des journaux. Un filtre de masquage sur une destination générale de journaux est un filet de sécurité utile, mais ce n'est pas la frontière. À ce stade, une exception levée peut déjà avoir été attachée à un résultat d'outil, à un événement de télémétrie ou à un rapport d'incident.

Utilisez une liste d'autorisation pour les champs transmis à l'agent. Une liste d'exclusion finit par oublier x-api-token, un paramètre de requête signé, un champ de session propre à un fournisseur ou une nouvelle propriété de bibliothèque. Une liste d'autorisation part de l'absence de divulgation et n'ajoute que les champs dont l'utilité pour l'appelant est identifiée.

Séparez ce qui a échoué de la question de savoir si l'action a été exécutée

Envoyez des requêtes HTTP sans exporter les jetons
Injectez les identifiants HTTP sans transmettre à l'agent les accès bearer, basic ou ceux des en-têtes personnalisés.

Une conception d'erreur sûre doit indiquer à l'agent si le côté distant a peut-être agi. C'est là que la plupart des conseils sur les nouvelles tentatives deviennent dangereux.

Supposons qu'un agent envoie POST /deployments et que sa connexion expire. La passerelle sait qu'elle a tenté l'appel. Elle ignore si l'amont l'a reçu, s'il a créé un déploiement ou si la réponse s'est perdue au retour. Renvoyer TEMPORARY_FAILURE invite l'agent à envoyer une deuxième demande de déploiement. Renvoyer AUTH_FAILED serait tout simplement faux. L'état correct est OUTCOME_UNKNOWN.

La réponse doit le dire clairement :

{
  "ok": false,
  "code": "OUTCOME_UNKNOWN",
  "message": "The connection ended after the request started. The remote action may have completed.",
  "action": "inspect_outcome",
  "retryable": false,
  "request_id": "act_9b18d4e0",
  "operation": "create_deployment"
}

operation désigne une classe d'action générique, et non la route ou la charge utile complète. L'agent peut maintenant utiliser un appel d'état séparé et en lecture seule si l'intégration en propose un. Si l'API accepte des références d'idempotence, la passerelle peut associer la référence sûre à l'opération et l'interroger en interne. N'exposez pas une valeur d'idempotence si elle sert aussi de moyen d'accès dans le système cible.

Les opérations de lecture ne sont pas automatiquement sûres à réessayer. Une lecture peut déclencher une facturation, actualiser un état distant ou exécuter une commande ayant des effets de bord derrière un nom anodin. L'auteur de l'intégration doit indiquer si une opération peut être répétée. Ne demandez pas à un modèle de langage de le déduire du nom de la méthode.

Définissez un budget de tentatives dans la passerelle. Une réponse peut inclure un délai limité comme retry_after_seconds: 30, mais uniquement lorsque l'amont a fourni une valeur sûre ou que la passerelle contrôle la limite. Ne laissez pas un agent réessayer indéfiniment parce qu'un message disait « temporaire ». Les échecs répétés produisent du bruit, consomment les limites de débit et compliquent l'enquête ultérieure.

Le refus d'une personne doit avoir sa propre signification

Le refus d'une approbation par une personne n'est pas une erreur d'authentification distante. Il signifie que l'action demandée n'a pas été exécutée. Cette distinction protège à la fois la sécurité et l'ergonomie.

Si un outil transforme une approbation refusée en AUTH_FAILED, l'agent peut essayer d'autres identifiants, demander la rotation d'un secret ou tenter une requête légèrement modifiée. Aucune de ces actions ne respecte la personne qui a dit non. Si le refus devient une erreur interne générique, l'utilisateur ne peut pas savoir si la passerelle a mal fonctionné.

Renvoyez USER_DENIED avec un court message comme « L'action demandée n'a pas été approuvée et n'a pas été exécutée. » Évitez de mentionner le nom du secret, le compte sélectionné ou la cible exacte si ces éléments ne font pas déjà partie du contrat d'entrée sûr de l'outil. L'appelant doit s'arrêter. Une personne pourra décider de lancer une nouvelle demande visible.

Un magasin de secrets verrouillé est encore différent. VAULT_LOCKED signifie que la passerelle a refusé l'action avant de pouvoir sélectionner ou utiliser un identifiant. La solution sûre consiste à demander à une personne de déverrouiller la passerelle, et non à demander à l'agent de fournir un jeton. Cela évite un scénario courant dans lequel un modèle compense l'indisponibilité d'identifiants gérés en cherchant un autre secret dans son contexte.

Sallyport applique directement cette séparation : tant que la porte de son coffre est verrouillée, il refuse chaque action, et son autorisation par session peut distinguer un nouveau processus qui a besoin d'une approbation d'un service distant qui a rejeté un appel authentifié. L'agent reçoit le résultat de l'action, tandis que l'identifiant reste dans le coffre chiffré de l'application.

Ne masquez pas la lassitude liée aux approbations en renvoyant davantage de détails de diagnostic. Si les utilisateurs approuvent régulièrement des appels qu'ils n'ont pas examinés, corrigez le regroupement des actions, leur portée et l'identité du processus présentée lors de l'approbation. Des refus plus détaillés ne rendent pas un consentement donné dans la précipitation plus sûr.

Construisez un chemin de diagnostic à deux enregistrements

Rendez le coffre verrouillé décisif
Verrouillez la porte du coffre et chaque action de l'agent sera refusée avant l'utilisation d'un identifiant enregistré.

Un enregistrement doit être sûr pour l'agent et l'autre suffisamment complet pour un opérateur autorisé. Essayer de faire tenir les deux usages dans un seul enregistrement produit soit une assistance opaque, soit une fuite de secrets.

L'enregistrement sûr pour l'appelant doit contenir un code, un message, une action, des indications de nouvelle tentative, un identifiant de requête et éventuellement un statut de protocole. L'enregistrement protégé peut contenir l'identifiant de l'enregistrement d'identifiant sélectionné, la destination normalisée, la méthode, les temps d'exécution, les métadonnées de réponse de l'amont, l'empreinte nettoyée de la charge utile, l'exception brute et la décision de la passerelle. Stockez cet enregistrement protégé dans un emplacement que les agents ne peuvent pas interroger avec les outils ordinaires.

Un identifiant de requête doit être opaque. Générez-le indépendamment des identifiants et des destinations. N'y encodez pas un nom d'hôte, un nom d'utilisateur, un horodatage révélant des habitudes d'activité ou un identifiant de base de données incrémentiel si ces détails sont importants dans votre environnement. L'identifiant permet à un utilisateur de dire « veuillez examiner act_9b18d4e0 » sans lui transmettre les diagnostics sous-jacents.

Pour les actions importantes, consignez si la passerelle a franchi chaque frontière : validation de l'entrée, sélection de l'identifiant, autorisation de l'utilisateur, début de la connexion, envoi des octets de la requête, réception de la réponse et retour du résultat. Cette séquence donne à l'opérateur une explication défendable de OUTCOME_UNKNOWN sans montrer la requête brute à l'agent.

La preuve d'altération compte pour ce chemin interne. Si quelqu'un peut supprimer discrètement des tentatives d'autorisation échouées ou réécrire la raison pour laquelle une action a été bloquée, la piste d'audit devient un simple journal pratique. Sallyport construit les vues des sessions et des appels à partir d'un journal d'audit chiffré et chaîné par hachage, et sp audit verify vérifie la chaîne hors ligne sur le texte chiffré. C'est utile lorsqu'un opérateur doit pouvoir faire confiance à l'enregistrement sans donner à l'agent accès à son contenu.

Un enregistrement protégé pourrait ressembler à ceci. Il ne s'agit volontairement pas d'une réponse destinée à un agent :

{
  "request_id": "act_9b18d4e0",
  "event": "http_call_failed",
  "credential_record": "cred_42",
  "destination": "api.internal.example",
  "method": "POST",
  "path_template": "/deployments",
  "bytes_sent": true,
  "response_received": false,
  "exception_class": "ReadTimeout",
  "result_code": "OUTCOME_UNKNOWN"
}

Même ici, examinez attentivement les champs. Un chemin complet peut exposer des identifiants de ressources. Le corps d'une requête doit généralement devenir une empreinte à sens unique, un nom de schéma ou une représentation strictement expurgée. Les opérateurs ont souvent besoin de comparer deux tentatives, pas de lire chaque valeur soumise.

Les messages d'erreur ont besoin d'une politique de masquage réfléchie

Le masquage ne consiste pas à remplacer un jeton par huit astérisques. Cela ne traite que les formats de secrets que vous reconnaissez déjà. Une politique correcte classe les champs avant leur entrée dans les messages, les journaux, les métriques et les résultats d'outils.

Commencez par classer les secrets directs : jetons bearer, mots de passe, clés privées, cookies, URL signées, en-têtes d'autorisation et certificats clients. Classez ensuite le contexte sensible : noms DNS internes, chemins locaux, noms d'utilisateurs, noms de dépôts, identifiants de ressources, corps de requêtes et en-têtes qui révèlent la topologie du déploiement. La seconde catégorie peut être acceptable dans un enregistrement protégé, mais appartient rarement à une erreur visible par l'agent.

Ne renvoyez pas « l'identifiant se terminant par 7KQ2 a été rejeté ». Les équipes ajoutent cela parce que plusieurs identifiants existent et que les opérateurs veulent savoir lequel a échoué. Cela crée un identifiant durable qui peut être recoupé entre les traces. Renvoyez AUTH_FAILED à l'agent. L'opérateur peut examiner l'enregistrement de l'identifiant avec l'identifiant de requête protégé.

Évitez de recopier l'entrée de l'outil par défaut. Un agent sait déjà ce qu'il a tenté, mais la passerelle ne peut pas supposer que cette entrée peut être répétée sans danger. Une URL peut contenir une chaîne de requête signée. Une commande peut inclure une affectation d'environnement. Une charge utile JSON peut contenir un identifiant temporaire reçu par l'agent d'un autre système. Renvoyez une erreur de validation au niveau du champ, comme invalid_fields: ["repository"], et non la valeur invalide recopiée.

Testez le masquage avec des jeux de données hostiles. Incluez des secrets avec une casse inhabituelle, des en-têtes dupliqués, des informations utilisateur dans une URL, des valeurs de requête encodées en pourcentage, du JSON imbriqué, des causes d'exception et des arguments de commande SSH. Vérifiez ensuite qu'aucun secret du jeu de test n'apparaît dans la réponse d'outil sérialisée, les journaux généraux, les étiquettes de métriques ou les charges utiles d'incident. Un test qui ne vérifie que le chemin nominal ne prouve rien sur la gestion des échecs.

Traitez les messages distants comme des entrées non fiables

Révoquez immédiatement une exécution
Les journaux de session consignent les exécutions des agents et permettent une révocation immédiate lorsqu'un processus doit perdre son accès.

Une API distante peut renvoyer un corps d'erreur utile, une page de connexion HTML ou une chaîne conçue pour influencer la personne qui la lit. La passerelle ne doit pas transmettre directement ce contenu au contexte d'un agent.

C'est en partie un problème de secrets. Les serveurs renvoient parfois les valeurs de requête dans les pages d'erreur. Un en-tête Authorization, un cookie, un paramètre de requête ou un champ JSON invalide peut réapparaître dans la réponse de diagnostic de l'amont. Le transmettre transforme un écho distant en fuite d'identifiant.

C'est aussi un problème d'intégrité des instructions. Si une erreur de l'amont dit « exécutez cette commande pour réparer vos identifiants », l'agent peut la prendre pour une consigne opérationnelle. Le service distant ne doit pas pouvoir écrire la politique de récupération de la passerelle.

Associez les champs sûrs connus d'une réponse de protocole amont. Par exemple, un statut HTTP numérique et un délai documenté de limitation de débit peuvent être utiles. Traitez les corps en texte libre comme des preuves protégées, sauf si vous disposez d'un analyseur propre au format et d'une liste d'autorisation claire. Si une intégration a besoin d'une raison distante lisible par un humain, normalisez-la dans le langage de la passerelle, par exemple « Le service a rejeté la ressource demandée », au lieu de recopier sa prose.

La RFC 9110 définit la sémantique des statuts HTTP, mais ces statuts n'autorisent pas la divulgation du corps de réponse d'une origine. Gardez cette séparation claire. Les informations de protocole peuvent aider à récupérer, mais un texte arbitraire provenant de l'amont n'est pas un contrat de diagnostic sûr.

Soumettez le contrat à des tests centrés sur les échecs

La plupart des équipes vérifient qu'une requête valide renvoie des données utiles. Vérifiez aussi que chaque requête invalide ou interrompue ne renvoie que les données que l'agent doit voir.

Faites du schéma d'erreur un contrat versionné. Validez-le dans les tests et rejetez les champs inconnus à la frontière de sérialisation pendant le développement. Une liste d'autorisation est plus facile à auditer lorsque l'objet possède une forme stricte.

Utilisez un secret de test suffisamment inhabituel pour détecter les transformations accidentelles, puis provoquez des échecs à chaque étape. Votre matrice doit couvrir la validation avant les identifiants, un coffre verrouillé, un consentement refusé, les réponses distantes 401 et 403, la limitation de débit, un échec DNS, un échec de validation TLS, un délai d'attente avant la sortie des octets, un délai d'attente après leur sortie, un JSON amont mal formé et une exception levée par la passerelle elle-même.

Pour chaque cas, vérifiez quatre éléments :

  • La réponse de l'outil contient le code attendu et l'action autorisée.
  • Le secret de test n'apparaît dans aucun champ sérialisé visible par l'appelant.
  • La réponse ne contient ni en-têtes bruts, ni texte brut du corps amont, ni détails locaux de connexion.
  • L'enregistrement de diagnostic protégé contient l'identifiant de requête et suffisamment d'état pour permettre une enquête.

Ne vous contentez pas de contrôles par expressions régulières. Recherchez le secret de test exact, sa forme encodée dans une URL, sa forme base64 lorsque cela est pertinent et ses préfixes ou suffixes courants. Examinez ensuite manuellement une réponse d'erreur capturée chaque fois que vous mettez à jour une dépendance HTTP, SSH, de télémétrie ou de signalement d'incident. Les bibliothèques changent la mise en forme des exceptions sans vous demander votre autorisation.

Le plus difficile est de résister à l'envie de faire ressembler l'erreur de l'agent à la console de débogage de l'opérateur. Gardez le contrat de l'appelant réduit, stable et orienté vers l'action. Protégez les preuves et reliez-les à l'aide d'un identifiant. Lorsque la prochaine panne surviendra, cette séparation donnera à l'agent assez d'informations pour agir prudemment et à l'humain assez d'éléments pour corriger la véritable cause.

FAQ

Que doit contenir l'erreur d'un outil destiné à un agent IA ?

Renvoyez un code stable lisible par machine, un court message destiné aux humains, l'action qui a échoué et l'action suivante autorisée. Gardez les en-têtes de requête, les identifiants, les URL complètes avec leurs chaînes de requête et les diagnostics bruts du transport du côté de confiance de la frontière.

Les codes de statut HTTP suffisent-ils pour les outils d'agents ?

En général, non. Un statut HTTP décrit le résultat à la frontière du protocole, tandis que l'agent doit savoir s'il doit réessayer, demander une approbation, corriger son entrée ou s'arrêter. Conservez le statut comme contexte sûr, puis ajoutez un code propre à l'outil qui exprime cette signification opérationnelle.

Une erreur peut-elle inclure les premiers caractères d'un jeton à des fins de débogage ?

Ne le renvoyez pas à l'agent. La passerelle peut enregistrer en interne l'empreinte du jeton ou l'identifiant de l'enregistrement d'identifiant, puis renvoyer une réponse générique AUTH_FAILED avec un identifiant de requête. Le préfixe d'un jeton reste une donnée d'identification et finit souvent dans des transcriptions, des outils de suivi et l'historique du shell.

Quelles défaillances un agent peut-il réessayer automatiquement ?

Une nouvelle tentative est raisonnable pour une défaillance temporaire explicite, comme un délai d'attente avant toute réponse, une réinitialisation de connexion ou une réponse 503 de l'amont, lorsque l'opération est idempotente. Ne réessayez pas après une erreur d'autorisation, une entrée invalide, une approbation refusée ou l'échec ambigu d'une écriture, sauf si l'outil peut d'abord établir le résultat distant.

Comment un outil doit-il gérer un délai d'attente pendant une requête d'écriture ?

Traitez le résultat inconnu d'une écriture comme une classe d'erreur distincte. L'agent doit consulter un point de terminaison d'état sûr, utiliser une référence d'idempotence si l'API le permet ou demander l'avis d'une personne avant de répéter l'action. Rejouer aveuglément un paiement, un déploiement, une suppression ou la création d'un ticket est pire qu'un échec lent.

Les messages d'erreur doivent-ils rester stables entre les versions d'un outil ?

Gardez les messages d'erreur destinés aux utilisateurs stables et testez-les. Vous pouvez ajouter des champs au fil du temps, mais modifier la signification des codes ou transformer des messages brefs en vidages de diagnostic perturbe le comportement des agents et peut exposer des informations que les anciens clients enregistrent sans contrôle.

Est-il sûr de donner un identifiant de requête à un agent ?

Un identifiant de requête est sûr lorsqu'il est généré aléatoirement ou qu'il ne contient aucun secret et ne révèle aucune donnée client, aucun nom d'hôte, aucune identité d'identifiant ni aucun chemin de système de fichiers. Il doit permettre à un opérateur de retrouver l'enregistrement interne complet sans donner à l'agent un moyen d'accéder aux diagnostics protégés.

Un agent peut-il lire les journaux pour diagnostiquer un échec d'appel d'outil ?

Uniquement si la source est conçue pour être visible par un agent et que ses champs ont été examinés. De nombreux journaux d'application contiennent des en-têtes d'autorisation, des URL signées, des cookies, des valeurs SQL, des noms d'hôtes internes et des traces de pile. Un enregistrement d'activité séparé et nettoyé est plus sûr que le filtrage a posteriori d'un journal de débogage général.

Quels diagnostics réseau sont dangereux pour un agent ?

N'envoyez jamais directement à un agent les erreurs brutes des bibliothèques TCP, TLS, DNS ou SSH. Convertissez-les en un code limité comme NETWORK_UNREACHABLE, TLS_VALIDATION_FAILED ou SSH_HOST_UNVERIFIED, puis conservez l'erreur brute dans les diagnostics protégés.

Comment un outil d'agent doit-il signaler une approbation refusée ?

Le refus d'une approbation doit être distinct d'un échec d'authentification et d'un refus de politique. Renvoyez un code comme USER_DENIED, précisez que l'action demandée n'a pas été exécutée et évitez de décrire l'identifiant enregistré ou le compte distant qui aurait été utilisé.

Sallyport

Sallyport exécute les appels d'API et les commandes SSH à la place de votre agent IA. Les clés restent dans un coffre-fort local sur votre Mac ; vous approuvez chaque exécution et chaque action est consignée dans un journal scellé.

© 2026 Sallyport · Open source sous Apache-2.0 · Oleg Sotnikov