Créer des agents avec état et personnalisés avec ADK

1. Introduction

titre

Le problème du "poisson rouge"

Imaginez que vous faites appel à un agent de voyage pour planifier les vacances de vos rêves à Tokyo. Utilisez l'agent de session pour voir "Le problème du poisson rouge" en action.

Vous entrez dans son bureau et dites :

"Bonjour ! Je veux planifier un voyage de deux jours à Tokyo. Je m'intéresse aux sites historiques et aux sushis."

L'agent répond avec enthousiasme :

"Great! J'ai prévu une visite du palais impérial et un dîner de sushis chez Sukiyabashi Jiro."

Vous souriez et dites :

"C'est parfait ! Peux-tu m'envoyer l'itinéraire ?"

L'agent vous regarde d'un air perplexe et vous demande :

"Bonjour ! Comment puis-je vous aider à planifier un voyage aujourd'hui ?"

C'est le "problème du poisson rouge". Sans mémoire, chaque interaction repart de zéro. L'intelligence est là : l'agent sait comment planifier des voyages, mais il manque de continuité. Pour qu'un agent IA soit vraiment utile, il doit avoir de la mémoire.

Votre mission du jour

Dans cet atelier, vous allez résoudre le problème du poisson rouge en créant un agent de voyage qui se souvient, apprend et s'adapte. Vous progresserez à travers six niveaux de mémoire d'agent, en créant un système qui se comporte moins comme un chatbot et plus comme un assistant personnel dédié.

Niveau

Concept

"Superpouvoir"

Niveau 1

Session et état

Discuter sans oublier

Niveau 2

État multi-agent

Partager des notes entre les membres de l'équipe

Niveau 3

Persistance

Se souvenir de vous même après un redémarrage du système

Niveau 4

Rappels

Mise à jour de la mémoire de manière totalement autonome

Niveau 5

Outils personnalisés

Lire et écrire des profils utilisateur structurés

Niveau 6

Mémoire multimodale

"Voir" et mémoriser des photos et des vidéos

La pile de mémoire ADK

Avant d'écrire du code, examinons les outils que nous allons utiliser. Google Agent Development Kit (ADK) fournit un moyen structuré de gérer la mémoire :

  1. Session : conteneur d'une conversation. Il contient l'historique de ce qui a été dit.
  2. État : "brouillon" clé-valeur associé à la session. Les agents l'utilisent pour stocker des faits spécifiques (par exemple, destination="Tokyo").
  3. MemoryService : stockage à long terme. C'est là que nous conservons les éléments de manière permanente, comme les préférences utilisateur ou les documents analysés.

2. Configurer

Pour alimenter nos agents IA, nous avons besoin de deux choses : un projet Google Cloud pour fournir la base.

Partie 1 : Activer le compte de facturation

Pour suivre cet atelier de programmation, vous devez disposer d'un compte de facturation avec un certain crédit. Utilisez les crédits de la bannière en haut de cet atelier de programmation pour commencer. Si vous êtes déjà connecté à un compte de facturation, vous pouvez ignorer cette étape.

Partie 2 : Ouvrir l'environnement

  1. 👉 Cliquez sur ce lien pour accéder directement à l'éditeur Cloud Shell.
  2. 👉 Si vous êtes invité à autoriser une action à un moment ou à un autre aujourd'hui, cliquez sur Autoriser pour continuer. Cliquez pour autoriser Cloud Shell
  3. 👉 Si le terminal ne s'affiche pas en bas de l'écran, ouvrez-le :
    • Cliquez sur Afficher.
    • Cliquez sur TerminalOuvrir un nouveau terminal dans l'éditeur Cloud Shell
  4. 👉💻 Dans le terminal, vérifiez que vous êtes déjà authentifié et que le projet est défini sur votre ID de projet à l'aide de la commande suivante :
    gcloud auth list
    
  5. 👉💻 Clonez le projet d'amorçage depuis GitHub :
    git clone https://github.com/cuppibla/memory_agent_starter
    
    
  6. 👉💻 Exécutez le script de configuration depuis le répertoire du projet.
    cd ~/memory_agent_starter
    ./init.sh
    
    Le script gérera automatiquement le reste du processus de configuration.
  7. 👉💻 Définissez l'ID du projet nécessaire :
    gcloud config set project $(cat ~/project_id.txt) --quiet
    

Partie 3 : Configurer les autorisations

  1. 👉💻 Activez les API requises à l'aide de la commande suivante. L'opération peut prendre quelques minutes.
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        servicenetworking.googleapis.com \
        run.googleapis.com \
        aiplatform.googleapis.com \
        compute.googleapis.com
    
  2. 👉💻 Accordez les autorisations nécessaires en exécutant les commandes suivantes dans le terminal :
    . ~/memory_agent_starter/set_env.sh
    

Notez qu'un fichier .env a été créé pour vous. Les informations sur votre projet s'affichent.

3. Les bases : session et état

avec état

Le concept : le contexte est primordial

La forme de mémoire la plus basique est la mémoire de session. C'est ce qui permet à un agent de savoir que le pronom "les" dans la phrase "Je veux les acheter" fait référence aux chaussures dont vous parliez il y a 10 secondes.

Dans ADK, nous gérons cela avec l'objet Session.

  • Approche sans état : créer une session pour chaque message.
  • Approche avec état : créer une session et la réutiliser pour l'ensemble de la conversation.

Étape 1 : Examiner l'agent

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

Ouvrez ~/memory_agent_starter/01_session_agent/agent.py.

👉 Recherchez le commentaire # TODO: Create a root agent dans la fonction agent.py.

Remplacez toute cette ligne par le code suivant :

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

L'instruction indique au LLM de se souvenir, mais le code doit fournir la capacité de se souvenir.

Étape 2 : Les deux scénarios

Ouvrez ~/memory_agent_starter/01_session_agent/main.py.

👉 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

Ouvrez ~/memory_agent_starter/01_session_agent/main.py, puis recherchez le commentaire # TODO: Create a runner with in memorysession service dans la fonction main.py.

Remplacez toute cette ligne par le code suivant :

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

👉 Recherchez le commentaire # TODO: create a different session to test dans la fonction main.py.

Remplacez toute cette ligne par le code suivant :

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

Tester

Nous avons deux fonctions qui illustrent la différence entre la mémoire d'un poisson rouge et celle d'un éléphant.

Scénario 1 : Stateful (session partagée)

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, ...)

Scénario 2 : Sans état (nouvelle session à chaque fois)

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, ...)

Étape 3 : Exécuter l'agent

Voyons la différence en action. Exécutez le script :

👉💻 Dans la ligne de commande, exécutez la commande ci-dessous :

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

Observez le scénario 1 : l'agent se souvient de vos préférences du premier message et adapte le plan dans le deuxième message.

Observez le scénario 2 : au deuxième tour ("do you remember what I liked about the food?"), l'agent échoue complètement, car il s'agit d'une nouvelle session. Il indique en fait : "Je ne sais pas de quoi vous parlez."

À retenir

Règle n° 1 de la mémoire : réutilisez toujours session.id pour conserver le contexte de la conversation. L'objet Session est le tampon de mémoire à court terme de votre agent.

4. L'équipe : état multi-agent

nourriture

Le concept : "Le jeu du téléphone"

Lorsque plusieurs agents travaillent ensemble, ils sont comme des collègues qui se passent un dossier. Si un agent écrit une note dans le dossier, l'agent suivant doit pouvoir la lire.

Dans l'ADK, ce "dossier" est l'état.

  • State est un dictionnaire ({"key": "value"}) qui se trouve dans la session.
  • Tous les agents de la session peuvent y lire ou y écrire des données.

Étape 1 : Examiner le workflow

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

👉 Dans le fichier ~/memory_agent_starter/02_multi_agent/agent.py, recherchez le commentaire # TODO: foodie agent.

Remplacez toute cette ligne par le code suivant :

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']
)

👉 Recherchez le commentaire # TODO: transportation agent dans la fonction agent.py.

Remplacez toute cette ligne par le code suivant :

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}.
    """,
)

👉 Recherchez le commentaire # TODO: root_agent dans la fonction agent.py.

Remplacez toute cette ligne par le code suivant :

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."
)

Nous avons maintenant deux agents qui travaillent en séquence :

  1. Agent Foodie : recherche un restaurant.
  2. Agent de transport : fournit un itinéraire vers ce restaurant.

La transition magique : remarquez comment foodie_agent passe le relais à 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" : la réponse de l'agent Foodie est enregistrée efficacement.
  2. {destination} : l'agent de transport lit automatiquement cette réponse.

(Aucune action requise) Étape 2 : L'orchestrateur

Ouvrez 02_multi_agent/main.py.

Nous utilisons un SequentialAgent pour les exécuter dans l'ordre.

# 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, ...)

L'utilisateur envoie un prompt :

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

Les agents travaillent ensemble pour y répondre.

Étape 3 : Diriger l'équipe

👉💻 Dans le terminal Cloud Shell, exécutez le workflow multi-agent :

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

Que se passe-t-il ?

  1. Agent Foodie : trouve "Jin Sho" (ou un restaurant similaire).
  2. ADK : enregistre "Jin Sho" dans state['destination'].
  3. Agent de transport : reçoit "Jin Sho" dans ses instructions.
  4. Résultat : "Pour vous rendre à Jin Sho depuis la gare Caltrain, descendez University Ave…"

À retenir

Règle n° 2 de la mémoire : utilisez l'état pour transmettre des informations structurées entre les agents. Utilisez output_key pour écrire et {placeholders} pour lire.

5. The Reboot - Persistence

avec état

Le concept : "Le problème du redémarrage"

Jusqu'à présent, notre mémoire était InMemory. Si vous arrêtez le script et le redémarrez, l'agent oublie tout. C'est comme un ordinateur qui efface son disque dur chaque fois que vous l'éteignez.

Pour résoudre ce problème, nous avons besoin de la persistance. Nous remplaçons InMemorySessionService par DatabaseSessionService.

Étape 1 : Changement de base de données

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

👉 Dans le fichier ~/memory_agent_starter/03_persistent_agent/main.py, recherchez le commentaire # TODO: Configuration for Persistent Sessions.

Remplacez toute cette ligne par le code suivant :

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}"

Désormais, chaque session et événement est enregistré dans un fichier SQLite.

Étape 2 : Récupération entre sessions

La persistance permet non seulement de reprendre une conversation, mais aussi d'apprendre des conversations passées.

Dans le même fichier ~/memory_agent_starter/03_persistent_agent/main.py, examinez le scénario de test 3 : récupération entre sessions.

👉 Recherchez le commentaire # TODO: retrieve the previous session manually.

Remplacez toute cette ligne par le code suivant :

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

👉 Recherchez le commentaire # TODO: Extract content from the OLD session dans la fonction main.py.

Remplacez toute cette ligne par le code suivant :

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

👉 Recherchez le commentaire # TODO: Manually inject the context to the query dans la fonction main.py.

Remplacez toute cette ligne par le code suivant :

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

Cela simule un utilisateur qui revient plusieurs mois plus tard. Seule une base de données vous permet de récupérer cet historique.

Éthought Analyse de la persistance après redémarrage

👉💻 Dans le terminal, exécutez le script :

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

Il crée un fichier ~/memory_agent_starter/trip_planner.db. À vous de jouer : exécutez le script deux fois.

  • Lors de la deuxième exécution, recherchez "Resumed existing session" (Session existante reprise).
  • L'agent se souviendra du contexte de la première exécution, car il le charge à partir du fichier de base de données.

À retenir

Règle n° 3 de la mémoire : utilisez DatabaseSessionService pour la production. Il garantit que les conversations des utilisateurs survivent aux redémarrages du serveur et permet d'analyser l'historique à long terme.

6. The Spy - Callbacks

avec état

Parfois, vous devez mettre à jour la mémoire automatiquement en fonction de ce que fait l'agent, et pas seulement de ce qu'il dit. Vous voulez un "espion" qui surveille l'agent et prend des notes.

Dans ADK, cet espion est le rappel. adk_callback

  • after_tool_callback : fonction qui s'exécute chaque fois que l'agent fonctionne.
  • ToolContext : un moyen d'écrire dans l'état à partir de cette fonction.

Étape 1 : La logique

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

👉 Dans le fichier ~/memory_agent_starter/04_stateful_agent/agent.py, recherchez le commentaire # TODO: Implement call back logic.

Remplacez toute cette ligne par le code suivant :

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

👉 Dans le même fichier, recherchez le commentaire # TODO: add callback to root agent dans la fonction 04_stateful_agent/agent.py.

Remplacez toute cette ligne par le code suivant :

    after_tool_callback=save_activity_type_callback,

Instruction dynamique : l'instruction de l'agent est désormais une fonction, et non une chaîne. Il change en fonction de l'état.

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.
    """

Étape 3 : Tester l'espion

👉💻 Dans le terminal, exécutez le script en copiant et collant la commande ci-dessous :

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

Lorsque vous exécutez cet agent, vous voyez une boucle.

  1. Tour 1 : vous demandez un musée. Ensembles d'espionnage last_activity="CULTURAL".
  2. Tour 2 : Vous demandez un autre musée.
  3. Mises à jour des instructions de l'agent : "CULTURAL is BANNED".
  4. L'agent dit : "Je ne peux pas faire un autre musée. Que dirais-tu d'un parc ?"

Surveillez les journaux de la console pour [CALLBACK] et [STATE UPDATE]. Vous pouvez voir la mémoire changer en temps réel à mesure que l'agent travaille.

À retenir

Règle n° 4 de la mémoire : utilisez des rappels pour automatiser la gestion de l'état. Votre agent crée son propre contexte simplement en effectuant son travail.

7. Le classeur : outils personnalisés

Le concept : "mémoire structurée"

avec état

Jusqu'à présent, la "mémoire" était un journal de chat ou une simple paire clé-valeur. Mais que faire si vous devez mémoriser un profil utilisateur complexe ? Par exemple, diet: vegan, budget: high, pets: [cat, dog].

Pour ce faire, nous traitons la mémoire comme un outil. L'agent décide explicitement quand ouvrir le classeur (lire) et quand classer un rapport (écrire). schéma des outils personnalisés

Étape 1 : Les outils

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

👉 Dans ce fichier : ~/memory_agent_starter/05_profile_agent/tools.py.

Nous devons implémenter ces deux outils spécifiques :

  1. save_user_preferences : écrit dans une base de données.
  2. recall_user_preferences : lit les données d'une base de données.

Recherchez le commentaire # TODO: implement save_user_preferences tools dans la fonction ~/memory_agent_starter/05_profile_agent/tools.py.

Remplacez toute cette ligne par le code suivant :

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())}"

👉 Recherchez le commentaire # TODO: implement recall_user_preferences tools dans la fonction 05/tools.py.

Remplacez toute cette ligne par le code suivant :

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

L'instruction force un 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`.
"""

Étape 2 : Exécution

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

Ouvrez ~/memory_agent_starter/05_profile_agent/main.py.

Contrairement aux modules précédents où ADK gérait l'état automatiquement, ici, c'est l'agent qui contrôle.

  • Il choisit d'appeler recall_user_preferences au début.
  • Il choisit d'appeler save_user_preferences lorsque vous dites "Je suis végan".

Étape 3 : Créez le profil

👉💻 Exécutez le script :

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

Essayez ce flux de conversation :

  1. "Salut, planifie un dîner." -> L'agent vérifie la base de données, mais ne trouve rien. Demande des préférences.
  2. "Je suis végan." -> L'agent enregistre "vegan" dans la base de données.
  3. Redémarrez le script.
  4. "Salut, planifie un dîner." -> L'agent vérifie la base de données, voit "végan" et suggère immédiatement un restaurant végan.

À retenir

Règle n° 5 de la mémoire : pour les données structurées complexes, fournissez à votre agent des outils de lecture/écriture. Laissez le LLM gérer son propre stockage à long terme.

8. Le cerveau : mémoire multimodale

avec état

Le concept : "L'expérience humaine"

Les humains se souviennent de plus que du texte. Nous nous souvenons de l'ambiance d'une photo, du son d'une voix, de l'émotion d'une vidéo.

Vertex AI Memory Bank permet à votre agent de gérer la mémoire multimodale. Il peut ingérer des images, des vidéos et des fichiers audio, les "comprendre" et les récupérer ultérieurement.

Étape 1 : Configuration

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

👉 Ouvrez 06_multimodal_agent/main.py. Recherchez le commentaire # TODO: Configure Memory Bank Topic.

Remplacez toute cette ligne par le code suivant :

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""",
        )
    ),
]

Recherchez le commentaire # TODO: Configure Memory Bank Customization.

Remplacez toute cette ligne par le code suivant :

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"
    },
}

Étape 2 : Ingérer le monde

Dans test_trip_planner, nous envoyons :

  1. Un message ("Bonjour")
  2. Image (repère)
  3. Vidéo (Mer Méditerranée)
  4. Un clip audio (note vocale sur Gaeta)

Recherchez le commentaire # TODO create session service and memory service dans la fonction 6_multimodal_agent/main.py.

Remplacez toute cette ligne par le code suivant :

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
)

👉 Dans le même fichier 06_multimodal_agent/main.py, recherchez le commentaire # TODO: create memory from session.

Remplacez toute cette ligne par le code suivant :

    await memory_service.add_session_to_memory(final_session_state)

C'est la ligne magique. Il envoie tous ces rich media à Vertex AI, qui les traite et les indexe.

Étape 3 : Récupération

👉💻 Dans votre terminal Cloud Shell, ouvrez le fichier dans l'éditeur Cloud Shell en exécutant la commande suivante :

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

L'agent dispose d'un PreloadMemoryTool.

tools=[PreloadMemoryTool(), budget_tool]

Lorsqu'une nouvelle session démarre, cet outil recherche automatiquement dans la banque de mémoire les expériences passées pertinentes et les injecte dans le contexte.

Étape 4 : Exécuter le cerveau

👉💻 Dans votre terminal Cloud Shell, exécutez le script (remarque : cela nécessite un projet Google Cloud avec Vertex AI activé) :

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

Regardez la dernière étape de validation :

"En fonction de l'image, de la vidéo ET de l'audio que je t'ai partagés précédemment..."

L'agent répondra :

"Vous devriez visiter Gaète ! Tu m'as montré une vidéo de la mer Méditerranée et un clip audio dans lequel tu disais que tu adorais Gaète."

Il a permis de relier les différents types de supports du passé.

À retenir

Règle n° 6 de la mémoire : utilisez Vertex AI Memory Bank pour une expérience de mémoire optimale. Il unifie le texte, les images et les vidéos dans un seul cerveau interrogeable.

9. Conclusion

Vous êtes passé d'un poisson rouge qui oublie tout à un éléphant multimodal.

Vous avez créé

La fonctionnalité

Agent de session

Mémoire conversationnelle à court terme

Multi-agent

Mémoire d'équipe partagée

Agent persistant

Historique à long terme

Agent avec état

Mémoire dynamique à mise à jour automatique

Agent de profil

Mémoire de données structurées

Agent multimodal

Mémoire sensorielle de type humain

La confiance repose sur la mémoire. En implémentant ces modèles, vous créez des agents qui respectent le temps et l'historique de l'utilisateur, ce qui permet des interactions plus approfondies et plus efficaces.

Commencez à créer vos agents personnalisés dès aujourd'hui.