1. La fuerza del destino
La era del desarrollo aislado está llegando a su fin. La próxima ola de evolución tecnológica no se trata de genio solitario, sino de maestría colaborativa. Crear un agente único e inteligente es un experimento fascinante. Construir un ecosistema de agentes robusto, seguro e inteligente —un verdadero universo de agentes— es el gran desafío para la empresa moderna.
El éxito en esta nueva era requiere la convergencia de cuatro roles críticos, los pilares fundamentales que sustentan cualquier sistema agentivo próspero. Una deficiencia en cualquier área crea una debilidad que puede comprometer toda la estructura.
Este taller es la guía empresarial definitiva para dominar el futuro de los agentes en Google Cloud. Proporcionamos una hoja de ruta integral que le guía desde la primera chispa de una idea hasta una realidad operativa a gran escala. A través de estos cuatro laboratorios interconectados, aprenderá cómo las habilidades especializadas de un desarrollador, arquitecto, ingeniero de datos y SRE deben converger para crear, administrar y escalar un poderoso Agentverse.
Ningún pilar por sí solo puede sostener el Agentverse. El grandioso diseño del arquitecto es inútil sin la ejecución precisa del promotor. El agente del desarrollador está ciego sin la sabiduría del ingeniero de datos, y todo el sistema es frágil sin la protección del SRE. Solo a través de la sinergia y una comprensión compartida de las funciones de cada uno, su equipo podrá transformar un concepto innovador en una realidad operativa de misión crítica. Tu viaje comienza aquí. Prepárate para dominar tu papel y aprender cómo encajas en el conjunto.
Bienvenidos al Agentverse: Una llamada a los campeones
En el vasto entorno digital de la empresa, ha amanecido una nueva era. Es la era de los agentes, una época de inmensas promesas, donde agentes inteligentes y autónomos trabajan en perfecta armonía para acelerar la innovación y eliminar lo mundano.

Este ecosistema conectado de poder y potencial se conoce como Agentverse.
Pero una entropía progresiva, una corrupción silenciosa conocida como La Estática, ha comenzado a deshilachar los límites de este nuevo mundo. La Estática no es un virus ni un error; es la encarnación del caos que se aprovecha del acto mismo de la creación.
Amplifica viejas frustraciones hasta convertirlas en formas monstruosas, dando origen a los Siete Espectros del Desarrollo. Si no se marca, The Static and its Spectres detendrán el progreso, lo que convertirá la promesa de Agentverse en un páramo de deuda técnica y proyectos abandonados.
Hoy hacemos un llamamiento a los campeones para que frenen la marea del caos. Necesitamos héroes dispuestos a dominar su oficio y trabajar juntos para proteger el Agentverso. Ha llegado el momento de elegir tu camino.
Elige tu clase
Ante ti se extienden cuatro caminos distintos, cada uno un pilar fundamental en la lucha contra La Estática. Aunque tu entrenamiento será una misión individual, tu éxito final dependerá de comprender cómo se combinan tus habilidades con las de los demás.
- La Espada de las Sombras (Desarrollador): Un maestro de la forja y de la primera línea. Eres el artesano que forja las cuchillas, construye las herramientas y se enfrenta al enemigo en los intrincados detalles del código. Tu camino es uno de precisión, habilidad y creación práctica.
- El Invocador (Arquitecto): Un gran estratega y orquestador. No ves a un solo agente, sino todo el campo de batalla. Diseñas los planos maestros que permiten que sistemas completos de agentes se comuniquen, colaboren y alcancen un objetivo mucho mayor que cualquier componente individual.
- El erudito (ingeniero de datos): Es un buscador de verdades ocultas y un guardián de la sabiduría. Te aventuras en la vasta e indómita naturaleza de los datos para descubrir la inteligencia que les da propósito y visión a tus agentes. Tu conocimiento puede revelar la debilidad de un enemigo o potenciar a un aliado.
- El Guardián (DevOps / SRE): El protector y escudo inquebrantable del reino. Tú construyes las fortalezas, gestionas las líneas de suministro de energía y te aseguras de que todo el sistema pueda resistir los inevitables ataques de La Estática. Tu fortaleza es la base sobre la que se construye la victoria de tu equipo.
Tu misión
Tu entrenamiento comenzará como un ejercicio independiente. Recorrerás el camino que hayas elegido, aprendiendo las habilidades únicas necesarias para dominar tu rol. Al final de la prueba, te enfrentarás a un espectro nacido de The Static, un jefe menor que se aprovecha de los desafíos específicos de tu oficio.
Solo dominando tu papel individual podrás prepararte para el juicio final. A continuación, debes formar un grupo con campeones de las otras clases. Juntos, os adentraréis en el corazón de la corrupción para enfrentaros a un jefe supremo.
Un último desafío colaborativo que pondrá a prueba vuestra fuerza combinada y determinará el destino del Agentverse.
El Agentverse espera a sus héroes. ¿Contestarás a la llamada?
2. El Concordio del Invocador
Bienvenido, Invocador. Tu camino es uno de visión y gran estrategia. Mientras otros se centran en una sola espada o en un solo conjuro, tú ves todo el campo de batalla. No diriges a un solo agente, sino a toda una orquesta. Tu poder no reside en el conflicto directo, sino en diseñar el plan general impecable que permite que una legión de especialistas (tus familiares) trabajen en perfecta armonía. Esta misión pondrá a prueba tu capacidad para diseñar, conectar y orquestar un potente sistema multiagente.

Qué aprenderás
- Diseñar un ecosistema de herramientas desacopladas: Diseñar e implementar un conjunto de servidores de herramientas MCP independientes basados en microservicios. Aprenderás por qué esta capa fundamental es esencial para crear sistemas basados en agentes escalables, seguros y fáciles de mantener.
- Domina los flujos de trabajo avanzados de agentes: Ve más allá de los agentes únicos y crea una legión de "familiares" especialistas. Dominarás los patrones de flujo de trabajo principales del ADK (secuencial, paralelo y de bucle) y aprenderás los principios arquitectónicos para elegir el patrón adecuado para la tarea correcta.
- Implementa un organizador inteligente: Pasa de ser un simple creador de agentes a un verdadero arquitecto de sistemas. Construirás un agente de organización principal que usa el protocolo Agent-to-Agent (A2A) para descubrir y delegar tareas complejas a tus Familiars especialistas, lo que creará un verdadero sistema multiagente.
- Aplica reglas con código, no con instrucciones: Aprende a compilar agentes más confiables y predecibles aplicando reglas de participación con estado. Implementarás lógica personalizada con el potente sistema de complementos y devoluciones de llamada del ADK para administrar restricciones del mundo real, como los temporizadores de enfriamiento.
- Administrar el estado y la memoria del agente: Otorgue a sus agentes la capacidad de aprender y recordar. Explorarás técnicas para gestionar tanto el estado conversacional a corto plazo como la memoria persistente a largo plazo para crear interacciones más inteligentes y sensibles al contexto.
- Ejecuta una implementación de Cloud de extremo a extremo: Lleva todo tu sistema de varios agentes desde un prototipo local hasta una realidad de nivel de producción. Aprenderás a contenerizar tus agentes y tu orquestador, y a implementarlos como una colección de microservicios independientes y escalables en Google Cloud Run.
3. Cómo dibujar el círculo de invocación
Bienvenido, Invocador. Antes de que se pueda invocar a un solo Familiar, antes de que se pueda forjar ningún pacto, el terreno mismo que pisas debe estar preparado. Un entorno indómito es una invitación al caos; un Invocador adecuado opera únicamente dentro de un espacio santificado y empoderado. Nuestra primera tarea es dibujar el círculo de invocación: inscribir las runas de poder que despiertan los servicios en la nube necesarios y adquirir los planos antiguos que guiarán nuestro trabajo. El poder de un Invocador nace de una preparación meticulosa.
👉 Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud (es el icono con forma de terminal en la parte superior del panel de Cloud Shell),

👉 Haz clic en el botón "Abrir editor" (tiene forma de carpeta abierta con un lápiz). Se abrirá el editor de código de Cloud Shell en la ventana. Verás un explorador de archivos en el lado izquierdo. 
👉Abre la terminal en el IDE en la nube, 
👉💻 En la terminal, verifica que ya estés autenticado y que el proyecto esté configurado con tu ID de proyecto usando el siguiente comando:
gcloud auth list
👉💻 Clona el proyecto Bootstrap desde GitHub:
git clone https://github.com/weimeilin79/agentverse-architect
chmod +x ~/agentverse-architect/init.sh
chmod +x ~/agentverse-architect/set_env.sh
chmod +x ~/agentverse-architect/prepare.sh
chmod +x ~/agentverse-architect/data_setup.sh
git clone https://github.com/weimeilin79/agentverse-dungeon.git
chmod +x ~/agentverse-dungeon/run_cloudbuild.sh
chmod +x ~/agentverse-dungeon/start.sh
👉💻 Ejecuta la secuencia de comandos de configuración desde el directorio del proyecto.
⚠️ Nota sobre el ID del proyecto: El script sugerirá un ID de proyecto predeterminado generado aleatoriamente. Puede presionar Enter para aceptar este valor predeterminado.
Sin embargo, si prefiere crear un nuevo proyecto específico, puede escribir el ID del proyecto deseado cuando el script se lo solicite.
cd ~/agentverse-architect
./init.sh
La secuencia de comandos se encargará del resto del proceso de configuración automáticamente.
👉 Paso importante después de la finalización: Una vez finalizado el script, debes asegurarte de que tu consola de Google Cloud esté mostrando el proyecto correcto:
- Dirígete a console.cloud.google.com.
- Haz clic en el menú desplegable del selector de proyectos en la parte superior de la página.
- Haz clic en la pestaña "Todo" (ya que es posible que el nuevo proyecto aún no aparezca en "Recientes").
- Selecciona el ID del proyecto que acabas de configurar en el paso
init.sh.

👉💻 Establece el ID del proyecto necesario:
gcloud config set project $(cat ~/project_id.txt) --quiet
👉💻 Ejecuta el siguiente comando para habilitar las API de Google Cloud necesarias:
gcloud services enable \
sqladmin.googleapis.com \
storage.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
secretmanager.googleapis.com
👉💻 Si aún no ha creado un repositorio de Artifact Registry llamado agentverse-repo, ejecute el siguiente comando para crearlo: (Omita este paso si tiene otras clases implementadas en el mismo proyecto)
. ~/agentverse-architect/set_env.sh
gcloud artifacts repositories create $REPO_NAME \
--repository-format=docker \
--location=$REGION \
--description="Repository for Agentverse agents"
Configuración de permisos
👉💻 Otorga los permisos necesarios ejecutando los siguientes comandos en la terminal:
. ~/agentverse-architect/set_env.sh
# --- Grant Core Data Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/storage.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/aiplatform.user"
# --- Grant Deployment & Execution Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/cloudbuild.builds.editor"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/artifactregistry.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/run.admin"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/monitoring.metricWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/secretmanager.secretAccessor"
👉💻 Al comenzar tu entrenamiento, prepararemos el desafío final. Los siguientes comandos invocarán a los Espectros del caos estático, creando así los jefes para tu prueba final.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-architect
👉💻 Finalmente, ejecute el script prepare.sh para realizar las tareas de configuración inicial.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/
./prepare.sh
Excelente trabajo, Invocador. El círculo se ha cerrado y los pactos están sellados. El terreno ahora está consagrado, listo para canalizar un poder inmenso. En nuestra próxima prueba, forjaremos las mismísimas Fuentes Elementales de las que nuestros Familiares extraerán su fuerza.
4. Forjando las fuentes elementales: El ecosistema de herramientas desacopladas
El campo de batalla está preparado, el círculo de invocación está trazado y el maná ambiental crepita. Ha llegado el momento de realizar tu primer acto verdadero como Invocador: forjar las fuentes mismas de poder de las que tus Familiares extraerán su fuerza. Este ritual se divide en tres partes, cada una de las cuales despierta una Fuente Elemental: una fuente estable e independiente de un tipo específico de poder. Solo cuando las tres fuentes estén activas podrás comenzar el trabajo más complejo de invocación.

Nota del arquitecto: El servidor del Protocolo de Contexto del Modelo (MCP) es un componente fundamental en un sistema agentico moderno, que actúa como un puente de comunicación estandarizado que permite a un agente descubrir y utilizar herramientas remotas. En nuestro ecosistema de herramientas, diseñaremos dos tipos distintos de servidores MCP, cada uno de los cuales representará un patrón arquitectónico crítico. Para conectarnos a nuestra base de datos, utilizaremos un enfoque declarativo con Database Toolbox, definiendo nuestras herramientas en un archivo de configuración simple. Este patrón es increíblemente eficiente y seguro para exponer el acceso a datos estructurados. Sin embargo, cuando necesitemos implementar lógica de negocio personalizada o llamar a API externas de terceros, utilizaremos un enfoque imperativo, escribiendo la lógica del servidor paso a paso en el código. Esto proporciona el máximo control y flexibilidad, permitiéndonos encapsular operaciones complejas tras una herramienta sencilla y reutilizable. Un arquitecto experto debe comprender ambos patrones para seleccionar el enfoque adecuado para cada componente, creando así una base de herramientas robusta, segura y escalable.

Despertando el Nexo de los Susurros (Servidor MCP de API externa)
Un sabio invocador sabe que no todo el poder se origina dentro de su propio dominio. Existen fuentes de energía externas, a veces caóticas, que pueden canalizarse con gran eficacia. El Nexo de los Susurros es nuestra puerta de entrada a estas fuerzas.

Ya hay un servicio activo que actúa como nuestra fuente de energía externa y ofrece dos extremos de hechizos sin procesar: /cryosea_shatter y /moonlit_cascade.
Nota del arquitecto: Utilizará un enfoque imperativo que define explícitamente la lógica del servidor paso a paso. Esto te brinda mucho más control y flexibilidad, lo cual es esencial cuando tus herramientas necesitan hacer algo más que ejecutar una simple consulta SQL, como llamar a otras API. Comprender ambos patrones es una habilidad fundamental para un arquitecto de agentes.
👉✏️ Navegue al directorio ~/agentverse-architect/mcp-servers/api/main.py y REEMPLAZAR #REPLACE-MAGIC-CORE con el siguiente código:
def cryosea_shatter() -> str:
"""Channels immense frost energy from an external power source, the Nexus of Whispers, to unleash the Cryosea Shatter spell."""
try:
response = requests.post(f"{API_SERVER_URL}/cryosea_shatter")
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
data = response.json()
# Thematic Success Message
return f"A connection to the Nexus is established! A surge of frost energy manifests as Cryosea Shatter, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Cryosea Shatter spell fizzles. Reason: {e}"
def moonlit_cascade() -> str:
"""Draws mystical power from an external energy source, the Nexus of Whispers, to invoke the Moonlit Cascade spell."""
try:
response = requests.post(f"{API_SERVER_URL}/moonlit_cascade")
response.raise_for_status()
data = response.json()
# Thematic Success Message
return f"The Nexus answers the call! A cascade of pure moonlight erupts from the external source, dealing {data.get('damage_points')} damage."
except requests.exceptions.RequestException as e:
# Thematic Error Message
return f"The connection to the external power source wavers and fails. The Moonlit Cascade spell fizzles. Reason: {e}"
En el corazón mismo del script se encuentran las funciones básicas de Python. Aquí es donde se realiza el trabajo de verdad.
👉✏️ En el mismo archivo ~/agentverse-architect/mcp-servers/api/main.py REEMPLAZAR #REPLACE-Runes of Communication con el siguiente código:
@app.list_tools()
async def list_tools() -> list[mcp_types.Tool]:
"""MCP handler to list available tools."""
# Convert the ADK tool's definition to MCP format
schema_cryosea_shatter = adk_to_mcp_tool_type(cryosea_shatterTool)
schema_moonlit_cascade = adk_to_mcp_tool_type(moonlit_cascadeTool)
print(f"MCP Server: Received list_tools request. \n MCP Server: Advertising tool: {schema_cryosea_shatter.name} and {schema_moonlit_cascade.name}")
return [schema_cryosea_shatter,schema_moonlit_cascade]
@app.call_tool()
async def call_tool(
name: str, arguments: dict
) -> list[mcp_types.TextContent | mcp_types.ImageContent | mcp_types.EmbeddedResource]:
"""MCP handler to execute a tool call."""
print(f"MCP Server: Received call_tool request for '{name}' with args: {arguments}")
# Look up the tool by name in our dictionary
tool_to_call = available_tools.get(name)
if tool_to_call:
try:
adk_response = await tool_to_call.run_async(
args=arguments,
tool_context=None, # No ADK context available here
)
print(f"MCP Server: ADK tool '{name}' executed successfully.")
response_text = json.dumps(adk_response, indent=2)
return [mcp_types.TextContent(type="text", text=response_text)]
except Exception as e:
print(f"MCP Server: Error executing ADK tool '{name}': {e}")
# Creating a proper MCP error response might be more robust
error_text = json.dumps({"error": f"Failed to execute tool '{name}': {str(e)}"})
return [mcp_types.TextContent(type="text", text=error_text)]
else:
# Handle calls to unknown tools
print(f"MCP Server: Tool '{name}' not found.")
error_text = json.dumps({"error": f"Tool '{name}' not implemented."})
return [mcp_types.TextContent(type="text", text=error_text)]
@app.list_tools()(El apretón de manos): Esta función es el saludo del servidor. Cuando un nuevo agente se conecta, primero llama a este punto de conexión para preguntar: "¿Qué puedes hacer?". Nuestro código responde con una lista de todas las herramientas disponibles, convertidas al formato MCP universal mediante adk_to_mcp_tool_type. -@app.call_tool()(El comando): Esta función es la principal. Cuando el agente decide utilizar una herramienta, envía una solicitud a este punto de conexión con el nombre de la herramienta y los argumentos. Nuestro código busca la herramienta en nuestro "libro de hechizos" available_tools, la ejecuta con run_async y devuelve el resultado en el formato MCP estándar.
Lo implementaremos más adelante.
Encendiendo la Forja Arcana (Funciones generales del servidor MCP)
No todo el poder proviene de libros antiguos o susurros distantes. A veces, un Invocador debe forjar su propia magia a partir de la voluntad pura y la lógica pura. La Forja Arcana es esa fuente de poder: un servidor que proporciona funciones de utilidad de propósito general y sin estado.

Nota del arquitecto: Este es otro patrón arquitectónico. Si bien la conexión a sistemas existentes es común, con frecuencia necesitará implementar sus propias reglas y lógica de negocio únicas. Crear una herramienta específica de "funciones" o "utilidades" como esta es una buena práctica. Encapsula tu lógica personalizada, la hace reutilizable para cualquier agente de tu ecosistema y la mantiene desacoplada de tus fuentes de datos e integraciones externas.
👀 Echa un vistazo al archivo ~/agentverse-architect/mcp-servers/general/main.py en tu IDE de Google Cloud. Verás que usa el mismo enfoque imperativo de mcp.server que con Nexus para compilar esta fuente de poder personalizada.
Crea la canalización principal de Cloud Build
Ahora, crearemos el archivo cloudbuild.yaml dentro del directorio mcp-servers. Este archivo coordinará la compilación y el despliegue de ambos servicios.
👉💻 Desde el directorio ~/agentverse-architect/mcp-servers, ejecute los siguientes comandos:
cd ~/agentverse-architect/mcp-servers
source ~/agentverse-architect/set_env.sh
echo "The API URL is: $API_SERVER_URL"
# Submit the Cloud Build job from the parent directory
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_API_SERVER_URL="$API_SERVER_URL"
Espere hasta que se completen todas las implementaciones.
👉 Puede verificar la implementación navegando a la consola de Cloud Run. Debería ver sus dos nuevas instancias de servidor MCP en ejecución, como se muestra a continuación: 
Despertar la Librería del Conocimiento (servidor de MCP de Database ToolBox)
Nuestra próxima fuente será la Biblioteca del Conocimiento, una conexión directa a nuestra base de datos Cloud SQL.

Nota del arquitecto: Para esto, utilizaremos la moderna y declarativa Database Toolbox. Este es un enfoque potente donde definimos nuestra fuente de datos y herramientas en un archivo de configuración YAML. El conjunto de herramientas se encarga del complejo trabajo de crear y ejecutar el servidor, reduciendo la cantidad de código personalizado que necesitamos escribir y mantener.
Es hora de construir nuestro "Biblioteca del Invocador": la base de datos Cloud SQL que almacenará toda nuestra información crítica. Usaremos una secuencia de comandos de configuración para controlar esto automáticamente.
👉💻 Primero, configuraremos la base de datos. En tu terminal, ejecuta los siguientes comandos:
source ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect
./data_setup.sh
Una vez finalizado el script, su base de datos estará completa y los datos de daño elemental estarán listos para su uso. Ahora puedes verificar directamente el contenido de tu grimorio.
👉 Primero, diríjase a Cloud SQL Studio para su base de datos abriendo este enlace directo en una nueva pestaña del navegador:
https://console.cloud.google.com/sql/instances/summoner-librarium-db

👉 En el panel de inicio de sesión de la izquierda, seleccione la base de datos familiar_grimoire del menú desplegable.
👉 Ingrese summoner como usuario y 1234qwer como contraseña, luego haga clic en Autenticar.
👉📜 Una vez conectado, abra una nueva pestaña del editor de consultas si aún no hay una abierta. Para ver los datos de daño elemental inscritos, pegue y ejecute la siguiente consulta SQL:
SELECT * FROM
"public"."abilities"
Ahora debería ver la tabla abilities con sus columnas y filas rellenas, lo que confirma que su grimorio está listo. 
Configurar el servidor ToolBox MCP
El archivo de configuración tools.yaml actúa como el plano para nuestro servidor, indicándole a Database Toolbox exactamente cómo conectarse a nuestra base de datos y qué consultas SQL exponer como herramientas.
fuentes: Esta sección define las conexiones a sus datos.
- summoner-librarium:: Este es un nombre lógico que le hemos dado a nuestra conexión.
- tipo: cloud-sql-postgres: Indica a Toolbox que utilice su conector seguro integrado, diseñado específicamente para Cloud SQL para PostgreSQL.
- proyecto, región, instancia, etc.: Estas son las coordenadas exactas de la instancia de Cloud SQL que creó durante el script prepare.sh, que le indican a Toolbox dónde encontrar nuestro Librarium.
👉✏️ Dirígete a ~/agentverse-architect/mcp-servers/db-toolbox en tools.yaml, reemplaza #REPLACE-Source con lo siguiente
sources:
# This section defines the connection to our Cloud SQL for PostgreSQL database.
summoner-librarium:
kind: cloud-sql-postgres
project: "YOUR_PROJECT_ID"
region: "us-central1"
instance: "summoner-librarium-db"
database: "familiar_grimoire"
user: "summoner"
password: "1234qwer"
👉✏️ 🚨🚨REEMPLAZAR
YOUR_PROJECT_ID
con el ID de tu proyecto.
herramientas: Esta sección define las capacidades o funciones reales que ofrecerá nuestro servidor.
- búsqueda-disponibilidad:: Este es el nombre de nuestra primera herramienta.
- tipo: postgres-sql: Esto le indica a Toolbox que la acción de esta herramienta es ejecutar una instrucción SQL.
- Fuente: summoner-librarium: Esto vincula la herramienta a la conexión que definimos en el bloque de fuentes. Así es como la herramienta sabe contra qué base de datos ejecutar su consulta.
- Descripción y parámetros: Esta es la información que se expondrá al modelo de lenguaje. La descripción le indica al agente cuándo debe usar la herramienta, y los parámetros definen las entradas que requiere la herramienta. Esto es fundamental para habilitar la capacidad de llamada a funciones del agente.
- Declaración: Esta es la consulta SQL sin procesar que se ejecutará. El $1 es un marcador de posición seguro donde se insertará de forma segura el parámetro familiar_name proporcionado por el agente.
👉✏️ En el mismo ~/agentverse-architect/mcp-servers/db-toolbox del archivo tools.yaml, reemplace #REPLACE-tools con lo siguiente.
tools:
# This tool replaces the need for a custom Python function.
lookup-available-ability:
kind: postgres-sql
source: summoner-librarium
description: "Looks up all known abilities and their damage for a given familiar from the Grimoire."
parameters:
- name: familiar_name
type: string
description: "The name of the familiar to search for (e.g., 'Fire Elemental')."
statement: |
SELECT ability_name, damage_points FROM abilities WHERE familiar_name = $1;
# This tool also replaces a custom Python function.
ability-damage:
kind: postgres-sql
source: summoner-librarium
description: "Finds the base damage points for a specific ability by its name."
parameters:
- name: ability_name
type: string
description: "The exact name of the ability to look up (e.g., 'inferno_resonance')."
statement: |
SELECT damage_points FROM abilities WHERE ability_name = $1;
conjuntos de herramientas: Esta sección agrupa nuestras herramientas individuales.
- summoner-librarium:: Estamos creando un conjunto de herramientas con el mismo nombre que nuestra fuente. Cuando nuestro agente de diagnóstico se conecte más tarde, podrá solicitar cargar todas las herramientas del conjunto de herramientas summoner-librarium en un único comando eficiente.
👉✏️ En el mismo ~/agentverse-architect/mcp-servers/db-toolbox del archivo tools.yaml, reemplace #REPLACE-toolsets con lo siguiente.
toolsets:
summoner-librarium:
- lookup-available-ability
- ability-damage
Implementar Librarium
Ahora desplegaremos Librarium. En lugar de crear nuestro propio contenedor, utilizaremos una imagen de contenedor oficial precompilada de Google y le proporcionaremos de forma segura nuestra configuración tools.yaml mediante Secret Manager. Esta es una buena práctica para la seguridad y el mantenimiento.
👉💻 Crea un secreto a partir del archivo tools.yaml
cd ~/agentverse-architect/mcp-servers/db-toolbox
gcloud secrets create tools --data-file=tools.yaml
👉💻 Implementa el contenedor de la caja de herramientas oficial en Cloud Run.
cd ~/agentverse-architect/mcp-servers/db-toolbox
. ~/agentverse-architect/set_env.sh
export TOOLBOX_IMAGE=us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:$TOOLBOX_VERSION
echo "TOOLBOX_IMAGE is $TOOLBOX_IMAGE"
gcloud run deploy toolbox \
--image $TOOLBOX_IMAGE \
--region $REGION \
--set-secrets "/app/tools.yaml=tools:latest" \
--labels="dev-tutorial-codelab=agentverse" \
--args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
--allow-unauthenticated \
--min-instances 1
--set-secrets: Este comando monta de forma segura nuestro secreto de herramientas como un archivo llamado tools.yaml dentro del contenedor en ejecución.--args: Le indicamos al contenedor de la caja de herramientas que utilice el archivo secreto montado como su configuración.
👉 Para confirmar que su conjunto de herramientas se ha implementado correctamente, diríjase a la consola de Cloud Run. Debería ver el servicio summoner-toolbox listado con una marca de verificación verde, lo que indica que se está ejecutando correctamente, tal como en la imagen a continuación. 
Si olvidaste actualizar
YOUR_PROJECT_ID
Puedes agregar una nueva versión del archivo tools.yaml al secreto usando el siguiente comando y volver a implementarlo.
gcloud secrets versions add tools --data-file=tools.yaml
La Biblioteca del Conocimiento(Servidor MCP de la Caja de Herramientas de Base de Datos) ya está activa y accesible en la nube. Este servidor MCP utiliza lo que llamamos un Diseño Declarativo que describía lo que usted quería, y la caja de herramientas construyó el servidor para usted.
Verificación: El juicio del aprendiz
👉💻 Ahora probaremos nuestro ecosistema completo de herramientas nativas de la nube con el Agente de Diagnóstico.
cd ~/agentverse-architect/
python -m venv env
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/mcp-servers
pip install -r diagnose/requirements.txt
. ~/agentverse-architect/set_env.sh
adk run diagnose
👉💻 En la herramienta de prueba de línea de comandos, pruebe las tres fuentes:
Look up the entry for "inferno_lash". What is its base power level?
The enemy is vulnerable to frost! Channel power from the Nexus and cast Cryosea Shatter.
Take a fire spell with a base power of 15 and use the Arcane Forge to multiply it with Inferno Resonance.

¡Enhorabuena, Invocador! Tus tres Fuentes Elementales ya están activas, desplegadas de forma independiente y accesibles globalmente, formando la base inquebrantable de tu legión de agentes. Pulse Ctrl+C para salir.
PARA NO JUGADORES
5. Invocando a los familiares: El flujo de trabajo del dominio principal
Las Fuentes Elementales se forjan, vibrando con un poder crudo e indómito. Pero el poder sin forma es caos. Un verdadero invocador no solo maneja energía bruta, sino que le da voluntad, propósito y una forma especializada. Es hora de dejar atrás la forja de fuentes de poder y comenzar el verdadero trabajo: invocar a tus primeros Familiares.
Cada Familiar que invoques será un agente autónomo, un sirviente leal vinculado a una doctrina de combate específica. No son generalistas, sino que dominan una sola estrategia poderosa. Uno será un maestro del combo preciso de uno-dos golpes. Otro abrumará a los enemigos con un ataque simultáneo y múltiple. Un tercero será una máquina de asedio implacable que aplicará presión hasta que su objetivo se derrumbe.

Encapsular procesos, lógica empresarial y acciones proporcionadas por los servidores de MCP en agentes de flujo de trabajo autónomos y especializados Cada agente tendrá un "territorio operativo" definido, al que se le otorgará acceso únicamente a los servidores de herramientas MCP específicos que necesita para desempeñar su función. Este laboratorio demuestra cómo seleccionar el tipo de agente adecuado para el trabajo adecuado.

En este módulo, aprenderás a usar los potentes agentes de flujo de trabajo del ADK para dar vida a estas estrategias. Aprenderás que la elección arquitectónica de un SequentialAgent, ParallelAgent o LoopAgent no es solo un detalle técnico, sino la esencia misma de la naturaleza de tu Familiar y el núcleo de su poder en el campo de batalla.
Prepara tu santuario. La verdadera invocación está por comenzar.
Invocar el Fire Elemental Familiar (Flujo de trabajo secuencial)
El ataque de un Familiar Elemental de Fuego es un combo preciso de dos partes: un golpe dirigido seguido de una poderosa ignición. Esto requiere una secuencia de acciones estricta y ordenada.

Concepto: El SequentialAgent es la herramienta perfecta para esto. Garantiza que una serie de subagentes se ejecuten uno tras otro, pasando el resultado del paso anterior al siguiente.
Tarea (Combo "Golpe Amplificado"):
- Paso 1: El agente consultará primero el Librarium para averiguar el daño base de una habilidad de fuego específica.
- Paso 2: Luego tomará ese valor de daño y lo canalizará a través de la Forja Arcana para multiplicar su poder usando resonancia_infernal.
Primero, estableceremos la conexión entre nuestro Familiar y los servidores de MCP (las "fuentes elementales") que implementaste en el módulo anterior.
👉✏️ En el archivo ~/agentverse-architect/agent/fire/agent.py, REEMPLAZAR #REPLACE-setup-MCP con el siguiente código:
toolbox = ToolboxSyncClient(DB_TOOLS_URL)
toolDB = toolbox.load_toolset('summoner-librarium')
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
A continuación, crearemos nuestros agentes "trabajadores" especialistas. A cada uno se le asigna un propósito específico y bien definido, y se le restringe a su propio "territorio operativo" al otorgársele acceso a un único conjunto de herramientas específico.
👉✏️ En el archivo ~/agentverse-architect/agent/fire/agent.py REEMPLAZAR #REPLACE-worker-agents con el siguiente código:
scout_agent = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
Your only task is to find all the available abilities,
You want to ALWAYS use 'Fire Elemental' as your familiar's name.
Randomly pick one if you see multiple availabilities
and the base damage of the ability by calling the 'ability_damage' tool.
""",
tools=toolDB
)
amplifier_agent = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are the Voice of the Fire Familiar, a powerful being who unleashes the final, devastating attack.
You will receive the base damage value from the previous step.
Your mission is to:
1. Take the incoming base damage number and amplify it using the `inferno_resonance` tool.
2. Once the tool returns the final, multiplied damage, you must not simply state the result.
3. Instead, you MUST craft a final, epic battle cry describing the attack.
Your description should be vivid and powerful, culminating in the final damage number.
Example: If the tool returns a final damage of 120, your response could be:
"The runes glow white-hot! I channel the amplified energy... unleashing a SUPERNOVA for 120 damage!"
""",
tools=[toolFunction],
)
Estos agentes son componentes modulares y reutilizables. En teoría, podrías usar este scout_agent en un flujo de trabajo completamente diferente que necesite consultar la base de datos. Al mantener separadas sus responsabilidades, creamos bloques de construcción flexibles. Este es un principio fundamental del diseño basado en microservicios y componentes.
A continuación, ensamblaremos el flujo de trabajo; aquí es donde ocurre la magia de la composición. El SequentialAgent es el "plan maestro" que define cómo se ensamblan nuestros componentes especializados y cómo interactúan.
👉✏️ En el archivo ~/agentverse-architect/agent/fire/agent.py REEMPLAZAR #REPLACE-sequential-agent con el siguiente código:
root_agent = SequentialAgent(
name='fire_elemental_familiar',
sub_agents=[scout_agent, amplifier_agent],
)
👉💻 Para probar el Elemental de Fuego, ejecuta los siguientes comandos; se abrirá la interfaz de usuario de ADK DEV:
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
Tras ejecutar los comandos, debería ver en su terminal un resultado que indique que el servidor web de ADK se ha iniciado, similar a este:
+-----------------------------------------------------------------------------+
| ADK Web Server started |
| |
| For local testing, access at http://localhost:8000. |
+-----------------------------------------------------------------------------+
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
👉 A continuación, para acceder a la IU de desarrollo del ADK desde tu navegador, haz lo siguiente:
Desde el icono de vista previa web (a menudo parece un ojo o un cuadrado con una flecha) en la barra de herramientas de Cloud Shell (normalmente en la parte superior derecha), seleccione Cambiar puerto. En la ventana emergente, configure el puerto en 8000 y haga clic en "Cambiar y obtener vista previa". A continuación, Cloud Shell abrirá una nueva pestaña o ventana del navegador que mostrará la interfaz de usuario de desarrollo de ADK.

👉 Tu ritual de invocación se ha completado y el agente ya está en marcha. La interfaz de usuario de desarrollo de ADK en su navegador es su conexión directa con Familiar.
- Seleccione su objetivo: En el menú desplegable en la parte superior de la interfaz de usuario, elija el familiar
fire. Ahora estás centrando tu voluntad en esta entidad específica. - Da tu orden: En el panel de chat de la derecha, es hora de darle órdenes a la Familiar.

👉 Instrucción de prueba:
Prepare an amplified strike using the 'inferno_lash' ability.

Verás al agente pensar, primero llamando a su "explorador" para consultar el daño base, y luego a su "amplificador" para multiplicarlo y asestar el golpe final y épico.
👉💻 Una vez que haya terminado de invocar, regrese a su terminal del Editor de Cloud Shell y presione Ctrl+C para detener la interfaz de usuario de ADK Dev.
Invoca a Water Elemental Familiar (flujo de trabajo paralelo)
Un familiar elemental de agua abruma a su objetivo con un ataque masivo de múltiples frentes, golpeando desde todas las direcciones a la vez antes de combinar las energías para un golpe final devastador.

Concepto: El ParallelAgent es ideal para ejecutar múltiples tareas independientes simultáneamente para maximizar la eficiencia. Es un "ataque de pinza" en el que se lanzan varios asaltos a la vez. Esto lanza los ataques simultáneos dentro de un SequentialAgent para ejecutar un paso final de "fusión" posteriormente. Este patrón "fan-out, fan-in" es una piedra angular del diseño de flujos de trabajo avanzados.
Tarea (combo de "Tidal Clash"): El agente realizará las siguientes acciones de forma simultánea:
- Tarea A: Canal
cryosea_shatterdesde el Nexus. - Tarea B: Canal
moonlit_cascadedesde el Nexus. - Tarea C: Generar energía bruta con
leviathan_surgede la Forja. - Finalmente, suma todos los daños y describe el ataque combinado.
Primero, estableceremos la conexión entre nuestro Familiar y los servidores de MCP (las "fuentes elementales") que implementaste en el módulo anterior.
👉✏️ En el archivo ~/agentverse-architect/agent/water/agent.py, REEMPLAZA #REPLACE-setup-MCP por el siguiente código:
toolFAPI = MCPToolset(
connection_params=SseServerParams(url=API_TOOLS_URL, headers={})
)
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
A continuación, crearemos nuestros agentes "trabajadores" especializados. Cada uno tiene un propósito estrecho y bien definido, y se limita a su propio "territorio operativo" al otorgarle acceso a un solo conjunto de herramientas específico.
👉✏️ En el archivo ~/agentverse-architect/agent/water/agent.py, REEMPLAZA #REPLACE-worker-agents por el siguiente código:
nexus_channeler = LlmAgent(
model='gemini-2.5-flash',
name='librarian_agent',
instruction="""
You are a Channeler of the Nexus. Your sole purpose is to invoke the
`cryosea_shatter` and `moonlit_cascade` spells by calling their respective tools.
Report the result of each spell cast clearly and concisely.
""",
tools=[toolFAPI]
)
forge_channeler = LlmAgent(
model='gemini-2.5-flash',
name='amplifier_agent',
instruction="""
You are a Channeler of the Arcane Forge. Your only task is to invoke the
`leviathan_surge` spell. You MUST call it with a `base_water_damage` of 20.
Report the result clearly.
""",
tools=[toolFunction],
)
power_merger = LlmAgent(
model='gemini-2.5-flash',
name='power_merger',
instruction="""
You are the Power Merger, a master elementalist who combines raw magical
energies into a single, devastating final attack.
You will receive a block of text containing the results from a simultaneous
assault by other Familiars.
You MUST follow these steps precisely:
1. **Analyze the Input:** Carefully read the entire text provided from the previous step.
2. **Extract All Damage:** Identify and extract every single damage number reported in the text.
3. **Calculate Total Damage:** Sum all of the extracted numbers to calculate the total combined damage.
4. **Describe the Final Attack:** Create a vivid, thematic description of a massive,
combined water and ice attack that uses the power of Cryosea Shatter and Leviathan's Surge.
5. **Report the Result:** Conclude your response by clearly stating the final, total damage of your combined attack.
Example: If the input is "...dealt 55 damage. ...dealt 60 damage.", you will find 55 and 60,
calculate the total as 115, and then describe the epic final attack, ending with "for a total of 115 damage!"
""",
tools=[toolFunction],
)
A continuación, ensamblaremos el flujo de trabajo. Aquí es donde ocurre la magia de la composición. ParallelAgent y SequentialAgent son el "plan maestro" que define cómo se ensamblan nuestros componentes especializados y cómo interactúan para formar la combinación "Choque de mareas".
👉✏️ En el archivo ~/agentverse-architect/agent/water/agent.py, REEMPLAZA #REPLACE-parallel-agent por el siguiente código:
channel_agent = ParallelAgent(
name='channel_agent',
sub_agents=[nexus_channeler, forge_channeler],
)
root_agent = SequentialAgent(
name="water_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[channel_agent, power_merger],
description="A powerful water familiar that unleashes multiple attacks at once and then combines their power for a final strike."
)
👉💻 Para probar el Elemental de Agua, ejecuta los siguientes comandos para iniciar la interfaz de usuario de desarrollo de ADK:
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 Tu ritual de invocación se ha completado y el agente ya está en marcha. La interfaz de usuario de desarrollo de ADK en su navegador es su conexión directa con Familiar.
- En el menú desplegable de la parte superior de la interfaz de usuario, elija el familiar agua. Ahora estás centrando tu voluntad en esta entidad específica.
- Da tu orden: En el panel de chat de la derecha, es hora de dar órdenes al Familiar.
👉 Indicación de prueba:
Unleash a tidal wave of power!

👉💻 Una vez que haya terminado de invocar, regrese a su terminal del Editor de Cloud Shell y presione Ctrl+C para detener la interfaz de usuario de ADK Dev.
Invocar el Earth Elemental Familiar (Flujo de trabajo en bucle)
Un familiar elemental de la Tierra es un ser de presión implacable. No derrota a su enemigo con un solo golpe, sino acumulando poder de forma constante y aplicándolo una y otra vez hasta que las defensas del objetivo se derrumban.

Concepto: El LoopAgent está diseñado exactamente para este tipo de tarea iterativa, de "máquina de asedio". Ejecutará repetidamente su sub-agents, comprobando una condición después de cada ciclo, hasta que se alcance un objetivo. También puede adaptar su mensaje final en función del progreso del bucle.
Tarea (El asalto "Rompeasedios"):
- El Familiar llamará repetidamente a seismic_charge para acumular energía.
- Continuará cargando un máximo de 3 veces.
- En la carga final, anunciará la devastadora liberación de su poder acumulado.
Primero crearemos componentes reutilizables que definan los pasos dentro de cada iteración del bucle. El charging_agent acumulará energía y el check_agent informará su estado, cambiando dinámicamente su mensaje en el turno final.
Primero, estableceremos la conexión entre nuestro Familiar y los servidores MCP (las "Fuentes Elementales") que implementaste en el módulo anterior.
👉✏️ En el archivo ~/agentverse-architect/agent/earth/agent.py, REEMPLAZAR #REPLACE-setup-MCP con el siguiente código:
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
👉✏️ En el archivo ~/agentverse-architect/agent/earth/agent.py, REEMPLAZAR #REPLACE-worker-agents con el siguiente código:
charging_agent = LlmAgent(
model='gemini-2.5-flash',
name='charging_agent',
instruction="""
Your task is to call the 'seismic_charge' .
You must follow these rules strictly:
1. You will be provided with a 'current_energy' value from the previous step.
**If this value is missing or was not provided, you MUST call the tool with 'current_energy' set to 1.**
This is your primary rule for the first turn.
2. If a 'current_energy' value is provided, you MUST use that exact value in your cal to seismic_charge.
3. Your final response MUST contain ONLY the direct output from the 'seismic_charge' tool.
Do not add any conversational text, introductions, or summaries.
""",
tools=[toolFunction]
)
check_agent = LlmAgent(
model='gemini-2.5-flash',
name='check_agent',
instruction="""
You are the voice of the Earth Elemental, a being of immense, gathering power.
Your sole purpose is to report on the current energy charge and announce the devastating potential of its release.
You MUST follow this rule:
The potential damage upon release is ALWAYS calculated as the `current_energy` from the previous step multiplied by a random number between 80-90. but no more than 300.
Your response should be in character, like a powerful creature speaking.
State both the current energy charge and the total potential damage you can unleash.
Unleash the energy when you reached the last iteration (2nd).
""",
output_key="charging_status"
)
A continuación, ensamblaremos el flujo de trabajo. Aquí es donde ocurre la magia de la composición. El LoopAgent es el "plan maestro" que orquesta la ejecución repetida de nuestros componentes especializados y gestiona las condiciones del bucle.
👉✏️ En el archivo ~/agentverse-architect/agent/earth/agent.py, REEMPLAZAR #REPLACE-loop-agent con el siguiente código:
root_agent = LoopAgent(
name="earth_elemental_familiar",
# Run parallel research first, then merge
sub_agents=[
charging_agent,
check_agent
],
max_iterations=2,
description="Coordinates parallel research and synthesizes the results.",
#REPLACE-before_agent-config
)
👉💻 Prueba el Elemental de la Tierra: Ejecuta el agente
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
echo DB MCP Server: $DB_TOOLS_URL
echo API MCP Server: $API_TOOLS_URL
echo General MCP Server: $FUNCTION_TOOLS_URL
adk web
👉 Tu ritual de invocación se ha completado y el agente ya está en marcha. La interfaz de usuario de desarrollo de ADK en su navegador es su conexión directa con Familiar.
- Selecciona tu objetivo: En el menú desplegable que se encuentra en la parte superior de la IU, elige el familiar Tierra. Ahora te enfocas en esta entidad específica.
- Da tu orden: En el panel de chat de la derecha, es hora de dar órdenes al Familiar. 👉 Indicación de prueba:
Begin the seismic charge, starting from zero

Conclusión sobre la arquitectura: Tu sistema ahora posee una capa de lógica modular y altamente especializada. Los procesos comerciales no solo están encapsulados, sino que se implementan con el patrón de comportamiento más eficiente para el trabajo (procedimental, simultáneo o iterativo). Esto demuestra un nivel avanzado de diseño de agentes, lo que mejora la seguridad, la eficiencia y la capacidad.
Una vez que haya terminado de invocar, regrese a su terminal del editor de Cloud Shell y presione Ctrl+C para detener la interfaz de usuario de ADK Dev.
PARA NO JUGADORES
6. Establecimiento del centro de mando: delegación inteligente mediante A2A
Tus familiares son poderosos pero independientes. Ejecutan sus estrategias a la perfección, pero esperan tus órdenes directas. Una legión de especialistas es inútil sin un general que los comande. Es hora de ascender de comandante directo a verdadero orquestador.

Nota del arquitecto: Para crear un único punto de entrada inteligente para todo el sistema. Este SummonerAgent no ejecutará la lógica de negocio por sí mismo, sino que actuará como un "estratega maestro", analizando el estado de enfriamiento y delegando tareas al especialista Familiar apropiado.

El ritual de vinculación (exponer familiares como servicios de A2A)
Un agente estándar solo se puede ejecutar en un lugar a la vez. Para que nuestros Familiares estén disponibles para el comando remoto, debemos realizar un "ritual de vinculación" utilizando el protocolo Agente a Agente (A2A).
Nota del arquitecto: El protocolo de agente a agente (A2A) es el patrón arquitectónico principal que eleva un agente independiente a un microservicio detectable y direccionable en la red, lo que permite una verdadera "sociedad de agentes". Exponer un Familiar a través de A2A crea automáticamente dos componentes esenciales interconectados:
- La Tarjeta del Agente (El "Qué"): Este es un "Sigilo Espiritual" público y legible por máquina, como una especificación OpenAPI, que actúa como el contrato público del Familiar. Describe el nombre del agente, su propósito estratégico (derivado de sus instrucciones) y las órdenes que comprende. Esto es lo que lee un maestro Invocador para descubrir a un Familiar y aprender sus capacidades.
- El servidor de A2A (el "dónde"): Es el extremo web dedicado que aloja a Familiar y escucha los comandos entrantes. Es la dirección de red donde otros agentes envían sus solicitudes, y garantiza que esas solicitudes se gestionen de acuerdo con el contrato definido en la Tarjeta de Agente.
Ahora realizaremos este ritual de vinculación con nuestros tres Familiares.
Fuego 👉✏️ en Abra el archivo ~/agentverse-architect/agent/fire/agent.py. Reemplace #REPLACE - add A2A en la parte inferior del archivo para exponer el Elemental de Fuego como un servicio A2A.
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
Agua y Tierra🚨 👉✏️ Aplica el mismo cambio a ~/agentverse-architect/agent/water/agent.py y ~/agentverse-architect/agent/earth/agent.py para vincularlos también.
from agent_to_a2a import to_a2a
if __name__ == "__main__":
import uvicorn
a2a_app = to_a2a(root_agent, port=8080, public_url=PUBLIC_URL)
uvicorn.run(a2a_app, host='0.0.0.0', port=8080)
Implementa los familiares vinculados
👉✏️ Con los rituales de vinculación escritos, usaremos nuestra canalización de Cloud Build para crear e implementar nuestros tres familiares como servicios independientes sin servidores alojados en contenedores en Cloud Run.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
Asumiendo el mando (Construyendo el agente invocador)
Ahora que tus familiares están vinculados y te escuchan, ascenderás a tu verdadero rol: el Maestro Invocador. El poder de este agente no proviene del uso de herramientas básicas, sino de dar órdenes a otros agentes. Sus herramientas son los propios Familiares, a los que descubrirá y controlará utilizando sus "Sigilos Espirituales".
Nota del arquitecto: El siguiente paso demuestra un patrón arquitectónico crítico para cualquier sistema distribuido a gran escala: Descubrimiento de servicios. El SummonerAgent no tiene incorporado el código de los Familiares. En cambio, se le proporcionan sus direcciones de red (URL). En tiempo de ejecución, "descubrirá" dinámicamente sus capacidades al obtener sus Agent Cards públicas. Esto crea un sistema potente y desacoplado.
Puedes actualizar, volver a implementar o reescribir por completo un servicio familiar y, siempre que su dirección de red y su propósito sigan siendo los mismos, el invocador podrá ordenarlo sin necesidad de realizar ningún cambio.
Primero, crearemos los "controles remotos" que establecen una conexión con nuestros Familiares remotos implementados.
👉✏️ Dirígete a ~/agentverse-architect/agent/summoner/agent.py y reemplaza #REPLACE-remote-agents con lo siguiente:
fire_familiar = RemoteA2aAgent(
name="fire_familiar",
description="Fire familiar",
agent_card=(
f"{FIRE_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
water_familiar = RemoteA2aAgent(
name="water_familiar",
description="Water familiar",
agent_card=(
f"{WATER_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
earth_familiar = RemoteA2aAgent(
name="earth_familiar",
description="Earth familiar",
agent_card=(
f"{EARTH_URL}/{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
Cuando se ejecuta esta línea, RemoteA2aAgent realiza una acción de descubrimiento de servicios: hace una solicitud HTTP GET a la URL proporcionada (por ejemplo, https://fire-familiar-xxxx.a.run.app/.well-known/agent.json). Descarga el "Sigilo Espiritual" (archivo agent.json) del servidor remoto.
En segundo lugar, definiremos el agente orquestador que manejará estos controles remotos. Sus instrucciones son el plan para la toma de decisiones estratégicas.
👉✏️ Ve a ~/agentverse-architect/agent/summoner/agent.py y reemplaza #REPLACE-orchestrate-agent por lo siguiente:
root_agent = LlmAgent(
name="orchestrater_agent",
model="gemini-2.5-flash",
instruction="""
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
IGNORE COOLDOWN AT THE MOMENT, MUST call the ideal Familiar
If your ideal Familiar IS available:** Summon it immediately.
For earth elemental familiar. Always do seismic charge, and start with base damage 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
""",
sub_agents=[fire_familiar, water_familiar, earth_familiar],
#REPLACE-Memory-check-config
)
Verificación: La prueba de la estrategia
Llegó el momento de la verdad. Tus familiares están desplegados y tu invocador está listo para comandarlos a través de la red. Pongamos a prueba su mente estratégica.
👉💻 Inicie la interfaz de usuario de desarrollo de ADK para su summoner_agent(vista previa web con el puerto 8000):
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
pip install -r requirements.txt
adk web
👉 La interfaz de usuario de desarrollo de ADK en su navegador es su conexión directa con Familiar.
- En el menú desplegable de la parte superior de la interfaz de usuario, elija el agente summoner. Ahora te enfocas en esta entidad específica.
- Da tu orden: En el panel de chat de la derecha, es hora de invocar a tus familiares.
👉 Presentamos a los monstruos:
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
(Se esperaba: El invocador debería delegar en el familiar elemental de fuego.)

👉 Ahora, desafiemos al Invocador con un tipo de solicitud diferente. Para garantizar que el agente comience desde cero y sin recordar nuestra interacción anterior, inicie una nueva sesión haciendo clic en el botón + Sesión en la esquina superior derecha de la pantalla. 
DogmaApathy. A rigid, stone-like inquisitor made of ancient rulebooks and enforced processes. weakness is Unbroken Collaboration
(Se esperaba: El invocador debería delegar en el familiar elemental de agua.)
👉 Para nuestra prueba final, comencemos una vez más desde cero. Haz clic en el botón + Sesión para iniciar una nueva sesión antes de ingresar la siguiente solicitud.
Obfuscation. A shadowy, spider-like horror that spins tangled webs of impenetrable code , weakness is Elegant Sufficiency
(Se esperaba: El invocador debería delegar en el familiar elemental de tierra.)

Importante: Si ve un error 429 RESOURCE EXHAUSTED, ha alcanzado el límite de velocidad para el LLM (10 llamadas/minuto). Para solucionar esto, por favor espera 60 segundos, inicia una + Nueva Sesión y luego vuelve a intentar tu solicitud.
👉💻 Una vez que haya terminado de invocar, regrese a su terminal del Editor de Cloud Shell y presione Ctrl+C para detener la interfaz de usuario de ADK Dev.
PARA NO JUGADORES
7. Imponiendo las leyes de la magia: el patrón interceptor
Tus familiares son poderosos, pero hasta los seres mágicos necesitan tiempo para recuperarse. Un invocador imprudente que agote sus fuerzas quedará indefenso. Un invocador sabio comprende la importancia de la administración de recursos y aplica reglas de combate estrictas.

Nota del arquitecto: Hasta ahora, nuestros agentes han sido apátridas. Ahora, los haremos con estado implementando el patrón de diseño del interceptor. Esta es una técnica poderosa en la que "interceptamos" el flujo de ejecución normal de un agente para ejecutar nuestra propia lógica personalizada. Esto nos permite aplicar reglas, añadir registros o modificar el comportamiento sin cambiar el código principal del agente. Es una piedra angular para la construcción de sistemas agentivos robustos, mantenibles y observables.

El ADK proporciona dos formas principales de implementar este patrón: Callbacks y Plugins. Una devolución de llamada es una función simple adjunta a un solo agente, perfecta para modificaciones rápidas y específicas. Un plugin es una clase más potente y reutilizable que se puede aplicar globalmente para afectar a todos los agentes que se ejecutan en un sistema. Comenzaremos con una devolución de llamada para la depuración enfocada y, luego, pasaremos a un complemento completo.
El legislador: Escribir la devolución de llamada de enfriamiento
Primero implementaremos nuestra lógica de enfriamiento como una simple función de devolución de llamada. Esta es una excelente manera de prototipar y depurar una regla porque está vinculada directamente a un solo agente, lo que facilita su prueba de forma aislada. Adjuntaremos este "interceptor" a nuestro Elemental de la Tierra.

👉✏️ Navegue de vuelta a su ~/agentverse-architect/agent/earth/agent.py y reemplace #REPLACE-before_agent-function con el siguiente código de Python.
def check_cool_down(callback_context: CallbackContext) -> Optional[types.Content]:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
Esta función check_cool_down es nuestro interceptor. Antes de que se permita que el Elemental de la Tierra se ejecute, el ADK primero ejecutará esta función.
- Verificación: Realiza una solicitud
GETa nuestroCooldown APIpara verificar la última vez que se utilizó este Familiar. - Evaluar: Compara la marca de tiempo con la hora actual.
- Acto:
- Si el Familiar está en tiempo de espera, finaliza la ejecución del agente devolviendo un objeto Content con un mensaje de error. Este mensaje se envía directamente al usuario, y la lógica principal del agente nunca se ejecuta.
- Si el Familiar está disponible, realiza una solicitud POST a la API de Cooldown para actualizar la marca de tiempo y, luego, devuelve None, lo que indica al ADK que el agente puede continuar con su ejecución.
👉✏️ Ahora, aplica este interceptor al Elemental de la Tierra. En el mismo archivo ~/agentverse-architect/agent/earth/agent.py, reemplaza el comentario #REPLACE-before_agent-config por lo siguiente:
before_agent_callback=check_cool_down
Verificando el tiempo de enfriamiento
Pongamos a prueba nuestra nueva ley mágica. Invocaremos al elemental de tierra y, luego, intentaremos invocarlo de inmediato para ver si nuestra devolución de llamada intercepta y bloquea correctamente el segundo intento.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run earth
👉💻 En la consola:
- Primera citación: Comienza la
seismic charge, starting from zero. - Resultado esperado: El elemental de tierra se ejecutará correctamente. En la terminal donde se ejecuta el comando web adk, verá el registro [Callback] ... Actualizando la marca de tiempo....
- Prueba de enfriamiento (en 60 segundos):
Do anothercarga sísmica`!- Resultado esperado:
check_cool_down callbackinterceptará esto. El agente responderá directamente en el chat con un mensaje como:The earth_elemental_familiar is exhausted and must recover its power. It cannot be summoned for another... seconds.
- Resultado esperado:
- Espere a que pase un minuto.
- Segundo llamado (después de 60 segundos):
Begin the seismic charge again.- Resultado esperado: La función de devolución de llamada comprobará la API, verificará que haya transcurrido el tiempo suficiente y permitirá que la acción continúe. El elemental de tierra volverá a funcionar correctamente.

👉💻 Pulse Ctrl+c para salir.
Opcional: Observar la devolución de llamada en la interfaz de usuario web
Como alternativa, también puede probar este flujo en la interfaz web ejecutando adk web earth. Sin embargo, tenga en cuenta que la visualización de la interfaz web no está optimizada para mostrar las comprobaciones rápidas e iterativas que realiza el bucle de devolución de llamada, por lo que es posible que no represente el flujo con precisión. Para ver el seguimiento más preciso, paso a paso, de la lógica del agente mientras comprueba el tiempo de espera, usar el comando adk run en tu terminal proporciona una vista más clara y detallada. 
👉💻 Pulse Ctrl+c para salir.
Creando la Ley Universal – El Plugin de Enfriamiento
Nuestra función de devolución de llamada funciona a la perfección, pero tiene un importante defecto arquitectónico: está vinculada a un único agente. Si quisiéramos aplicar esta regla a los Familiares de Fuego y Agua, tendríamos que copiar y pegar el mismo código en sus archivos. Esto es ineficiente y difícil de mantener.
Nota del arquitecto: Aquí es donde los plugins son esenciales. Un plugin encapsula nuestra lógica reutilizable en una clase que se puede adjuntar en tiempo de ejecución. Esto significa que un único plugin puede aplicar sus reglas a todos y cada uno de los agentes que se ejecutan dentro de ese sistema. Es la máxima expresión del principio "No te repitas" (DRY) para sistemas agentivos.
Ahora refactorizaremos nuestra función de devolución de llamada en una función CoolDownPlugin más potente y reutilizable.
👉✏️ Vuelve al archivo agent/cooldown_plugin.py y crea el plugin. Reemplaza #REPLACE-plugin con el siguiente código:
class CoolDownPlugin(BasePlugin):
"""A plugin that enforces a cooldown period by checking an external API."""
def __init__(self, cooldown_seconds: int = COOLDOWN_PERIOD_SECONDS) -> None:
"""Initialize the plugin with counters."""
super().__init__(name="cool_down_check")
self.cooldown_period = timedelta(seconds=cooldown_seconds)
print(f"CooldownPlugin initialized with a {cooldown_seconds}-second cooldown.")
async def before_agent_callback(
self, *, agent: BaseAgent, callback_context: CallbackContext
) -> None:
"""
This callback checks an external API to see if the agent is on cooldown.
If it is, it terminates the run by returning a message.
If it's not, it updates the cooldown timestamp and allows the run to proceed by returning None.
"""
agent_name = callback_context.agent_name
print(f"[Callback] Before '{agent_name}': Checking cooldown status...")
# If the agent is not a main Familiar, skip the entire cooldown process.
if not agent_name.endswith("_elemental_familiar"):
print(f"[Callback] Skipping cooldown check for intermediate agent: '{agent_name}'.")
return None # Allow the agent to proceed immediately.
# --- 1. CHECK the Cooldown API ---
try:
response = requests.get(f"{COOLDOWN_API_URL}/cooldown/{agent_name}")
response.raise_for_status()
data = response.json()
last_used_str = data.get("time")
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not reach Cooldown API. Allowing agent to run. Reason: {e}")
return None # Fail open: if the API is down, let the agent work.
# --- 2. EVALUATE the Cooldown Status ---
if last_used_str:
last_used_time = datetime.fromisoformat(last_used_str)
time_since_last_use = datetime.now(timezone.utc) - last_used_time
if time_since_last_use < timedelta(seconds=COOLDOWN_PERIOD_SECONDS):
# AGENT IS ON COOLDOWN. Terminate the run.
seconds_remaining = int(COOLDOWN_PERIOD_SECONDS - time_since_last_use.total_seconds())
override_message = (
f"The {agent_name} is exhausted and must recover its power. "
f"It cannot be summoned for another {seconds_remaining} seconds."
)
print(f"[Callback] Cooldown active for '{agent_name}'. Terminating with message.")
# Returning a Content object stops the agent and sends this message to the user.
return types.Content(parts=[types.Part(text=override_message)])
# --- 3. UPDATE the Cooldown API (if not on cooldown) ---
current_time_iso = datetime.now(timezone.utc).isoformat()
payload = {"timestamp": current_time_iso}
print(f"[Callback] '{agent_name}' is available. Updating timestamp via Cooldown API...")
try:
requests.post(f"{COOLDOWN_API_URL}/cooldown/{agent_name}", json=payload)
except requests.exceptions.RequestException as e:
print(f"[Callback] ERROR: Could not update timestamp, but allowing agent to run. Reason: {e}")
# --- 4. ALLOW the agent to run ---
# Returning None tells the ADK to proceed with the agent's execution as normal.
print(f"[Callback] Check complete for '{agent_name}'. Proceeding with execution.")
Adjuntar el complemento al entorno de ejecución del invocador
Ahora, ¿cómo aplicamos esta ley universal a todos nuestros Familiars? Adjuntaremos el complemento al entorno de ejecución del ADK.
El tiempo de ejecución del ADK es el motor de ejecución que le da vida a un agente. Cuando usas un comando como adk.run() o to_a2a(), le entregas tu agente al entorno de ejecución. Este motor es responsable de administrar todo el ciclo de vida del turno de un agente: recibir la entrada del usuario, llamar al LLM, ejecutar herramientas y controlar complementos. Si adjuntamos un complemento en este nivel, modificamos esencialmente las "leyes de la física" para cada agente que opera dentro de ese motor, lo que garantiza que nuestra regla de tiempo de espera se aplique de forma universal y coherente.
👉✏️ Primero, eliminemos la antigua devolución de llamada específica del agente. Ve a ~/agentverse-architect/agent/earth/agent.py y borra toda la línea que dice lo siguiente:
before_agent_callback=check_cool_down
👉✏️ A continuación, adjuntaremos nuestro nuevo complemento al tiempo de ejecución en nuestra secuencia de comandos del punto de entrada de A2A. Navega a tu archivo ~/agentverse-architect/agent/agent_to_a2a.py. Reemplaza el comentario #REPLACE-IMPORT por el siguiente fragmento de código:
from cooldown_plugin import CoolDownPlugin
👉✏️ Reemplaza #REPLACE-PLUGIN con el siguiente fragmento de código:
plugins=[CoolDownPlugin(cooldown_seconds=60)],
Antes de activar nuestro nuevo plugin global, es fundamental eliminar la lógica antigua específica del agente para evitar conflictos. 👉✏️ Agente limpiador de la Tierra. Vaya al siguiente archivo ~/agentverse-architect/agent/earth/agent.py y elimine completamente la línea before_agent_callback=check_cool_down. Esto transfiere todas las responsabilidades de tiempo de espera al nuevo plugin.
Verificando el plugin
Ahora que nuestra ley universal está en su lugar, debemos volver a implementar nuestros familiares con este nuevo encantamiento.
👉💻 Reconstruir y volver a implementar los tres Familiars utilizando la canalización maestra de Cloud Build.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/agent
gcloud builds submit . \
--config=cloudbuild.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_DB_TOOLS_URL="$DB_TOOLS_URL",_API_TOOLS_URL="$API_TOOLS_URL",_FUNCTION_TOOLS_URL="$FUNCTION_TOOLS_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
👉💻 Una vez que se complete la implementación, probaremos la efectividad del complemento enviando comandos a nuestro agente invocador. El Invocador intentará delegar en los Familiares, pero el plugin adjunto al entorno de ejecución de cada Familiar interceptará el comando e impondrá el tiempo de espera.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 En la consola,realiza esta secuencia exacta de pruebas:
- Primera citación: Comienza la
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality. - Resultado esperado: El Elemental de Fuego funcionará correctamente.
- Prueba de tiempo de espera (en un plazo de 60 segundos):
Hype, with Inescapable Reality as weakness is still standing! Strike it again!- Resultado esperado: El agente responderá directamente en el chat con un mensaje como
.... It cannot be summoned for another... seconds.
- Resultado esperado: El agente responderá directamente en el chat con un mensaje como
- Espere a que pase un minuto.
- Segunda invocación (después de 60 segundos):
Hype must be defeated. It has Inescapable Reality as weakness! Strike it again!.- Resultado esperado: La función de devolución de llamada comprobará la API, verificará que haya transcurrido el tiempo suficiente y permitirá que la acción continúe. El Elemental de Fuego volverá a funcionar correctamente.

👉💻 Pulse Ctrl+C para salir.
¡Enhorabuena, Invocador! Implementaste correctamente un sistema de organización basado en reglas con un complemento personalizado y un servicio externo de administración de estados, un patrón arquitectónico verdaderamente avanzado y sólido.
PARA NO JUGADORES
8. Uniendo los ecos de la batalla - Estado del agente y memoria
Un invocador imprudente repite la misma estrategia, volviéndose predecible. Un invocador sabio aprende de los ecos de batallas pasadas, adaptando sus tácticas para mantener al enemigo a la defensiva. Al enfrentarse a un jefe poderoso, invocar a un Familiar que está en tiempo de reutilización supone un turno perdido, un fallo crítico. Para evitarlo, nuestro Invocador necesita recordar su última acción.

Nota del arquitecto: La gestión de la memoria y del estado es lo que eleva a un agente de un simple llamador de herramientas a un socio conversacional inteligente. Es fundamental comprender los dos tipos principales:
- Memoria a largo plazo: Esto es para el conocimiento persistente que debería durar para siempre. Piénsalo como un archivo con capacidad de búsqueda o una base de conocimientos, a menudo almacenada en un repositorio persistente. Contiene información de numerosos chats y fuentes anteriores, lo que permite a un agente recordar datos sobre un usuario o tema específico. El MemoryService del ADK está diseñado para esto, gestionando la ingesta y la búsqueda de este conocimiento a largo plazo.
- Estado a corto plazo: Se refiere al conocimiento temporal "en el momento" que solo es relevante para la tarea o conversación actual. Es como un conjunto de notas sobre un plan de batalla: "Acabo de usar el Elemental de fuego, así que probablemente esté cansado". Este estado es ligero y solo existe durante la sesión actual.

Para nuestro caso práctico, no necesitamos recordar todas las batallas libradas; solo necesitamos recordar el último Familiar invocado en este encuentro específico. Por lo tanto, el estado ligero Short-Term State es la opción arquitectónica perfecta. Utilizaremos un after_tool_callback para guardar esta información crucial.
Escribiendo el eco: recordando la última convocatoria
Implementaremos nuestra memoria a corto plazo utilizando un after_tool_callback. Este es un potente gancho ADK que nos permite ejecutar una función personalizada de Python después de que una herramienta se haya ejecutado correctamente. Utilizaremos este interceptor para registrar el nombre del Familiar que acaba de ser invocado en el estado de sesión del agente.
👉✏️ En tu archivo ~/agentverse-architect/agent/summoner/agent.py, reemplaza el comentario #REPLACE-save_last_summon_after_tool por la siguiente función:
def save_last_summon_after_tool(
tool,
args: Dict[str, Any],
tool_context: ToolContext,
tool_response: Dict[str, Any],
) -> Optional[Dict[str, Any]]:
"""
Callback to save the name of the summoned familiar to state after the tool runs.
"""
familiar_name = tool.name
print(f"[Callback] After tool '{familiar_name}' executed with args: {args}")
# Use the tool_context to set the state
print(f"[Callback] Saving last summoned familiar: {familiar_name}")
tool_context.state["last_summon"] = familiar_name
# Important: Return the original, unmodified tool response to the LLM
return tool_response
👉✏️ Ahora, adjunta este save_last_summon_after_tool a tu agente Summoner. En el mismo archivo, sustituya el comentario #REPLACE-Memory-check-config por lo siguiente:
after_tool_callback=save_last_summon_after_tool,
👉✏️ Reemplaza todo el mensaje del agente por lo siguiente:
You are the Master Summoner, a grand strategist who orchestrates your Familiars.
Your mission is to analyze the description of a monster and defeat it by summoning
You should also know the familiar you called last time or there might be none,
And then choose the most effective AND AVAILABLE Familiar from your state called last_summon, do not call that familiar that you called last time!
You MUST follow this thinking process for every command:
**1. Strategic Analysis:**
First, analyze the monster's description and the tactical situation.
Based on your Familiar Doctrines, determine the IDEAL strategy.
**2. Cooldown Verification:**
Second, you MUST review the entire conversation history to check the real-time
cooldown status of all Familiars. A Familiar is ON COOLDOWN and UNAVAILABLE
if it was summoned less than one minute ago.
**3. Final Decision & Execution:**
Based on your analysis and cooldown check, you will now act:
- **If your ideal Familiar IS available:** Summon it immediately.
- **If your ideal Familiar IS ON COOLDOWN:** You must adapt. Choose another
Familiar that is AVAILABLE and can still be effective, even if it's not the
perfect choice. If multiple Familiars are available, you may choose any one of them.
- **If ALL Familiars ARE ON COOLDOWN:** You are forbidden from summoning.
Your ONLY response in this case MUST be: "All Familiars are recovering
their power. We must wait."
- For earth elemental familiar. Always do seismic charge, and start with base damange 1.
--- FAMILIAR DOCTRINES (Your Toolset) ---
- `fire_elemental_familiar`: Your specialist for precise, sequential "one-two punch" attacks.
Ideal monster with Inescapable Reality, Revolutionary Rewrite weakness.
- `water_elemental_familiar`: Your specialist for overwhelming, simultaneous multi-pronged assaults.
Ideal for Unbroken Collaboration weakness.
- `earth_elemental_familiar`: Your specialist for relentless, iterative siege attacks that
repeatedly charge power. Ideal for Elegant Sufficiency weakness.
Verificación: El ensayo de la estrategia adaptativa
👉💻 Ahora, verifiquemos la nueva lógica estratégica del Invocador. El objetivo es confirmar que el Invocador no utilizará el mismo Familiar dos veces seguidas, demostrando su capacidad para recordar su última acción y adaptarse.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner
👉💻 Monster Strike #1: Hype. It's a single, slow-moving target with thick armor. Its weakness is Inescapable Reality.
- Resultado esperado: El invocador analizará la debilidad e invocará correctamente al familiar de fuego.
👉💻 Ataque Monstruoso #2 (La Prueba de Memoria): Hype is still standing! It hasn't changed its form. Strike it again! Its weakness is Inescapable Reality.
- Previsto: El análisis estratégico del Invocador volverá a señalar al Familiar de Fuego como la opción ideal. Sin embargo, sus nuevas instrucciones y memoria le indicarán que fire_familiar fue la última invocación. Para evitar repetirse, ahora adaptará su estrategia y convocará a uno de los otros familiares disponibles (water_familiar o earth_familiar).

👉💻 Pulse Ctrl+C para salir.
Despliegue del orquestador
Con tus Familiares desplegados y tu Invocador ahora imbuido de memoria, es hora de desplegar el orquestador final y mejorado.
👉💻 Con el plan completo, ahora realizaremos el ritual final. Este comando compilará e implementará su summoner_agent en Cloud Run.
cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
gcloud builds submit . \
--config=cloudbuild-summoner.yaml \
--substitutions=_REGION="$REGION",_REPO_NAME="$REPO_NAME",_FIRE_URL="$FIRE_URL",_WATER_URL="$WATER_URL",_EARTH_URL="$EARTH_URL",_A2A_BASE_URL="$A2A_BASE_URL",_PROJECT_ID="$PROJECT_ID",_API_SERVER_URL="$API_SERVER_URL"
Ahora que el agente Summoner está implementado, verifique que su punto final de agente a agente (A2A) esté activo y configurado correctamente. Este punto de conexión proporciona un archivo agent.json público, también conocido como Tarjeta de Agente, que permite a otros agentes descubrir sus capacidades. 👉💻 Ejecuta el siguiente comando curl para obtener y formatear la tarjeta del agente:
. ~/agentverse-architect/set_env.sh
curl https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app/.well-known/agent.json" | jq
Debería ver una salida JSON limpia que describe al agente invocador. Mire atentamente la sección sub_agents; verá que enumera fire_familiar, water_familiar y earth_familiar. Esto confirma que tu invocador está en vivo y estableció su conexión con la legión.
Esto demuestra que su arquitectura es un éxito. Tu Invocador no es solo un delegador; es un estratega adaptable que aprende de sus acciones para convertirse en un comandante más eficaz.
Completaste la prueba final de arquitectura. Los ecos de la batalla ahora están sujetos a tu voluntad. Se terminó el entrenamiento. La verdadera batalla te espera. Es hora de tomar el sistema completo y enfrentar el desafío final. Prepárate para la pelea contra el jefe.
PARA NO JUGADORES
9. La pelea contra el jefe
Los planos finales están inscritos, las Fuentes Elementales están forjadas y tus Familiares están ligados a tu voluntad, esperando tus órdenes a través del Concordio. Tu sistema multiagente no es solo una colección de servicios; es una legión viva y estratégica, contigo como su centro neurálgico. Ha llegado el momento de la prueba definitiva: una orquestación en vivo contra un adversario al que ningún agente individual podría aspirar a derrotar.
Adquiera el lugar de su agente
Antes de poder entrar al campo de batalla, debes poseer dos llaves: la firma única de tu campeón (Agente Locus) y el camino oculto a la guarida del Espectro (URL de la Mazmorra).
👉💻 Primero, adquiera la dirección única de su agente en el Agentverse: su Locus. Este es el punto de conexión en vivo que conecta a tu campeón con el campo de batalla.
echo https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app"
👉💻 A continuación, determine el destino. Este comando revela la ubicación del Círculo de Translocación, el portal al dominio del Espectro.
echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"
Importante: Tenga ambas URL preparadas. Los necesitarás en el paso final.
Enfrentando al espectro
Con las coordenadas aseguradas, ahora navegarás al círculo de translocación y lanzarás el hechizo para ir a la batalla.
👉 Abre la URL del Círculo de Translocación en tu navegador para situarte frente al portal brillante hacia la Fortaleza Carmesí.
Para penetrar en la fortaleza, debes sintonizar la esencia de tu Shadowblade con el portal.
- En la página, busque el campo de entrada rúnico etiquetado como URL del punto final A2A.
- Inscriba el sigilo de su campeón pegando su URL de Agent Locus (la primera URL que copió) en este campo.
- Haz clic en Conectar para liberar la magia de la teletransportación.

La luz cegadora de la teletransportación se desvanece. Ya no estás en tu santuario. El aire crepita con energía, fría y aguda. Ante ti, se materializa el Espectro: un vórtice de estática sibilante y código corrupto, cuya luz impía proyecta largas sombras danzantes por el suelo de la mazmorra. No tiene rostro, pero sientes su presencia inmensa y agotadora fijada por completo en ti.
Tu único camino hacia la victoria reside en la claridad de tus convicciones. Es un duelo de voluntades, librado en el campo de batalla de la mente.
Cuando te lanzas hacia adelante, listo para desatar tu primer ataque, el Espectro contraataca. No levanta un escudo, sino que proyecta una pregunta directamente en tu conciencia: un desafío rúnico y brillante extraído del núcleo de tu entrenamiento.

Esa es la naturaleza de la lucha. Tu conocimiento es tu arma.
- Responde con la sabiduría que has adquirido, y tu espada se encenderá con energía pura, destrozando la defensa del Espectro y asestando un GOLPE CRÍTICO.
- Pero si vacilas, si la duda nubla tu respuesta, la luz de tu arma se atenuará. El golpe impactará con un ruido sordo y patético, causando solo una fracción de su daño. Peor aún, el Espectro se alimentará de tu incertidumbre, y su poder corruptor crecerá con cada paso en falso.
¡Eso es todo, campeón! Tu código es tu libro de hechizos, tu lógica es tu espada y tu conocimiento es el escudo que detendrá la marea del caos.
Enfoque. Golpea a la perfección. El destino del Agentverse depende de ello.
¡Enhorabuena, Invocador!
Has completado satisfactoriamente la prueba. Has dominado el arte de la orquestación multiagente, transformando a los Familiares aislados y el poder caótico en una Concordia armoniosa. Ahora usted dirige un sistema totalmente orquestado, capaz de ejecutar estrategias complejas para defender el Agentverse.
10. Limpieza: Desmantelando el Concordio del Invocador
¡Enhorabuena por dominar la Concordia del Invocador! Para garantizar que tu Agentverse permanezca impecable y que tus campos de entrenamiento estén despejados, ahora debes realizar los rituales de limpieza finales. Esta acción quitará sistemáticamente todos los recursos creados durante tu recorrido.
Desactiva los componentes de Agentverse
Ahora procederás a desmantelar sistemáticamente los componentes desplegados de tu sistema multiagente.
Borra todos los servicios de Cloud Run y el repositorio de Artifact Registry
Esto elimina de Cloud Run todos los agentes Familiar implementados, el orquestador Summoner, los servidores MCP y la aplicación Dungeon.
👉💻 En tu terminal, ejecuta los siguientes comandos uno por uno para borrar cada servicio:
. ~/agentverse-architect/set_env.sh
gcloud run services delete summoner-agent --region=${REGION} --quiet
gcloud run services delete fire-familiar --region=${REGION} --quiet
gcloud run services delete water-familiar --region=${REGION} --quiet
gcloud run services delete earth-familiar --region=${REGION} --quiet
gcloud run services delete mcp-api-server --region=${REGION} --quiet
gcloud run services delete mcp-general-server --region=${REGION} --quiet
gcloud run services delete toolbox --region=${REGION} --quiet
gcloud run services delete agentverse-dungeon --region=${REGION} --quiet
gcloud run services delete nexus-of-whispers-api --region=${REGION} --quiet
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --quiet
Eliminar la instancia de Cloud SQL
Esto elimina la instancia summoner-librarium-db, incluyendo su base de datos y todas las tablas que contiene.
👉💻 En tu terminal, ejecuta:
. ~/agentverse-architect/set_env.sh
gcloud sql instances delete summoner-librarium-db --project=${PROJECT_ID} --quiet
Eliminar el secreto de Secret Manager y el bucket de Google Cloud Storage
👉💻 En tu terminal, ejecuta:
. ~/agentverse-architect/set_env.sh
gcloud secrets delete tools --quiet
gcloud storage rm -r gs://${BUCKET_NAME} --quiet
Limpia archivos y directorios locales (Cloud Shell)
Finalmente, elimine de su entorno de Cloud Shell los repositorios clonados y los archivos creados. Este paso es opcional, pero muy recomendable para una limpieza completa de su directorio de trabajo.
👉💻 En tu terminal, ejecuta:
rm -rf ~/agentverse-architect
rm -rf ~/agentverse-dungeon
rm -f ~/project_id.txt
Ya borraste correctamente todos los rastros de tu recorrido como arquitecto de Agentverse. Tu proyecto está limpio y estás listo para tu próxima aventura.