8 min de lecture

Des API sûres pour les agents IA : des écritures traçables

Les API sûres pour les agents IA limitent les opérations, rendent les écritures idempotentes, fournissent des erreurs exploitables et conservent des identifiants de requête pour garder le contrôle et assurer la traçabilité.

Des API sûres pour les agents IA : des écritures traçables

Un agent IA ne rend pas une API dangereuse par lui-même. Une API devient dangereuse lorsqu'elle propose des verbes trop larges, des résultats ambigus et des erreurs qui obligent l'appelant à deviner. Les opérateurs humains compensent avec le contexte, la prudence et un message rapide dans une conversation. Un agent compense avec des nouvelles tentatives et un nouvel appel d'outil. Cette différence peut transformer un simple délai d'attente en deux remboursements, deux déploiements ou la suppression d'un enregistrement que personne ne voulait toucher.

Les API sûres pour les agents IA limitent l'action autorisée, rendent les écritures répétées inoffensives et laissent une trace qu'une personne pourra suivre plus tard. C'est un travail de conception d'API, pas de rédaction d'invite. Une invite peut demander à un agent d'être prudent, mais le point d'accès doit tout de même refuser une action qui sort de son contrat.

J'ai vu des équipes placer des écrans d'approbation devant un point d'accès d'administration trop permissif et appeler cela un contrôle. Ce n'est pas suffisant. Si l'appel approuvé signifie « modifier n'importe quoi dans ce compte », l'approbation demande à une personne d'examiner, sous pression, un ensemble de conséquences cachées. Commencez par donner de la précision à l'API. L'approbation aura alors quelque chose de compréhensible à valider.

Les verbes trop larges obligent les agents à deviner

Un agent doit appeler une opération dont le nom, les entrées et les effets secondaires tiennent en une phrase. Les points d'accès trop larges l'obligent à déduire les règles métier à partir de champs vagues, d'anciens exemples ou d'une erreur qui dit seulement « requête incorrecte ». C'est ainsi que commence l'improvisation dangereuse.

Prenons un point d'accès comme POST /admin/execute, avec un corps contenant action et un JSON arbitraire. Un client écrit par un humain n'utilisera peut-être que cinq actions aujourd'hui, mais le point d'accès expose toutes les actions actuelles et futures à chaque appelant qui obtient l'accès. Le serveur ne peut pas définir une limite d'autorisation utile et la personne qui approuve ne peut pas savoir ce que fera l'agent sans lire le corps comme du code source.

Remplacez-le par des opérations qui nomment une transition d'état :

  • POST /projects/{project_id}/deployments crée un déploiement à partir d'une révision précise.
  • POST /invoices/{invoice_id}/refunds crée un remboursement avec un montant et un motif explicites.
  • POST /users/{user_id}/access-revocations retire l'accès d'un utilisateur donné.
  • POST /exports lance un export défini avec une catégorie de données déclarée.

Ces opérations peuvent toujours comporter des risques. L'essentiel est que chacune donne au serveur un endroit où appliquer les règles : transitions valides, limites de montant, propriété de la cible, approbations requises et champ de motif au bon endroit.

Ne confondez pas une interface CRUD générique avec une interface adaptée aux agents. PATCH /customers/{id} invite l'appelant à modifier n'importe quel champ accessible en écriture. Si la modification de billing_email est courante, tandis que celle de tax_status déclenche une procédure de conformité, ces changements ne doivent pas se trouver derrière le même patch banal. Créez une opération dédiée pour la transition importante et faites refléter cette décision par son modèle d'entrée.

Une opération limitée facilite aussi la reprise. Lorsqu'un agent dit « la demande de déploiement a expiré », un opérateur peut rechercher la création d'un seul déploiement. Lorsqu'il dit « la commande d'administration a expiré », l'opérateur doit d'abord découvrir quelle commande l'agent a assemblée.

Placez les préconditions dans la requête

Les écritures doivent indiquer la condition dans laquelle elles ont un sens. Une requête qui approuve une dépense peut inclure l'état de contrôle attendu. Une requête qui met à jour un document peut inclure la version lue. Si l'état a changé, le serveur doit refuser l'écriture au lieu de l'appliquer discrètement à une autre réalité.

HTTP fournit déjà des mécanismes utiles. La RFC 9110 définit les requêtes conditionnelles avec des en-têtes comme If-Match ; un serveur peut refuser une balise d'entité obsolète avec 412 Precondition Failed. Vous pouvez aussi exposer un champ expected_version si cela convient mieux à votre API. Le choix compte moins que la discipline : le client doit nommer la version ou l'état qu'il veut modifier.

N'acceptez pas un champ client comme force: true pour contourner tous les conflits. Ce champ devient souvent un moyen pour les agents d'écraser précisément le contrôle de sécurité que vous aviez ajouté. Réservez la dérogation à une opération distincte, un niveau d'autorisation différent et une trace d'audit visible.

Une écriture a besoin d'une identité distincte de la tentative HTTP

Toute écriture visible de l'extérieur doit avoir un identifiant d'idempotence fourni par le client. Le serveur l'utilise pour reconnaître que plusieurs tentatives de transmission expriment la même action souhaitée.

Un identifiant de requête et un identifiant d'idempotence résolvent des problèmes différents. Une passerelle ou un serveur crée souvent un identifiant de requête pour chaque tentative HTTP. Si le réseau tombe après la validation de l'écriture par le serveur, mais avant que la réponse n'atteigne l'appelant, la nouvelle tentative reçoit un nouvel identifiant de requête. L'identifiant d'idempotence doit rester le même, car l'écriture souhaitée n'a pas changé.

La séquence d'échec habituelle ressemble à ceci :

  1. L'agent envoie une requête pour créer un versement.
  2. Votre serveur enregistre le versement et appelle un fournisseur externe.
  3. La connexion échoue avant que l'agent ne reçoive la réponse de réussite.
  4. L'agent constate un résultat inconnu et recommence.
  5. Votre serveur crée un autre versement, car il voit une nouvelle requête HTTP.

La politique de nouvelle tentative n'a pas créé le défaut. C'est l'API qui l'a créé en confondant la transmission et l'intention.

Utilisez un en-tête ou un champ de requête créé par le client avant la première tentative et conservé jusqu'à l'obtention d'une réponse définitive. Les noms d'en-tête HTTP utilisent généralement Idempotency-Key, même si l'identifiant n'a pas besoin d'être secret. Un UUID aléatoire convient bien. Ne le déduisez pas uniquement d'un horodatage et n'utilisez pas un identifiant susceptible d'entrer en collision entre des écritures sans rapport.

Enregistrez l'empreinte de la requête et le résultat

Le serveur doit associer un identifiant d'idempotence à davantage qu'un simple indicateur d'état. Enregistrez l'identité de l'appelant, la route cible, une empreinte canonique du corps de requête pertinent sur le plan sémantique et le résultat complet nécessaire à la relecture. Lorsque le même appelant recommence avec le même identifiant et la même empreinte, renvoyez la réponse initiale. Si le corps diffère, refusez la requête avec un conflit.

Le projet IETF « The Idempotency-Key HTTP Header Field » décrit cet en-tête comme un moyen de rendre tolérantes aux défaillances les méthodes HTTP non idempotentes côté client. Son avertissement sur l'unicité est important : le client ne doit pas réutiliser une valeur pour une autre requête. J'irais même plus loin dans l'implémentation. Faites respecter cet avertissement par le serveur, car les agents recommencent, redémarrent et réutilisent parfois un état qu'un client humain aurait abandonné.

Un contrat compact peut ressembler à ceci :

POST /v1/projects/prj_48/deployments
Idempotency-Key: 8c8d77c1-4ef9-4fae-b0ba-5480f686ce4c
Content-Type: application/json

{
  "revision": "a1b2c3d4",
  "environment": "staging",
  "expected_project_version": 17
}

Lors du premier appel accepté, renvoyez une ressource et les deux identifiants :

{
  "request_id": "req_01J8X7QK3JZ6",
  "deployment": {
    "id": "dep_01J8X7R5G2",
    "state": "queued",
    "revision": "a1b2c3d4",
    "environment": "staging"
  }
}

Si l'agent répète la requête identique après un délai d'attente, renvoyez le même dep_01J8X7R5G2, pas un second déploiement. S'il remplace environment par production tout en conservant l'identifiant, renvoyez un conflit qui indique clairement la correction à apporter :

{
  "error": {
    "code": "idempotency_payload_mismatch",
    "message": "This idempotency identifier belongs to a deployment request with different parameters.",
    "request_id": "req_01J8X84S9P2V"
  }
}

Conservez les enregistrements d'idempotence au moins aussi longtemps que peuvent raisonnablement durer les nouvelles tentatives du client et la reprise des tâches. Une durée de conservation trop courte crée un doublon tardif qui semble intermittent en production. Si la pression sur le stockage impose une expiration, documentez clairement cette période et faites choisir aux consommateurs un comportement de nouvelle tentative qui la respecte.

Une nouvelle tentative n'a de sens que si le résultat est suffisamment connu

Un agent peut recommencer après des erreurs de transport et certaines réponses temporaires, mais il ne doit jamais inventer une nouvelle action pour échapper à l'incertitude. Les catégories de réponses doivent permettre ce choix.

La RFC 9110 définit 429 Too Many Requests et autorise Retry-After ; respectez ce mécanisme si vous l'envoyez. L'appelant peut attendre la durée indiquée, conserver son identifiant d'idempotence et soumettre la même requête. Pour une défaillance temporaire du serveur, renvoyez une réponse 5xx avec un identifiant de requête et indiquez si le serveur a accepté l'opération. N'utilisez pas un 500 vague pour une erreur de validation ou un refus d'autorisation. Vous enseigneriez aux clients un mauvais comportement de nouvelle tentative.

Pour les écritures asynchrones, l'acceptation et l'achèvement sont deux faits distincts. Une réponse 202 Accepted doit renvoyer une ressource d'opération qui décrit la tâche et son état. Après un délai d'attente, l'agent peut interroger cette ressource au lieu de soumettre à nouveau un effet secondaire.

{
  "request_id": "req_01J8X9FW7GH2",
  "operation": {
    "id": "op_01J8X9FTVX",
    "state": "running",
    "status_url": "/v1/operations/op_01J8X9FTVX"
  }
}

La ressource d'état doit fournir davantage que running et failed. Incluez un état final, une référence au résultat en cas de réussite et un code d'échec public lorsque le processus ne peut pas terminer la tâche. Un déploiement qui a échoué aux contrôles de santé ne doit pas ressembler à une défaillance de transport de l'API. L'agent doit signaler ou corriger l'échec du déploiement ; il ne doit recommencer après une défaillance de connexion que lorsque le serveur n'a jamais accepté la requête.

Évitez les nouvelles tentatives automatiques pour les actions qui envoient un e-mail, débitent de l'argent, font tourner des identifiants ou appellent un système externe, sauf si votre serveur contrôle la déduplication jusqu'à l'effet final. L'idempotence de votre base de données n'empêche pas l'envoi de deux e-mails si un processus s'arrête après l'acceptation du message par le fournisseur d'e-mails et avant l'enregistrement de l'achèvement. Utilisez un enregistrement outbox avec une référence stable de déduplication côté fournisseur lorsque celui-ci le permet. Si le système externe ne peut pas dédupliquer, rendez l'opération observable et demandez une décision humaine après un résultat inconnu.

Les erreurs doivent expliquer comment corriger la requête

Les messages d'erreur utiles décrivent le contrat qui a échoué, pas la gêne du serveur. Un agent peut travailler avec une erreur précise. Il ne peut pas travailler sans danger avec une page d'erreur HTML, une trace d'exécution ou « entrée invalide » après une requête de dix champs.

Renvoyez une enveloppe JSON cohérente pour chaque échec attendu. Donnez-lui un code stable pour les programmes, un message concis pour les journaux et les personnes, un identifiant de requête et des détails au niveau des champs lorsque ceux-ci peuvent être exposés sans risque. La RFC 9457, « Problem Details for HTTP APIs », propose une structure standard avec des champs comme type, title, status, detail et instance. Vous n'avez pas besoin d'adopter chaque champ pour retenir sa leçon centrale : les erreurs font partie du contrat de l'API, elles ne sont pas un texte ajouté après coup.

Cette réponse indique exactement à l'agent ce qu'il doit modifier :

{
  "error": {
    "code": "invalid_state_transition",
    "message": "A refund can be created only for a paid invoice.",
    "request_id": "req_01J8XAS2D8M4",
    "details": {
      "invoice_id": "inv_204",
      "current_state": "draft",
      "allowed_states": ["paid", "partially_paid"]
    }
  }
}

Cette réponse pousse à deviner :

{
  "error": "Request failed"
}

La seconde renvoie l'agent vers la documentation, le code source ou des appels exploratoires. Les appels exploratoires sur une API d'écriture sont la façon dont un petit défaut devient un incident bruyant.

Ne placez pas de secrets dans les erreurs. Ne renvoyez pas les en-têtes d'autorisation, les jetons d'accès, les URL signées, les requêtes brutes de base de données ni une réponse de service externe pouvant contenir les données d'un autre client. Une mauvaise pratique courante consiste à envelopper chaque exception interceptée et à renvoyer son message à l'appelant. Cela facilite le débogage pendant une journée et crée pendant des années un canal de divulgation.

Séparez les données invalides de l'autorité insuffisante. 422 Unprocessable Content peut décrire un contenu bien formé qui enfreint une règle métier. 403 Forbidden doit indiquer que l'opération demandée exige une permission ou une approbation, sans révéler les ressources que l'appelant ne peut pas consulter. 404 Not Found peut convenir si vous masquez volontairement l'existence de la ressource. Choisissez la sémantique, documentez-la et appliquez-la de façon cohérente.

Une bonne erreur indique aussi quand une nouvelle tentative est inutile. invalid_state_transition, idempotency_payload_mismatch et approval_required doivent arrêter les nouvelles tentatives aveugles. rate_limited avec un délai d'attente et upstream_temporarily_unavailable peuvent inviter à une nouvelle tentative contrôlée. Cette distinction évite davantage de dommages qu'une invite d'agent ingénieuse.

Les identifiants de requête transforment une action contestée en enquête

Demandez à nouveau les clés sensibles
Un réglage par clé peut exiger une approbation en un clic ou via Touch ID à chaque utilisation.

Donnez un identifiant de requête à chaque requête entrante, renvoyez-le dans le corps ou les en-têtes de la réponse et transmettez-le dans chaque appel interne, message en file d'attente, tâche de processus et appel à un fournisseur externe. Lorsqu'un agent dit ne pas avoir reçu de réponse, vous devez répondre à deux questions distinctes : votre API a-t-elle accepté l'action et qu'a fait chaque composant ensuite ?

Générez l'identifiant de requête à la frontière de confiance si l'appelant n'en fournit pas. Vous pouvez accepter un identifiant de corrélation fourni par l'appelant pour sa propre organisation, mais ne laissez pas un appelant non fiable remplacer l'identifiant attribué par votre serveur. Conservez les deux lorsque c'est utile. L'identifiant du serveur ancre vos journaux ; celui de l'appelant relie une séquence de décisions de l'agent.

Enregistrez des événements structurés plutôt que d'assembler des lignes de texte que les opérateurs devront ensuite analyser avec des expressions régulières. Au minimum, notez l'identifiant de requête, le principal authentifié, le nom de l'opération, la ressource cible, l'identifiant d'idempotence s'il existe, la décision d'autorisation, le statut du résultat et les références aux ressources créées. Masquez les champs de requête selon un schéma, pas avec un filtre de chaînes ajouté au dernier moment. Un champ nommé token est facile à masquer. Un identifiant secret placé dans un texte arbitraire ne l'est pas.

La trace doit préserver l'ordre sans prétendre prouver davantage qu'elle ne le peut. Un identifiant de requête peut montrer que votre API a accepté une tâche et qu'un processus a envoyé un appel à un fournisseur. Il ne peut pas prouver qu'une personne a voulu l'action, sauf si votre système enregistre cette décision séparément. Gardez la distinction nette :

  • Un enregistrement de corrélation relie les événements appartenant à une même requête.
  • Un enregistrement d'audit indique qui ou quoi a autorisé une action et ce que le système a fait.
  • Un enregistrement d'idempotence empêche une écriture logique en double.

Les équipes regroupent souvent ces éléments dans une seule ligne de base de données. Cette ligne doit alors servir aux nouvelles tentatives, au débogage, aux contrôles de conformité et à l'historique présenté à l'utilisateur, sans remplir correctement aucun de ces rôles. Vous pouvez conserver des références liées ensemble, mais préservez leur signification distincte dans le modèle de données.

Pour les actions plus risquées, enregistrez la requête normalisée, le contexte d'autorisation, le résultat de la politique ou de l'approbation et une empreinte du résultat dans un flux d'audit en ajout seulement. Protégez ce flux du compte applicatif habituel. Sinon, un service compromis pourrait réécrire l'historique qui permettrait de le découvrir.

Sallyport adopte une approche utile pour les actions d'agents : il enregistre les sessions d'agents et les appels individuels dans un journal d'audit chiffré, aveugle aux écritures et chaîné par hachage, tandis que sp audit verify vérifie la chaîne hors ligne sans clé de coffre. Votre API a tout de même besoin de ses propres enregistrements, car une passerelle peut montrer qu'elle a envoyé un appel, alors que seul votre service peut montrer la transition d'état qu'il a validée.

La portée de l'authentification ne corrige pas une opération dangereuse

Faites passer les actions MCP par Sallyport
Les agents se connectent via le shim sp mcp fourni au lieu de manipuler directement les identifiants.

Des identifiants de courte durée et des portées limitées réduisent l'ampleur des dégâts, mais ne rendent pas sûr un point d'accès trop large. Un jeton limité à un seul projet peut tout de même détruire chaque déploiement, exporter toutes les données autorisées ou déclencher chaque action d'administration disponible dans ce projet.

Liez l'autorisation à l'opération et à la cible. Un appelant autorisé à créer un déploiement ne doit pas automatiquement pouvoir le promouvoir en production. Un appelant autorisé à retirer l'accès d'un utilisateur ne doit pas recevoir le droit de modifier son profil de facturation parce que les deux opérations se trouvent sous /users/{id}.

Gardez les identifiants hors de l'agent chaque fois que possible. Un agent qui reçoit un jeton bearer peut le copier dans une transcription, un fichier de débogage, l'historique d'un shell ou un appel à un service externe. Placez plutôt l'utilisation des identifiants derrière une passerelle d'actions locale ou un intermédiaire côté serveur qui sélectionne l'identifiant pour une opération approuvée. L'agent envoie l'intention et les paramètres ; le composant de confiance injecte le secret uniquement lors de l'appel sortant.

Cette conception ne dispense pas de valider les paramètres. Si un agent peut fournir url: https://anything.example, un assistant HTTP qui injecte des identifiants peut devenir un outil d'exfiltration de secrets. Liez les identifiants à des services externes et à des méthodes nommés. Validez les hôtes après les redirections comme avant. Pour SSH, liez si possible un identifiant à des hôtes connus et à une interface de commandes limitée, au lieu d'offrir un accès arbitraire à un shell distant.

L'approbation humaine a sa place, mais elle doit couvrir une petite action avec une cible et une conséquence visibles. L'approbation par session répond à « ce processus d'agent peut-il agir ? ». L'approbation par appel répond à « peut-il effectuer cette action sensible précise maintenant ? ». Aucune ne sauve un point d'accès dont le contenu peut vouloir dire n'importe quoi.

La concurrence a besoin d'un perdant explicite

L'idempotence empêche la transmission en double d'une même intention. Elle ne résout pas la course entre deux intentions différentes. Si deux agents lisent une facture à l'état paid et soumettent tous deux un remboursement intégral avec des identifiants d'idempotence différents, votre serveur doit décider quelle requête l'emporte.

Utilisez une transition d'état transactionnelle lorsque votre système de stockage le permet. La mise à jour doit inclure l'état attendu, et le serveur doit signaler le conflit lorsqu'un autre auteur l'a modifié en premier. Un champ de version, une balise d'entité ou une mise à jour conditionnelle donne à l'API un moyen de refuser une intention obsolète au lieu de l'appliquer après le changement des faits.

Par exemple, modélisez un remboursement comme une opération sur le solde encore remboursable, pas comme une commande aveugle qui fait confiance au montant fourni par le client. Dans une transaction, vérifiez le montant actuellement payé, soustrayez les remboursements précédents, validez le montant demandé, réservez le nouveau remboursement et créez son enregistrement. Un processus asynchrone distinct peut appeler le fournisseur de paiement une fois cette réservation créée. S'il recommence, il reprend le même enregistrement de remboursement au lieu d'en créer un nouveau.

Ne dites pas aux agents de « vérifier d'abord, puis agir » en guise de seul contrôle de concurrence. Une requête préliminaire GET aide l'agent à construire une demande utile, mais un autre appelant peut modifier l'état entre la lecture et l'écriture. Le point d'accès d'écriture est responsable de la correction, car il voit l'état réel au moment de la validation.

Concevez l'annulation avec le même soin. DELETE /operations/{id} ne doit pas promettre qu'une action externe n'a jamais eu lieu. Il doit renvoyer l'état réel de l'annulation : annulation demandée, annulée avant l'envoi, terminée avant l'annulation ou annulation impossible après l'envoi. Les agents comme les humains ont besoin d'un langage qui reflète la frontière entre votre système et le fournisseur externe.

Testez les résultats inconnus avant que les agents ne les découvrent en production

Suivez chaque action de l'agent
Son journal d'activité enregistre chaque action HTTP ou SSH envoyée par un agent.

Une suite de tests qui ne vérifie qu'une réponse 200 apprend à tout le monde à ignorer la partie la plus difficile des API d'action. Ajoutez les cas d'échec aux tests de contrat et exécutez-les sur une vraie frontière de service, pas seulement sur un gestionnaire simulé.

Pour chaque opération d'écriture, testez une séquence dans laquelle le serveur valide l'effet et le client perd la réponse. Soumettez de nouveau le même identifiant d'idempotence et vérifiez que le serveur renvoie la ressource initiale. Soumettez ensuite cet identifiant avec un corps modifié et vérifiez que le serveur renvoie un conflit sans créer une autre ressource.

Testez les requêtes concurrentes avec des identifiants d'idempotence différents sur la même transition d'état. Vérifiez que l'une réussit et que l'autre reçoit une erreur précise d'état obsolète ou de règle métier. Si les deux réussissent dans une base de test parce que chaque test s'exécute seul, vous n'avez pas testé la propriété importante.

Testez le contrat d'erreur comme des données. Vérifiez les codes d'état, les codes d'erreur stables, les noms de champs et la présence d'un identifiant de requête. Ne faites pas uniquement une comparaison figée du message en anglais. Vous améliorerez la formulation avec le temps ; les clients doivent choisir leur branche selon code, pas selon le texte.

Enfin, faites un exercice pour les opérateurs. Prenez une action terminée, une action refusée, un délai d'attente avec validation réussie côté serveur et un échec asynchrone. Donnez uniquement les identifiants de requête à un ingénieur et demandez-lui de reconstituer les faits. S'il doit rechercher dans des journaux sans rapport, consulter la transcription d'un agent et deviner quelle nouvelle tentative a créé quel enregistrement, corrigez l'instrumentation avant d'autoriser les écritures sans supervision.

La première action à corriger est généralement le point d'accès d'écriture le plus large. Divisez-le en transitions nommées, exigez un identifiant d'idempotence et faites en sorte que la réponse identifie la ressource créée. Une fois ce contrat en place, les agents peuvent agir rapidement sans traiter chaque incident réseau comme la permission d'essayer autre chose.

FAQ

Comment rendre une API existante sûre pour les agents IA ?

Commencez par des opérations en lecture seule et par un ensemble très limité d'opérations d'écriture dont les effets peuvent être décrits précisément. Donnez à chaque écriture un contrat d'idempotence, un identifiant de requête stable et un point d'accès d'état clair si elle s'exécute de manière asynchrone. Ne confiez pas à un agent une vaste API d'administration en espérant que l'invite suffira à le retenir.

Qu'est-ce qui rend un point d'accès API adapté aux agents ?

Un point d'accès adapté aux agents produit un effet précis et limité, avec une structure de requête qui rend les actions invalides difficiles à exprimer. « Créer un remboursement pour une facture » est plus facile à encadrer que « exécuter une modification de facturation arbitraire ». Le point d'accès doit renvoyer la ressource créée, son état et l'identifiant de requête à l'origine de l'action.

Pourquoi les agents IA ont-ils besoin d'écritures API idempotentes ?

L'idempotence signifie que le serveur traite plusieurs soumissions d'une même écriture logique comme une seule opération. Elle protège contre les nouvelles tentatives après un délai d'attente, une coupure de connexion ou une reprise d'activité de l'agent. L'identifiant d'idempotence créé par le client doit être lié au corps de la requête, pas seulement au point d'accès.

Que doit faire une API lorsqu'une clé d'idempotence est réutilisée avec des données différentes ?

Traitez la réutilisation d'un identifiant d'idempotence avec un corps de requête différent comme une erreur, généralement HTTP 409 Conflict. Si vous acceptez silencieusement le nouveau corps, un client peut associer par erreur le résultat d'une ancienne action à une nouvelle intention. Enregistrez une empreinte de la requête avec le résultat initial et comparez-la à chaque nouvelle tentative.

Quel format d'erreur une API doit-elle renvoyer à un agent IA ?

Renvoyez un statut HTTP, un code d'erreur stable et lisible par une machine, un court message compréhensible par une personne et un identifiant de requête. N'incluez le champ en cause que si cela ne risque pas de divulguer des données sensibles. Indiquez à l'appelant ce qu'il peut faire sans danger ensuite, par exemple corriger les données, attendre ou utiliser un autre parcours d'autorisation.

Les identifiants de requête et les clés d'idempotence sont-ils la même chose ?

Un identifiant de requête désigne une tentative d'appel à votre API. Un identifiant d'idempotence désigne une écriture souhaitée au fil de plusieurs tentatives. Conservez les deux : les opérateurs ont besoin du premier pour les journaux et les traces, tandis que le serveur utilise le second pour éviter les effets en double.

Comment une API doit-elle gérer les actions longues lancées par un agent ?

Non. Une réponse HTTP réussie peut signifier qu'un processus en file d'attente a accepté la tâche, pas que l'effet externe est terminé. Renvoyez une ressource de tâche ou d'opération avec un état explicite, puis laissez l'agent l'interroger ou recevoir un rappel via un canal contrôlé.

Les messages d'erreur d'une API doivent-ils contenir des détails internes pour faciliter le débogage ?

Ne renvoyez pas d'erreurs brutes de base de données, de traces d'exécution, de corps de réponses externes, d'identifiants secrets ou de détails internes sur l'autorisation. Conservez ces informations sur le serveur avec des contrôles d'accès adaptés, puis renvoyez un code d'erreur public et stable. Les agents ont besoin de suffisamment de détails pour corriger une requête, pas d'une carte de vos systèmes internes.

Une authentification limitée suffit-elle à contrôler un agent IA ?

Utilisez ensemble la portée des droits et la conception des points d'accès. Un jeton limité à un projet reste dangereux si l'API lui permet de supprimer toutes les ressources du projet ou d'exécuter des commandes arbitraires. Donnez à l'agent uniquement les opérations nécessaires, puis faites vérifier par chaque opération la cible et la transition d'état demandée.

Quels tests API comptent le plus pour les agents autonomes ?

Testez les soumissions en double, les nouvelles tentatives après un résultat inconnu, les mises à jour concurrentes, les identifiants expirés, les identifiants mal formés et l'achèvement tardif des tâches. Vérifiez aussi qu'un identifiant de requête permet à un opérateur de reconstituer le parcours complet dans vos systèmes. Le scénario nominal ne dit presque rien sur le comportement d'un agent face à l'incertitude.

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