1. Introduzione

Il problema del "pesce rosso"
Immagina di assumere un agente di viaggi per pianificare la vacanza dei tuoi sogni a Tokyo. Utilizza l'agente di sessione per vedere "Il problema del pesce rosso" in azione.
Entri nel suo ufficio e dici:
"Ciao! Voglio pianificare un viaggio di due giorni a Tokyo. Mi interessano i siti storici e il sushi".
L'agente risponde con entusiasmo:
"Great! Ho pianificato una visita al Palazzo imperiale e una cena a base di sushi da Sukiyabashi Jiro".
Sorriderai e dirai:
"Sembra perfetto! Puoi inviarmi l'itinerario?"
L'agente ti guarda senza espressione 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 è presente: l'agente sa come pianificare i viaggi, ma manca la continuità. Affinché un agente AI sia davvero utile, deve ricordare.
La tua missione di oggi
In questo workshop, risolverai il problema del pesce rosso creando un agente di viaggi che ricorda, impara e si adatta. Avanzerai 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 | Sessione e stato | Avere una conversazione senza dimenticare |
Livello 2 | Stato multi-agente | Condividere note tra i membri del team |
Livello 3 | Persistenza | Ricordarti 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 della memoria ADK
Prima di scrivere il codice, vediamo gli strumenti che utilizzeremo. 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" di coppie chiave-valore collegato alla sessione. Gli agenti lo utilizzano per memorizzare fatti specifici (ad es.
destination="Tokyo"). - MemoryService: archiviazione a lungo termine. Qui conserviamo i dati per sempre, 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 per fornire le basi.
Parte 1: abilita l'account di fatturazione
- Per richiedere il tuo account di fatturazione con un credito di 5 $, ti servirà per il deployment. Assicurati di accedere al tuo account Gmail.
Parte 2: Open Environment
- 👉 Fai clic su questo link per passare direttamente all'editor di Cloud Shell
- 👉 Se ti viene richiesto di concedere l'autorizzazione in qualsiasi momento della giornata, 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 di 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: configurazione dell'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 questi comandi nel terminale:
. ~/memory_agent_starter/set_env.sh
Nota che viene creato un file .env. Vengono visualizzate le informazioni del progetto.
3. Le basi: sessione e stato

Il concetto: il contesto è fondamentale
La forma più semplice di memoria è la memoria di sessione. È ciò che consente a un agente di sapere che "it" nella frase "I want to buy it" si riferisce alla scarpa di cui stavi parlando 10 secondi prima.
In ADK, questa operazione viene gestita con l'oggetto Session.
- Approccio stateless: creazione di una nuova sessione per ogni messaggio.
- Approccio stateful: creazione di una sessione e riutilizzo 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 al LLM di ricordare, ma il codice deve fornire la capacità di 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
)
Testalo
Abbiamo due funzioni che dimostrano la differenza tra la memoria "Pesce rosso" e "Elefante".
Scenario 1: con stato (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: senza stato (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 riportato di seguito:
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 piaceva del cibo?"), l'agente non riesce a rispondere perché si tratta di una nuova sessione. In pratica, dice: "Non so di cosa stai parlando".
Punti chiave
Regola n. 1 della Memoria:riutilizza sempre il session.id per mantenere il contesto della conversazione. L'oggetto Session è il buffer della memoria a breve termine dell'agente.
4. Il team - Stato multi-agente

Il concept: "Il gioco del telefono"
Quando più agenti lavorano insieme, si comportano come colleghi che si scambiano una cartella di file. Se un agente scrive una nota nella cartella, l'agente successivo dovrebbe essere in grado di leggerla.
Nell'ADK, questa "cartella" è lo stato.
- State è un dizionario (
{"key": "value"}) che si trova all'interno della sessione. - Qualsiasi agente della sessione può leggerlo o scriverci.
Passaggio 1: esamina il flusso di lavoro
👉💻 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:
- Foodie Agent: trova un ristorante.
- Agente di trasporto: fornisce indicazioni stradali per raggiungere il ristorante.
Il passaggio 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 necessaria) 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: esegui la squadra
👉💻 Nel terminale Cloud Shell, esegui il flusso di lavoro multiagente:
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" nelle istruzioni.
- Risultato: "Per arrivare a Jin Sho dalla stazione Caltrain, percorri University Ave..."
Punti chiave
Regola n. 2 della memoria:utilizza State per trasferire informazioni strutturate tra gli agenti. Utilizza output_key per scrivere e {placeholders} per leggere.
5. Il riavvio - Persistenza

Il concetto: "Il problema del riavvio"
Finora, la nostra memoria è stata di 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 il problema, abbiamo bisogno di Persistenza. Sostituiamo InMemorySessionService con DatabaseSessionService.
Passaggio 1: il 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, consulta Scenario di test 3: recupero tra sessioni.
👉 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 viene simulato il ritorno di un utente mesi dopo. 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 a eseguire lo script due volte.
- Nella seconda esecuzione, cerca "Ripresa della sessione esistente".
- L'agente ricorderà il contesto della prima esecuzione perché viene caricato dal file di database.
Punti chiave
Regola n. 3 di Memory: utilizza DatabaseSessionService per la produzione. Garantisce che le conversazioni degli utenti sopravvivano ai riavvii del server e consente l'analisi della cronologia a lungo termine.
6. The Spy - Callbacks

A volte, devi aggiornare la memoria automaticamente in base a ciò che fa l'agente, non solo a ciò che dice. Vuoi una "spia" che osservi l'agente e prenda appunti.
Nell'ADK, questa spia è il callback. 
after_tool_callback: una funzione che viene eseguita ogni volta che l'agente funziona.ToolContext: un modo per scrivere nello stato dall'interno della funzione.
Passaggio 1: la 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,
L'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: prova la spia
👉💻 Nel terminale, esegui lo script copiando e incollando il seguente comando:
cd ~/memory_agent_starter
uv run python ~/memory_agent_starter/04_stateful_agent/main.py
Quando esegui questo agente, vedrai un ciclo.
- Turno 1: chiedi un museo. Spy sets
last_activity="CULTURAL". - Turno 2: chiedi un altro museo.
- Aggiornamenti delle istruzioni dell'agente: "CULTURAL is BANNED".
- L'agente dice: "Non posso fare 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.
Punti 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, "Memoria" è stato un log della 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 l'archivio (lettura) e quando presentare una segnalazione (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 flusso di lavoro:
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 ADK gestiva automaticamente lo stato, qui è l'agente a controllare.
- 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, pianifica una cena." -> L'agente controlla il database e non trova nulla. Chiede le preferenze.
- "Sono vegano." -> L'agente salva "vegana" nel database.
- Riavvia lo script.
- "Ciao, pianifica una cena." -> L'agente controlla il database, vede "vegani" e suggerisce immediatamente un ristorante vegano.
Punti chiave
Regola n. 5 della memoria:per dati strutturati complessi, fornisci al tuo agente gli Strumenti di lettura/scrittura. Lascia che l'LLM gestisca 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ò acquisire 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: inserimento del mondo
In test_trip_planner, inviamo:
- Un messaggio di testo ("Hello")
- 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 contenuti multimediali avanzati a Vertex AI, che li elabora e li indicizza.
Passaggio 3: il 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 nell'archivio di ricordi esperienze passate pertinenti e le inserisce nel contesto.
Passaggio 4: esegui Brain
👉💻 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 di verifica finale:
"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 clip audio in cui dicevi di amare Gaeta".
Ha collegato i puntini tra diversi tipi di media del passato.
Punti chiave
Regola n. 6 di Memory: utilizza Vertex AI Memory Bank per un'esperienza di memoria ottimale. Unifica testo, immagini e video in un unico cervello consultabile.
9. Conclusione
Sei passato da un Pesce rosso smemorato a un Elefante multimodale.
Hai creato | La funzionalità |
Session Agent | Memoria delle conversazioni a breve termine |
Multi-Agent | Memoria del team condivisa |
Agente persistente | Cronologia a lungo termine |
Stateful Agent | Ricordo dinamico e autoaggiornante |
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 subito a creare i tuoi agenti personalizzati.