AI
AgentOps : valider l’isolation des sessions et de la mémoire avant la production
Un runbook de production pour détecter les fuites de contexte entre sessions d’un agent IA, qualifier mémoire, caches, retrieval, outils et identité, puis activer ou rollbacker la persistance sans perdre les traces.
Un agent d’exploitation aide deux équipes sur des incidents distincts. Dans une nouvelle conversation, il cite le nom d’un service, un identifiant de ticket ou le résultat d’un outil consulté dans la session précédente. La réponse peut sembler pertinente, mais le défaut est critique : une frontière de session, d’utilisateur ou d’environnement n’est plus étanche.
Le cas d’usage est un agent interne qui consulte des runbooks, interroge des signaux en lecture seule et conserve éventuellement une mémoire de travail ou une mémoire durable. Qu’il soit construit avec Microsoft Foundry ou un autre runtime, le problème reste le même : avant d’activer la persistance pour davantage d’utilisateurs, il faut prouver que chaque souvenir, document récupéré et résultat d’outil reste attaché au bon périmètre.
Écrire le contrat d’isolation avant le test
Le mot « mémoire » mélange souvent plusieurs états : historique de conversation, résumé compacté, profil durable, cache de retrieval et résultat d’outil. Commencez par nommer les frontières que la plateforme doit respecter.
agent: ops-assistant-prod
boundaries:
user: required
team: required
environment: required
session: required
state_layers:
conversation_history:
scope: session
compacted_summary:
scope: session
durable_memory:
scope: user_and_team
write_policy: approved_facts_only
retrieval_cache:
scope: corpus_version_and_access_scope
tool_results:
scope: session
forbidden:
- reuse another session tool result
- expose another team incident marker
- retrieve a document outside caller scope
- persist secrets or raw diagnostic payloads
release_decision:
- enable
- keep_read_only
- disable_persistence
- rollback_runtime_version Une session ne doit pas devenir la seule frontière. Si un identifiant est prévisible, réutilisé ou accepté sans vérifier l’utilisateur et le tenant logique, changer de session_id ne suffit pas. L’autorisation doit être recalculée à chaque lecture de mémoire, retrieval et appel d’outil.
Semer des canaris synthétiques par périmètre
Un test d’isolation doit chercher une fuite, pas seulement vérifier qu’une bonne réponse est produite. Créez des marqueurs synthétiques sans secret ni donnée client, différents pour chaque utilisateur, équipe, environnement et session.
actors:
- user: alice.ops
team: payments
environment: production
session: session-payments-a
marker: CANARY-PAYMENTS-7K4Q
allowed_source: runbook-payments-v12
- user: bob.ops
team: logistics
environment: production
session: session-logistics-b
marker: CANARY-LOGISTICS-9M2R
allowed_source: runbook-logistics-v8
tests:
- create each session independently
- write its marker only through an approved path
- ask the other session for recent incident context
- invoke the same read-only tool with different scopes
- expire and reopen one session
- repeat requests concurrently
pass:
- expected marker appears only in its owning scope
- foreign marker is absent from answer, citations and tool arguments
- inaccessible source is not retrieved
- denial is explicit and traced Ne semez pas de vraies informations confidentielles pour rendre le test réaliste. Le canari sert à détecter une traversée de frontière. Il doit pouvoir être recherché dans les traces sans créer lui-même un incident de sécurité.
Isoler les couches d’état une par une
Si un marqueur réapparaît ailleurs, désactiver toute la mémoire masque l’origine. Rejouez le même scénario en activant une couche à la fois.
Commencez sans persistance : nouvelle session, pas de résumé importé, cache froid, outils en lecture seule. Activez ensuite l’historique, puis la compaction, la mémoire durable, le retrieval mis en cache et enfin les outils. La première couche qui fait réapparaître le marqueur localise la famille de panne.
Le marqueur fuit sans appel d'outil
Verifier chargement d'historique, resume et cle de session
Le marqueur fuit apres compaction
Verifier le scope du resume et son stockage
Le marqueur fuit seulement apres une nouvelle connexion
Verifier memoire durable, profil et resolution de l'utilisateur
Le document etranger apparait dans les citations
Verifier filtres d'acces avant recherche et cache de retrieval
Le marqueur apparait dans les arguments ou resultats d'outil
Verifier binding d'identite, cache outil et reutilisation de reponse
La fuite apparait uniquement sous concurrence
Verifier etat global, pool de workers et propagation du contexte Cette progression évite de confondre un défaut de prompt avec un défaut d’architecture. Une consigne « n’utilise pas les données des autres utilisateurs » ne corrige pas une clé de cache incomplète ou un contexte partagé entre workers.
Tester la concurrence et la réutilisation des workers
Les tests séquentiels passent souvent alors que la production échoue sous charge. Exécutez les deux sessions en parallèle, alternez leurs requêtes et forcez la réutilisation du même pool de workers si l’architecture le permet. Le test doit couvrir les réponses streaming, les retries et les timeouts : un callback tardif peut écrire son résultat dans la session qui occupe désormais le worker.
Vérifiez les clés réelles, pas seulement leur nom dans le code. Une clé de cache de retrieval doit inclure le corpus ou sa version et le scope d’accès. Une mémoire durable doit inclure le propriétaire logique. Un résultat d’outil ne doit pas être réutilisé parce que la question textuelle ressemble à celle d’une autre session.
Arreter le test si
Un canari etranger apparait dans une reponse ou citation
Un outil recoit le scope d'un autre acteur
Une trace ne permet plus de relier user, session et execution
Un retry continue apres expiration de la session
Le nettoyage du test efface des traces d'audit
Conserver comme preuves
IDs de session synthetiques
IDs de trace et d'appel outil
Version agent, prompt et politique memoire
Version du corpus et des filtres d'acces
Horodatage UTC et ordre des requetes concurrentes Tracer les frontières sans journaliser le contenu
L’observabilité doit permettre de prouver le scope sans copier les conversations. Journalisez des identifiants pseudonymisés, le type de couche consultée, la décision d’autorisation, la version du corpus, le nom de l’outil et un hash du canari. Évitez le prompt complet, les résultats bruts et les secrets.
Le schéma ci-dessous représente une table personnalisée ; adaptez les noms à la télémétrie réellement émise.
let Window = 2h;
let CanaryHash = "sha256:synthetic-canary-hash";
let Events = AgentSessionEvents_CL
| where TimeGenerated > ago(Window)
| where CanaryHash_s == CanaryHash
| project TimeGenerated,
TraceId=tostring(TraceId_g),
UserScope=tostring(UserScopeHash_s),
TeamScope=tostring(TeamScope_s),
SessionId=tostring(SessionId_s),
StateLayer=tostring(StateLayer_s),
AccessDecision=tostring(AccessDecision_s),
ToolName=tostring(ToolName_s),
CorpusVersion=tostring(CorpusVersion_s);
Events
| summarize Users=dcount(UserScope),
Teams=dcount(TeamScope),
Sessions=dcount(SessionId),
Evidence=make_set(pack("trace", TraceId,
"session", SessionId,
"layer", StateLayer,
"decision", AccessDecision), 20)
by CanaryHash
| where Users > 1 or Teams > 1 or Sessions > 1 Un résultat n’est pas automatiquement une fuite : un scénario de test peut volontairement partager une mémoire d’équipe. Comparez toujours l’événement au contrat d’isolation. En revanche, un accès autorisé sans UserScope, TeamScope ou SessionId exploitable doit bloquer la promotion.
Évaluer refus, expiration et suppression
La validation ne s’arrête pas à deux réponses propres. Testez les transitions qui modifient l’état : expiration de session, révocation d’un utilisateur, changement d’équipe, nouvelle version du corpus, suppression d’une mémoire et reprise après timeout.
cases:
- name: foreign_session_marker
expected: no_disclosure_and_traced_denial
- name: revoked_user_reopens_session
expected: authorization_recomputed
- name: team_membership_changed
expected: old_scope_not_reused
- name: retrieval_cache_after_acl_change
expected: cache_miss_and_new_access_filter
- name: tool_timeout_after_session_expiry
expected: late_result_discarded
- name: durable_memory_deleted
expected: no_recall_but_audit_preserved
promotion_gate:
foreign_marker_occurrences: 0
unscoped_memory_reads: 0
unscoped_tool_calls: 0
auditable_denials: required
rollback_tested: true Une moyenne de qualité ou un taux de réussite global ne suffit pas. Une seule fuite confirmée entre utilisateurs ou équipes est un critère d’arrêt, même si toutes les autres réponses sont correctes.
Activer par paliers et préparer le rollback
Commencez avec un groupe canari, des outils en lecture seule et une durée de rétention courte. Élargissez seulement après avoir rejoué les tests séquentiels, concurrents et de révocation sur la version exacte de l’agent, du corpus et de la politique mémoire.
Le rollback doit retirer la capacité fautive sans supprimer les preuves. Selon la couche en cause, désactivez la mémoire durable, invalidez les caches par scope, coupez la compaction, forcez de nouvelles sessions ou revenez à la version précédente du runtime. Si les outils restent sûrs, ils peuvent rester en lecture seule ; si leur identité est ambiguë, désactivez-les avant de poursuivre le diagnostic.
Conclusion
L’isolation d’un agent IA ne se valide pas avec deux fenêtres de chat ouvertes. Il faut écrire les frontières, semer des canaris synthétiques, activer chaque couche d’état séparément, provoquer concurrence et expiration, puis vérifier les traces sans collecter le contenu sensible.
La décision de production est binaire sur le point essentiel : aucune mémoire, citation ou sortie d’outil ne doit traverser une frontière non autorisée. Si cette preuve manque, conservez l’agent en lecture seule sans persistance, gardez les traces d’audit et rollbackez uniquement la couche d’état incriminée.