VALORA
Pitch Tech · 2026 · 33 min

Apprendre aux machines
à se souvenir

Une mémoire persistante inspirée de la biologie
pour l'orchestration d'agents IA

Épisodique · Sémantique · Décisions Coffre-fort Obsidian · Zéro dépendance native Ebbinghaus · Règle de Hebb · Activation par diffusion

01 — Le problème d'amnésie

11 agents. Chaque session
repart de zéro.

Valora orchestre 11 agents IA spécialisés à travers des pipelines multi-étapes. Chacun est capable. Mais dès qu'une session se termine, tout ce qui a été appris disparaît.

Erreurs répétées

Un agent signale le même anti-pattern au sprint 1, au sprint 5, au sprint 12. À chaque fois, une découverte fraîche.

Motifs redécouverts

Des conventions émergent dans la base de code. Les agents les reconstituent à chaque exécution au lieu de capitaliser sur les connaissances accumulées.

Décisions perdues

L'équipe choisit une direction architecturale. Les agents proposent des alternatives déjà rejetées. Le répertoire knowledge-base/ était vide.

11Agents
0Mémoires persistantes
Découvertes répétées

02 — Inspiration neuroscientifique

"
Sans répétition mentale, les connexions nouvellement formées dans le cerveau sont soumises à un processus d'oubli qui, suivant une courbe régulière, est le plus rapide immédiatement après l'apprentissage.
Hermann Ebbinghaus — Über das Gedächtnis, 1885
La courbe de l'oubli Vieux de 141 ans · toujours la spécification

02 — Courbe de l'oubli

Trois stockages.
Trois échelles de temps.

Chaque catégorie de mémoire a une demi-vie calibrée à sa nature. Les observations s'estompent vite. Les motifs persistent. Les décisions survivent aux deux.

episodic/7j
decisions/21j
semantic/30j

strength = 0.5^(elapsed / halfLife)

Courbe de l'oubli d'Ebbinghaus 1.0 0.5 0.0 0 7j 14j 21j 28j 30j ½ ½ @ 7j ½ @ 21j ½ @ 30j

Neurosciences

Le modèle biologique

Courbe de l'oubli d'Ebbinghaus

La force mémorielle décroît exponentiellement sans renforcement.

Répétition espacée

Récupérer un souvenir le renforce, repoussant la courbe de déclin vers le futur.

Amplification des erreurs (amygdale)

Les erreurs sont marquées d'une durabilité accrue. Nous nous souvenons des gênes plus longtemps que des anecdotes.

Consolidation hippocampique

Les souvenirs épisodiques se condensent en connaissances sémantiques durant les périodes d'activité réduite (le sommeil).

v1 — Équivalent Valora

Le modèle agent v1

strength = 0.5^(t / halfLife)

La spécification prise directement d'Ebbinghaus. Mathématiques pures, zéro abstraction.

halfLife += accessCount × 2d

Chaque récupération ajoute 2 jours à la demi-vie effective. Les motifs fréquemment interrogés persistent.

isError → halfLife × 2

Les entrées d'erreur reçoivent le double de la demi-vie de base. Les leçons difficiles survivent aux observations routinières.

valora consolidate

La fusion par similarité de Jaccard élève les observations en motifs sémantiques durables.

03 — Architecture v1

Trois stockages. Un modèle cohérent.

Toute la mémoire réside dans .valora/memory/ — ignoré par git par défaut, par projet, aucune infrastructure requise.

episodic.json7 jours
7j
Demi-vie par défaut
Observations horodatées brutes écrites durant l'exécution du pipeline. Se dégrade rapidement — bruitées, spécifiques au contexte, éphémères par conception.
"no-console lint rule triggered in src/cli/index.ts — suppressed with eslint-disable"
decisions.json21 jours
21j
Demi-vie par défaut
Choix architecturaux avec justification. Taux de déclin intermédiaire — les décisions vieillissent, mais le raisonnement qui les sous-tend compte plus longtemps que les observations.
"Auth middleware rewritten for compliance, not tech debt — session tokens stored differently"
semantic.json30 jours
30j
Demi-vie par défaut
Motifs distillés et réutilisables, consolidés à partir de plusieurs observations épisodiques. Connaissances validées. Survivent le plus longtemps.
"Integration tests always use Testcontainers; mock-based integration tests are forbidden"
Zéro nouvelle dépendance d'exécution TypeScript pur · E/S de fichiers uniquement Similarité Jaccard uniquement · listes plates isolées

03 — Le moteur de déclin

Une seule formule régit toute la mémoire.

strength = 0.5 ^ ( elapsed / halfLife )
À t=0, la force est 1,0.
Après une demi-vie, 0,5.
Asymptotique — pas de falaises d'expiration abruptes.
decay.ts · inchangé en v2
export function computeStrength(referenceAt: string, halfLifeDays: number, now = Date.now()): number {
  const elapsedDays = (now - new Date(referenceAt).getTime()) / MS_PER_DAY;
  return Math.pow(0.5, elapsedDays / halfLifeDays);  // injectable pour tests déterministes
}

export function computeEffectiveHalfLife(
  base: number, accessCount: number, isError: boolean,
  retrievalBoostDays = 2, errorMultiplier = 2
): number {
  const b = isError ? base * errorMultiplier : base;   // effet amygdale
  return b + accessCount * retrievalBoostDays;          // répétition espacée
}
Multiplicateur d'erreur
+2j
Par récupération
0.05
Seuil d'élagage
pure fn
Aucun effet de bord

03 — Entrée mémoire

Les niveaux de confiance
déterminent l'ordre d'injection.

Chaque entrée porte un niveau de confiance. Les agents pondèrent les mémoires en conséquence : les niveaux supérieurs l'emportent sur les niveaux inférieurs en cas de conflit.

memory.types.ts · préservé en v2
type ConfidenceTier =
  | 'verified'   // ← confiance maximale
  | 'observed'
  | 'inferred'
  | 'stale';    // ← jamais injectée

// Injection : verified → observed → inferred
// Les entrées périmées sont toujours exclues.
Vérifié
Vérité confirmée
Plusieurs agents ou exécutions ont validé cette observation. Priorité maximale dans l'injection de prompt — le plus respecté.
→ Injecté en premier
Observé
Fait de source unique
Enregistré une fois par un agent. Suffisamment fiable pour être affiché, mais pas encore corroboré. Deuxième priorité.
→ Injecté en deuxième
Inféré
Motif dérivé
Généré par la consolidation par regroupement cosinus. Un motif potentiel, non encore confirmé. Troisième priorité.
→ Injecté en dernier
Périmé
Invalidé par Git
Déclassé lorsque les relatedPaths intersectent des fichiers modifiés depuis la dernière consolidation. Les décisions annulées deviennent automatiquement périmées.
→ Jamais injecté

04 — Où v1 a échoué

Trois lacunes que le modèle plat ne pouvait pas combler.

v1 a fidèlement traduit Ebbinghaus. Mais la biologie n'est pas un classeur — le cerveau est un réseau, et le réseau est la mémoire.

#

Jaccard est trop grossier

Les synonymes ne se correspondent jamais. Les antonymes peuvent correspondre. Le choix des tags est arbitraire — deux mémoires sur le même concept avec des labels différents ne se consolideront jamais. L'ADR-011 reconnaissait explicitement cette faiblesse.

∩(tags) / ∪(tags) ≥ 0.6

Les mémoires sont des îlots isolés

Aucun lien entre les entrées connexes. « Refonte du middleware auth » (decisions.json) et « format du token de session » (episodic.json) vivent dans des tableaux JSON séparés sans pointeur entre eux. Toute connexion existait uniquement dans la tête d'un développeur.

episodic.json ⟵╌╌ decisions.json

Aucun index hippocampique

Chaque rappel chargeait l'intégralité du seau, calculait la force de chaque entrée et triait. O(n) par requête, sans moyen structurel de passer les catégories non pertinentes. Le cerveau ne scanne pas tout son cortex pour se souvenir du petit-déjeuner.

query → sort(all entries) → top-k
Limites de v1 → motivation de v2 ADR-011 les reconnaissait toutes les trois

05 — L'intuition du graphe

Les neurones qui s'activent
ensemble se connectent ensemble.

La règle de Donald Hebb (1949) décrit comment la force synaptique croît avec la co-activation — le même mécanisme que la potentialisation à long terme dans l'hippocampe.

Co-accès hebbien

Chaque paire co-récupérée incrémente co_access[otherId] dans le frontmatter. Les mémoires fréquemment associées développent des liens forts.

Activation par diffusion

Une requête active des graines cosinus-similaires. L'activation se propage ensuite sur les arêtes related et co_accessed, décroissant de γ=0,6 par saut.

Consolidation synaptique

Le regroupement cosinus (≥0,82) promeut les clusters épisodiques en mémoires sémantiques — le transfert cortical du sommeil biologique.

Graphe de rappel REQUÊTE embed() k=1 ANN k=2 ANN k=3 ANN cosinus [[related]] γ = 0,6 k=12 graines profondeur 2 ANN cosinus (k=12) Activation par diffusion BFS
Plasticité hebbienne Activation par diffusion Consolidation synaptique

06 — Architecture v2

Un fichier Markdown par mémoire. Un coffre-fort, pas une base de données.

Chaque mémoire est un fichier .md avec frontmatter YAML et des liens wiki [[id|kind]]. Le coffre-fort s'ouvre dans Obsidian — aucun outil supplémentaire requis.

arborescence du coffre-fort
.valora/memory/
├── version
├── meta.json
├── embeddings.bin          ← Float32Array
├── embeddings.index.json   ← id → offset
├── episodic/
│   └── mem-abc123def456.md
├── semantic/
│   └── mem-xyz789pqr012.md
├── decisions/
│   └── mem-def456ghi789.md
└── .obsidian/               ← compat. Obsidian
mem-abc123def456.md
---
id: mem-abc123def456
category: episodic
created_at: "2026-04-28T10:23:00Z"
last_accessed_at: "2026-04-30T09:10:00Z"
agent_role: code-reviewer
confidence: observed
tags: ["typescript", "testing"]
half_life_days: 7
access_count: 3
is_error: false
co_access: {"mem-xyz789pqr012": 2}
---

Found a flaky test in the auth suite — timeout
too short for the CI environment.

[[mem-xyz789pqr012|related]]
Un fichier Markdown par mémoire lié par [[id|kind]] ouvert dans Obsidian écriture atomique · tmp → rename

06 — Rappel

Cinq étapes de la requête aux mémoires classées.

Le pipeline de rappel remplace les scans de seau par un parcours de graphe amorcé par les embeddings — puis renforce les paires co-récupérées.

ÉTAPE 1
Encoder
embed(query) via LLMProvider. Ollama avec nomic-embed-text. Retour lexical gracieux si aucun embedder configuré — aucun changement de chemin d'exécution.
EmbedderPort.embed()
ÉTAPE 2
Graines ANN
Recherche cosinus kNN sur embeddings.bin (Float32Array). Top k=12 sélectionnés comme points de départ de l'activation.
k = 12 · cosinus
ÉTAPE 3
Diffusion BFS
BFS bidirectionnel sur les arêtes related et co_accessed jusqu'à profondeur 2. L'activation décroît de γ=0,6 par saut multiplié par le poids de l'arête.
profondeur 2 · γ = 0,6
ÉTAPE 4
Score
Score final : activation × decayStrength × confidenceWeight. Pondérations : vérifié=1,0 · observé=0,7 · inféré=0,4 · périmé=0,1.
activation × decay × conf
ÉTAPE 5
Hebbien
Renforcer chaque entrée récupérée (accessCount++ · bonus demi-vie). Incrémenter co_access[otherId] dans le frontmatter pour chaque paire co-récupérée — la mise à jour du poids synaptique.
co_access[id]++
Zéro nouvelle dépendance d'exécution retour lexical sans embedder ADR-013 §5

07 — Consolidation synaptique

Cinq étapes nocturnes. Le cosinus remplace Jaccard.

valora consolidate — le transfert hippocampique du sommeil biologique. Les observations épisodiques se regroupent en motifs sémantiques durables.

ÉTAPE 1
Élaguer
Supprimer les entrées dont la force de déclin est inférieure à 0,05. La mémoire non renforcée s'efface d'elle-même — aucune maintenance manuelle.
strength < 0.05 → delete
ÉTAPE 2
Invalider Git
Les entrées dont related_paths intersectent des fichiers modifiés depuis la dernière consolidation sont déclassées en stale. Le code bouge ; les mémoires doivent suivre.
relatedPaths ∩ changed → stale
ÉTAPE 3
Regroupement cosinus
Encoder toutes les entrées épisodiques et former des clusters où cosinus(a,b) ≥ 0,82. Remplace la fusion Jaccard — Jaccard reste disponible hors ligne sans embedder.
cosinus ≥ 0,82
ÉTAPE 4
Promouvoir
Le centroïde du cluster devient un nouveau fichier semantic/*.md avec confidence inferred. Chaque membre reçoit un lien wiki [[centroïdeId|decays_from]].
semantic/*.md + [[|decays_from]]
ÉTAPE 5
Renforcer
Les entrées épisodiques survivantes qui ont contribué à un cluster voient leur accessCount incrémenté et leur demi-vie prolongée.
accessCount++ · bonus demi-vie
valora consolidate regroupement cosinus remplace Jaccard Jaccard retenu en repli hors ligne

08 — Injection de contexte

Les mémoires atteignent
l'agent via le prompt système.

Chaque invocation de pipeline prépend le bloc MÉMOIRE AGENT — construit par le rappel du coffre-fort, limité à 2 000 tokens, ordonné par niveau de confiance.

01
Graines sélectionnées par activation par diffusion depuis le coffre-fort
nouveau en v2
02
Trier : vérifié → observé → inféré (périmé exclu)
03
Appliquer le budget de 2 000 tokens
04
Prépendre le bloc MÉMOIRE AGENT au message système
buildSystemMessage()
05
Entrées périmées jamais exposées — silencieusement exclues
Bloc AGENT MEMORY · prompt système
AGENT MEMORY  ·  vault recall  ·  2 000 tok budget
──────────────────────────────────────────────────
[VERIFIED · 0.97] Integration tests must use
Testcontainers; mock-based integration tests
are forbidden. (recalled 8×)

[OBSERVED · 0.72] Auth middleware rewritten for
compliance, not tech debt — session tokens
stored differently. (recalled 3×)

[INFERRED · 0.51] Pattern: no-console lint
suppression is consistently followed by an
eslint-disable comment explanation. (cluster)

09 — Décisions de conception

Ce qu'on a gardé. Ce qu'on a rejeté.

Conservé de v1

Déclin
Déclin exponentiel — inchangé ; fonction pure sans état.
Erreurs
Amplification des erreurs (2×) — effet amygdale préservé.
Espacement
Répétition espacée (+2j par accès) — inchangée.
Niveaux
Niveaux de confiance (vérifié / observé / inféré / périmé) — inchangés.
E/S
Écriture atomique (tmp → rename). Ignoré Git. Zéro dépendance.

Rejeté pour v2

Kuzu
Binding natif C++ ; binaire opaque ; contraire à l'objectif zéro-dep.
sqlite-vec
Extension SQLite ; contredit ADR-009 (pas de SQLite dans Valora).
sql.js WASM
Surcharge WASM inutile quand BFS sur fichiers plats suffit.
graph.json
Fichier monolithique unique ; non compatible Obsidian ; conflits de fusion.
API externe
API d'embedding externe ; contredit ADR-005 (fournisseur LLM local).
TypeScript pur coffre-fort Markdown par mémoire Hebbien + activation par diffusion ADR-005 · ADR-009 · ADR-013

10 — Résultats

Livrer le coffre-fort. Ajouter le graphe. Le reste, c'est de la biologie.

valora consolidate
$ valora consolidate Élagage des entrées sous 0,05... élagué 3 entrées périmées Invalidation Git des chemins modifiés... déclassé 2 → stale Encodage des entrées épisodiques... encodé 47 / 47 Regroupement cosinus (seuil 0,82)... fusionné 4 clusters épisodiques → 4 sémantiques Renforcement des survivants... renforcé 43 entrées épisodiques consolidation terminée en 1,8s

Feuille de route

Fusion basée sur les embeddings

Livré en v2 — ANN cosinus + activation par diffusion.

Découverte de motifs

Analyse des clusters pour faire émerger les conventions implicites — les agents découvrent des règles jamais explicitement enregistrées.

valora memory reembed

Migrer les embeddings lors d'un changement de modèle sans toucher au contenu des mémoires.

Export Kuzu

Export analytique en lecture seule pour les requêtes et visualisations de graphe. Le coffre-fort reste l'autorité d'écriture.

16Diapositives
33Minutes
v2Coffre-fort · livré