Le Graphe de Connaissances

GraphMemoryService est une forme de mémoire différente : au lieu d'une pile d'entrées de texte, il stocke un graphe de connaissances de l'utilisateur — entités, faits ("observations") qui leur sont attachés, et relations typées entre eux — et il suit tout cela bi-temporellement. C'est le backend qui se trouve derrière l'exemple Mindfulness-with-Mia et la page de mémoire en temps réel.

Il implémente le même trait MemoryService que les autres backends, de sorte qu'il s'intègre à un agent de la même manière — mais il expose une API de graphe plus riche en plus.

Le modèle de données

   Entity "Alice"  (type: person)
     ├─ observation: "prefers email over phone"   valid_from 2026-06-01
     ├─ observation: "timezone is CET"            valid_from 2026-06-10
     └─ relation:    Alice ──works_at──▶ "Acme"
  • Entity — une chose nommée (une personne, un lieu, une préférence, un sujet) avec une entity_type de forme libre.
  • Observation — un fait attaché à une entité, avec un id stable et un horodatage valid_from.
  • Relation — une arête typée entre deux entités (source ──relation_type──▶ target), par exemple Alice ──works_at──▶ Acme.

Il existe également un stockage épisodique (kg_episodic) qui enregistre les tours bruts, séparément du graphe organisé — vous conservez donc à la fois la transcription et le modèle distillé.

Pourquoi bi-temporel

Chaque observation et relation est suivie le long de deux axes temporels :

  • temps de validité — quand le fait était vrai dans le monde (valid_fromvalid_to).
  • temps d'ingestion — quand le système l'a appris.

Lorsqu'un fait change, l'ancien n'est pas supprimé — il est invalidé (son valid_to est défini) et le nouveau est ajouté. Cela signifie que le graphe peut répondre "quelle est la préférence actuelle de l'utilisateur ?" sans perdre "ce qu'elle était auparavant." Les faits remplacés restent dans l'historique au lieu de réécrire le présent — ce qui est exactement ce que l'on attend d'une mémoire fiable sur plusieurs mois.

kg.invalidate_observation(old_id).await?;   // mark a fact no longer valid
kg.invalidate_relation(old_id).await?;      // mark an edge no longer valid

Créer une

graph-memory est basé sur SQLite, il s'agit donc d'un fichier (ou en mémoire pour les tests) :

use adk_memory::GraphMemoryService;
use std::sync::Arc;

let kg = GraphMemoryService::new("sqlite://mia-memory.db").await?;
kg.migrate().await?;                         // idempotent schema setup
let kg = Arc::new(kg);

Écrire dans le graphe

use adk_memory::{CreateEntityInput, CreateRelationInput};

kg.create_entities("coach", "alice", vec![CreateEntityInput {
    name: "Alice".into(),
    entity_type: "person".into(),
    observations: vec!["prefers morning sessions".into(), "goal: run a 10k".into()],
}]).await?;

kg.create_relations("coach", "alice", vec![CreateRelationInput {
    source: "Alice".into(), relation_type: "training_for".into(), target: "10k race".into(),
}]).await?;

// add facts to an existing entity later
kg.add_observations("coach", "alice", /* entity */ "Alice", vec!["timezone is CET".into()]).await?;

La création d'une entité est un upsert — recréer une entité connue met à jour son type et son horodatage au lieu de la dupliquer.

Le relire

Trois formes de rappel, en plus du search du trait :

// 1. Token-scored relevance search → entities + their relations + a score
let hits = kg.search_nodes("coach", "alice", "what is she training for?", 5).await?;

// 2. Fetch specific entities by name
let nodes = kg.open_nodes("coach", "alice", &["Alice".into()]).await?;

// 3. The whole graph (small graphs / debugging)
let graph = kg.read_graph("coach", "alice").await?;

La carte de profil

La fonctionnalité clé pour les agents : profile_card génère un résumé compact et actuel de l'identité de l'utilisateur — les entités les plus récemment mises à jour et leurs observations valides — prêt à être injecté dans un prompt système au début de la session.

let card = kg.profile_card("coach", "alice").await?;
// → a short text block: "Alice (person): prefers morning sessions; goal: run a 10k…"

Limitez sa taille avec un budget afin que le prompt reste petit à mesure que le graphe grandit :

let kg = GraphMemoryService::new(url).await?
    .with_profile_budget(/* entities */ 12, /* observations per entity */ 5);

Laisser l'agent le gérer

Vous appelez rarement create_entities manuellement en production — vous donnez à l'agent des outils pour écrire dans le graphe à mesure qu'il apprend. Voir Outils & agents pour remember et relate, qui se mappent directement sur les appels ci-dessus et sont livrés dans adk-tool.

Suivant : Outils & agents →