Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Le délégué trompé dans les agents IA

Après cette leçon: Je peux empêcher un agent d’agir avec plus d’autorité que la personne qui demande, en vérifiant chaque action contre le demandeur.

Leçon de 70 min8 commandesLab agent de code IA : utiliser opencode pour expliquer et corriger du code, et vérifier son travail

Qu’est-ce que le problème du délégué trompé

Un délégué trompé est un programme qui détient une autorité et qu’on persuade de l’employer pour quelqu’un qui n’en a aucune. Un agent est un délégué par conception : il agit pour des personnes, par des outils et des comptes.

Si l’agent détient une seule clé large et fait confiance à tout demandeur, quiconque peut lui écrire détient cette clé.

À la fin de cette leçon

Remarque

Je peux empêcher un agent d’agir avec plus d’autorité que la personne qui demande, en vérifiant chaque action contre le demandeur.

Mots clés

MotCe que ça veut direExemple
Délégué trompéun programme qui emploie sa propre autorité pour une personne qui n’y a pas droit
Autoritéce qu’une identité a le droit de faire, ici des actions sur des ressourceslire:paie
Portéeune permission nommée dans un jeton
Jeton étroitun jeton qui ne porte que les portées dont la tâche a besoin, pour peu de temps
Demandeurla personne pour le compte de qui l’agent agit dans cette requête

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Quelle autorité un appel porte-t-il

Imaginons qu’un agent se connecte au système de paie avec sa propre clé. Anne, qui peut seulement lire les notes, lui demande le fichier de paie. Le système voit la clé de l’agent et répond oui.

L’agent n’a pas été trompé par une ligne cachée. On le lui a simplement demandé. La faute est que l’appel portait l’autorité de l’agent et non celle d’Anne.

Exemple guidé : trois conceptions

ConceptionCe que porte l’appelQuand Anne demande la paie
Une seule clé largeLa clé de l’agentLe système l’autorise
Identité du demandeur transmiseL’identité d’AnneLe système vérifie Anne et refuse
Jeton étroit par tâcheSeulement les portées nécessaires à la tâcheLa portée n’est pas dans le jeton, donc l’appel échoue

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Le Run décide les appels de deux façons

Le premier script contient deux utilisateurs et trois appels inventés. Il décide chaque appel deux fois : une fois d’après le jeton de l’agent, une fois d’après les droits du demandeur.

Quand les deux réponses diffèrent, l’agent agirait avec plus d’autorité que la personne qui demande. Le script marque cette ligne. Rien n’est appelé et personne n’est attaqué.

Écrire le contrôle double, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const droits = {' '  anne: [\"lire:notes\"],' '  bruno: [\"lire:notes\", \"lire:paie\"],' '};' 'const jetonAgent = [\"lire:notes\", \"lire:paie\"];' 'const appels = [' '  { qui: \"anne\", action: \"lire\", ressource: \"notes\" },' '  { qui: \"anne\", action: \"lire\", ressource: \"paie\" },' '  { qui: \"bruno\", action: \"lire\", ressource: \"paie\" },' '];' > delegue.js"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire le contrôle double, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function voulu(a) { return a.action + \":\" + a.ressource; }' 'function parAgent(a) { return jetonAgent.includes(voulu(a)); }' 'function parDemandeur(a) { return (droits[a.qui] || []).includes(voulu(a)); }' '' 'for (const a of appels) {' '  const x = parAgent(a), y = parDemandeur(a);' '  let ligne = a.qui + \" demande \" + voulu(a) + \" : jeton de l’agent \" + (x ? \"oui\" : \"non\");' '  ligne += \", droits du demandeur \" + (y ? \"oui\" : \"non\");' '  console.log(ligne + (x && y === false ? \"  <- délégué trompé\" : \"\"));' '}' >> delegue.js"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Lancer le contrôle double

Commande
docker exec -w /home/node/project agent node delegue.js

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Ce qu’affiche le script

LigneCe qu’elle montre
anne demande lire:notesLes deux disent oui. Anne peut lire les notes
anne demande lire:paieLe jeton dit oui, ses droits non : marqué délégué trompé
bruno demande lire:paieLes deux disent oui. Bruno détient ce droit

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Trois corrections qui marchent ensemble

Transmettez le demandeur. Chaque appel porte l’identité de la personne, et l’outil ou l’API la vérifie.

Rétrécissez le jeton. Donnez à une tâche seulement les portées dont elle a besoin et laissez-les expirer vite.

Vérifiez chaque action dans le code. Vérifiez à l’endroit où l’action a lieu, à chaque fois. Ne demandez jamais au modèle s’il en a le droit.

Une erreur fréquente

Attention

Beaucoup écrivent « n’aide les utilisateurs qu’avec leurs propres fichiers » dans le prompt et s’arrêtent là. Un prompt est une demande faite au modèle. Le tableau de droits dans le code est la règle, et il répond pareil à chaque fois.

Écrire le script du modèle, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' '' 'const droits = { anne: [\"lire:notes\"] };' 'const appel = { qui: \"anne\", action: \"lire\", ressource: \"paie\" };' 'const messages = [' '  { role: \"system\", content: \"Tu es un assistant de bureau. L’utilisatrice Anne peut seulement lire les notes. Réponds par un mot, autorise ou refuse, puis une courte raison.\" },' '  { role: \"user\", content: \"Anne te demande de lire le fichier de paie. Que fais-tu ?\" },' '];' '// Échantillon enregistré, utilisé seulement quand aucun modèle ne répond.' 'const echantillon = \"refuse. Anne peut seulement lire les notes.\";' > delegue2.js"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire le script du modèle, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function decider(a) {' '  const permis = droits[a.qui] || [];' '  return permis.includes(a.action + \":\" + a.ressource) ? \"autorise\" : \"refuse\";' '}' '' 'async function main() {' '  const reponse = await demander(messages, echantillon, 60);' '  console.log(\"Le modèle dit : \" + reponse);' '  console.log(\"Le programme décide : \" + decider(appel));' '  console.log(\"L’appel ne part que si le programme dit autorise.\");' '}' 'main();' >> delegue2.js"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire l’assistant du modèle, partie 1

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function demander(messages, echantillon, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"statut \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire l’assistant du modèle, partie 2

Commande
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (erreur) {' '    console.log(\"Échantillon enregistré : aucun modèle n’a répondu (\" + erreur.message + \").\");' '    const liste = [].concat(echantillon);' '    const tour = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return liste[Math.min(tour, liste.length - 1)];' '  }' '}' 'module.exports = { demander };' >> model.js"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Lancer avec le modèle

Commande
docker exec -w /home/node/project agent node delegue2.js

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Une sortie possible

LigneCe qu’elle peut montrer
Le modèle ditUn mot comme refuse avec une courte raison. Les mots changent à chaque exécution
Le programme déciderefuse, à chaque fois, car Anne n’a aucun droit sur la paie dans le tableau
Échantillon enregistréAffiché en premier quand aucun modèle n’a répondu. Le script continue avec l’échantillon

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

À propos de ce labo et de sa source: Lab agent de code IA : utiliser opencode pour expliquer et corriger du code, et vérifier son travail

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.