Gedächtnis in Realtime-Sitzungen

Eine Stimme, die sich zwischen Anrufen nicht an dich erinnert, wirkt wie ein Kiosk. ADK-Rust lässt einen Realtime-Agenten sich erinnern — das, was er vor dem Sprechen über einen Benutzer gelernt hat, abrufen und neue Fakten mitten im Gespräch kuratieren — indem eine MemoryService in die IntegratedRealtimeRunner eingebunden wird.

Es gibt zwei zusammenarbeitende Mechanismen:

  1. Automatische Kontextinjektion + Turn-Speicherung — die Integrationsschicht erledigt das für dich.
  2. Vom Agenten kuratierter Speicher über Tools — der Agent entscheidet, was es wert ist, behalten zu werden, mithilfe angebundener Knowledge-Graph-Tools.

1. Automatische Injektion und Speicherung

Hänge eine MemoryService an, und der Runner übernimmt den Hin- und Rückweg:

let runner = IntegratedRealtimeRunner::builder()
    .model(model)
    .config(config)
    .identity("support", &user_id, &session_id)
    .session_service(sessions)
    .memory_service(memory.clone())
    .integration_config(IntegrationConfig {
        inject_memory_context: true,   // query memory at connect
        max_memory_injection: 10,      // cap injected items
        store_to_memory: true,         // write each completed turn back
        persist_transcripts: true,
    })
    .build()?;
  • Beim Verbinden wird der Speicher für den Benutzer abgefragt, und die Ergebnisse werden in den Sitzungskontext eingearbeitet, sodass der Agent ihn begrüßt und die relevante Historie bereits kennt.
  • Pro Turn werden abgeschlossene Austausche zurückgeschrieben (wenn store_to_memory), sodass die nächste Sitzung auf dieser aufbaut.

Jedes MemoryService funktioniert — das In-Memory-Backend für die Entwicklung oder das Knowledge-Graph-Backend unten.

2. Das Knowledge-Graph-Backend

adk-memorys GraphMemoryService speichert Speicher als bi-temporalen Knowledge Graph: Entitäten und Beziehungen, jeweils nach Ereigniszeit (wann es wahr war) und Ingestionszeit (wann das System es gelernt hat) erfasst. Das bedeutet, dass der Agent die Frage „was ist der aktuelle Plan des Benutzers?“ beantworten kann, ohne an der Tatsache zu scheitern, dass es früher etwas anderes war — überholte Fakten bleiben in der Historie statt die Gegenwart zu überschreiben.

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

let kg = Arc::new(GraphMemoryService::new(/* backing store */));

Übergib das als die memory_service, und die automatische Injektion oben greift nun auf den Graphen zu.

3. Den Agenten den Speicher kuratieren lassen

Das mächtigste Muster: Gib dem Agenten Tools, um direkt in den Graphen zu schreiben, damit er sich bewusst erinnert, statt einfach jedes Transkript abzulegen. adk-tool (Funktion graph-memory-tools) liefert zwei davon, die direkt in eine Realtime Sitzung eingebunden werden:

WerkzeugWas der Agent damit macht
RememberTool (remember)Eine wichtige Tatsache speichern („bevorzugt E-Mail statt Telefon“).
RelateTool (relate)Zwei Entitäten verbinden („Bestellung A-10293 → gehört-zu → dieser Benutzer“).

Verbinden Sie sie mit .adk_tool(...) (siehe Tools):

use adk_tool::{RememberTool, RelateTool};

let runner = IntegratedRealtimeRunner::builder()
    .model(model).config(config)
    .identity("support", &user_id, &session_id)
    .memory_service(kg.clone())
    .adk_tool(Arc::new(RememberTool::new(kg.clone())))
    .adk_tool(Arc::new(RelateTool::new(kg)))
    .build()?;

Weisen Sie dann den Agenten an, sie zu verwenden:

When you learn a durable fact about the customer (a preference, an account
detail, a decision), call `remember` to store it. Use `relate` to link orders
or items to the customer. Recall naturally — don't announce that you're saving.

Recall ist tokenbasiert: Der Graph gibt die Entitäten/Beziehungen zurück, die für die Unterhaltung am relevantesten sind, begrenzt durch max_memory_injection, sodass der Kontext klein bleibt, auch wenn der Graph wächst.

Eine Tiefe wählen

  • Stateless-Demo → kein memory_service. Jede Sitzung beginnt neu.
  • Kontinuität über Sitzungen hinweg → in-memory oder GraphMemoryService mit automatischer Einfügung/Speicherung. Kein Aufwand für den Agenten.
  • Ein LernagentGraphMemoryService + remember/relate-Tools, damit der Agent ein sauberes, abfragbares Modell des Benutzers kuratiert statt eines Protokollhaufens.

Das MIA-Coaching-Beispiel verwendet den Graphen + Tools, damit sich der Coach an die Ziele und Präferenzen des Benutzers zwischen den Sitzungen erinnert; siehe Examples.

Weiter: Web-Apps erstellen →

Was in eine wiederaufgenommene Sitzung übernommen wird

IntegratedRealtimeRunner::connect baut einen Kontextblock und stellt ihn dem System Instruction voran, bevor die Provider-Sitzung erstellt wird:

AbschnittQuelleGrenze
Earlier in this conversation:Die Ereignisse der vorherigen SitzungIntegrationConfig::max_history_injection (standardmäßig 20 Züge)
Relevant recalled context:MemoryService::searchIntegrationConfig::max_memory_injection (standardmäßig 10 Einträge)

Beide sind begrenzt, weil die Anweisung einmal bei der Sitzungserstellung gesendet wird und gegen den Kontext des Modells zählt. Jede Runde wird als role: text dargestellt, auf 400 Zeichen gekürzt, und Runden ohne Text werden verworfen. Wenn eine Begrenzung auf null gesetzt wird, wird dieser Abschnitt deaktiviert.

IntegratedRealtimeRunner::instruction() gibt zurück, womit die Sitzung erstellt wurde, sodass der übernommene Kontext bestätigt statt nur abgeleitet werden kann:

runner.connect().await?;
let instruction = runner.instruction().await.unwrap_or_default();
assert!(instruction.contains("Relevant recalled context"));

Wichtig: Dieser Kontext wurde zuvor geladen und verworfen — die vorherige Sitzung wurde in _session abgerufen und verworfen, und der Memory-Zweig protokollierte „injecting memory entries into session context“ neben einem Kommentar, der besagte, dass die Injektion eine zukünftige Verbesserung sei. Eine wiederaufgenommene Sitzung begann ohne beides, während die Protokolle etwas anderes behaupteten.