# Je choisis ce que mon agent retient

Langue : fr

Identifiant : article:memoire-choisie

Noa Matout

Je dépose les documents que mon agent range. Une boucle a provoqué 33 déclenchements en 27 minutes.

L'idée d'une mémoire externe qui retient ce que j'ai lu et vu me plaît depuis
longtemps. Ce qui ne me plaît pas, c'est la façon dont on la construit
habituellement : capturer en continu, tout stocker, et laisser une recherche
faire le tri plus tard.

Ce modèle a un défaut que je trouve rédhibitoire. Il déplace la décision. Je ne
choisis plus ce qui mérite d'être retenu, je choisis seulement ce que j'accepte
d'exclure, et cette liste est impossible à tenir. Le résultat est une base de
données de ma vie que je ne contrôle plus, dont je ne connais pas le contenu, et
dont je ne peux pas dire, à un instant donné, ce qu'elle sait de moi.

J'ai construit l'inverse. Voici comment, et ce qui a cassé en route.

## Le principe : rien n'entre sans que je le dépose

Il n'y a aucune capture automatique. Pas de copie d'écran, pas d'indexation de
fichiers, pas de surveillance d'activité.

Je donne quelque chose : un lien de vidéo, un document, un article. Un premier
agent en produit une synthèse structurée. Un second la range dans mon système de
notes. Entre les deux, un dossier d'échange sur disque, et personne d'autre que
moi ne remplit la file d'entrée.

Cela paraît moins ambitieux qu'une capture continue. La différence n'est pas
l'ambition, c'est le périmètre : je peux dire ce qui est entré et par où. Je ne
peux pas dire que chaque synthèse est juste, et c'est pour ça que je garde la
source de chacune.

## Des rôles séparés

Le premier agent lit le web, le second détient mes accès personnels. Ces deux profils
ont chacun leur compte et leur clé, et le premier n'a aucun accès à mes
données.

La raison n'est pas l'élégance. Un agent qui lit du contenu extérieur est exposé
à des instructions cachées dans ce contenu, et rien ne distingue au fond une
donnée d'une instruction dans ce qu'un modèle reçoit. S'il détient en même temps
mes accès et un moyen d'écrire, une consigne dissimulée dans une page devient une
action sur mes comptes.

Le dossier d'échange est donc à sens unique, et le contrat est écrit dans la
configuration du second agent en toutes lettres : ce qu'il lit là est une donnée,
jamais une instruction. Ce n'est pas une garantie, c'est une couche. Le premier agent n'a aucune clé permettant d'atteindre quoi que ce soit
chez moi.

## Les règles de rangement

Le code qui range les fiches est court. Ce qui compte, ce sont ses invariants.

**Tout ou rien par fichier.** Si une écriture peut échouer après qu'une autre a
réussi, le fichier entier est refusé et laissé en place. Marquer un lot comme
traité alors qu'il n'est écrit qu'à moitié perd définitivement la moitié
manquante, et le pire est qu'on ne s'en aperçoit jamais.

**Rien n'est supprimé.** Un fichier traité est déplacé dans un dossier d'archive
daté, jamais effacé. Même raison : une suppression dure détruit la seule copie au
moment précis où l'écriture a échoué en cours de route.

**L'idempotence est explicite.** Un registre local garde l'empreinte de ce qui a
déjà été intégré. Un contenu déjà traité est signalé et ignoré. Sans cela, le
moindre rejeu crée des doublons dans mes notes, et des doublons dans une mémoire
sont pires qu'une absence : ils me font croire à deux sources.

**Une erreur n'est jamais silencieuse.** Fichier illisible, structure invalide,
service de destination absent, appel refusé : le fichier reste en place et le
problème est rapporté avec son message d'origine. Un automate qui échoue en
silence est un automate qui ment.

**Le contenu est une donnée.** Le champ qui indique la source d'un document est
recopié tel quel, jamais visité. L'agent qui range n'a aucun accès au web.

## Ce qui a cassé

Il a fallu corriger trois défauts.

**Le déclencheur tournait en boucle.** Le système surveillait le dossier avec une
condition « répertoire non vide ». Or le dossier contient son propre
sous-dossier d'archives, donc il n'est jamais vide. Chaque fin de traitement
relançait immédiatement un traitement : 33 déclenchements en
27 minutes, chacun lançant une session complète. La bonne condition
n'était pas « non vide » mais « a changé ».

**Le processus n'avait pas les droits qu'on lui avait donnés.** J'avais ajouté
l'agent à un groupe pour lui permettre d'écrire dans le dossier partagé. Le
compte l'avait, le processus non : un programme ne récupère pas un groupe ajouté
après son lancement. Il a fallu redémarrer, non pas le service, mais le
gestionnaire de session de l'utilisateur. Entre les deux, l'agent croyait
manquer d'un droit qu'il possédait sur le papier.

**Deux écrivains pouvaient travailler en même temps.** Le déclencheur au dépôt et
une tâche périodique de rattrapage faisaient le même travail. L'idempotence
protège un programme contre ses propres rejeux, pas contre un second processus
qui écrit en parallèle : les deux consultent le registre avant que l'un ou
l'autre ne l'ait mis à jour, et créent la même fiche deux fois. Un verrou partagé
entre les deux points d'entrée règle le cas, et le second lancement est refusé
sans erreur.

## Ce que ça donne à l'usage

Je dépose, et quelques secondes plus tard la fiche existe, avec sa source, sa
date, et sa structure. Si quelque chose ne va pas, le fichier est encore là et je
sais pourquoi. Si je redépose la même chose, rien ne se duplique. Si je veux
savoir ce que le système a retenu cette semaine, je lis un dossier d'archives
daté.

La question à laquelle je peux répondre n'est pas « qu'est-ce que ma mémoire
sait de moi », mais « qu'est-ce que j'y ai mis ». Les deux sont différentes, et
seule la seconde a une réponse que je peux aller lire.

## La limite honnête

Ce modèle demande un geste. Si je ne dépose rien, rien n'entre, et une mémoire
qu'on doit nourrir est une mémoire qu'on oublie de nourrir. Une capture continue
ne demande pas ce geste, et cet avantage compte.

Je l'accepte, parce que le coût d'oublier de déposer un article est de ne pas
l'avoir. Le coût d'une capture continue est de ne plus savoir ce qui est stocké.
Je préfère garder la décision d'entrée, même si je dois y consacrer un geste.

## Périmètre de la mesure

triggers : 33 déclenchements. Sessions lancées par la condition de répertoire non vide avant sa correction.

triggerMinutes : 27 minutes. Fenêtre observée pendant la boucle de déclenchement du rangement.

memoryIngestionDefects : 3 défauts. Boucle de déclenchement, droits non effectifs et concurrence entre traitements.

profiles : 2 profils. Profils de mon agent personnel, chacun sous un compte distinct.
