O Grafo de Conhecimento

GraphMemoryService é uma forma diferente de memória: em vez de um monte de entradas de texto, ele armazena um grafo de conhecimento do usuário — entidades, os fatos ("observações") anexados a elas e relações tipadas entre elas — e ele rastreia tudo isso bi-temporalmente. Este é o backend por trás do exemplo Mindfulness-with-Mia e da página de memória em tempo real.

Ele implementa o mesmo MemoryService trait que os outros backends, então ele se encaixa em um agent da mesma forma — mas ele expõe uma API de grafo mais rica por cima.

O modelo de dados

   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 — uma coisa nomeada (uma pessoa, lugar, preferência, tópico) com um entity_type.
  • Observation — um fato anexado a uma entidade, com um id e um valid_from carimbo de data/hora.
  • Relation — uma aresta tipada entre duas entidades (source ──relation_type──▶ target), por exemplo, Alice ──works_at──▶ Acme.

Há também um armazenamento episódico (kg_episodic) que registra turnos brutos, separado do grafo curado — assim você mantém tanto a transcrição quanto o modelo destilado.

Por que bitemporal

Cada observação e relação é rastreada ao longo de dois eixos de tempo:

  • tempo válido — quando o fato era verdadeiro no mundo (valid_fromvalid_to).
  • tempo de ingestão — quando o sistema o aprendeu.

Quando um fato muda, o antigo não é excluído — ele é invalidado (seu valid_to é definido) e o novo é adicionado. Isso significa que o grafo pode responder "qual é a preferência atual do usuário?" sem perder "o que costumava ser." Fatos substituídos permanecem no histórico em vez de sobrescrever o presente — o que é exatamente o que você deseja para uma memória em que confiará por 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

Criando um

graph-memory é baseado em SQLite, então é um arquivo (ou em memória para testes):

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

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

Criar uma entidade é upsert — recriar uma entidade conhecida atualiza seu tipo e timestamp em vez de duplicá-la.

Lendo de volta

Três formas de recuperação, além do search do 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?;

O cartão de perfil

O recurso matador para agentes: profile_card renderiza um resumo compacto e atual de quem é o usuário — as entidades mais recentemente atualizadas e suas observações válidas — pronto para ser injetado em um prompt de sistema no início da sessão.

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

Limite seu tamanho com um orçamento para que o prompt permaneça pequeno à medida que o grafo cresce:

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

Deixando o agente curar

Você raramente chama create_entities manualmente em produção — você dá ao agente ferramentas para escrever no grafo à medida que ele aprende. Veja Ferramentas e agentes para remember e relate, que mapeiam diretamente para as chamadas acima e são enviados em adk-tool.

Próximo: Ferramentas e agentes →