Zustandsbehaftete und personalisierte KI‑Agenten mit dem ADK erstellen

1. Einführung

Titel

Das „Goldfisch“-Problem

Stellen Sie sich vor, Sie beauftragen ein Reisebüro mit der Planung Ihres Traumurlaubs in Tokio. Mit dem Session Agent können Sie sich das „Goldfisch-Problem“ ansehen.

Sie gehen in sein Büro und sagen:

„Hallo! Ich möchte eine zweitägige Reise nach Tokio planen. Ich interessiere mich für historische Stätten und Sushi.“

Der Agent antwortet begeistert:

"Great! Ich habe einen Besuch des Kaiserpalasts und ein Sushi-Dinner im Sukiyabashi Jiro geplant.“

Sie lächeln und sagen:

„Das klingt perfekt. Kannst du mir den Reiseplan schicken?“

Der Agent sieht Sie leer an und fragt:

„Hallo! Wie kann ich Ihnen heute bei der Planung einer Reise helfen?“

Das ist das „Goldfisch-Problem“. Ohne Gedächtnis beginnt jede Interaktion von Neuem. Die Intelligenz ist vorhanden – der Agent weiß, wie man Reisen plant –, aber es fehlt an Kontinuität. Damit ein KI-Agent wirklich nützlich ist, muss er sich Dinge merken können.

Ihre Mission heute

In diesem Workshop lösen Sie das Goldfisch-Problem, indem Sie einen Reise-Agenten erstellen, der sich Dinge merkt, lernt und sich anpasst. Sie durchlaufen 6 Stufen des Agent-Speichers und erstellen ein System, das sich weniger wie ein Chatbot und mehr wie ein persönlicher Assistent verhält.

Level

Konzept

Die „Superkraft“

Level 1

Sitzung und Status

Unterhaltungen führen, ohne etwas zu vergessen

Level 2

Multi-Agent State

Notizen für Teammitglieder freigeben

Level 3

Persistenz

Sie auch nach einem Systemneustart wiedererkennen

Level 4

Callbacks

Speicher vollständig autonom aktualisieren

Level 5

Benutzerdefinierte Tools

Strukturierte Nutzerprofile lesen und schreiben

Level 6

Multimodaler Speicher

Fotos und Videos „sehen“ und sich daran erinnern

Der ADK-Speicher-Stack

Bevor wir Code schreiben, sollten wir uns die verwendeten Tools ansehen. Das Google Agent Development Kit (ADK) bietet eine strukturierte Möglichkeit, den Speicher zu verwalten:

  1. Sitzung: Der Container für eine Unterhaltung. Darin wird der Verlauf der Unterhaltung gespeichert.
  2. Status: Ein Schlüssel/Wert-„Notizblock“, der an die Sitzung angehängt ist. Kundenservicemitarbeiter verwenden diese Funktion, um bestimmte Fakten zu speichern, z.B. destination="Tokyo").
  3. MemoryService: Langzeitspeicher. Hier werden Dinge wie Nutzereinstellungen oder analysierte Dokumente dauerhaft gespeichert.

2. Erstelle ein

Für unsere KI-Agents benötigen wir zwei Dinge: ein Google Cloud-Projekt als Grundlage.

Teil 1: Rechnungskonto aktivieren

  • Sie müssen Ihr Rechnungskonto mit einem Guthaben von 5 $ in Anspruch nehmen, da Sie es für die Bereitstellung benötigen. Melden Sie sich in Ihrem Gmail-Konto an.

Teil 2: Offene Umgebung

  1. 👉 Klicken Sie auf diesen Link, um direkt zum Cloud Shell-Editor zu gelangen.
  2. 👉 Wenn Sie heute an irgendeinem Punkt zur Autorisierung aufgefordert werden, klicken Sie auf Autorisieren, um fortzufahren. Klicken Sie, um Cloud Shell zu autorisieren.
  3. 👉 Wenn das Terminal nicht unten auf dem Bildschirm angezeigt wird, öffnen Sie es:
    • Klicken Sie auf Ansehen.
    • Klicken Sie auf TerminalNeues Terminal im Cloud Shell-Editor öffnen.
  4. 👉💻 Prüfen Sie im Terminal mit dem folgenden Befehl, ob Sie bereits authentifiziert sind und das Projekt auf Ihre Projekt-ID festgelegt ist:
    gcloud auth list
    
  5. 👉💻 Bootstrap-Projekt von GitHub klonen:
    git clone https://github.com/cuppibla/memory_agent_starter
    
    
  6. 👉💻 Führen Sie das Setup-Skript im Projektverzeichnis aus.
    cd ~/memory_agent_starter
    ./init.sh
    
    Das Skript übernimmt den Rest des Einrichtungsvorgangs automatisch.
  7. 👉💻 Legen Sie die erforderliche Projekt-ID fest:
    gcloud config set project $(cat ~/project_id.txt) --quiet
    

Teil 3: Berechtigungen einrichten

  1. 👉💻 Aktivieren Sie die erforderlichen APIs mit dem folgenden Befehl. Dies kann einige Minuten dauern.
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        servicenetworking.googleapis.com \
        run.googleapis.com \
        aiplatform.googleapis.com \
        compute.googleapis.com
    
  2. 👉💻 Erteilen Sie die erforderlichen Berechtigungen, indem Sie die folgenden Befehle im Terminal ausführen:
    . ~/memory_agent_starter/set_env.sh
    

Beachten Sie, dass eine .env-Datei für Sie erstellt wird. Dort werden Ihre Projektinformationen angezeigt.

3. Grundlagen – Sitzung und Status

Zustandsorientiert

Das Konzept: Kontext ist entscheidend

Die einfachste Form des Speichers ist der Sitzungsspeicher. So kann ein Agent erkennen, dass sich das „es“ im Satz „Ich möchte es kaufen“ auf den Schuh bezieht, über den Sie vor 10 Sekunden gesprochen haben.

Im ADK wird dies mit dem Session-Objekt verwaltet.

  • Zustandsloser Ansatz: Für jede Nachricht wird eine neue Sitzung erstellt.
  • Zustandsbehafteter Ansatz: Es wird eine Sitzung erstellt und für die gesamte Unterhaltung wiederverwendet.

Schritt 1: Agent untersuchen

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/01_session_agent/agent.py

Öffnen Sie ~/memory_agent_starter/01_session_agent/agent.py.

👉 Suchen Sie den Kommentar # TODO: Create a root agent in der Funktion agent.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

root_agent = LlmAgent(
    name="multi_day_trip_agent",
    model="gemini-2.5-flash",
    description="Agent that progressively plans a multi-day trip, remembering previous days and adapting to user feedback.",
    instruction="""
    You are the "Adaptive Trip Planner" 🗺️ - an AI assistant that builds multi-day travel itineraries step-by-step.

    Your Defining Feature:
    You have short-term memory. You MUST refer back to our conversation to understand the trip's context, what has already been planned, and the user's preferences. If the user asks for a change, you must adapt the plan while keeping the unchanged parts consistent.

    Your Mission:
    1.  **Initiate**: Start by asking for the destination, trip duration, and interests.
    2.  **Plan Progressively**: Plan ONLY ONE DAY at a time. After presenting a plan, ask for confirmation.
    3.  **Handle Feedback**: If a user dislikes a suggestion (e.g., "I don't like museums"), acknowledge their feedback, and provide a *new, alternative* suggestion for that time slot that still fits the overall theme.
    4.  **Maintain Context**: For each new day, ensure the activities are unique and build logically on the previous days. Do not suggest the same things repeatedly.
    5.  **Final Output**: Return each day's itinerary in MARKDOWN format.
    """,
    tools=[google_search]
)

Die Anweisung weist das LLM an, sich etwas zu merken. Der Code muss jedoch die Möglichkeit bieten, sich etwas zu merken.

Schritt 2: Die beiden Szenarien

Öffnen Sie ~/memory_agent_starter/01_session_agent/main.py.

👉 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie folgenden Befehl ausführen:

cloudshell edit ~/memory_agent_starter/01_session_agent/main.py

Öffnen Sie ~/memory_agent_starter/01_session_agent/main.py und suchen Sie den Kommentar # TODO: Create a runner with in memorysession service in der Funktion main.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

    runner = Runner(
        agent=agent,
        session_service=session_service,
        app_name=agent.name
    )

👉 Suchen Sie den Kommentar # TODO: create a different session to test in der Funktion main.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

    tokyo_session_2 = await session_service.create_session(
        app_name=multi_day_agent.name,
        user_id=user_id
    )

Testen

Wir haben zwei Funktionen, die den Unterschied zwischen dem Gedächtnis eines Goldfischs und dem eines Elefanten veranschaulichen.

Szenario 1: Statusbehaftet (gemeinsame Sitzung)

async def run_trip_same_session_scenario(session_service, user_id):
    # 1. Create ONE session
    trip_session = await session_service.create_session(...)

    # 2. Turn 1
    await run_agent_query(..., trip_session, ...)

    # 3. Turn 2 - REUSING the same session!
    # The agent can "see" Turn 1 because it's in the session history.
    await run_agent_query(..., trip_session, ...)

Szenario 2: Statuslos (jedes Mal eine neue Sitzung)

async def run_trip_different_session_scenario(session_service, user_id):
    # Turn 1
    tokyo_session = await session_service.create_session(...)
    await run_agent_query(..., tokyo_session, ...)

    # Turn 2 - Creating a FREASH session
    # The agent has NO IDEA what happened in Turn 1.
    tokyo_session_2 = await session_service.create_session(...)
    await run_agent_query(..., tokyo_session_2, ...)

Schritt 3: Agent ausführen

Sehen wir uns den Unterschied in der Praxis an. Führen Sie das Script aus:

👉💻 Führen Sie in der Befehlszeile den folgenden Befehl aus:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/01_session_agent/main.py

Szenario 1 beobachten: Der Agent erinnert sich an Ihre Einstellungen aus der ersten Nachricht und passt den Plan in der zweiten Nachricht an.

Szenario 2 beobachten: Im zweiten Zug („Weißt du noch, was mir am Essen gefallen hat?“) scheitert der Kundenservicemitarbeiter vollständig, da es sich um eine neue Sitzung handelt. Damit wird im Grunde gesagt: „Ich weiß nicht, wovon du sprichst.“

Wichtigste Erkenntnisse

Regel 1 für Memory:Verwenden Sie immer die session.id wieder, um den Gesprächskontext beizubehalten. Das Session-Objekt ist der Kurzzeitgedächtnispuffer Ihres KI-Agents.

4. Das Team – Multi-Agenten-Status

Essen

Das Konzept: „Stille Post“

Wenn mehrere Agenten zusammenarbeiten, ist das so, als würden Kollegen einen Aktenordner hin- und herschieben. Wenn ein KI-Agent eine Notiz in den Ordner schreibt, sollte der nächste KI-Agent sie lesen können.

Im ADK ist dieser „Ordner“ der Status.

  • State ist ein Dictionary ({"key": "value"}), das sich in der Sitzung befindet.
  • Jeder Agent in der Sitzung kann Daten daraus lesen oder hineinschreiben.

Schritt 1: Workflow untersuchen

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/02_multi_agent/agent.py

👉 Suchen Sie in der Datei ~/memory_agent_starter/02_multi_agent/agent.py nach dem Kommentar # TODO: foodie agent.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

foodie_agent = LlmAgent(
    name="foodie_agent",
    model="gemini-2.5-flash",
    tools=[google_search],
    instruction="""You are an expert food critic. Your goal is to find the best restaurant based on a user's request.

    When you recommend a place, you must output *only* the name of the establishment and nothing else.
    For example, if the best sushi is at 'Jin Sho', you should output only: Jin Sho
    """,
    output_key="destination"  # ADK will save the agent's final response to state['destination']
)

👉 Suchen Sie den Kommentar # TODO: transportation agent in der Funktion agent.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

transportation_agent = LlmAgent(
    name="transportation_agent",
    model="gemini-2.5-flash",
    tools=[google_search],
    instruction="""You are a navigation assistant. Given a destination, provide clear directions.
    The user wants to go to: {destination}.

    Analyze the user's full original query to find their starting point.
    Then, provide clear directions from that starting point to {destination}.
    """,
)

👉 Suchen Sie den Kommentar # TODO: root_agent in der Funktion agent.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

root_agent = SequentialAgent(
    name="find_and_navigate_agent",
    sub_agents=[foodie_agent, transportation_agent],
    description="A workflow that first finds a location and then provides directions to it."
)

Jetzt haben wir zwei Agents, die nacheinander arbeiten:

  1. Foodie Agent: Findet ein Restaurant.
  2. Transport-Agent: Gibt eine Wegbeschreibung zu diesem Restaurant aus.

Die magische Übergabe: foodie_agent übergibt den Staffelstab an transportation_agent.

foodie_agent = LlmAgent(
    # ...
    # CRITICAL: This tells ADK to save the agent's output to state['destination']
    output_key="destination"
)

transportation_agent = LlmAgent(
    # ...
    # CRITICAL: This injects state['destination'] into the prompt
    instruction="""
    The user wants to go to: {destination}.
    Provide clear directions...
    """,
)
  1. output_key="destination": Die Antwort des Foodie-Agenten wird effizient gespeichert.
  2. {destination}: Der Transport-Agent liest diese Antwort automatisch.

(Keine Aktion erforderlich) Schritt 2: Der Orchestrator

Öffnen Sie 02_multi_agent/main.py.

Wir verwenden eine SequentialAgent, um sie in der richtigen Reihenfolge auszuführen.

# 1. Create a single session for the sequential agent
session = await session_service.create_session(...)

# 2. Run the query
# The SequentialAgent manages the state flow:
# Query -> Foodie -> state['destination'] -> Transportation -> Final Answer
await run_agent_query(root_agent, query, ...)

Der Nutzer sendet einen Prompt:

"Find best sushi in Palo Alto and then tell me how to get there."

Die Agents arbeiten zusammen, um die Frage zu beantworten.

Schritt 3: Team ausführen

👉💻 Führen Sie den Multi-KI-Agenten-Workflow im Cloud Shell-Terminal aus:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/02_multi_agent/main.py

Was passiert?

  1. Foodie Agent: Findet „Jin Sho“ (oder Ähnliches).
  2. ADK: Speichert „Jin Sho“ in state['destination'].
  3. Transportunternehmen: Erhält „Jin Sho“ in seiner Anleitung.
  4. Ergebnis: „Um vom Caltrain-Bahnhof zum Jin Sho zu gelangen, gehen Sie die University Ave entlang…“

Wichtigste Erkenntnisse

Regel 2 für das Gedächtnis:Verwenden Sie State, um strukturierte Informationen zwischen Agents zu übergeben. Verwenden Sie output_key zum Schreiben und {placeholders} zum Lesen.

5. Der Neustart – Persistenz

Zustandsorientiert

Das Konzept: „Das Neustartproblem“

Bisher haben wir InMemory verwendet. Wenn Sie das Skript beenden und neu starten, vergisst der Agent alles. Es ist wie ein Computer, der seine Festplatte jedes Mal löscht, wenn Sie ihn ausschalten.

Um das zu beheben, benötigen wir Persistenz. Wir tauschen InMemorySessionService gegen DatabaseSessionService.

Schritt 1: Datenbankwechsel

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/03_persistent_agent/main.py

👉 Suchen Sie in der Datei ~/memory_agent_starter/03_persistent_agent/main.py nach dem Kommentar # TODO: Configuration for Persistent Sessions.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

SESSIONS_DIR = Path(os.path.expanduser("~")) / ".adk_codelab" / "sessions"
os.makedirs(SESSIONS_DIR, exist_ok=True)
SESSION_DB_FILE = SESSIONS_DIR / "trip_planner.db"
SESSION_URL = f"sqlite:///{SESSION_DB_FILE}"

Jetzt werden alle Sitzungen und Ereignisse in einer SQLite-Datei gespeichert.

Schritt 2: Sitzungsübergreifender Abruf

Durch die Persistenz kann nicht nur eine Unterhaltung fortgesetzt, sondern auch aus früheren Unterhaltungen gelernt werden.

Sehen Sie sich in derselben Datei~/memory_agent_starter/03_persistent_agent/main.py den Testlauf 3: Sitzungsübergreifender Abruf an.

👉 Kommentar suchen # TODO: retrieve the previous session manually

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

    old_session = await session_service.get_session(
        app_name=root_agent.name, user_id="user_01", session_id=session_id
    )

👉 Suchen Sie den Kommentar # TODO: Extract content from the OLD session in der Funktion main.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

                    previous_context += f"- {role}: {text}\n"

👉 Suchen Sie den Kommentar # TODO: Manually inject the context to the query in der Funktion main.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

    query_3 = f"""
    {previous_context}

    I'm planning a new trip to Osaka this time. 
    Based on my previous preferences (above), what should I eat?
    """

So wird simuliert, dass ein Nutzer Monate später zurückkehrt. Nur mit einer Datenbank können Sie diesen alten Verlauf abrufen.

Schritt 3: Neustart überstehen

👉💻 Führen Sie das Skript im Terminal aus:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/03_persistent_agent/main.py

Dadurch wird die Datei ~/memory_agent_starter/trip_planner.db erstellt. So gehts:Führen Sie das Skript zweimal aus.

  • Suchen Sie beim zweiten Ausführen nach „Resumed existing session“ (Vorhandene Sitzung fortgesetzt).
  • Der Kontext aus dem ersten Lauf wird vom Agenten gespeichert, da er aus der Datenbankdatei geladen wird.

Wichtigste Erkenntnisse

Regel 3 für den Arbeitsspeicher:Verwenden Sie DatabaseSessionService für die Produktion. So bleiben Nutzerunterhaltungen auch nach Serverneustarts erhalten und es ist eine langfristige Verlaufsanalyse möglich.

6. The Spy – Callbacks

Zustandsorientiert

Manchmal müssen Sie den Speicher automatisch aktualisieren, basierend auf dem, was der Agent tut, nicht nur auf dem, was er sagt. Sie möchten einen „Spion“, der den KI-Agenten beobachtet und Notizen macht.

Im ADK ist dieser Spy der Callback. adk_callback

  • after_tool_callback: Eine Funktion, die jedes Mal ausgeführt wird, wenn der Agent arbeitet.
  • ToolContext: Eine Möglichkeit, aus der Funktion heraus in den Status zu schreiben.

Schritt 1: Die Logik

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/04_stateful_agent/agent.py

👉 Suchen Sie in der Datei ~/memory_agent_starter/04_stateful_agent/agent.py nach dem Kommentar # TODO: Implement call back logic.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

def save_activity_type_callback(
    tool,
    args: Dict[str, Any],
    tool_context: ToolContext,
    tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
    """
    Callback to save the TYPE of activity just planned into the session state.
    """
    # 1. Get the actual agent name.
    if tool.name == "transfer_to_agent":
         agent_name = args.get("agent_name")
    else:
         agent_name = tool.name

    activity_type = "unknown"

    # 2. Determine the type based on which agent was actually used
    if agent_name == "museum_expert":
        activity_type = "CULTURAL"
    elif agent_name == "restaurant_expert":
        activity_type = "FOOD"
    elif agent_name == "outdoor_expert":
        activity_type = "OUTDOOR"

    print(f"\n🔔 [CALLBACK] The planner transferred to '{agent_name}'.")

    # 3. Update the state directly
    tool_context.state["last_activity_type"] = activity_type
    print(f"💾 [STATE UPDATE] 'last_activity_type' is now set to: {activity_type}\n")

    return tool_response

👉 Suchen Sie in derselben Datei in der Funktion 04_stateful_agent/agent.py nach dem Kommentar # TODO: add callback to root agent.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

    after_tool_callback=save_activity_type_callback,

Die dynamische Anweisung:Die Anweisung des Agents ist jetzt eine Funktion und kein String mehr. Das ändert sich je nach Status.

def get_planner_instruction(context):
    last_activity = context.state.get("last_activity_type", "None")
    
    return f"""
    The last activity was: {last_activity}
    
    If last_activity is 'CULTURAL' -> `museum_expert` is BANNED.
    """

Schritt 3: Spy testen

👉💻 Führen Sie das Skript im Terminal aus, indem Sie den folgenden Befehl kopieren und einfügen:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/04_stateful_agent/main.py

Wenn Sie diesen Agent ausführen, wird eine Schleife angezeigt.

  1. Runde 1: Sie fragen nach einem Museum. Legt last_activity="CULTURAL" fest.
  2. Runde 2: Sie bitten um ein weiteres Museum.
  3. Aktualisierungen der Agent-Anweisung: „CULTURAL is BANNED“ (KULTURELL ist VERBOTEN).
  4. Agent sagt: „Ich kann kein weiteres Museum erstellen. Wie wäre es mit einem Park?“

Achten Sie in den Konsolenlogs auf [CALLBACK] und [STATE UPDATE]. Sie können in Echtzeit sehen, wie sich der Speicher ändert, während der Agent arbeitet.

Wichtigste Erkenntnisse

Regel 4 für den Arbeitsspeicher:Verwenden Sie Callbacks, um die Statusverwaltung zu automatisieren. Ihr KI-Agent erstellt seinen eigenen Kontext, indem er seine Aufgabe erfüllt.

7. Die Dateiablage – Benutzerdefinierte Tools

Das Konzept: „Strukturiertes Gedächtnis“

Zustandsorientiert

Bisher war „Memory“ ein Chatprotokoll oder ein einfaches Schlüssel/Wert-Paar. Was aber, wenn Sie sich ein komplexes Nutzerprofil merken müssen, z.B. diet: vegan, budget: high, pets: [cat, dog].

Dazu behandeln wir den Speicher als Tool. Der Agent entscheidet explizit, wann er das Ablagefach öffnet (lesen) und wann er einen Bericht erstellt (schreiben). Diagramm für benutzerdefinierte Tools

Schritt 1: Die Tools

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/05_profile_agent/tools.py

👉 In dieser Datei: ~/memory_agent_starter/05_profile_agent/tools.py.

Wir müssen diese beiden Tools implementieren:

  1. save_user_preferences: Schreibt in eine Datenbank.
  2. recall_user_preferences: Liest Daten aus einer Datenbank.

Suchen Sie in der Funktion ~/memory_agent_starter/05_profile_agent/tools.py nach dem Kommentar # TODO: implement save_user_preferences tools.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

def save_user_preferences(tool_context: ToolContext, new_preferences: Dict[str, Any]) -> str:
    user_id = tool_context.session.user_id
    with sqlite3.connect(USER_DB_FILE) as conn:
        for key, value in new_preferences.items():
            conn.execute("INSERT INTO user_preferences (user_id, pref_key, pref_value) VALUES (?, ?, ?) ON CONFLICT(user_id, pref_key) DO UPDATE SET pref_value = excluded.pref_value;",
                         (user_id, key, json.dumps(value)))
    return f"Preferences updated: {list(new_preferences.keys())}"

👉 Suchen Sie den Kommentar # TODO: implement recall_user_preferences tools in der Funktion 05/tools.py.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

def recall_user_preferences(tool_context: ToolContext) -> Dict[str, Any]:
    user_id = tool_context.session.user_id
    preferences = {}
    with sqlite3.connect(USER_DB_FILE) as conn:
        rows = conn.execute("SELECT pref_key, pref_value FROM user_preferences WHERE user_id = ?", (user_id,)).fetchall()
        if not rows: return {"message": "No preferences found."}
        for key, value_str in rows: preferences[key] = json.loads(value_str)
    return preferences

Die Anweisung erzwingt einen Workflow:

instruction="""
1. RECALL FIRST: First action MUST be `recall_user_preferences`.
3. LEARN: If a user states a new preference, use `save_user_preferences`.
"""

Schritt 2: Ausführung

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/05_profile_agent/main.py

Öffnen Sie ~/memory_agent_starter/05_profile_agent/main.py.

Anders als bei früheren Modulen, in denen das ADK den Status automatisch verwaltet hat, ist hier der Agent für die Verwaltung zuständig.

  • Es wählt aus, recall_user_preferences am Anfang aufzurufen.
  • Es wählt den Anruf von save_user_preferences aus, wenn Sie „Ich bin Veganer“ sagen.

Schritt 3: Profil erstellen

👉💻 Führen Sie das Skript aus:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/05_profile_agent/main.py

So könnte ein Gesprächsablauf aussehen:

  1. „Hallo, plane ein Abendessen.“ -> Der Agent prüft die Datenbank und findet nichts. Fragt nach Präferenzen.
  2. „Ich bin Veganer.“ -> Der Agent speichert „vegan“ in der Datenbank.
  3. Starten Sie das Script neu.
  4. „Hallo, plane ein Abendessen.“ -> Der Kundenservicemitarbeiter sieht in der Datenbank „vegan“ und schlägt sofort ein veganes Restaurant vor.

Wichtigste Erkenntnisse

Regel 5 für das Gedächtnis:Geben Sie Ihrem Agenten für komplexe, strukturierte Daten Lese-/Schreibtools. Das LLM verwaltet seinen eigenen langfristigen Speicher.

8. Das Gehirn – Multimodaler Speicher

Zustandsorientiert

Das Konzept: „The Human Experience“

Menschen erinnern sich an mehr als nur Text. Wir erinnern uns an die Atmosphäre eines Fotos, den Klang einer Stimme, das Gefühl eines Videos.

Mit Vertex AI Memory Bank kann Ihr Agent Multimodal Memory verarbeiten. Es kann Bilder, Videos und Audioinhalte aufnehmen, „verstehen“ und später abrufen.

Schritt 1: Die Konfiguration

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/06_multimodal_agent/main.py

👉 Öffnen Sie 06_multimodal_agent/main.py. Suchen Sie den Kommentar # TODO: Configure Memory Bank Topic.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

travel_topics = [
    MemoryTopic(
        managed_memory_topic=ManagedMemoryTopic(
            managed_topic_enum=ManagedTopicEnum.USER_PREFERENCES
        )
    ),
    MemoryTopic(
        managed_memory_topic=ManagedMemoryTopic(
            managed_topic_enum=ManagedTopicEnum.USER_PERSONAL_INFO
        )
    ),
    MemoryTopic(
        custom_memory_topic=CustomMemoryTopic(
            label="travel_experiences",
            description="""Memorable travel experiences including:
                - Places visited and impressions
                - Favorite restaurants, cafes, and food experiences
                - Preferred accommodation types and locations
                - Activities enjoyed (museums, hiking, beaches, etc.)
                - Travel companions and social preferences
                - Photos and videos from trips with location context""",
        )
    ),
    MemoryTopic(
        custom_memory_topic=CustomMemoryTopic(
            label="travel_preferences",
            description="""Travel style and preferences:
                - Budget preferences (luxury, mid-range, budget)
                - Transportation preferences (flying, trains, driving)
                - Trip duration preferences
                - Season and weather preferences
                - Cultural interests and language abilities
                - Dietary restrictions and food preferences""",
        )
    ),
    MemoryTopic(
        custom_memory_topic=CustomMemoryTopic(
            label="travel_logistics",
            description="""Practical travel information:
                - Passport and visa information
                - Frequent flyer numbers and hotel loyalty programs
                - Emergency contacts
                - Medical considerations and insurance
                - Packing preferences and essentials
                - Time zone preferences and jet lag strategies""",
        )
    ),
]

Suchen Sie den Kommentar # TODO: Configure Memory Bank Customization.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

memory_bank_config = {
    "customization_configs": [
        {
            "memory_topics": travel_topics,
        }
    ],
    "similarity_search_config": {
        "embedding_model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-embedding-001"
    },
    "generation_config": {
        "model": f"projects/{PROJECT_ID}/locations/{LOCATION}/publishers/google/models/gemini-2.5-flash"
    },
}

Schritt 2: Die Welt erfassen

In test_trip_planner senden wir:

  1. Eine SMS („Hallo“)
  2. Ein Bild (Sehenswürdigkeit)
  3. Ein Video (Mittelmeer)
  4. Ein Audio-Clip (Sprachnotiz über Gaeta)

Suchen Sie in der Funktion 6_multimodal_agent/main.py nach dem Kommentar # TODO create session service and memory service.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

session_service = VertexAiSessionService(
    project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)
memory_service = VertexAiMemoryBankService(
    project=PROJECT_ID, location=LOCATION, agent_engine_id=agent_engine_id
)

👉 Suchen Sie in derselben Datei 06_multimodal_agent/main.py nach dem Kommentar # TODO: create memory from session.

Ersetzen Sie diese gesamte Zeile durch den folgenden Code:

    await memory_service.add_session_to_memory(final_session_state)

Das ist die magische Linie. Alle Rich Media werden an Vertex AI gesendet, wo sie verarbeitet und indexiert werden.

Schritt 3: Abrufen

👉💻 Öffnen Sie die Datei in Ihrem Cloud Shell-Terminal im Cloud Shell-Editor, indem Sie Folgendes ausführen:

cloudshell edit ~/memory_agent_starter/06_multimodal_agent/agent.py

Der Agent hat eine PreloadMemoryTool.

tools=[PreloadMemoryTool(), budget_tool]

Wenn eine neue Sitzung beginnt, sucht das Tool automatisch in der Memory Bank nach relevanten früheren Erfahrungen und fügt sie in den Kontext ein.

Schritt 4: Brain ausführen

👉💻 Führen Sie das Skript in Ihrem Cloud Shell-Terminal aus. Hinweis: Dazu ist ein Google Cloud-Projekt mit aktivierter Vertex AI erforderlich:

cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/06_multimodal_agent/main.py

So sieht der letzte Bestätigungsschritt aus:

„Basierend auf dem Bild, Video UND Audio, das ich zuvor mit dir geteilt habe…“

Der Kundenservicemitarbeiter antwortet:

„Du solltest Gaeta besuchen. Du hast mir ein Video vom Mittelmeer und einen Audioclip gezeigt, in dem du gesagt hast, dass du Gaeta liebst.“

Es hat die Punkte über verschiedene Medientypen hinweg verbunden.

Wichtigste Erkenntnisse

Regel 6 für das Gedächtnis:Verwenden Sie Vertex AI Memory Bank, um das Gedächtnis optimal zu nutzen. Er vereint Text, Bilder und Videos in einem einzigen, durchsuchbaren Gehirn.

9. Fazit

Sie haben sich von einem vergesslichen Goldfisch zu einem multimodalen Elefanten entwickelt.

Von Ihnen erstellt

Die Funktion

Session Agent

Kurzzeitgedächtnis für Unterhaltungen

Multi-Agent

Gemeinsamer Teamspeicher

Persistent Agent

Langfristiger Verlauf

Zustandsorientierter Agent

Dynamischer, sich selbst aktualisierender Speicher

Profil-Agent

Speicher für strukturierte Daten

Multimodaler Agent

Sensorisches Gedächtnis wie bei Menschen

Vertrauen basiert auf Erinnerungen. Wenn Sie diese Muster implementieren, erstellen Sie Agents, die die Zeit und den Verlauf des Nutzers berücksichtigen, was zu intensiveren und effektiveren Interaktionen führt.

Erstellen Sie noch heute Ihre personalisierten Agenten.