1. Introducción
En esta sesión práctica, irás más allá de los chatbots básicos sin estado para crear un asistente inteligente para cafeterías, un agente de IA potenciado por Gemini que actúa como un barista amigable. Toma pedidos de café que se registran en el estado de la sesión, recuerda las preferencias dietéticas a largo plazo en el estado con alcance del usuario y persiste todo en una base de datos de Cloud SQL PostgreSQL. Al final, tu agente recordará que eres intolerante a la lactosa incluso después de reiniciar la aplicación y comenzar una conversación completamente nueva.
Esta es la arquitectura del sistema que compilaremos

Requisitos previos
- Una cuenta de Google Cloud con una cuenta de facturación de prueba
- Conocimientos básicos sobre Python
- No se requiere experiencia previa con el ADK, los agentes de IA ni Cloud SQL.
Qué aprenderás
- Crea un agente de IA con el Kit de desarrollo de agentes (ADK) de Google y herramientas personalizadas
- Define herramientas que leen y escriben el estado de la sesión a través de
ToolContext - Distingue entre el estado centrado en la sesión y el estado centrado en el usuario (prefijo
user:). - Aprovisiona una instancia de Cloud SQL PostgreSQL y conéctate a ella desde Cloud Shell
- Migra del almacenamiento local (que es el valor predeterminado cuando usas el comando
adk web) aDatabaseSessionServicepara el almacenamiento persistente con una base de datos dedicada - Verifica que la memoria del agente persista en los reinicios de la aplicación y en las sesiones de conversación separadas.
Requisitos
- Una computadora que funcione y una conexión a Internet confiable
- Un navegador, como Chrome, para acceder a la consola de Google Cloud
- Una mente curiosa y ganas de aprender
2. Configura tu entorno
En este paso, se prepara tu entorno de Cloud Shell y se configura tu proyecto de Google Cloud.
Abra Cloud Shell
Abre Cloud Shell en tu navegador. Cloud Shell proporciona un entorno preconfigurado con todas las herramientas que necesitas para este codelab. Haz clic en Autorizar cuando se te solicite
Tu interfaz debería verse similar a la siguiente

Esta será nuestra interfaz principal, con el IDE en la parte superior y la terminal en la parte inferior.
Configura tu directorio de trabajo
Crea tu directorio de trabajo. Todo el código que escribas en este codelab se encontrará aquí, separado del repositorio de referencia:
# Create your working directory
mkdir -p ~/build-agent-adk-cloudsql
# Change cloudshell workspace and working directory into previously created dir
cloudshell workspace ~/build-agent-adk-cloudsql && cd ~/build-agent-adk-cloudsql
Para generar tu terminal, busca Ver -> Terminal.

Configura tu proyecto de Google Cloud y las variables de entorno iniciales
Descarga la secuencia de comandos de configuración del proyecto en tu directorio de trabajo:
curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh
Ejecuta la secuencia de comandos. Verifica tu cuenta de facturación de prueba, crea un proyecto nuevo (o valida uno existente), guarda el ID del proyecto en un archivo .env en el directorio actual y establece el proyecto activo en la terminal.
bash setup_verify_trial_project.sh && source .env
Cuando ejecutes este comando, se te solicitará un nombre de ID del proyecto sugerido. Puedes presionar Enter para continuar.

Después de esperar un tiempo, si ves este resultado en la consola, puedes continuar con el siguiente paso
.
La secuencia de comandos ejecutada realiza los siguientes pasos:
- Verifica que tengas una cuenta de facturación de prueba activa
- Verifica si existe un proyecto en
.env(si corresponde) - Crea un proyecto nuevo o reutiliza el existente
- Vincula la cuenta de facturación de prueba a tu proyecto
- Guarda el ID del proyecto en .env
- Configura el proyecto como el proyecto activo de gcloud
Para verificar que el proyecto esté configurado correctamente, revisa el texto amarillo junto a tu directorio de trabajo en el mensaje de la terminal de Cloud Shell. Debería mostrar el ID de tu proyecto.

Habilita las APIs obligatorias
Habilita las APIs de Google Cloud necesarias para este codelab:
gcloud services enable \
aiplatform.googleapis.com \
sqladmin.googleapis.com \
compute.googleapis.com
- API de Vertex AI (
aiplatform.googleapis.com): Tu agente usa los modelos de Gemini a través de Vertex AI. - API de Cloud SQL Admin (
sqladmin.googleapis.com): Aprovisionas y administras una instancia de PostgreSQL para el almacenamiento persistente. - API de Compute Engine (
compute.googleapis.com): Se requiere para crear instancias de Cloud SQL.
Configura la región de los productos de Gemini y Cloud
Antes de continuar, también configuraremos la ubicación o región necesarias para el producto con el que interactuamos. Agrega la siguiente configuración a nuestro archivo .env
# This is for our Gemini endpoint
echo "GOOGLE_CLOUD_LOCATION=global" >> .env
# This is for our other Cloud products
echo "REGION=us-central1" >> .env
source .env
Continuemos con el siguiente paso
3. Configura Cloud SQL
En este paso, se aprovisiona una instancia de Cloud SQL PostgreSQL y se cambia el agente del almacenamiento en memoria al almacenamiento respaldado por la base de datos. La creación de la instancia tarda unos minutos, por lo que la iniciarás primero y podremos continuar con nuestra conversación sobre el siguiente tema mientras esperamos a que finalice.
Inicia la creación de la instancia
Agrega la contraseña de la base de datos a tu archivo .env y vuelve a cargarlo. Usaremos cafe-agent-pwd-2025 como contraseña.
echo "DB_PASSWORD=cafe-agent-pwd-2025" >> .env
source .env
Ejecuta este comando para crear una instancia de Cloud SQL PostgreSQL. La operación tarda unos minutos en completarse, por lo que puedes dejarla en ejecución y continuar con la siguiente sección.
gcloud sql instances create cafe-concierge-db \
--database-version=POSTGRES_17 \
--edition=ENTERPRISE \
--region=${REGION} \
--availability-type=ZONAL \
--project=${GOOGLE_CLOUD_PROJECT} \
--tier=db-f1-micro \
--root-password=${DB_PASSWORD} \
--quiet &
Algunas notas sobre el comando anterior:
db-f1-microes el nivel de Cloud SQL más pequeño (y económico), suficiente para este codelab.--root-passwordestablece la contraseña para el usuario de postgres predeterminado.- El sufijo
&en el comando ejecuta el comando en segundo plano para que puedas seguir trabajando.
El proceso se ejecutará en segundo plano, pero el resultado de la consola se mostrará ocasionalmente en la terminal actual. Abramos una pestaña de terminal nueva en Cloud Shell (haz clic en el ícono +) para que podamos concentrarnos más.

Vuelve a tu directorio de trabajo y activa el proyecto con la secuencia de comandos de configuración anterior.
cd ~/build-agent-adk-cloudsql
bash setup_verify_trial_project.sh && source .env
Luego, continuemos con la siguiente sección.
4. Compila el agente de conserjería de la cafetería
En este paso, se crea la estructura del proyecto para tu agente de ADK y se define un asistente de cafetería básico con una herramienta de menú.
Inicializa el proyecto de Python
En este codelab, se usa uv, un administrador de paquetes de Python rápido que controla los entornos virtuales y las dependencias en una sola herramienta. Ya está preinstalada en Cloud Shell.
Inicializa un proyecto de Python y agrega el ADK como dependencia:
uv init
uv add google-adk==1.25.0 asyncpg
uv init crea un pyproject.toml y un entorno virtual. uv add instala la dependencia y la registra en pyproject.toml.
Inicializa la estructura del proyecto del agente
El ADK espera un diseño de carpeta específico: un directorio con el nombre de tu agente que contenga __init__.py, agent.py y también .env dentro del directorio del agente.
El ADK tiene un comando integrado para ayudarte a establecer esto rápidamente. Ejecuta el siguiente comando:
uv run adk create cafe_concierge \
--model gemini-2.5-flash \
--project ${GOOGLE_CLOUD_PROJECT} \
--region ${GOOGLE_CLOUD_LOCATION}
Este comando creará una estructura de agente con gemini-2.5-flash como cerebro. Ahora, tu directorio debería verse así:
build-agent-adk-cloudsql/ ├── cafe_concierge/ │ ├── __init__.py │ ├── agent.py │ └── .env ├── pyproject.toml ├── .env ├── .venv/ └── ...
Escribe el agente
Abre cafe_concierge/agent.py en el editor de Cloud Shell.
cloudshell edit cafe_concierge/agent.py
y reemplaza el archivo con el siguiente código
# cafe_concierge/agent.py
from google.adk.agents import LlmAgent
from google.adk.tools import ToolContext
CAFE_MENU = {
"espresso": {
"price": 3.50,
"description": "Rich and bold single shot",
"tags": ["vegan", "dairy-free", "gluten-free"],
},
"latte": {
"price": 5.00,
"description": "Espresso with steamed milk",
"tags": ["gluten-free"],
},
"oat milk latte": {
"price": 5.50,
"description": "Espresso with steamed oat milk",
"tags": ["vegan", "dairy-free", "gluten-free"],
},
"cappuccino": {
"price": 4.50,
"description": "Espresso with equal parts steamed milk and foam",
"tags": ["gluten-free"],
},
"cold brew": {
"price": 4.00,
"description": "Slow-steeped for 12 hours, served over ice",
"tags": ["vegan", "dairy-free", "gluten-free"],
},
"matcha latte": {
"price": 5.50,
"description": "Ceremonial grade matcha with steamed milk",
"tags": ["gluten-free"],
},
"croissant": {
"price": 3.00,
"description": "Buttery, flaky French pastry",
"tags": [],
},
"banana bread": {
"price": 3.50,
"description": "Homemade with walnuts",
"tags": ["vegan"],
},
}
def get_menu() -> dict:
"""Returns the full cafe menu with prices, descriptions, and dietary tags.
Use this tool when the customer asks what's available, wants to see
the menu, or asks about specific items.
"""
return CAFE_MENU
root_agent = LlmAgent(
name="cafe_concierge",
model="gemini-2.5-flash",
instruction="""You are a friendly and knowledgeable barista at "The Cloud Cafe".
Your job:
- Help customers browse the menu and answer questions about items.
- Take coffee and food orders.
- Remember and respect dietary preferences.
Be conversational, warm, and concise. If a customer mentions a dietary
restriction, acknowledge it and suggest suitable options from the menu.
""",
tools=[get_menu],
)
Esto define un agente básico con una herramienta: get_menu(). El agente puede responder preguntas sobre el menú, pero aún no puede hacer un seguimiento de los pedidos ni recordar las preferencias.
Verifica que el agente se ejecute
Inicia la IU de desarrollo del ADK desde tu directorio de trabajo:
cd ~/build-agent-adk-cloudsql
uv run adk web
Abre la URL que se muestra en la terminal (por lo general, http://localhost:8000) con la función de Vista previa en la Web de Cloud Shell. Selecciona cafe_concierge en el menú desplegable del agente, ubicado en la esquina superior izquierda.
Escribe el siguiente texto en la barra de chat y verifica que el agente responda con elementos de menú y precios.
What's on the menu?

Detén la IU para desarrolladores con Ctrl + C antes de continuar.
5. Agrega la administración de pedidos con estado
El agente puede mostrar el menú, pero no puede tomar pedidos ni recordar preferencias. En este paso, se agregan cuatro herramientas que usan el sistema de estado de ADK para hacer un seguimiento de los pedidos dentro de una conversación y almacenar las preferencias dietéticas en todas las conversaciones.
Información sobre los eventos y el estado de la sesión
Cada conversación del ADK se encuentra dentro de un objeto Session. Una sesión hace un seguimiento de dos elementos distintos: eventos y estado. Comprender la diferencia es clave para crear agentes que recuerden las cosas correctas de la manera adecuada.
Los eventos son el registro cronológico de todo lo que sucede en una conversación. Cada mensaje del usuario, cada respuesta del agente, cada llamada a una herramienta y su valor de devolución se registran como un Event y se agregan a la lista de eventos de la sesión. Los eventos son inmutables: una vez que se registran, nunca cambian. Piensa en los eventos como la transcripción completa de una conversación.
El estado es un bloc de notas de clave-valor que el agente lee y escribe durante una conversación. A diferencia de los eventos, el estado es mutable: los valores cambian a medida que evoluciona la conversación. El estado es donde el agente almacena los datos estructurados que necesita para actuar: el pedido actual, las preferencias del cliente y un total acumulado. Piensa en el estado como notas adhesivas que el agente guarda junto a la transcripción.
A continuación, se explica cómo se relacionan:

Las herramientas leen y escriben el estado a través de ToolContext, un objeto que el ADK inyecta automáticamente en cualquier función de herramienta que lo declare como parámetro. No lo creas tú mismo. A través de tool_context.state, una herramienta puede leer y escribir en el bloc de notas de la sesión. El ADK inspecciona la firma de la función: se inyectan los parámetros con el tipo ToolContext y el LLM completa todos los demás parámetros según la conversación.
Cuando una herramienta escribe en tool_context.state, ADK registra ese cambio como un state_delta dentro del evento. Luego, SessionService aplica el delta al estado actual de la sesión. Esto significa que los cambios de estado siempre se pueden rastrear hasta el evento que los causó. Esto también se aplica a otras formas de contexto, como callback_context.
Información sobre los prefijos de estado
Las claves de estado usan prefijos para controlar su alcance:
Prefijo | Alcance | ¿Sobrevive al reinicio? (con DB) |
(ninguno) | Solo la sesión actual | Sí |
| Todas las sesiones de este usuario | Sí |
| Todas las sesiones y todos los usuarios | Sí |
| Solo la invocación actual | No |
En este codelab, usarás dos de estos prefijos: claves sin prefijo para los datos con alcance de sesión (el pedido actual, relevante solo para esta conversación) y claves user: para los datos con alcance del usuario (preferencias dietéticas, relevantes para todas las conversaciones de este usuario).
Agrega las herramientas con estado
Abre cafe_concierge/agent.py en el editor de Cloud Shell.
cloudshell edit cafe_concierge/agent.py
Luego, agrega las siguientes cuatro funciones encima de la definición de root_agent:
# cafe_concierge/agent.py (add below get_menu, above root_agent)
def place_order(tool_context: ToolContext, items: list[str]) -> dict:
"""Places an order for the specified menu items.
Use this tool when the customer confirms they want to order something.
Args:
tool_context: Provided automatically by ADK.
items: A list of menu item names the customer wants to order.
"""
valid_items = []
invalid_items = []
total = 0.0
for item in items:
item_lower = item.lower()
if item_lower in CAFE_MENU:
valid_items.append(item_lower)
total += CAFE_MENU[item_lower]["price"]
else:
invalid_items.append(item)
if not valid_items:
return {"error": f"None of these items are on our menu: {invalid_items}"}
order = {"items": valid_items, "total": round(total, 2)}
tool_context.state["current_order"] = order
result = {"order": order}
if invalid_items:
result["warning"] = f"These items are not on our menu: {invalid_items}"
return result
def get_order_summary(tool_context: ToolContext) -> dict:
"""Returns the current order summary for this session.
Use this tool when the customer asks about their current order,
wants to review what they ordered, or asks for the total.
Args:
tool_context: Provided automatically by ADK.
"""
order = tool_context.state.get("current_order")
if order:
return {"order": order}
return {"message": "No order has been placed yet in this session."}
def set_dietary_preference(tool_context: ToolContext, preference: str) -> dict:
"""Saves a dietary preference that persists across all conversations.
Use this tool when the customer mentions a dietary restriction or
preference (e.g., "I'm vegan", "I'm lactose intolerant",
"I have a nut allergy").
Args:
tool_context: Provided automatically by ADK.
preference: The dietary preference to save (e.g., "vegan",
"lactose intolerant", "nut allergy").
"""
existing = tool_context.state.get("user:dietary_preferences", [])
if not isinstance(existing, list):
existing = []
preference_lower = preference.lower().strip()
if preference_lower not in existing:
existing.append(preference_lower)
tool_context.state["user:dietary_preferences"] = existing
return {
"saved": preference_lower,
"all_preferences": existing,
}
def get_dietary_preferences(tool_context: ToolContext) -> dict:
"""Retrieves the customer's saved dietary preferences.
Use this tool when you need to check the customer's dietary
restrictions before making recommendations.
Args:
tool_context: Provided automatically by ADK.
"""
preferences = tool_context.state.get("user:dietary_preferences", [])
if preferences:
return {"preferences": preferences}
return {"message": "No dietary preferences saved yet."}
Debes tener en cuenta lo siguiente:
place_orderyget_order_summaryusan claves sin prefijo (current_order). Este estado está vinculado a la sesión actual: una conversación nueva comienza con un pedido vacío.set_dietary_preferenceyget_dietary_preferencesusan el prefijouser:(user:dietary_preferences). Este estado se comparte en todas las sesiones del mismo usuario.
Actualiza el agente con nuevas herramientas e instrucciones
Reemplaza la definición de root_agent existente en la parte inferior del archivo por lo siguiente:
# cafe_concierge/agent.py (replace the existing root_agent)
root_agent = LlmAgent(
name="cafe_concierge",
model="gemini-2.5-flash",
instruction="""You are a friendly and knowledgeable barista at "The Cloud Cafe".
Your job:
- Help customers browse the menu and answer questions about items.
- Take coffee and food orders.
- Remember and respect dietary preferences.
The customer's saved dietary preferences are: {user:dietary_preferences?}
IMPORTANT RULES:
- When a customer mentions a dietary restriction, ALWAYS save it using the
set_dietary_preference tool before doing anything else.
- Before recommending items, check the customer's dietary preferences. If they
have preferences saved, only recommend items compatible with those
restrictions. Check the menu item tags to determine compatibility.
- When placing an order, confirm the items and total with the customer.
Be conversational, warm, and concise.
""",
tools=[
get_menu,
place_order,
get_order_summary,
set_dietary_preference,
get_dietary_preferences,
],
)
La instrucción usa la plantilla de inyección de estado {user:dietary_preferences?} para insertar las preferencias guardadas de este cliente directamente en la instrucción.
Verifica el archivo completo
Tu cafe_concierge/agent.py ahora debería contener lo siguiente:
- El diccionario de
CAFE_MENU - Cinco funciones de herramientas:
get_menu,place_order,get_order_summary,set_dietary_preferenceyget_dietary_preferences - La definición de
root_agentcon las cinco herramientas
6. Prueba el agente con la IU de desarrollo del ADK
En este paso, se ejecuta el agente y se ejercitan todas las funciones con estado: ordenamiento, seguimiento de preferencias y memoria entre sesiones (dentro del mismo proceso). También inspeccionarás los paneles Events y State para ver cómo el ADK hace un seguimiento interno de la conversación.
Cómo iniciar la IU de desarrollo
cd ~/build-agent-adk-cloudsql
uv run adk web
Abre la vista previa en la Web en el puerto 8000 y selecciona cafe_concierge en el menú desplegable.
Conversación 1: Haz un pedido y establece preferencias
Prueba estas instrucciones en secuencia:
What's on the menu?
I'm lactose intolerant
What would you recommend?
I'll have an oat milk latte and a banana bread
What's my order?
Cómo inspeccionar eventos de sesión
Todos los Eventos se capturarán y mostrarán en la IU web. Verás que, en el cuadro de chat, no solo se muestran tu instrucción y tu respuesta, sino también tool_call y tool_response.

Deberías ver una lista de eventos en orden. Cada evento tiene un autor (quien lo produjo) y un tipo (qué tipo de interacción representa):
Autor | Tipo | Qué representa |
|
| Un mensaje que escribiste en el chat |
|
| La respuesta de texto del agente |
|
| El agente decidió llamar a una herramienta (muestra el nombre de la función y los argumentos). |
|
| El valor de retorno de una llamada a una herramienta |
Haz clic en uno de los eventos tool_call, por ejemplo, la llamada set_dietary_preference. Deberías ver lo siguiente:
- Nombre de la función:
set_dietary_preference - Argumentos:
{"preference": "lactose intolerant"}
Ahora haz clic en el evento tool_response correspondiente que se encuentra directamente debajo. Deberías ver el valor de devolución:
- Respuesta:
{"saved": "lactose intolerant", "all_preferences": ["lactose intolerant"]}

Busca el campo state_delta dentro del evento tool_response. Esto muestra exactamente qué estado cambió como resultado de esta llamada a la herramienta:
state_delta: {"user:dietary_preferences": ["lactose intolerant"]}
Cada cambio de estado se puede rastrear hasta un evento específico. Así es como el ADK garantiza que el bloc de notas de estado se mantenga sincronizado con el historial de conversación.
Cómo inspeccionar el estado de la sesión
Haz clic en la pestaña Estado. A diferencia del registro de eventos (que muestra el historial completo), la pestaña de estado muestra una instantánea de lo que sabe el agente en este momento, es decir, el valor actual de cada clave de estado.

Deberías ver dos entradas:
current_order:{"items": ["oat milk latte", "banana bread"], "total": 9.0}user:dietary_preferences:["lactose intolerant"]
Observa la diferencia en los nombres de las claves:
current_orderno tiene prefijo, ya que se limita a la sesión. Solo existe en esta conversación y desaparece cuando finaliza la sesión.user:dietary_preferencestiene el prefijouser:, por lo que se limita al usuario. Se comparte en todas las sesiones de este usuario.
Esta distinción es invisible en el código (ambos usan tool_context.state), pero controla hasta dónde llegan los datos. Verás cómo se desarrolla esto en la siguiente prueba.
Conversación 2: Verifica el estado del usuario en varias sesiones
Haz clic en el botón New Session en la IU de desarrollo para iniciar una conversación nueva. Esto crea una sesión nueva para el mismo usuario.

Prueba esta instrucción:
What do you recommend for me?
Verifica la pestaña Estado en la sesión nueva. La tecla user:dietary_preferences se mantiene, pero current_order desaparece, ya que ese estado estaba vinculado a la sesión anterior.

7. Observa la limitación del almacenamiento local
El agente recuerda las preferencias entre sesiones, pero solo mientras exista el almacenamiento local. En este paso, se demuestra la limitación fundamental del almacenamiento local.
Vuelve a iniciar el agente
Detuviste la IU de desarrollo al final del paso anterior. Ahora, quitemos el almacenamiento local y volvamos a iniciarlo para simular el entorno sin servidores que no tiene estado:
cd ~/build-agent-adk-cloudsql
rm -f cafe_concierge/.adk/session.db
uv run adk web
Ahora, abre la vista previa en la Web en el puerto 8000 y selecciona cafe_concierge.
Prueba de recuperación de preferencias
Tipo:
Do you remember my dietary preferences?
El agente no recuerda nada. Las preferencias alimentarias, el historial de pedidos… todo desapareció.

Todo se borró cuando eliminamos el almacenamiento local, lo que suele ocurrir cuando utilizamos un entorno sin servidor. session.db almacena todo el estado en la memoria del proceso. Si lo quitas, se borrará todo.
La solución es especificar DatabaseSessionService, que, en este instructivo, almacenará todos los datos de la sesión en una base de datos de PostgreSQL en Cloud SQL. El código y las herramientas del agente siguen siendo exactamente los mismos, solo cambia el backend de almacenamiento.
Detén la IU para desarrolladores con Ctrl+C antes de continuar.
8. Vuelve a analizar la configuración de la base de datos
En este punto, ya debería haber finalizado la creación de la instancia de base de datos. Para verificarlo, ejecuta el siguiente comando:
gcloud sql instances describe cafe-concierge-db --format="value(state)"
Deberías ver el siguiente resultado. Márcalo como finalizado.
RUNNABLE
Crea la base de datos
Crea una base de datos dedicada para los datos de la sesión del agente:
gcloud sql databases create agent_db --instance=cafe-concierge-db
Inicia el proxy de Cloud SQL Auth
El proxy de autenticación de Cloud SQL proporciona una conexión segura y autenticada desde Cloud Shell a tu instancia de Cloud SQL sin necesidad de incluir direcciones IP en la lista de entidades permitidas. Ya está preinstalado en Cloud Shell.
cloud-sql-proxy ${GOOGLE_CLOUD_PROJECT}:${REGION}:cafe-concierge-db --port 5432 &
El sufijo & en el comando hace que el proxy se ejecute en segundo plano. Deberías ver un resultado que confirme que el proxy está listo, como se muestra a continuación.
[your-project-id:your-region:cafe-concierge-db] Listening on 127.0.0.1:5432 The proxy has started successfully and is ready for new connections!
Verifica la conexión
Prueba que puedes conectarte a la base de datos a través del proxy:
psql "host=127.0.0.1 port=5432 dbname=agent_db user=postgres password=$DB_PASSWORD" -c "SELECT 'Connection ok' AS status;"
Deberías ver lo siguiente:
status --------------------- Connection ok (1 row)
9. Cómo verificar la memoria persistente en las sesiones
Este paso demuestra que la memoria del agente sobrevive al restablecimiento cuando nos aseguramos de que se quite cafe_concierge/.adk/session_db (la base de datos local) y abarque sesiones de conversación.
Inicia el agente
Asegúrate de que el proxy de Cloud SQL Auth siga en ejecución (verifica los trabajos). Si no es así, reinícialo:
if ss -tlnp | grep -q ':5432 '; then
echo "Cloud SQL Auth Proxy is already running."
else
cloud-sql-proxy ${GOOGLE_CLOUD_PROJECT}:${REGION}:cafe-concierge-db --port 5432 &
fi
Luego, inicia la IU de desarrollo del ADK especificando la base de datos como el servicio de sesión.
uv run adk web --session_service_uri postgresql+asyncpg://postgres:${DB_PASSWORD}@127.0.0.1:5432/agent_db
Abre la vista previa web en el puerto 8000 y selecciona cafe_concierge.
Prueba 1: Haz un pedido y establece preferencias
En la primera sesión, ejecuta estos mensajes:
Show me the menu
I'm vegan
What can I eat?
I'll have a cold brew and banana bread
Prueba 2: Sobrevive a un reinicio
Detén la IU para desarrolladores con Ctrl+C y asegúrate de que se quite el session.db local.
rm -f cafe_concierge/.adk/session.db
Luego, vuelve a ejecutar el servidor de la IU para desarrolladores.
uv run adk web --session_service_uri postgresql+asyncpg://postgres:${DB_PASSWORD}@127.0.0.1:5432/agent_db
Abre la vista previa web en el puerto 8000, selecciona cafe_concierge y comienza una sesión nueva. Luego, pregunta
What are my dietary preferences?
El agente responde con tus preferencias guardadas: vegana. Los datos sobrevivieron al reinicio porque ahora se almacenan en PostgreSQL, no en el almacenamiento local. Este será el mismo caso si creamos una sesión nueva, ya que el estado de user: se transfiere a cada sesión nueva de este usuario.

Inspecciona la base de datos directamente
Abre una nueva pestaña de la terminal en Cloud Shell y consulta la base de datos para ver los datos almacenados:
psql "host=127.0.0.1 port=5432 dbname=agent_db user=postgres password=$DB_PASSWORD" -c "\dt"
Deberías ver tablas que el ADK creó automáticamente para almacenar sesiones, eventos y estados, como en este ejemplo.
List of relations Schema | Name | Type | Owner --------+-----------------------+-------+---------- public | adk_internal_metadata | table | postgres public | app_states | table | postgres public | events | table | postgres public | sessions | table | postgres public | user_states | table | postgres (5 rows)
Resumen del comportamiento del estado
Clave de estado | Prefijo | Alcance | ¿Se comparte entre sesiones? |
| (ninguno) | Sesión | No |
|
| Usuario | Sí |
10. Felicitaciones y limpieza
¡Felicitaciones! Creaste correctamente un agente de IA persistente y con estado usando el ADK y Cloud SQL.
Qué aprendiste
- Cómo crear un agente de ADK con herramientas personalizadas que leen y escriben el estado de la sesión
- La diferencia entre el estado con alcance de sesión (sin prefijo) y el estado con alcance del usuario (prefijo
user:) - Por qué el
session.dblocal predeterminado del ADK solo es adecuado para el desarrollo: todos los datos se pierden cuando se quita (y es fácil de quitar, no hay copia de seguridad), no es adecuado para la implementación sin servidores que no tiene estado - Cómo aprovisionar una instancia de Cloud SQL para PostgreSQL y conectarse a ella con el proxy de autenticación de Cloud SQL
- Cómo conectarse a DatabaseSessionService con PostgreSQL en CloudSQL con un cambio de código mínimo: mismas herramientas, mismo agente, diferente backend
- Cómo persiste el estado centrado en el usuario en diferentes sesiones de conversación
Realiza una limpieza
Para evitar que se apliquen cargos a tu cuenta de Google Cloud, limpia los recursos que creaste en este codelab.
Opción 1: Borra el proyecto (recomendada)
La manera más fácil de realizar una limpieza es borrar el proyecto. Esto quita todos los recursos asociados con el proyecto.
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}
Opción 2: Borra los recursos individuales
Si deseas conservar el proyecto, pero quitar solo los recursos creados en este codelab, haz lo siguiente:
gcloud sql instances delete cafe-concierge-db --quiet