El Grafo de Conocimiento

GraphMemoryService es una forma diferente de memoria: en lugar de un montón de entradas de texto, almacena un grafo de conocimiento del usuario — entidades, los hechos ("observaciones") asociados a ellas y las relaciones tipadas entre ellas — y lo rastrea todo bi-temporalmente. Este es el backend detrás del ejemplo de Mindfulness-with-Mia y la página de memoria en tiempo real.

Implementa el mismo MemoryService trait que los otros backends, por lo que se integra en un Agent de la misma manera — pero expone una API de grafo más rica.

El modelo de datos

   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 — una cosa con nombre (una persona, lugar, preferencia, tema) con un entity_type de forma libre.
  • Observation — un hecho asociado a una entidad, con un id estable y una marca de tiempo (valid_from).
  • Relation — un borde tipado entre dos entidades (source ──relation_type──▶ target), por ejemplo, Alice ──works_at──▶ Acme.

También hay un almacén episódico (kg_episodic) que registra turnos brutos, separado del grafo curado — para que conserves tanto la transcripción como el modelo destilado.

Por qué bi-temporal

Cada observación y relación se rastrea a lo largo de dos ejes de tiempo:

  • tiempo válido — cuando el hecho fue verdadero en el mundo (valid_fromvalid_to).
  • tiempo de ingesta — cuando el sistema lo aprendió.

Cuando un hecho cambia, el antiguo no se elimina, sino que se invalida (se establece su valid_to) y se añade el nuevo. Esto significa que el grafo puede responder a "¿cuál es la preferencia actual del usuario?" sin perder "cuál era antes." Los hechos reemplazados permanecen en el historial en lugar de sobrescribir el presente, que es exactamente lo que se desea para una memoria en la que se confiará durante meses.

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

Creando uno

graph-memory está respaldado por SQLite, por lo que es un archivo (o en memoria para pruebas):

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);

Escribiendo en el grafo

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?;

Crear una entidad es una operación de upsert: volver a crear una entidad conocida actualiza su tipo y marca de tiempo en lugar de duplicarla.

Leyéndolo de vuelta

Tres formas de recuperación, además del search del rasgo:

// 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 tarjeta de perfil

La característica clave para los agentes: profile_card genera un resumen compacto y actual de quién es el usuario — las entidades actualizadas más recientemente y sus observaciones válidas — listo para inyectarse en un prompt del sistema al inicio de la sesión.

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

Limite su tamaño con un presupuesto para que el prompt permanezca pequeño a medida que el grafo crece:

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

Dejando que el agente lo gestione

Raramente se llama a create_entities manualmente en producción; se le dan al agente herramientas para escribir en el grafo a medida que aprende. Ver Herramientas y agentes para remember y relate, que se corresponden directamente con las llamadas anteriores y se envían en adk-tool.

Siguiente: Herramientas y agentes →