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.

31 août 2026 aiagentopsagentsmemorysession-isolationsecurityevaluationobservabilityguardrailsrunbookrollbackproduction

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.

yaml agent-session-isolation-contract.yml
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.

yaml session-isolation-canaries.yml
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.

text state-layer-diagnostic.txt
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.

text concurrency-stop-conditions.txt
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.

kusto find-cross-session-canary.kql
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.

yaml session-isolation-evaluation.yml
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.