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 un genio solitario, sino de un dominio colaborativo. Crear un agente único e inteligente es un experimento fascinante. Crear un ecosistema sólido, seguro e inteligente de agentes, un verdadero Agentverse, es el gran desafío para la empresa moderna.
El éxito en esta nueva era requiere la convergencia de cuatro roles fundamentales, los pilares básicos que sustentan cualquier sistema agentivo próspero. Una deficiencia en cualquier área crea una debilidad que puede comprometer toda la estructura.
Este taller es el manual empresarial definitivo para dominar el futuro de los agentes en Google Cloud. Proporcionamos una hoja de ruta integral que te guía desde la primera idea hasta una realidad operativa a gran escala. En estos cuatro labs interconectados, aprenderás cómo las habilidades especializadas de un desarrollador, un arquitecto, un ingeniero de datos y un SRE deben converger para crear, administrar y escalar un Agentverse potente.
Ningún pilar por sí solo puede admitir Agentverse. El gran diseño del arquitecto es inútil sin la ejecución precisa del desarrollador. El agente del desarrollador no puede funcionar sin la sabiduría del ingeniero de datos, y todo el sistema es frágil sin la protección del ingeniero de SRE. Solo a través de la sinergia y la comprensión mutua de los roles, tu equipo puede transformar un concepto innovador en una realidad operativa fundamental. Tu viaje comienza aquí. Prepárate para dominar tu rol y aprender cómo encajas en el conjunto.
Te damos la bienvenida a The Agentverse: A Call to Champions
En la extensa expansión digital de la empresa, comenzó una nueva era. Es la era de los agentes, un momento de inmensas promesas, en el que los 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.
Sin embargo, una entropía sigilosa, una corrupción silenciosa conocida como La Estática, comenzó a deshilachar los bordes de este nuevo mundo. El Estático no es un virus ni un error, sino la encarnación del caos que se aprovecha del acto mismo de la creación.
Amplifica las frustraciones antiguas y las convierte en formas monstruosas, lo que da lugar a los Siete Espectros del Desarrollo. Si no se marca, The Static y sus espectros detendrán el progreso, lo que convertirá la promesa del Agentverse en un páramo de deuda técnica y proyectos abandonados.
Hoy hacemos un llamado a los campeones para que detengan la marea del caos. Necesitamos héroes dispuestos a dominar su oficio y trabajar juntos para proteger el Agentverse. Llegó el momento de elegir tu ruta.
Elige tu clase
Tienes ante ti cuatro caminos distintos, cada uno de ellos un pilar fundamental en la lucha contra The Static. Si bien tu capacitación será una misión en solitario, tu éxito final dependerá de que comprendas cómo se combinan tus habilidades con las de otras personas.
- The Shadowblade (Developer): Un maestro de la forja y el frente de batalla. Eres el artesano que fabrica las cuchillas, construye las herramientas y enfrenta al enemigo en los intrincados detalles del código. Tu camino es de precisión, habilidad y creación práctica.
- El invocador (arquitecto): Es un gran estratega y organizador. 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): Es el protector y escudo firme del reino. Construirás las fortalezas, administrarás las líneas de suministro de energía y te asegurarás de que todo el sistema pueda resistir los inevitables ataques de The Static. Tu fuerza es la base sobre la que se construye la victoria de tu equipo.
Tu misión
Tu entrenamiento comenzará como un ejercicio independiente. Seguirás el camino que elijas y aprenderás las habilidades únicas necesarias para dominar tu rol. Al final de la prueba, te enfrentarás a un espectro nacido de la estática, un jefe menor que se aprovecha de los desafíos específicos de tu oficio.
Solo si dominas tu rol individual podrás prepararte para la prueba final. Luego, debes formar un grupo con campeones de las otras clases. Juntos, se aventurarán en el corazón de la corrupción para enfrentarse a un jefe final.
Un desafío final y colaborativo que pondrá a prueba su fuerza combinada y determinará el destino del Agentverse.
El Agentverse espera a sus héroes. ¿Responderás la llamada?
2. El Concord de los invocadores
Te damos la bienvenida, invocador. Tu camino es de visión y estrategia grandiosa. Mientras que otros se concentran 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. En esta misión, se pondrá a prueba tu capacidad para diseñar, conectar y organizar un sistema multiagente potente.
Qué aprenderás
- Diseña un ecosistema de herramientas desacoplado: Diseña e implementa un conjunto de servidores de herramientas de 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 Intelligent Orchestrator: Pasa de ser un simple creador de agentes a un verdadero arquitecto de sistemas. Construirás un agente de orquestación principal que usa el protocolo de agente a agente (A2A) para descubrir y delegar tareas complejas a tus familiares 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.
- Administra el estado y la memoria del agente: Dales a tus agentes la capacidad de aprender y recordar. Explorarás técnicas para administrar tanto el estado conversacional a corto plazo como la memoria persistente a largo plazo para crear interacciones más inteligentes y contextuales.
- Ejecuta una implementación de Cloud de extremo a extremo: Lleva todo tu sistema multiagente 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
Te damos la bienvenida, invocador. Antes de que se pueda invocar a un solo Familiar, antes de que se pueda forjar cualquier pacto, se debe preparar el suelo sobre el que te encuentras. Un entorno indómito es una invitación al caos; un invocador adecuado solo opera dentro de un espacio santificado y potenciado. 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 ícono con forma de terminal en la parte superior del panel de Cloud Shell).
👉 Haz clic en el botón "Abrir editor" (parece una 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.
👉 Busca tu ID del proyecto de Google Cloud:
- Abre la consola de Google Cloud:
https://console.cloud.google.com
- Selecciona el proyecto que deseas usar para este taller en el menú desplegable de proyectos que se encuentra en la parte superior de la página.
- Tu ID del proyecto se muestra en la tarjeta de información del proyecto en el panel
👉Abre la terminal en el IDE de Cloud,
👉💻 En la terminal, verifica que ya te autenticaste y que el proyecto esté configurado con tu ID del proyecto usando el siguiente comando:
gcloud auth list
👉💻 Clona el proyecto de arranque 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 inicialización. Esta secuencia te pedirá que ingreses tu ID del proyecto de Google Cloud. Ingresa el ID del proyecto de Google Cloud que encontraste en el último paso cuando el script init.sh
te lo solicite.
cd ~/agentverse-architect
./init.sh
👉💻 Configura el ID del proyecto necesario:
gcloud config set project $(cat ~/project_id.txt) --quiet
👉💻 Ejecuta el siguiente comando para habilitar las APIs 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 creaste un repositorio de Artifact Registry llamado agentverse-repo, ejecuta el siguiente comando para crearlo: (omite este paso si tienes 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"
Cómo configurar permisos
👉💻 Ejecuta los siguientes comandos en la terminal para otorgar los permisos necesarios:
. ~/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"
👉💻 Mientras comienzas tu entrenamiento, prepararemos el desafío final. Los siguientes comandos invocarán a los espectros desde la estática caótica, lo que creará a los jefes para tu prueba final.
. ~/agentverse-architect/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-architect
👉💻 Por último, ejecuta la secuencia de comandos 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 completó y los pactos se sellaron. El suelo ahora está consagrado y listo para canalizar un poder inmenso. En nuestra próxima prueba, forjaremos las fuentes elementales de las que nuestros familiares obtendrán su fuerza.
4. Forjando las fuentes elementales: El ecosistema de herramientas desacoplado
El campo de batalla está preparado, el círculo de invocación está dibujado y el maná ambiental crepita. Es hora de realizar tu primer acto verdadero como invocador: forjar las fuentes de poder de las que tus familiares obtendrá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 la invocación.
Nota del arquitecto: El servidor del Protocolo de contexto del modelo (MCP) es un componente fundamental en un sistema basado en agentes moderno, ya que actúa como un puente de comunicación estandarizado que permite que un agente descubra y use herramientas remotas. En nuestro ecosistema de herramientas, diseñaremos dos tipos distintos de servidores de MCP, cada uno de los cuales representa un patrón arquitectónico crítico. Para conectarnos a nuestra base de datos, usaremos un enfoque declarativo con Database Toolbox, y definiremos 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 negocios personalizada o llamar a APIs externas de terceros, usaremos un enfoque imperativo y escribiremos la lógica del servidor paso a paso en el código. Esto proporciona el máximo control y flexibilidad, lo que nos permite encapsular operaciones complejas detrás de una herramienta simple y reutilizable. Un arquitecto principal debe comprender ambos patrones para seleccionar el enfoque adecuado para cada componente y crear una base de herramientas sólida, segura y escalable.
Despertar el Nexus de los susurros (servidor de MCP de la 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 se pueden canalizar con gran efecto. El Nexus 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: Usarás un enfoque imperativo que define de forma explícita la lógica del servidor paso a paso. Esto te brinda mucho más control y flexibilidad, lo que es fundamental cuando tus herramientas necesitan hacer algo más que ejecutar una simple consulta SQL, como llamar a otras APIs. Comprender ambos patrones es una habilidad fundamental para un arquitecto de agentes.
👉✏️ Navega al directorio ~/agentverse-architect/mcp-servers/api/main.py
y REEMPLAZA #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 centro de la secuencia de comandos, se encuentran las funciones de Python simples. Aquí es donde se realiza el trabajo real.
👉✏️ En el mismo archivo ~/agentverse-architect/mcp-servers/api/main.py
, REEMPLAZA #REPLACE-Runes of Communication
por 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 saludo): Esta función es el saludo del servidor. Cuando se conecta un agente nuevo, primero llama a este endpoint para preguntar: "¿Qué puedes hacer?". Nuestro código responde con una lista de todas las herramientas disponibles, convertidas al formato universal de MCP con adk_to_mcp_tool_type. -@app.call_tool()
(el comando): Esta función es la más importante. Cuando el agente decide usar una herramienta, envía una solicitud a este endpoint 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 estándar de MCP.
Implementaremos esto más adelante.
Cómo encender la forja arcana (servidor de MCP de funciones generales)
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. La Forja Arcana es esta 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 es común conectarse a sistemas existentes, con frecuencia deberás implementar tus propias reglas y lógica empresariales únicas. Crear una herramienta dedicada de "funciones" o "utilidades" como esta es una práctica recomendada. Encapsula tu lógica personalizada, la hace reutilizable para cualquier agente de tu ecosistema y la mantiene desacoplada de tus fuentes de datos y las integraciones externas.
👀 Consulta el 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 la implementación de ambos servicios.
👉💻 Desde el directorio ~/agentverse-architect/mcp-servers
, ejecuta 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"
Espera hasta que se completen todas las implementaciones.
👉 Para verificar la implementación, navega a la consola de Cloud Run. Deberías ver las dos nuevas instancias del servidor de MCP en ejecución, como se muestra a continuación:
Despertar el Librarium del conocimiento (servidor de MCP de Database ToolBox)
Nuestra próxima fuente será Librarium of Knowledge, una conexión directa a nuestra base de datos de Cloud SQL.
Nota del arquitecto: Para esto, usaremos la moderna y declarativa Caja de herramientas de la base de datos. Este es un enfoque eficaz en el que definimos nuestra fuente de datos y nuestras herramientas en un archivo de configuración YAML. La caja de herramientas controla el trabajo complejo de crear y ejecutar el servidor, lo que reduce la cantidad de código personalizado que debemos escribir y mantener.
Es hora de compilar nuestra "Biblioteca de invocadores", la base de datos de Cloud SQL que contendrá 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
Cuando finalice la secuencia de comandos, se completará tu base de datos y los datos de daño elemental estarán listos para usarse. Ahora puedes verificar el contenido de tu Grimoire directamente.
👉 Primero, navega a Cloud SQL Studio para tu base de datos. Para ello, abre este vínculo directo en una nueva pestaña del navegador:
https://console.cloud.google.com/sql/instances/summoner-librarium-db
👉 En el panel de acceso de la izquierda, selecciona la base de datos familiar_grimoire
en el menú desplegable.
👉 Ingresa summoner
como usuario y 1234qwer
como contraseña. Luego, haz clic en Autenticar.
👉📜 Una vez que te hayas conectado, abre una nueva pestaña del editor de consultas si aún no hay una abierta. Para ver los datos de daño elemental grabado, pega y ejecuta la siguiente consulta en SQL:
SELECT * FROM
"public"."abilities"
Ahora deberías ver la tabla abilities
con sus columnas y filas completadas, lo que confirma que tu Grimoire está listo.
Configura el servidor de MCP de ToolBox
El archivo de configuración tools.yaml
actúa como el plano de nuestro servidor, ya que le indica a Database Toolbox exactamente cómo conectarse a nuestra base de datos y qué consultas de SQL exponer como herramientas.
sources: En esta sección, se definen las conexiones a tus datos.
- summoner-librarium:: Este es el nombre lógico que le dimos a nuestra conexión.
- kind: cloud-sql-postgres: Le indica a la caja de herramientas que use su conector seguro integrado diseñado específicamente para Cloud SQL para PostgreSQL.
- proyecto, región, instancia, etcétera: Estas son las coordenadas exactas de la instancia de Cloud SQL que creaste durante el script prepare.sh, que le indican a Toolbox dónde encontrar nuestra Librarium.
👉✏️ Dirígete a ~/agentverse-architect/mcp-servers/db-toolbox
en tools.yaml
, reemplaza #REPLACE-Source
por 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.
tools: En esta sección, se definen las capacidades o funciones reales que ofrecerá nuestro servidor.
- lookup-available-ability:: Este es el nombre de nuestra primera herramienta.
- kind: postgres-sql: Indica a la caja de herramientas que la acción de esta herramienta es ejecutar una instrucción SQL.
- source: summoner-librarium: Vincula la herramienta a la conexión que definimos en el bloque de fuentes. Así es como la herramienta sabe en qué base de datos ejecutar su consulta.
- Descripción y parámetros: Es la información que se expondrá al modelo de lenguaje. La descripción le indica al agente cuándo 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.
- instrucción: Es la consulta de SQL sin procesar que se ejecutará. El signo de dólar ($) es un marcador de posición seguro en el que 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
, reemplaza #REPLACE-tools
por 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: En esta sección, se agrupan 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 que se carguen todas las herramientas del conjunto de herramientas de la biblioteca de invocadores en un solo comando eficiente.
👉✏️ En el mismo ~/agentverse-architect/mcp-servers/db-toolbox
del archivo tools.yaml
, reemplaza #REPLACE-toolsets
por lo siguiente:
toolsets:
summoner-librarium:
- lookup-available-ability
- ability-damage
Implementa Librarium
Ahora implementaremos Librarium. En lugar de compilar nuestro propio contenedor, usaremos una imagen de contenedor oficial compilada previamente de Google y le proporcionaremos de forma segura nuestra configuración de tools.yaml con Secret Manager. Esta es una práctica recomendada 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 oficial de la caja de herramientas 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" \
--args="--tools-file=/app/tools.yaml","--address=0.0.0.0","--port=8080" \
--allow-unauthenticated \
--min-instances 1
--set-secrets
: Este comando une 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 use el archivo de secretos montado como su configuración.
👉 Para confirmar que tu caja de herramientas se implementó correctamente, navega a la consola de Cloud Run. Deberías ver el servicio summoner-toolbox
con una marca de verificación verde, lo que indica que se está ejecutando correctamente, como en la siguiente imagen.
Qué hacer si olvidaste actualizar
YOUR_PROJECT_ID
Puedes agregar una nueva versión del archivo tools.yaml al secreto con el siguiente comando y volver a realizar la implementación.
gcloud secrets versions add tools --data-file=tools.yaml
La Librarium of Knowledge(Database ToolBox MCP Server) ahora está activa y accesible en la nube. Este servidor de MCP usa lo que llamamos un diseño declarativo que describe lo que querías, y la caja de herramientas creó el servidor por ti.
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, prueba 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.
Felicitaciones, invocador. Tus tres fuentes elementales ahora están activas, implementadas de forma independiente y accesibles a nivel mundial, lo que constituye la base inquebrantable de tu legión de agentes. Presiona Ctrl+C
para salir.
PARA LOS QUE NO SON GAMERS
5. Cómo invocar a los familiares: El flujo de trabajo del dominio principal
Las fuentes elementales se forjan y emiten un zumbido con poder bruto 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 de forjar 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 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 ejercerá 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, ya que se le otorgará acceso solo a los servidores de herramientas de MCP específicos que necesite para realizar su función. En este lab, se muestra cómo seleccionar el tipo de agente adecuado para el trabajo correcto.
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, un ParallelAgent o un 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.
Invoca a 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 potente ignición. Esto requiere una secuencia de acciones estricta y ordenada.
Concepto: La 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 de "falta amplificada"):
- Paso 1: Primero, el agente consultará el Librarium para encontrar 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 con inferno_resonance.
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
, REEMPLAZA #REPLACE-setup-MCP
por 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. Cada una 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/fire/agent.py
, REEMPLAZA #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 componentes básicos flexibles. Este es un principio fundamental del diseño basado en microservicios y componentes.
A continuación, ensamblaremos el flujo de trabajo, que 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
, REEMPLAZA #REPLACE-sequential-agent
con el siguiente código:
root_agent = SequentialAgent(
name='fire_elemental_familiar',
sub_agents=[scout_agent, amplifier_agent],
)
👉💻 Para probar el Fire Elemental, ejecuta los siguientes comandos que iniciarán la IU 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
Después de ejecutar los comandos, deberías ver un resultado en tu terminal que indique que se inició el servidor web del ADK, 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 para desarrolladores del ADK desde tu navegador, haz lo siguiente:
En el ícono de Vista previa en la Web (a menudo, parece un ojo o un cuadrado con una flecha) en la barra de herramientas de Cloud Shell (por lo general, en la parte superior derecha), selecciona Cambiar puerto. En la ventana emergente, establece el puerto en 8000 y haz clic en "Cambiar y obtener vista previa". Luego, Cloud Shell abrirá una nueva pestaña o ventana del navegador en la que se mostrará la IU de ADK Dev.
👉 Se completó el ritual de invocación y el agente ahora se está ejecutando. La IU para desarrolladores del ADK en tu navegador es tu conexión directa con Familiar.
- Selecciona tu objetivo: En el menú desplegable que se encuentra en la parte superior de la IU, elige el
fire
familiar. Ahora te enfocas en esta entidad específica. - Da tu orden: En el panel de chat de la derecha, es hora de darle órdenes a Familiar.
👉 Instrucción de prueba:
Prepare an amplified strike using the 'inferno_lash' ability.
Verás cómo el agente piensa, primero llamando a su "explorador" para buscar el daño base y, luego, a su "amplificador" para multiplicarlo y asestar el golpe épico final.
👉💻 Cuando termines de invocar, regresa a la terminal del editor de Cloud Shell y presiona Ctrl+C
para detener la IU de desarrollo del ADK.
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 varias tareas independientes de forma simultánea y maximizar la eficiencia. Es un "ataque de pinza" en el que lanzas varios ataques a la vez. Esto lanza los ataques simultáneos dentro de un SequentialAgent
para ejecutar un paso de "fusión" final después. Este patrón "fan-out, fan-in
" es una piedra angular del diseño avanzado de flujos de trabajo.
Tarea (combo de "Tidal Clash"): El agente realizará las siguientes acciones de forma simultánea:
- Tarea A: Canal
cryosea_shatter
del Nexus. - Tarea B: Canal
moonlit_cascade
desde el Nexus. - Tarea C: Genera potencia bruta con
leviathan_surge
desde Forge. - Por último, suma todo el daño 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" especialistas. Cada una 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. El ParallelAgent
y el SequentialAgent
son el "plan maestro" que define cómo se ensamblan nuestros componentes especializados y cómo interactúan para formar el combo "Tidal Clash".
👉✏️ 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 IU 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
👉 Se completó el ritual de invocación y el agente ahora se está ejecutando. La IU para desarrolladores del ADK en tu navegador es tu conexión directa con Familiar.
- En el menú desplegable que se encuentra en la parte superior de la IU, elige el familiar agua. Ahora te enfocas en esta entidad específica.
- Da tu orden: En el panel de chat de la derecha, es hora de darle órdenes a Familiar.
👉 Instrucción de prueba:
Unleash a tidal wave of power!
👉💻 Cuando termines de invocar, regresa a la terminal del editor de Cloud Shell y presiona Ctrl+C
para detener la IU de desarrollo del ADK.
Invoca a Earth Elemental
Familiar (flujo de trabajo de Loop)
Un familiar elemental de la Tierra es un ser de presión implacable. No derrota a su enemigo con un solo golpe, sino que acumula poder de forma constante y lo aplica 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á su sub-agents
de forma repetida, verificando una condición después de cada ciclo, hasta que se cumpla un objetivo. También puede adaptar su mensaje final según el progreso del bucle.
Tarea (Asalto "Siegebreaker"):
- El Familiar llamará a seismic_charge de forma repetida para acumular energía.
- Seguirá cargándose hasta 3 veces como máximo.
- 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, y cambiará dinámicamente su mensaje en el turno final.
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/earth/agent.py
, REEMPLAZA #REPLACE-setup-MCP
por el siguiente código:
toolFunction = MCPToolset(
connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)
👉✏️ En el archivo ~/agentverse-architect/agent/earth/agent.py
, REEMPLAZA #REPLACE-worker-agents
por 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. LoopAgent es el "plan maestro" que coordina la ejecución repetida de nuestros componentes especializados y administra las condiciones del bucle.
👉✏️ En el archivo ~/agentverse-architect/agent/earth/agent.py
, REEMPLAZA #REPLACE-loop-agent
por 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
👉 Se completó el ritual de invocación y el agente ahora se está ejecutando. La IU para desarrolladores del ADK en tu navegador es tu 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 darle órdenes a Familiar. 👉 Instrucción de prueba:
Begin the seismic charge, starting from zero
Conclusión sobre la arquitectura: Tu sistema ahora posee una capa de lógica altamente especializada y modular. Los procesos comerciales no solo están encapsulados, sino que también 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.
Cuando termines de invocar, vuelve a la terminal del editor de Cloud Shell y presiona Ctrl+C
para detener la IU de desarrollo del ADK.
PARA LOS QUE NO SON GAMERS
6. Establecimiento del Locus de Comando: Delegación Inteligente a través de A2A
Tus familiares son poderosos, pero independientes. Ejecutan sus estrategias a la perfección, pero esperan tu orden directa. Una legión de especialistas es inútil sin un general que los dirija. Es hora de ascender de comandante directo a un verdadero organizador.
Nota del arquitecto: Para crear un único punto de entrada inteligente para todo el sistema. Este SummonerAgent no realizará la lógica empresarial por sí mismo, sino que actuará como un "estrategista principal", analizará el estado de enfriamiento y delegará tareas al Familiar especialista adecuado.
El ritual de vinculación (exponer familiares como servicios A2A)
Un agente estándar solo se puede ejecutar en un lugar a la vez. Para que nuestros Familiares estén disponibles para el control remoto, debemos realizar un "ritual de vinculación" con el protocolo Agent-to-Agent (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". Cuando expones un Familiar a través de A2A, se crean automáticamente dos componentes esenciales interconectados:
- La tarjeta del agente (el "qué"): Es un "sello espiritual" público y legible por máquina, como una especificación de 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 los comandos que comprende. Esto es lo que lee un invocador maestro para descubrir a un familiar y conocer 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 a la que otros agentes envían sus solicitudes y garantiza que estas se controlen según el contrato definido en la tarjeta del agente.
Ahora realizaremos este ritual de vinculación en nuestros tres familiares.
Fuego 👉✏️ en Abre el archivo ~/agentverse-architect/agent/fire/agent.py
. Reemplaza #REPLACE - add A2A
en la parte inferior del archivo para exponer el Fire Elemental como un servicio de 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 exactamente 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"
Suposición de comandos (construcción del agente de invocación)
Ahora que tus familiares están vinculados y escuchando, 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, que descubrirá y controlará con sus "Sellos espirituales".
Nota del arquitecto: El siguiente paso demuestra un patrón arquitectónico fundamental para cualquier sistema distribuido a gran escala: el descubrimiento de servicios. El SummonerAgent no tiene incorporado el código de los Familiars. En cambio, se le proporcionan las direcciones de red (URLs). En el tiempo de ejecución, "descubrirá" de forma dinámica sus capacidades recuperando sus tarjetas de agente 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.
👉✏️ Ve a ~/agentverse-architect/agent/summoner/agent.py
y reemplaza #REPLACE-remote-agents
por 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 detección de servicios: hace una solicitud HTTP GET a la URL proporcionada (p.ej., https://fire-familiar-xxxx.a.run.app/.well-known/agent.json). Descarga el "Sello de espíritu" (archivo agent.json
) del servidor remoto.
En segundo lugar, definiremos el agente organizador que usará 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 darles órdenes en toda la red. Probemos su mente estratégica.
👉💻 Inicia la IU para desarrolladores del ADK de tu 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 IU para desarrolladores del ADK en tu navegador es tu conexión directa con Familiar.
- En el menú desplegable que se encuentra en la parte superior de la IU, elige el agente invocador. Ahora te enfocas en esta entidad específica.
- Emite tu comando: En el panel de chat de la derecha, es hora de invocar a tus familiares.
👉 Presenta a los Monsters:
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
(Se espera que el invocador delegue en el familiar elemental de fuego).
👉 Ahora, desafiemos al Summoner con otro tipo de solicitud. Para asegurarte de que el agente comience con una pizarra limpia y sin memoria de nuestra interacción anterior, haz clic en el botón + Sesión en la esquina superior derecha de la pantalla para iniciar una sesión nueva.
DogmaApathy. A rigid, stone-like inquisitor made of ancient rulebooks and enforced processes. weakness is Unbroken Collaboration
(Se espera que el invocador delegue en el familiar elemental de agua).
👉 Para nuestra prueba final, volvamos a comenzar con una pizarra limpia. Haz clic en el botón + Sesión para iniciar una sesión nueva antes de ingresar la siguiente instrucción.
Obfuscation. A shadowy, spider-like horror that spins tangled webs of impenetrable code , weakness is Elegant Sufficiency
(Se espera que el invocador delegue en el familiar elemental de tierra).
Importante: Si ves un error 429 RESOURCE EXHAUSTED
, significa que alcanzaste el límite de frecuencia de la LLM (10 llamadas por minuto). Para solucionar este problema, espera 60 segundos, inicia una + sesión nueva y, luego, vuelve a intentar tu instrucción.
👉💻 Cuando termines de invocar, regresa a la terminal del editor de Cloud Shell y presiona Ctrl+C
para detener la IU de desarrollo del ADK.
PARA LOS QUE NO SON GAMERS
7. Imposing the Laws of Magic: The Interceptor Pattern
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 no han tenido estado. 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, agregar registros o modificar el comportamiento sin cambiar el código principal del agente. Es una piedra angular para crear sistemas basados en agentes sólidos, observables y que admitan mantenimiento.
El ADK proporciona dos formas principales de implementar este patrón: devoluciones de llamada y complementos. Una devolución de llamada es una función simple adjunta a un solo agente, perfecta para modificaciones rápidas y específicas. Un complemento es una clase más potente y reutilizable que se puede aplicar de forma global 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.
The Law Giver: Escribir la devolución de llamada de Cooldown
Primero, implementaremos nuestra lógica de período de recuperación como una función de devolución de llamada simple. Esta es una excelente manera de crear prototipos y depurar una regla, ya que se adjunta directamente a un solo agente, lo que facilita la prueba de forma aislada. Adjuntaremos este "interceptor" a nuestro Elemental de la Tierra.
👉✏️ Vuelve a tu ~/agentverse-architect/agent/earth/agent.py
y reemplaza #REPLACE-before_agent-function
por 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 la ejecución del Elemental de Tierra, el ADK primero ejecutará esta función.
- Verificación: Realiza una solicitud
GET
a nuestroCooldown API
para verificar la última vez que se usó este Familiar. - Evaluar: Compara la marca de tiempo con la hora actual.
- Medida:
- 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
Cómo verificar el período de enfriamiento
Probemos nuestra nueva ley de la magia. 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:
- Primer citatorio: Comienza el
seismic charge, starting from zero
. - Resultado esperado: El elemental de tierra se ejecutará correctamente. En la terminal que ejecuta el comando web del ADK, verás el registro [Callback] … Updating timestamp….
- Prueba de inactividad (en un plazo de 60 segundos):
Do another
carga sísmica.- Resultado esperado:
check_cool_down callback
interceptará esta solicitud. 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:
- Espera un minuto.
- Segundo llamado (después de 60 segundos):
Begin the seismic charge again
.- Resultado esperado: La devolución de llamada verificará la API, verá que transcurrió el tiempo suficiente y permitirá que continúe la acción. El elemental de tierra volverá a funcionar correctamente.
👉💻 Presiona Ctrl+c
para salir.
Opcional: Observa la devolución de llamada en la IU web
Como alternativa, también puedes probar este flujo en la interfaz web ejecutando adk web earth
. Sin embargo, ten en cuenta que la visualización de la IU web no está optimizada para mostrar las verificaciones rápidas e iterativas que realiza el bucle de devolución de llamada, por lo que es posible que no renderice el flujo con precisión. Para ver el registro más preciso y paso a paso de la lógica del agente a medida que verifica el período de espera, usa el comando adk run
en tu terminal, que proporciona una vista más clara y detallada.
👉💻 Presiona Ctrl+c
para salir.
Cómo crear la ley universal: el complemento de enfriamiento
Nuestra devolución de llamada funciona perfectamente, pero tiene un defecto arquitectónico importante: está vinculada a un solo 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 complementos son esenciales. Un complemento encapsula nuestra lógica reutilizable en una clase que se puede adjuntar a nivel del tiempo de ejecución. Esto significa que un solo complemento puede aplicar sus reglas a cada uno de los agentes que se ejecutan dentro de ese sistema. Es la expresión máxima del principio "No te repitas" (DRY) para los sistemas basados en agentes.
Ahora refactorizaremos nuestra función de devolución de llamada en una CoolDownPlugin
más potente y reutilizable.
👉✏️ Vuelve al archivo agent/cooldown_plugin.py
y crea el complemento. Reemplaza #REPLACE-plugin
por 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.")
Cómo 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 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, quitemos la devolución de llamada anterior 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
por el siguiente fragmento de código:
plugins=[CoolDownPlugin(cooldown_seconds=60)],
Antes de activar nuestro nuevo complemento global, es fundamental quitar la lógica anterior específica del agente para evitar conflictos. 👉✏️ Limpia el agente de la Tierra. Ve al siguiente archivo ~/agentverse-architect/agent/earth/agent.py
y borra la línea before_agent_callback=check_cool_down
por completo. De esta manera, se transfieren todas las responsabilidades de los períodos de espera al nuevo complemento.
Cómo verificar el complemento
Ahora que nuestra ley universal está en su lugar, debemos volver a implementar nuestros familiares con este nuevo encantamiento.
👉💻 Vuelve a compilar y a implementar los tres Familiars con la canalización principal 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 eficacia del complemento con el comando de nuestro summoner_agent. El Summoner intentará delegar en los Familiars, pero el complemento adjunto al tiempo de ejecución de cada Familiar interceptará el comando y aplicará 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:
- Primer citatorio: Comienza el
Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality
. - Resultado esperado: El elemental de fuego se ejecutará 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
- Espera un minuto.
- Segundo llamado (después de 60 segundos):
Hype must be defeated. It has Inescapable Reality as weakness! Strike it again!
.- Resultado esperado: La devolución de llamada verificará la API, verá que transcurrió el tiempo suficiente y permitirá que continúe la acción. El Elemental de fuego volverá a ejecutarse correctamente.
👉💻 Presiona Ctrl+C
para salir.
Felicitaciones, 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 LOS QUE NO SON GAMERS
8. Cómo unir los ecos de la batalla: estado y memoria del agente
Un invocador imprudente repite la misma estrategia y se vuelve predecible. Un sabio invocador aprende de los ecos de las batallas pasadas y adapta sus tácticas para mantener al enemigo en desequilibrio. Cuando te enfrentas a un jefe poderoso, invocar a un Familiar que está en tiempo de espera es un turno desperdiciado, un error crítico. Para evitar esto, nuestro invocador necesita recordar su última acción.
Nota del arquitecto: La administración de la memoria y el estado son lo que elevan a un agente de un simple llamador de herramientas a un socio inteligente y conversacional. Es fundamental comprender los dos tipos principales:
- Memoria a largo plazo: Se usa para el conocimiento persistente que debería durar para siempre. Piensa en ella como un archivo o una base de conocimiento en la que se pueden realizar búsquedas y que, a menudo, se almacena en un almacén persistente. Contiene información de muchos chats y fuentes anteriores, lo que permite que un agente recuerde datos sobre un usuario o tema específico. El MemoryService del ADK está diseñado para esto, ya que administra la transferencia 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 de uso, no necesitamos recordar cada batalla que se haya librado, sino solo el último Familiar invocado en este encuentro específico. Por lo tanto, el Short-Term State ligero es la opción arquitectónica perfecta. Usaremos un after_tool_callback
para guardar esta información crucial.
Escribiendo el eco: Recordando la última convocatoria
Implementaremos nuestra memoria a corto plazo con un after_tool_callback
. Este es un potente gancho del ADK que nos permite ejecutar una función personalizada de Python después de que se haya ejecutado correctamente una herramienta. Usaremos este interceptor para registrar el nombre del Familiar que se acaba de invocar en el estado de la 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 de Summoner. En el mismo archivo, reemplaza el comentario #REPLACE-Memory-check-config
por lo siguiente:
after_tool_callback=save_last_summon_after_tool,
👉✏️ Reemplaza todo el mensaje del agente por el 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: La prueba de la estrategia adaptable
👉💻 Ahora, verifiquemos la nueva lógica estratégica del invocador. El objetivo es confirmar que el invocador no usará el mismo familiar dos veces seguidas, lo que demuestra su capacidad de 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 y convocará correctamente al familiar de fuego. 👉💻 Monster Strike #2 (La prueba de memoria):
Hype is still standing! It hasn't changed its form. Strike it again! Its weakness is Inescapable Reality.
- Resultado esperado: 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 el último en ser invocado. Para evitar repetirse, ahora adaptará su estrategia y convocará a uno de los otros familiares disponibles (water_familiar o earth_familiar).
👉💻 Presiona Ctrl+C
para salir.
Implementa el organizador
Ahora que tus familiares están desplegados y tu invocador está imbuido de memoria, es momento de desplegar el orquestador final actualizado.
👉💻 Con el plan completo, ahora realizaremos el ritual final. Este comando compilará e implementará tu 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 se implementó el agente de Summoner, verifica que su extremo de agente a agente (A2A) esté activo y configurado correctamente. Este extremo entrega un archivo agent.json público, también conocido como tarjeta del agente, que permite que otros agentes descubran sus capacidades. 👉💻 Ejecuta el siguiente comando de curl para recuperar y dar formato a la tarjeta de agente:
. ~/agentverse-architect/set_env.sh
curl https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app/.well-known/agent.json" | jq
Deberías ver un resultado JSON limpio que describa al agente de invocación. Observa con atención la sección sub_agents. Verás 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 tu arquitectura es un éxito. Tu invocador no es solo un delegado, sino 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 LOS QUE NO SON GAMERS
9. La pelea final
Los planos finales están inscritos, las fuentes elementales están forjadas y tus familiares están vinculados a tu voluntad, a la espera de tus órdenes a través del Concord. Tu sistema multiagente no es solo una colección de servicios, sino una legión estratégica y activa, con vos como su centro. Llegó el momento de la prueba definitiva: una orquestación en tiempo real contra un adversario al que ningún agente podría derrotar por sí solo.
Adquiere el Locus de tu agente
Antes de ingresar al campo de batalla, debes tener dos llaves: la firma única de tu campeón (Agent Locus) y la ruta oculta a la guarida de Spectre (URL de Dungeon).
👉💻 Primero, adquiere la dirección única de tu agente en Agentverse, es decir, su Locus. Este es el extremo 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, indica el destino. Este comando revela la ubicación del círculo de translocación, el portal hacia el dominio de Spectre.
echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"
Importante: Ten listas ambas URLs. Los necesitarás en el paso final.
Confrontando al Spectre
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 pararte frente al brillante portal que lleva a La Fortaleza Carmesí.
Para entrar en la fortaleza, debes sintonizar la esencia de tu Shadowblade con el portal.
- En la página, busca el campo de entrada rúnica etiquetado como URL del extremo de A2A.
- Inscribe el sello de tu campeón pegando su URL de Agent Locus (la primera URL que copiaste) 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 radica en la claridad de tu convicción. Es un duelo de voluntades, librado en el campo de batalla de la mente.
Mientras 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.
Esta 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 se asestará con un golpe sordo patético, y solo infligirá UNA FRACCIÓN DE SU DAÑO. Peor aún, el Spectre 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. El golpe es verdadero. El destino del Agentverse depende de ello.
Felicitaciones, invocador.
Completaste la prueba correctamente. Dominaste el arte de la orquestación de varios agentes, transformando a los Familiares aislados y el poder caótico en una Concordia armoniosa. Ahora comandas un sistema completamente orquestado, capaz de ejecutar estrategias complejas para defender el Agentverse.
10. Limpieza: Desmantelamiento de la Concordia del Invocador
¡Felicitaciones por dominar el Concord 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 desmantelarás sistemáticamente los componentes implementados de tu sistema multiagente.
Borra todos los servicios de Cloud Run y el repositorio de Artifact Registry
Se quitarán de Cloud Run todos los agentes de Familiar implementados, el orquestador de Summoner, los servidores de MCP y la aplicación de 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
Borra la instancia de Cloud SQL
Esto quita la instancia summoner-librarium-db
, incluida su base de datos y todas las tablas que contiene.
👉💻 En tu terminal, ejecuta lo siguiente:
. ~/agentverse-dataengineer/set_env.sh
gcloud sql instances delete summoner-librarium-db --database-version=POSTGRES_14 --project=${PROJECT_ID} --quiet
Borra el secreto de Secret Manager y el bucket de Google Cloud Storage
👉💻 En tu terminal, ejecuta lo siguiente:
. ~/agentverse-dataengineer/set_env.sh
gcloud secrets delete tools --quiet
gcloud storage rm -r gs://${BUCKET_NAME} --quiet
Limpia los archivos y directorios locales (Cloud Shell)
Por último, borra de tu entorno de Cloud Shell los repositorios clonados y los archivos creados. Este paso es opcional, pero se recomienda para limpiar por completo tu directorio de trabajo.
👉💻 En tu terminal, ejecuta lo siguiente:
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 listo para tu próxima aventura.