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

1. Introduction

title

Le problème du poisson rouge

Imaginez que vous fassiez appel à une agence de voyages pour planifier le séjour 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 au palais impérial et un dîner de sushis à Sukiyabashi Jiro."

Vous souriez et dites :

"Parfait ! Peux-tu m'envoyer l'itinéraire ?"

L'agent vous regarde sans rien dire et vous demande :

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

C'est ce qu'on appelle le "problème du poisson rouge". Sans mémoire, chaque interaction est une page blanche. L'intelligence est là : l'agent sait comment planifier des voyages, mais la continuité fait défaut. Pour qu'un agent IA soit vraiment utile, il doit se souvenir des informations.

Votre mission aujourd'hui

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 allez passer par six niveaux de mémoire de l'agent pour créer un système qui se comporte moins comme un chatbot et plus comme un assistant personnel dédié.

Niveau

Concept

Le "Superpouvoir"

Niveau 1

Session et état

Tenir une conversation sans rien oublier

Niveau 2

État multi-agent

Partager des notes entre les membres de l'équipe

Niveau 3

Persistance

Mémorisation de vos préférences, 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

Lecture et écriture de profils utilisateur structurés

Niveau 6

Mémoire multimodale

"Voir" et se souvenir des photos et des vidéos

Pile de mémoire ADK

Avant d'écrire du code, comprenons les outils que nous utilisons. Le Google Agent Development Kit (ADK) fournit une méthode structurée pour gérer la mémoire :

  1. Session : conteneur d'une conversation. Il contient l'historique de ce qui a été dit.
  2. État : "bloc-notes" 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 indéfiniment, comme les préférences utilisateur ou les documents analysés.

2. Configurer

Pour alimenter nos agents d'IA, nous avons besoin de deux éléments : un projet Google Cloud pour fournir les bases.

Première partie : Activer le compte de facturation

  • Revendiquez votre compte de facturation avec un crédit de 5 $, dont vous aurez besoin pour votre déploiement. Assurez-vous d'utiliser votre compte Gmail.

Deuxième partie : Environnement ouvert

  1. 👉 Cliquez sur ce lien pour accéder directement à l'éditeur Cloud Shell.
  2. 👉 Si vous êtes invité à autoriser l'accès à un moment donné 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 bootstrap depuis GitHub :
    git clone https://github.com/cuppibla/memory_agent_starter
    
    
  6. 👉💻 Exécutez le script de configuration à partir du répertoire du projet.
    cd ~/memory_agent_starter
    ./init.sh
    
    Le script gère automatiquement le reste du processus de configuration.
  7. 👉💻 Définissez l'ID de projet requis :
    gcloud config set project $(cat ~/project_id.txt) --quiet
    

Troisième partie : 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. Bases : session et état

avec état

Le concept : le contexte est roi

La forme la plus élémentaire de mémoire est la mémoire de session. C'est ce qui permet à un agent de savoir que "il" dans la phrase "Je veux l'acheter" fait référence à la chaussure dont vous parliez 10 secondes auparavant.

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

  • Approche sans état : création d'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.

👉 Localisez 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
    )

👉 Localisez 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 "Poisson rouge" et la mémoire "Éléphant".

Scénario 1 : Avec état (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écutez 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

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

Observer le scénario 2 : lors du 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. En gros, cela signifie "Je ne sais pas de quoi vous parlez".

Point clé

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

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

nourriture

Le concept : "Le téléphone arabe"

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

Dans ADK, ce "dossier" correspond à l'état.

  • State est un dictionnaire ({"key": "value"}) qui se trouve dans la session.
  • Tout agent de la session peut lire ou écrire dans la session.

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

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

👉 Localisez 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 : trouve un restaurant.
  2. Agent de transport : fournit l'itinéraire vers le restaurant.

Le transfert magique : notez 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 : Orchestrator

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 une requête :

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

Les agents travaillent ensemble pour y répondre.

Étape 3 : Exécutez 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…"

Point clé

Règle 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. Redémarrage : persistance

avec état

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

Jusqu'à présent, notre mémoire était de 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 Persistence. Nous remplaçons InMemorySessionService par DatabaseSessionService.

Étape 1 : Passer à la nouvelle 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 chaque événement sont enregistrés dans un fichier SQLite.

Étape 2 : Récupération inter-sessions

La persistance permet non seulement de reprendre une conversation, mais aussi d'apprendre à partir des précédentes.

Dans le même fichier~/memory_agent_starter/03_persistent_agent/main.py, examinez Test Case 3: Cross-Session Retrieval (Cas de test 3 : Récupération intersession).

👉 Localisez 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
    )

👉 Localisez 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"

👉 Localisez 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 des mois plus tard. Seule une base de données vous permet de récupérer cet ancien historique.

Étape 3 : Survivre au 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. Essayez ceci : 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 se charge à partir du fichier de base de données.

Point clé

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

6. The Spy : rappels

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 souhaitez un "espion" qui observe l'agent et prend des notes.

Dans ADK, cette fonction espion est le Callback. adk_callback

  • after_tool_callback : fonction qui s'exécute chaque fois que l'agent fonctionne.
  • ToolContext : méthode pour é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,

L'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 : Testez le Spy

👉💻 Dans le terminal, exécutez le script en copiant et en 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, une boucle s'affiche.

  1. Tour 1 : Vous demandez un musée. Définit les ensembles d'espionnage last_activity="CULTURAL".
  2. Tour 2 : vous demandez un autre musée.
  3. Mise à jour des instructions pour les agents : "CULTURAL est BANNED".
  4. L'agent répond : "Je ne peux pas vous proposer un autre musée. Que dirais-tu d'un parc ?"

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

Point clé

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

7. Classeur à tiroirs : outils personnalisés

Le concept : "Mémoire structurée"

avec état

Jusqu'à présent, la "mémoire" était un journal de discussion ou une simple paire clé/valeur. Mais que se passe-t-il 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 (lecture) et quand déposer un rapport (écriture). Diagramme 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.

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

👉 Localisez 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ù l'ADK gérait automatiquement l'état, c'est ici l'Agent qui est aux commandes.

  • 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. "Bonjour, planifie un dîner." -> L'agent vérifie la base de données et 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. "Bonjour, planifie un dîner." -> L'agent consulte la base de données, voit "vegan" et suggère immédiatement un restaurant vegan.

Point clé

Règle 5 de la mémoire : pour les données complexes et structurées, 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.

La banque de mémoire Vertex AI 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 texte ("Bonjour")
  2. Une image (repère)
  3. Vidéo (mer Méditerranée)
  4. Un clip audio (note vocale sur Gaeta)

Localisez 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 contenus multimédias enrichis à Vertex AI, qui les traite et les indexe.

Étape 3 : La 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 a un PreloadMemoryTool.

tools=[PreloadMemoryTool(), budget_tool]

Lorsqu'une nouvelle session commence, cet outil recherche automatiquement les expériences passées pertinentes dans la mémoire 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 :

"Sur la base de l'image, de la vidéo ET de l'audio que je t'ai envoyés avant…"

L'agent répond :

"Tu devrais visiter Gaeta ! Tu m'as montré une vidéo de la mer Méditerranée et un extrait audio dans lequel tu disais aimer Gaeta."

Il a fait le lien entre différents types de médias du passé.

Point clé

Règle 6 de Memory : 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 amnésique à un éléphant multimodal.

Vous avez créé

Fonctionnalité

Agent de session

Mémoire à court terme des conversations

Multi-Agent

Mémoire d'équipe partagée

Agent persistant

Historique à long terme

Agent avec état

Mémoire dynamique et auto-actualisée

Agent de profil

Mémoire de données structurées

Agent multimodal

Mémoire sensorielle semblable à celle d'un 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 !