e-naxosMAF COURSE / COURS
English

MICROSOFT AGENT FRAMEWORK · 0.16.0-rc.1

Historique et persistance de session

Séparer contexte SQLite, historique en mémoire et session MAF sérialisée.

Objectifs

Que doit retrouver une nouvelle exécution ?

Une demande de support porte sur Reporting. Fermer la console puis la rouvrir permet de poser une question précise : le programme retrouve-t-il le contexte produit, les anciens messages ou seulement ses instructions ? J2 introduisait ces mécanismes ensemble. Les programmes actuels les séparent pour que chaque promesse de reprise ait un support identifiable.

Cinq états à ne pas confondre
ÉtatDurée et responsabilité
HistoriqueMessages conservés par la session active ; disparaissent avec le processus sans sauvegarde.
Session nativeConteneur MAF sérialisé par Demo140 dans session/session.json.
Contexte métierValeur explicite AgentState en SQLite dans context/state.db pour Demo130.
Faits partagésWorkingMemory de Demo150/160, en processus avec provenance.
Contexte injectéVue fabriquée pour un appel ; ne garantit aucune persistance.

Un contexte durable ciblé

Demo130 initialise AgentState sans supprimer les lignes. setctx TEXT remplace la valeur context puis crée une session vide. showctx relit SQLite. Chaque question reçoit la valeur courante comme donnée utilisateur non vérifiée. Le dialogue précédent reste dans la session du processus, sans être enregistré en base. Après redémarrage, le contexte subsiste et le dialogue repart à zéro.

public void Set(string value)
{
    ArgumentException.ThrowIfNullOrWhiteSpace(value);
    if (value.Length > 4096)
        throw new ArgumentException("Context must not exceed 4096 characters.");
    Execute("INSERT INTO AgentState(Key, Value) VALUES ('context', $value) ON CONFLICT(Key) DO UPDATE SET Value=excluded.Value;", value);
}

/// <summary>Clears rows transactionally without deleting pooled SQLite files.</summary>
public void Reset() => Execute("DELETE FROM AgentState;");

shared/Maf.Memory/StateStorage.cs · L49–L58 · 9a895c94534c

Code source · Maf.Memory · Dossier

Sauver et restaurer la session native

Demo140 appelle SerializeSessionAsync et DeserializeSessionAsync. Une enveloppe associe version de format 1 et version d’instructions memory-1.1 au snapshot. Le chargement est automatique au démarrage ; chaque réponse réussie est suivie d’une sauvegarde. save et load permettent une manipulation explicite. Le fichier temporaire voisin est renommé après écriture ; ce mécanisme ne transforme pas une conversation en transaction métier ou checkpoint de workflow.

public async Task<AgentSession> LoadOrCreateAsync(AIAgent agent, CancellationToken cancellationToken = default)
{
    if (!File.Exists(path))
        return await agent.CreateSessionAsync(cancellationToken);
    var envelope = JsonSerializer.Deserialize<Envelope>(await File.ReadAllTextAsync(path, cancellationToken))
        ?? throw new InvalidDataException("Empty session envelope.");
    if (envelope.Version != 1 || envelope.InstructionVersion != instructionVersion)
        throw new InvalidDataException("Session version or instruction version mismatch. Reset explicitly.");
    return await agent.DeserializeSessionAsync(envelope.Session, cancellationToken: cancellationToken);

shared/Maf.Memory/StateStorage.cs · L79–L87 · 9a895c94534c

Code source · Maf.Memory · Dossier

Un JSON corrompu ou une version incompatible provoque une erreur visible. Ne pas ignorer cette erreur pour démarrer silencieusement une conversation neuve. Examiner la cause ; --reset-state=true est une destruction volontaire du snapshot de cette démo, à réserver à un état de travail choisi.

Reprise, remplacement et isolation

Cycle de Demo140 ; chaque étape est aussi décrite ci-dessous
  1. Démarrage → charger le snapshot ou créer une session si absent
  2. Réponse réussie → sérialiser → remplacer le snapshot
  3. forget → supprimer le snapshot + remplacer la session active
  4. Redémarrage → une session vide si aucun nouveau snapshot

Dans Demo140, newsession, reset, deletesession et forget suppriment tous le snapshot et remplacent l’historique actif. L’ancien scénario J2 « newsession puis load pour retrouver la sauvegarde » ne correspond plus au contrat actuel. Utiliser deux racines MAF_STATE_ROOT absolues distinctes pour isoler deux essais. Deux processus dans la même racine ne sont pas une isolation multi-utilisateur et peuvent se concurrencer.

Vérifier avant et après redémarrage

$env:MAF_STATE_ROOT = Join-Path $env:TEMP ('maf-memory-' + [guid]::NewGuid().ToString('N'))

Garder cette variable dans le même terminal pendant les relances. Avec Demo130 : setctx module=Reporting, showctx, quit ; relancer et exécuter showctx. Puis reset, quit, relancer et showctx : la valeur doit être vide. Avec Demo140, dans cette racine de travail : envoyer module=Reporting, attendre une réponse réussie, quit, relancer et demander Which module did we discuss? Inspecter aussi le snapshot. Ensuite forget, quit, relancer et load : le snapshot absent ne peut restaurer l’ancien échange.

dotnet test tests/Maf.Memory.Tests/Maf.Memory.Tests.csproj -m:1 -c Release --no-build --no-restore

Portée de l’oubli

Effacer l’historique ne supprime pas AgentState, un autre store, un journal, une sauvegarde ni les données éventuellement conservées par un fournisseur. DELETE de lignes SQLite ne prouve pas un effacement sécurisé des pages sur disque. Ces exemples sont locaux, séquentiels, sans chiffrement ni contrôle d’accès multiprocessus. Les manipulations avec réponses sont des essais guidés à exécuter avec un chat qualifié ; les tests déterministes vérifient séparément SQLite et la sérialisation avec un client scripté.

Passer aux faits partagés

Prérequis

Pour poursuivre

Précédent

Suivant

lot008-memory-rag-1 · 2026-10-24 · 9a895c94534cd5fc6f3da883e37e5f7856e588c1