1. Introduzione

Il problema del "pesce rosso"
Immagina di assumere un'agenzia viaggi per pianificare la tua vacanza da sogno a Tokyo. Utilizza l'agente di sessione per vedere "The Goldfish Problem" in azione.
Entri nel suo ufficio e dici:
"Ciao! Voglio pianificare un viaggio di 2 giorni a Tokyo. Mi interessano i siti storici e il sushi."
L'agente risponde con entusiasmo:
"Great! Ho programmato una visita al Palazzo Imperiale e una cena a base di sushi da Sukiyabashi Jiro."
Sorridi e dici:
"Sembra perfetto! Puoi inviarmi l'itinerario?"
L'agente ti guarda con aria assente e ti chiede:
"Ciao! Come posso aiutarti a pianificare un viaggio oggi?"
Questo è il "problema del pesce rosso". Senza memoria, ogni interazione è una tabula rasa. L'intelligenza c'è: l'agente sa come pianificare i viaggi, ma manca la continuità. Per essere veramente utile, un agente AI deve ricordare.
La tua missione di oggi
In questo workshop, risolverai il problema del pesce rosso creando un'agenzia viaggi che ricorda, impara e si adatta. Passerai attraverso 6 livelli di memoria dell'agente, creando un sistema che si comporta meno come un chatbot e più come un assistente personale dedicato.
Livello | Concetto | Il "superpotere" |
Livello 1 | Session & State | Sostenere una conversazione senza dimenticare |
Livello 2 | Stato multi-agente | Condivisione di note tra i membri del team |
Livello 3 | Persistenza | Ricordare le tue preferenze anche dopo il riavvio del sistema |
Livello 4 | Callback | Aggiornamento della memoria in modo completamente autonomo |
Livello 5 | Strumenti personalizzati | Lettura e scrittura di profili utente strutturati |
Livello 6 | Memoria multimodale | "Vedere" e ricordare foto e video |
Lo stack di memoria ADK
Prima di scrivere il codice, cerchiamo di capire gli strumenti che stiamo utilizzando. Google Agent Development Kit (ADK) fornisce un modo strutturato per gestire la memoria:
- Sessione: il contenitore di una conversazione. Contiene la cronologia di ciò che è stato detto.
- Stato: un "blocco note" coppia chiave-valore collegato alla sessione. Gli agenti utilizzano questa memoria per archiviare informazioni specifiche (ad es.
destination="Tokyo"). - MemoryService: archiviazione a lungo termine. È qui che conserviamo i dati in modo permanente, ad esempio le preferenze utente o i documenti analizzati.
2. Configura
Per alimentare i nostri agenti AI, abbiamo bisogno di due cose: un progetto Google Cloud che fornisca le basi.
Parte 1: attiva l'account di fatturazione
Per eseguire questo codelab, devi disporre di un account di fatturazione con un po' di credito. Per iniziare, utilizza i crediti del banner nella parte superiore di questo codelab. Se hai già un collegamento a un account di fatturazione, puoi saltare questo passaggio.
Parte 2: Ambiente aperto
- 👉 Fai clic su questo link per andare direttamente all'editor di Cloud Shell
- 👉 Se ti viene richiesto di concedere l'autorizzazione in qualsiasi momento oggi, fai clic su Autorizza per continuare.

- 👉 Se il terminale non viene visualizzato nella parte inferiore dello schermo, aprilo:
- Fai clic su Visualizza.
- Fai clic su Terminale

- 👉💻 Nel terminale, verifica di aver già eseguito l'autenticazione e che il progetto sia impostato sul tuo ID progetto utilizzando il seguente comando:
gcloud auth list - 👉💻 Clona il progetto bootstrap da GitHub:
git clone https://github.com/cuppibla/memory_agent_starter - 👉💻 Esegui lo script di configurazione dalla directory del progetto.
Lo script gestirà automaticamente il resto della procedura di configurazione.cd ~/memory_agent_starter ./init.sh - 👉💻 Imposta l'ID progetto necessario:
gcloud config set project $(cat ~/project_id.txt) --quiet
Parte 3: configura l'autorizzazione
- 👉💻 Abilita le API richieste utilizzando il seguente comando. L'operazione potrebbe richiedere alcuni minuti.
gcloud services enable \ cloudresourcemanager.googleapis.com \ servicenetworking.googleapis.com \ run.googleapis.com \ aiplatform.googleapis.com \ compute.googleapis.com - 👉💻 Concedi le autorizzazioni necessarie eseguendo i seguenti comandi nel terminale:
. ~/memory_agent_starter/set_env.sh
Tieni presente che viene creato un file .env. che mostra le informazioni sul progetto.
3. Le fondamenta: sessione e stato

Il concetto: il contesto è fondamentale
La forma più elementare di memoria è la memoria della sessione. In questo modo, un agente può sapere che "lo" nella frase "Voglio comprarlo" si riferisce alla scarpa di cui parlavi 10 secondi fa.
In ADK, gestiamo questo aspetto con l'oggetto Session.
- Approccio stateless: creazione di una nuova sessione per ogni messaggio.
- Approccio stateful: crea una sessione e riutilizzala per l'intera conversazione.
Passaggio 1: esamina l'agente
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/01_session_agent/agent.py
Apri ~/memory_agent_starter/01_session_agent/agent.py.
👉 Individua il commento # TODO: Create a root agent all'interno della funzione agent.py.
Sostituisci l'intera riga con il seguente codice:
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'istruzione indica all'LLM di ricordare, ma il codice deve fornire la funzionalità per ricordare.
Passaggio 2: i due scenari
Apri ~/memory_agent_starter/01_session_agent/main.py.
👉 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/01_session_agent/main.py
Apri ~/memory_agent_starter/01_session_agent/main.py, individua il commento # TODO: Create a runner with in memorysession service all'interno della funzione main.py.
Sostituisci l'intera riga con il seguente codice:
runner = Runner(
agent=agent,
session_service=session_service,
app_name=agent.name
)
👉 Individua il commento # TODO: create a different session to test all'interno della funzione main.py.
Sostituisci l'intera riga con il seguente codice:
tokyo_session_2 = await session_service.create_session(
app_name=multi_day_agent.name,
user_id=user_id
)
Provalo
Abbiamo due funzioni che mostrano la differenza tra la memoria "Goldfish" ed "Elephant".
Scenario 1: stateful (sessione condivisa)
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, ...)
Scenario 2: stateless (nuova sessione ogni volta)
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, ...)
Passaggio 3: esegui l'agente
Vediamo la differenza in azione. Esegui lo script:
👉💻 Nella riga di comando, esegui il comando seguente:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/01_session_agent/main.py
Osserva lo scenario 1: l'agente ricorda le tue preferenze dal primo messaggio e adatta il piano nel secondo messaggio.
Osserva lo scenario 2: nel secondo turno ("ti ricordi cosa mi è piaciuto del cibo?"), l'agente fallisce completamente perché si tratta di una nuova sessione. In pratica, dice: "Non so di cosa stai parlando".
Concetto chiave
Regola n. 1 della memoria: riutilizza sempre session.id per mantenere il contesto della conversazione. L'oggetto Session è il buffer di memoria a breve termine dell'agente.
4. Il team: stato multi-agente

Il concetto: "Il gioco del telefono"
Quando più agenti lavorano insieme, sono come colleghi che si passano una cartella di file. Se un agente scrive una nota nella cartella, l'agente successivo dovrebbe essere in grado di leggerla.
In ADK, questa "cartella" è lo stato.
- State è un dizionario (
{"key": "value"}) che si trova all'interno della sessione. - Qualsiasi agente nella sessione può leggere o scrivere nella sessione.
Passaggio 1: esamina il workflow
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/02_multi_agent/agent.py
👉Nel file ~/memory_agent_starter/02_multi_agent/agent.py, individua il commento # TODO: foodie agent.
Sostituisci l'intera riga con il seguente codice:
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']
)
👉 Individua il commento # TODO: transportation agent all'interno della funzione agent.py.
Sostituisci l'intera riga con il seguente codice:
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}.
""",
)
👉 Individua il commento # TODO: root_agent all'interno della funzione agent.py.
Sostituisci l'intera riga con il seguente codice:
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."
)
Ora abbiamo due agenti che lavorano in sequenza:
- Agente Foodie: trova un ristorante.
- Agente di trasporto: fornisce le indicazioni stradali per raggiungere il ristorante.
Il passaggio di testimone magico: nota come foodie_agent passa il testimone a 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...
""",
)
output_key="destination": la risposta dell'agente Foodie viene salvata in modo efficiente.{destination}: l'agente di trasporto legge automaticamente la risposta.
(Nessuna azione richiesta) Passaggio 2: l'orchestratore
Apri 02_multi_agent/main.py.
Utilizziamo un SequentialAgent per eseguirli in ordine.
# 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'utente invia un prompt:
"Find best sushi in Palo Alto and then tell me how to get there."
Gli agenti collaborano per rispondere.
Passaggio 3: gestisci il team
👉💻 Nel terminale Cloud Shell, esegui il workflow multi-agente:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/02_multi_agent/main.py
Che cosa succede?
- Agente Foodie: trova "Jin Sho" (o simili).
- ADK: salva "Jin Sho" in
state['destination']. - Agente di trasporto: riceve "Jin Sho" nella sua istruzione.
- Risultato: "Per raggiungere Jin Sho dalla stazione Caltrain, cammina lungo University Ave…"
Concetto chiave
Regola n. 2 della memoria: utilizza State per passare informazioni strutturate tra gli agenti. Utilizza output_key per scrivere e {placeholders} per leggere.
5. Riavvio - Persistenza

Il concetto: "Il problema del riavvio"
Finora, la nostra memoria è stata InMemory. Se interrompi lo script e lo riavvii, l'agente dimentica tutto. È come un computer che cancella il disco rigido ogni volta che lo spegni.
Per risolvere questo problema, abbiamo bisogno della persistenza. Sostituiamo InMemorySessionService con DatabaseSessionService.
Passaggio 1: cambio di database
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/03_persistent_agent/main.py
👉 Nel file ~/memory_agent_starter/03_persistent_agent/main.py, individua il commento # TODO: Configuration for Persistent Sessions.
Sostituisci l'intera riga con il seguente codice:
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}"
Ora ogni sessione ed evento viene salvato in un file SQLite.
Passaggio 2: recupero tra sessioni
La persistenza consente non solo di riprendere una conversazione, ma anche di imparare da quelle passate.
Nello stesso file ~/memory_agent_starter/03_persistent_agent/main.py, guarda Scenario di test 3: Cross-Session Retrieval.
👉 Individua il commento # TODO: retrieve the previous session manually
Sostituisci l'intera riga con il seguente codice:
old_session = await session_service.get_session(
app_name=root_agent.name, user_id="user_01", session_id=session_id
)
👉 Individua il commento # TODO: Extract content from the OLD session all'interno della funzione main.py.
Sostituisci l'intera riga con il seguente codice:
previous_context += f"- {role}: {text}\n"
👉 Individua il commento # TODO: Manually inject the context to the query all'interno della funzione main.py.
Sostituisci l'intera riga con il seguente codice:
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?
"""
In questo modo, simuli un utente che torna dopo mesi. Solo con un database puoi recuperare la cronologia precedente.
Passaggio 3: sopravvivere al riavvio
👉💻 Nel terminale, esegui lo script:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/03_persistent_agent/main.py
Crea un file ~/memory_agent_starter/trip_planner.db. Prova questo: esegui lo script due volte.
- Alla seconda esecuzione, cerca "Resumed existing session".
- L'agente ricorderà il contesto della prima esecuzione perché lo carica dal file del database.
Concetto chiave
Regola n. 3 di Memory: utilizza DatabaseSessionService per la produzione. In questo modo, le conversazioni degli utenti vengono conservate anche dopo il riavvio del server e viene abilitata l'analisi della cronologia a lungo termine.
6. The Spy - Callbacks

A volte è necessario aggiornare la memoria automaticamente in base a ciò che l'agente fa, non solo a ciò che dice. Vuoi una "spia" che osservi l'agente e prenda appunti.
In ADK, questa spia è il callback. 
after_tool_callback: una funzione che viene eseguita ogni volta che l'agente lavora.ToolContext: un modo per scrivere nello stato dall'interno della funzione.
Passaggio 1: logica
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/04_stateful_agent/agent.py
👉 Nel file ~/memory_agent_starter/04_stateful_agent/agent.py, individua il commento # TODO: Implement call back logic
Sostituisci l'intera riga con il seguente codice:
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
👉 Nello stesso file, individua il commento # TODO: add callback to root agent all'interno della funzione 04_stateful_agent/agent.py.
Sostituisci l'intera riga con il seguente codice:
after_tool_callback=save_activity_type_callback,
Istruzione dinamica: l'istruzione dell'agente è ora una funzione, non una stringa. Cambia in base allo stato.
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.
"""
Passaggio 3: testa lo spia
👉💻 Nel terminale, esegui lo script copiando e incollando il comando seguente:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/04_stateful_agent/main.py
Quando esegui questo agente, vedrai un loop.
- Turno 1: chiedi un museo. La spia imposta
last_activity="CULTURAL". - Turno 2: chiedi di un altro museo.
- Aggiornamenti delle istruzioni per l'agente: "CULTURAL is BANNED".
- L'agente dice: "Non posso visitare un altro museo. Che ne dici di un parco?"
Controlla i log della console per [CALLBACK] e [STATE UPDATE]. Puoi vedere la memoria cambiare in tempo reale mentre l'agente lavora.
Concetto chiave
Regola n. 4 della memoria: utilizza i callback per automatizzare la gestione dello stato. L'agente crea il proprio contesto semplicemente svolgendo il suo lavoro.
7. Schedario - Strumenti personalizzati
Il concetto: "Memoria strutturata"

Finora, la "memoria" è stata un log di chat o una semplice coppia chiave-valore. Ma cosa succede se devi ricordare un profilo utente complesso? Ad esempio, diet: vegan, budget: high, pets: [cat, dog].
Per questo, trattiamo la memoria come uno strumento. L'agente decide esplicitamente quando aprire lo schedario (lettura) e quando archiviare un report (scrittura). 
Passaggio 1: gli strumenti
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/05_profile_agent/tools.py
👉 In questo file: ~/memory_agent_starter/05_profile_agent/tools.py.
Dobbiamo implementare questi due strumenti specifici:
save_user_preferences: scrive in un database.recall_user_preferences: legge da un database.
Individua il commento # TODO: implement save_user_preferences tools all'interno della funzione ~/memory_agent_starter/05_profile_agent/tools.py.
Sostituisci l'intera riga con il seguente codice:
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())}"
👉 Individua il commento # TODO: implement recall_user_preferences tools all'interno della funzione 05/tools.py.
Sostituisci l'intera riga con il seguente codice:
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'istruzione forza 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`.
"""
Passaggio 2: l'esecuzione
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/05_profile_agent/main.py
Apri ~/memory_agent_starter/05_profile_agent/main.py.
A differenza dei moduli precedenti in cui l'ADK gestiva lo stato automaticamente, qui è l'agente ad avere il controllo.
- Sceglie di chiamare
recall_user_preferencesall'inizio. - Sceglie di chiamare
save_user_preferencesquando dici "Sono vegano".
Passaggio 3: crea il profilo
👉💻 Esegui lo script:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/05_profile_agent/main.py
Prova questo flusso di conversazione:
- "Ciao, organizza una cena." -> L'agente controlla il database, ma non trova nulla. Chiede le preferenze.
- "Sono vegano." -> L'agente salva "vegana" nel database.
- Riavvia lo script.
- "Ciao, organizza una cena." -> L'agente controlla il database, vede "vegano" e suggerisce immediatamente un ristorante vegano.
Concetto chiave
Regola n. 5 della memoria: per dati complessi e strutturati, fornisci all'agente strumenti di lettura/scrittura. Consenti all'LLM di gestire il proprio spazio di archiviazione a lungo termine.
8. Il cervello: memoria multimodale

Il concetto: "The Human Experience"
Gli esseri umani ricordano più del testo. Ricordiamo l'atmosfera di una foto, il suono di una voce, la sensazione di un video.
Vertex AI Memory Bank consente all'agente di gestire la memoria multimodale. Può importare immagini, video e audio, "comprenderli" e recuperarli in un secondo momento.
Passaggio 1: la configurazione
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/06_multimodal_agent/main.py
👉 Apri 06_multimodal_agent/main.py. Individua il commento # TODO: Configure Memory Bank Topic.
Sostituisci l'intera riga con il seguente codice:
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""",
)
),
]
Individua il commento # TODO: Configure Memory Bank Customization
Sostituisci l'intera riga con il seguente codice:
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"
},
}
Passaggio 2: importazione del mondo
In test_trip_planner, inviamo:
- Un messaggio ("Ciao")
- Un'immagine (punto di riferimento)
- Un video (Mar Mediterraneo)
- Un clip audio (nota vocale su Gaeta)
Individua il commento # TODO create session service and memory service all'interno della funzione 6_multimodal_agent/main.py.
Sostituisci l'intera riga con il seguente codice:
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
)
👉 Nello stesso file 06_multimodal_agent/main.py, individua il commento # TODO: create memory from session
Sostituisci l'intera riga con il seguente codice:
await memory_service.add_session_to_memory(final_session_state)
Questa è la linea magica. Invia tutti questi rich media a Vertex AI, che li elabora e li indicizza.
Passaggio 3: recupero
👉💻 Nel terminale di Cloud Shell, apri il file nell'editor di Cloud Shell eseguendo:
cloudshell edit ~/memory_agent_starter/06_multimodal_agent/agent.py
L'agente ha un PreloadMemoryTool.
tools=[PreloadMemoryTool(), budget_tool]
Quando inizia una nuova sessione, questo strumento cerca automaticamente nella banca della memoria le esperienze passate pertinenti e le inserisce nel contesto.
Passaggio 4: esegui il cervello
👉💻 Nel terminale Cloud Shell, esegui lo script (nota: è necessario un progetto Google Cloud con Vertex AI abilitato):
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/06_multimodal_agent/main.py
Guarda il passaggio finale della verifica:
"In base all'immagine, al video E all'audio che ho condiviso con te in precedenza…"
L'agente risponderà:
"Dovresti visitare Gaeta! Mi hai mostrato un video del Mar Mediterraneo e un'audio clip in cui dicevi di amare Gaeta."
Ha collegato i punti tra diversi tipi di media del passato.
Concetto chiave
Regola n. 6 della memoria: utilizza Vertex AI Memory Bank per un'esperienza di memoria ottimale. Unifica testo, immagini e video in un unico cervello ricercabile.
9. Conclusione
Hai fatto un viaggio da un pesce rosso smemorato a un elefante multimodale.
Hai creato | La funzionalità |
Session Agent | Memoria conversazionale a breve termine |
Multi-agente | Memoria condivisa del team |
Persistent Agent | Cronologia a lungo termine |
Agente stateful | Memoria dinamica con aggiornamento automatico |
Profile Agent | Memoria dei dati strutturati |
Agente multimodale | Memoria sensoriale simile a quella umana |
La fiducia si basa sulla memoria. Implementando questi pattern, crei agenti che rispettano il tempo e la cronologia dell'utente, portando a interazioni più profonde ed efficaci.
Inizia a creare i tuoi agenti personalizzati oggi stesso.