Agentverse - The Summoner's Concord - Architecting Multi-Agent Systems

1. l'ouverture de "La force du destin".

L'ère du développement cloisonné touche à sa fin. La prochaine vague d'évolution technologique ne concerne pas le génie solitaire, mais la maîtrise collaborative. La création d'un agent unique et intelligent est une expérience fascinante. Le grand défi pour l'entreprise moderne consiste à créer un écosystème d'agents robuste, sécurisé et intelligent, un véritable Agentverse.

Pour réussir dans cette nouvelle ère, il est nécessaire de réunir quatre rôles essentiels, qui sont les piliers fondamentaux de tout système agentique prospère. Une lacune dans l'un de ces domaines crée une faiblesse qui peut compromettre l'ensemble de la structure.

Cet atelier constitue le guide de référence pour les entreprises souhaitant maîtriser l'avenir des agents sur Google Cloud. Nous vous proposons une feuille de route de bout en bout qui vous guide de la première idée à une réalité opérationnelle à grande échelle. À travers ces quatre laboratoires interconnectés, vous apprendrez comment les compétences spécialisées d'un développeur, d'un architecte, d'un ingénieur de données et d'un ingénieur SRE doivent converger pour créer, gérer et faire évoluer un Agentverse puissant.

Aucun pilier ne peut prendre en charge l'Agentverse à lui seul. Le grand projet de l'architecte est inutile sans l'exécution précise du développeur. L'agent du développeur est aveugle sans la sagesse de l'ingénieur des données, et l'ensemble du système est fragile sans la protection de l'ingénieur SRE. C'est uniquement grâce à la synergie et à une compréhension mutuelle des rôles de chacun que votre équipe pourra transformer un concept innovant en une réalité opérationnelle essentielle. L'aventure commence ici. Préparez-vous à maîtriser votre rôle et à comprendre comment vous vous inscrivez dans l'ensemble.

Bienvenue dans l'univers des agents : un appel aux champions

Dans l'immensité numérique de l'entreprise, une nouvelle ère s'est ouverte. Nous vivons à l'ère de l'agentivité, une époque pleine de promesses, où des agents intelligents et autonomes travaillent en parfaite harmonie pour accélérer l'innovation et balayer la monotonie.

agentverse.png

Cet écosystème connecté de puissance et de potentiel est connu sous le nom d'Agentverse.

Mais une entropie rampante, une corruption silencieuse connue sous le nom de "Statique", a commencé à effilocher les bords de ce nouveau monde. Le Statique n'est pas un virus ni un bug. Il est l'incarnation du chaos qui se nourrit de l'acte de création lui-même.

Il amplifie les anciennes frustrations pour les transformer en formes monstrueuses, donnant ainsi naissance aux sept spectres du développement. Si on ne les contrôle pas, The Static et ses Spectres paralyseront tout progrès, transformant la promesse de l'Agentverse en un désert de dettes techniques et de projets abandonnés.

Aujourd'hui, nous faisons appel à des champions pour repousser la vague du chaos. Nous avons besoin de héros prêts à maîtriser leur art et à travailler ensemble pour protéger l'Agentverse. Il est temps de choisir votre parcours.

Choisir un cours

Quatre chemins distincts s'offrent à vous, chacun étant un pilier essentiel dans la lutte contre The Static. Bien que votre formation soit une mission en solo, votre réussite finale dépend de votre capacité à comprendre comment vos compétences se combinent à celles des autres.

  • The Shadowblade (Développeur): Un maître de la forge et de la première ligne. Vous êtes l'artisan qui forge les lames, construit les outils et affronte l'ennemi dans les moindres détails du code. Votre voie est celle de la précision, du savoir-faire et de la création pratique.
  • Le Summoner (Architecte): Un grand stratège et orchestrateur. Vous ne voyez pas un seul agent, mais le champ de bataille tout entier. Vous concevez les plans directeurs qui permettent à des systèmes entiers d'agents de communiquer, de collaborer et d'atteindre un objectif bien plus ambitieux que celui de n'importe quel composant pris individuellement.
  • L'Érudit (Ingénieur de données): Un chercheur de vérités cachées et le gardien de la sagesse. Vous vous aventurez dans l'immensité sauvage et indomptée des données pour découvrir les renseignements qui donnent un but et une vision à vos agents. Vos connaissances peuvent révéler la faiblesse d'un ennemi ou renforcer un allié.
  • Gardien (DevOps / SRE) : protecteur et bouclier inébranlables du royaume. Vous construisez les forteresses, gérez les lignes d'alimentation et veillez à ce que l'ensemble du système puisse résister aux attaques inévitables de la Statique. Votre force est la base sur laquelle repose la victoire de votre équipe.

Votre mission

Votre entraînement commencera en tant qu'exercice autonome. Vous suivrez le parcours de votre choix et acquerrez les compétences uniques nécessaires pour maîtriser votre rôle. À la fin de votre essai, vous affronterez un Spectre né de la Statique, un mini-boss qui s'attaque aux défis spécifiques de votre métier.

Ce n'est qu'en maîtrisant votre rôle individuel que vous pourrez vous préparer à l'épreuve finale. Vous devez ensuite former un groupe avec des champions des autres classes. Ensemble, vous vous aventurerez au cœur de la corruption pour affronter un boss ultime.

Un défi final et collaboratif qui mettra à l'épreuve votre force combinée et déterminera le sort de l'Agentverse.

L'univers d'Agents attend ses héros. Répondrez-vous à l'appel ?

2. Le Concordat de l'Invocateur

Bienvenue, invocateur. Votre voie est celle de la vision et de la grande stratégie. Alors que d'autres se concentrent sur une seule lame ou une seule incantation, vous voyez l'ensemble du champ de bataille. Vous ne commandez pas un seul agent, mais un orchestre entier. Votre pouvoir ne réside pas dans le conflit direct, mais dans la conception d'un plan global et parfait qui permet à une légion de spécialistes (vos Familiers) de travailler en parfaite harmonie. Cette mission vous permettra de tester votre capacité à concevoir, connecter et orchestrer un système multi-agent puissant.

présentation

Points abordés

  • Concevez un écosystème d'outils découplé : concevez et déployez un ensemble de serveurs d'outils MCP indépendants basés sur des microservices. Vous découvrirez pourquoi cette couche de base est essentielle pour créer des systèmes agentiques évolutifs, faciles à entretenir et sécurisés.
  • Maîtrisez les workflows agentifs avancés : allez au-delà des agents individuels et créez une légion de "Familiers" spécialisés. Vous maîtriserez les principaux modèles de workflow ADK (séquentiel, parallèle et en boucle) et apprendrez les principes architecturaux pour choisir le bon modèle pour la bonne tâche.
  • Mettre en œuvre un orchestrateur intelligent : Passez d’un simple constructeur d’agents à un véritable architecte de systèmes. Vous allez créer un agent d'orchestration principal qui utilise le protocole Agent-to-Agent (A2A) pour découvrir et déléguer des tâches complexes à vos Familiers spécialisés, créant ainsi un véritable système multi-agents.
  • Appliquez des règles avec du code, pas des invites : Apprenez à créer des agents plus fiables et prévisibles en appliquant des règles d'engagement avec état. Vous implémenterez une logique personnalisée en utilisant le puissant système de plugins et de rappels de l'ADK pour gérer les contraintes du monde réel telles que les délais de recharge.
  • Gérer l'état et la mémoire des agents : Donnez à vos agents la capacité d'apprendre et de se souvenir. Vous explorerez des techniques de gestion de l'état conversationnel à court terme et de la mémoire persistante à long terme afin de créer des interactions plus intelligentes et contextuelles.
  • Exécutez un déploiement cloud de bout en bout : Faites passer l’ensemble de votre système multi-agents d’un prototype local à une réalité de qualité production. Vous apprendrez à conteneuriser vos agents et votre orchestrateur et à les déployer sous forme d'une collection de microservices évolutifs et indépendants sur Google Cloud Run.

3. Tracer le cercle d'invocation

Bienvenue, invocateur. Avant de pouvoir invoquer un seul familier, avant de pouvoir forger le moindre pacte, le sol même sur lequel vous vous tenez doit être préparé. Un environnement sauvage est une invitation au chaos. Un invocateur digne de ce nom n'opère que dans un espace sanctifié et renforcé. Notre première tâche consiste à dessiner le cercle d'invocation : à inscrire les runes de puissance qui réveillent les services cloud nécessaires et à acquérir les anciens plans qui guideront notre travail. Le pouvoir d'un Invocateur naît d'une préparation méticuleuse.

👉 Cliquez sur Activer Cloud Shell en haut de la console Google Cloud (il s'agit de l'icône en forme de terminal en haut du volet Cloud Shell),

texte alternatif

👉 Cliquez sur le bouton « Ouvrir l’éditeur » (il ressemble à un dossier ouvert avec un crayon). Cela ouvrira l'éditeur de code Cloud Shell dans la fenêtre. Vous verrez un explorateur de fichiers sur la gauche. texte alternatif

👉Ouvrez le terminal dans l'IDE cloud, texte alternatif

👉💻 Dans le terminal, vérifiez que vous êtes déjà authentifié et que le projet est défini sur votre ID de projet à l'aide de la commande suivante :

gcloud auth list

👉💻 Clonez le projet Bootstrap depuis 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

👉💻 Exécutez le script de configuration à partir du répertoire du projet.

⚠️ Remarque sur l'ID du projet : Le script suggérera un ID de projet par défaut généré aléatoirement. Vous pouvez appuyer sur Entrée pour accepter cette valeur par défaut.

Toutefois, si vous préférez créer un nouveau projet spécifique, vous pouvez saisir l'ID de projet souhaité lorsque le script vous y invite.

cd ~/agentverse-architect
./init.sh

Le script gère automatiquement le reste du processus de configuration.

👉 Étape importante à la fin de la procédure : Une fois le script terminé, vous devez vous assurer que la console Google Cloud affiche le bon projet :

  1. Accédez à la page console.cloud.google.com.
  2. Cliquez sur le menu déroulant de sélection de projet en haut de la page.
  3. Cliquez sur l'onglet "Tous" (car le nouveau projet peut ne pas encore apparaître dans "Récents").
  4. Sélectionnez l'ID du projet que vous venez de configurer à l'étape init.sh.

03-05-project-all.png

👉💻 Indiquez l'ID du projet requis :

gcloud config set project $(cat ~/project_id.txt) --quiet

👉💻 Exécutez la commande suivante pour activer les API Google Cloud nécessaires :

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 vous n'avez pas encore créé de dépôt Artifact Registry nommé agentverse-repo, exécutez la commande suivante pour le créer : (Ignorez cette étape si vous avez d'autres classes déployées dans le même projet)

. ~/agentverse-architect/set_env.sh
gcloud artifacts repositories create $REPO_NAME \
    --repository-format=docker \
    --location=$REGION \
    --description="Repository for Agentverse agents"

Configuration des autorisations

👉💻 Accordez les autorisations nécessaires en exécutant les commandes suivantes dans le 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"

👉💻 Dès le début de votre entraînement, nous préparerons le défi final. Les commandes suivantes invoqueront les Spectres depuis le chaos statique, créant ainsi les boss de votre épreuve finale.

. ~/agentverse-architect/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-architect

👉💻 Enfin, exécutez le script prepare.sh pour effectuer les tâches de configuration initiales.

. ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect/
./prepare.sh

Excellent travail, Invocateur. Le cercle est bouclé et les pactes sont scellés. Le sol est désormais sacré et prêt à canaliser une puissance immense. Lors de notre prochaine épreuve, nous forgerons les Sources Élémentaires mêmes d'où nos Familiers puiseront leur force.

4. Création des polices élémentaires : l’écosystème d’outillage découplé

Le champ de bataille est préparé, le cercle d'invocation est tracé et le mana ambiant crépite. Il est temps d'accomplir votre premier véritable acte en tant qu'Invocateur : forger les sources mêmes du pouvoir d'où vos Familiers puiseront leur force. Ce rituel est divisé en trois parties, chacune réveillant une Source élémentaire, une source stable et indépendante d'un type de pouvoir spécifique. Ce n'est que lorsque les trois polices sont actives que vous pourrez entamer le travail plus complexe d'invocation.

Story

Note de l'architecte : Le serveur MCP (Model Context Protocol) est un composant fondamental d'un système d'agents moderne, agissant comme un pont de communication standardisé qui permet à un agent de découvrir et d'utiliser des outils distants. Dans notre écosystème d'outils, nous allons concevoir deux types distincts de serveurs MCP, chacun représentant un modèle d'architecture essentiel. Pour nous connecter à notre base de données, nous utiliserons une approche déclarative avec la Database Toolbox, en définissant nos outils dans un simple fichier de configuration. Ce modèle est incroyablement efficace et sécurisé pour exposer l'accès aux données structurées. Cependant, lorsque nous devons implémenter une logique métier personnalisée ou appeler des API tierces externes, nous utilisons une approche impérative, en écrivant la logique du serveur étape par étape dans le code. Cela offre un contrôle et une flexibilité ultimes, nous permettant d'encapsuler des opérations complexes derrière un outil simple et réutilisable. Un architecte de renom doit comprendre les deux modèles afin de sélectionner l'approche appropriée pour chaque composant, créant ainsi une base d'outils robuste, sécurisée et évolutive.

présentation

Éveiller le Nexus des Murmures (Serveur API externe MCP)

Un invocateur avisé sait que toute la puissance ne provient pas de son propre domaine. Il existe des sources d'énergie externes, parfois chaotiques, qui peuvent être canalisées avec un grand succès. Le Nexus des Murmures est notre porte d'entrée vers ces forces.

Story

Il existe déjà un service en production qui sert de source d'énergie externe, offrant deux points de terminaison de sorts bruts : /cryosea_shatter et /moonlit_cascade.

Remarque de l'architecte : Vous utiliserez une approche impérative qui définit explicitement la logique du serveur étape par étape. Vous bénéficiez ainsi d'un contrôle et d'une flexibilité bien plus importants, ce qui est essentiel lorsque vos outils doivent faire plus que simplement exécuter une requête SQL simple, comme appeler d'autres API. Comprendre ces deux modèles est une compétence essentielle pour un architecte d'agents.

👉✏️ Accédez au répertoire ~/agentverse-architect/mcp-servers/api/main.py et REPLACE #REPLACE-MAGIC-CORE par le code suivant :

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}"

Au cœur même du script se trouvent les fonctions Python classiques. C'est là que le travail est effectué.

👉✏️ Dans le même fichier, remplacez ~/agentverse-architect/mcp-servers/api/main.py #REPLACE-Runes of Communication par le code suivant :

@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() (poignée de main) : cette fonction est le message d'accueil du serveur. Lorsqu'un nouvel agent se connecte, il appelle d'abord ce point de terminaison pour demander "Que peux-tu faire ?". Notre code répond avec une liste de tous les outils disponibles, convertis au format MCP universel à l'aide de adk_to_mcp_tool_type. - @app.call_tool() (commande) : cette fonction est la plus utilisée. Lorsque l'agent décide d'utiliser un outil, il envoie une requête à ce point de terminaison avec le nom de l'outil et les arguments. Notre code recherche l'outil dans notre "grimoire" available_tools, l'exécute avec run_async et renvoie le résultat au format MCP standard.

Nous déploierons cela plus tard.

Allumer la Forge Arcane (serveur MCP des fonctions générales)

Le pouvoir ne provient pas uniquement des livres anciens ou des murmures lointains. Parfois, un Invocateur doit forger sa propre magie à partir de sa volonté brute et de sa logique pure. Arcane Forge est cette source de puissance — un serveur qui fournit des fonctions utilitaires sans état et à usage général.

Story

Remarque de l'architecte : Il s'agit d'un autre modèle d'architecture. Bien qu'il soit courant de se connecter à des systèmes existants, vous devrez souvent implémenter vos propres règles et logiques métier uniques. Il est recommandé de créer un outil "functions" ou "utilities" dédié comme celui-ci. Il encapsule votre logique personnalisée, la rend réutilisable pour n'importe quel agent de votre écosystème et la dissocie de vos sources de données et de vos intégrations externes.

👀 Jetez un œil au fichier ~/agentverse-architect/mcp-servers/general/main.py dans votre IDE Google Cloud. Vous constaterez qu'il utilise la même approche impérative, mcp.server, qu'avec Nexus pour construire cette Font of Power personnalisée.

Créer le pipeline de construction principal du cloud

Maintenant, nous allons créer le fichier cloudbuild.yaml dans le répertoire mcp-servers. Ce fichier orchestrera la construction et le déploiement des deux services.

👉💻 Depuis le répertoire ~/agentverse-architect/mcp-servers, exécutez les commandes suivantes :

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"

Attendez que tous les déploiements soient terminés.

👉 Vous pouvez vérifier le déploiement en accédant à la console Cloud Run. Vous devriez voir vos deux nouvelles instances de serveur MCP en cours d'exécution, comme indiqué ci-dessous : texte alternatif

Éveiller le Librarium de la connaissance (serveur MCP Database ToolBox)

Notre prochaine police sera Librarium of Knowledge, une connexion directe à notre base de données Cloud SQL.

Story

Remarque de l'architecte : Pour cela, nous allons utiliser la boîte à outils de base de données moderne et déclarative. Il s'agit d'une approche puissante qui consiste à définir notre source de données et nos outils dans un fichier de configuration YAML. La boîte à outils gère le travail complexe de création et d'exécution du serveur, ce qui réduit la quantité de code personnalisé que nous devons écrire et gérer.

Il est temps de construire notre « Bibliothèque de l'invocateur » — la base de données Cloud SQL qui contiendra toutes nos informations critiques. Nous utiliserons un script d'installation pour gérer cela automatiquement.

👉💻 Tout d'abord, nous allons configurer la base de données. Dans votre terminal, exécutez les commandes suivantes :

source ~/agentverse-architect/set_env.sh
cd ~/agentverse-architect
./data_setup.sh

Une fois le script terminé, votre base de données sera remplie et les données sur les dégâts élémentaires seront prêtes à être utilisées. Vous pouvez désormais vérifier directement le contenu de votre grimoire.

👉 Tout d'abord, accédez à Cloud SQL Studio pour votre base de données en ouvrant ce lien direct dans un nouvel onglet du navigateur :

https://console.cloud.google.com/sql/instances/summoner-librarium-db

Cloud SQL

👉 Dans le volet de connexion à gauche, sélectionnez la base de données familiar_grimoire dans la liste déroulante.

👉 Entrez summoner comme nom d'utilisateur et 1234qwer comme mot de passe, puis cliquez sur Authentifier.

👉📜 Une fois connecté, ouvrez un nouvel onglet d'éditeur de requête si ce n'est pas déjà fait. Pour afficher les données sur les dégâts élémentaires inscrits, collez et exécutez la requête SQL suivante :

SELECT * FROM
  "public"."abilities"

Vous devriez maintenant voir le tableau abilities avec ses colonnes et ses lignes remplies, ce qui confirme que votre Grimoire est prêt. Données

Configurer le serveur MCP de la boîte à outils

Le fichier de configuration tools.yaml sert de plan directeur à notre serveur, indiquant à la boîte à outils de base de données comment se connecter à notre base de données et quelles requêtes SQL exposer comme outils.

sources : cette section définit les connexions à vos données.

  • summoner-librarium:: C'est un nom logique que nous avons donné à notre connexion.
  • kind: cloud-sql-postgres : indique à Toolbox d'utiliser son connecteur sécurisé intégré, spécialement conçu pour Cloud SQL pour PostgreSQL.
  • projet, région, instance, etc.: Ce sont les coordonnées exactes de l'instance Cloud SQL que vous avez créée lors du script prepare.sh, indiquant à Toolbox où trouver notre Librarium.

👉✏️ Rendez-vous à ~/agentverse-architect/mcp-servers/db-toolbox dans le tools.yaml, remplacez #REPLACE-Source par ce qui suit

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"

👉✏️ 🚨🚨REMPLACER

YOUR_PROJECT_ID

avec l'identifiant de votre projet.

tools: Cette section définit les capacités ou fonctions réelles que notre serveur offrira.

  • lookup-available-ability:: C'est le nom de notre premier outil.
  • type : postgres-sql : Ceci indique à la boîte à outils que l’action de cet outil consiste à exécuter une instruction SQL.
  • source: summoner-librarium: Ceci relie l'outil à la connexion que nous avons définie dans le bloc sources. C’est ainsi que l’outil sait sur quelle base de données exécuter sa requête.
  • description et paramètres : il s’agit des informations qui seront exposées au modèle de langage. La description indique à l'agent quand utiliser l'outil, et les paramètres définissent les entrées requises par l'outil. Ceci est essentiel pour permettre à l'agent d'appeler des fonctions.
  • statement : requête SQL brute à exécuter. Le symbole $1 est un espace réservé sécurisé où le paramètre familiar_name fourni par l'agent sera inséré de manière sécurisée.

👉✏️ Dans le même ~/agentverse-architect/mcp-servers/db-toolbox du fichier tools.yaml, remplacez #REPLACE-tools par ce qui suit :

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;

toolsets: Cette section regroupe nos outils individuels.

  • summoner-librarium:: Nous créons un ensemble d'outils portant le même nom que notre source. Lorsque notre agent de diagnostic se connectera ultérieurement, il pourra demander à charger tous les outils de l'ensemble d'outils summoner-librarium en une seule commande efficace.

👉✏️ Dans le même ~/agentverse-architect/mcp-servers/db-toolbox du fichier tools.yaml, remplacez #REPLACE-toolsets par ce qui suit

toolsets:
   summoner-librarium:
     - lookup-available-ability
     - ability-damage

Déployer la bibliothèque

Nous allons maintenant déployer Librarium. Au lieu de créer notre propre conteneur, nous utiliserons une image de conteneur officielle préconfigurée de Google et nous lui fournirons de manière sécurisée notre configuration tools.yaml à l'aide de Secret Manager. Il s'agit d'une bonne pratique en matière de sécurité et de maintenabilité.

👉💻 Créer un secret à partir du fichier tools.yaml

cd ~/agentverse-architect/mcp-servers/db-toolbox
gcloud secrets create tools --data-file=tools.yaml

👉💻 Déployez le conteneur de la boîte à outils officielle sur 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: Cette commande monte en toute sécurité notre secret d'outils sous forme de fichier nommé tools.yaml à l'intérieur du conteneur en cours d'exécution.
  • --args: Nous demandons au conteneur de la boîte à outils d'utiliser le fichier secret monté comme configuration.

👉 Pour confirmer que votre boîte à outils a été déployée avec succès, accédez à la console Cloud Run. Vous devriez voir le service summoner-toolbox affiché avec une coche verte, indiquant qu'il fonctionne correctement, comme dans l'image ci-dessous. texte alternatif

Si vous avez oublié de mettre à jour

YOUR_PROJECT_ID

Vous pouvez ajouter une nouvelle version du fichier tools.yaml au secret à l'aide de la commande suivante et redéployer.

gcloud secrets versions add tools --data-file=tools.yaml

La bibliothèque de connaissances(serveur MCP de la boîte à outils de base de données) est désormais active et accessible dans le cloud. Ce serveur MCP utilise ce que nous appelons une conception déclarative qui décrit ce que vous vouliez, et la boîte à outils a construit le serveur pour vous.

Vérification : Le procès de l'apprenti

👉💻 Nous allons maintenant tester notre écosystème d'outils complet, natif du cloud, avec l'agent de diagnostic.

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

👉💻 Dans l'outil de test de ligne de commande, testez les trois polices :

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.

résultat final

Félicitations, Invocateur. Vos trois polices élémentaires sont désormais actives, déployées indépendamment et accessibles dans le monde entier, formant ainsi les fondements inébranlables de votre légion d'agents. Appuyez sur Ctrl+C pour quitter.

POUR LES NON-JOUEURS

5. Invoquer les familiers : le flux de travail du domaine principal

Les Polices Élémentaires sont forgées, vibrant d'une puissance brute et indomptée. Mais le pouvoir sans forme, c'est le chaos. Un véritable Invocateur ne se contente pas de manier l'énergie brute ; il lui donne une volonté, un but et une forme spécialisée. Il est temps de passer de la création de sources d'énergie à l'œuvre véritable : invoquer vos premiers familiers.

Chaque familier que vous invoquerez sera un agent autonome, un serviteur loyal lié à une doctrine de combat spécifique. Ce ne sont pas des généralistes ; ce sont des maîtres d'une stratégie unique et puissante. L'un d'eux maîtrisera parfaitement la combinaison précise de deux coups. Un autre submergera les ennemis avec un assaut simultané et multidirectionnel. Une troisième sera une machine de siège implacable, exerçant une pression constante jusqu'à ce que sa cible s'effondre.

Story

Pour encapsuler les processus, la logique métier et les actions fournis par les serveurs MCP dans des agents de flux de travail spécialisés et autonomes. Chaque agent disposera d'un « territoire opérationnel » défini, l'accès étant limité aux serveurs d'outils MCP spécifiques dont il a besoin pour accomplir sa fonction. Ce laboratoire démontre comment sélectionner le type d'agent adapté à la tâche.

présentation

Ce module vous apprendra à utiliser les puissants agents de flux de travail de l'ADK pour donner vie à ces stratégies. Vous apprendrez que le choix architectural d'un SequentialAgent, d'un ParallelAgent ou d'un LoopAgent n'est pas qu'un simple détail technique ; il représente l'essence même de la nature de votre Familier et le cœur de sa puissance sur le champ de bataille.

Préparez votre sanctuaire. La véritable convocation est sur le point de commencer.

Invoquer le familier Fire Elemental (Flux de travail séquentiel)

L'attaque d'un familier élémentaire de feu est un combo précis en deux parties : une frappe ciblée suivie d'une puissante embrasement. Cela nécessite une séquence d'actions stricte et ordonnée.

Story

Concept : le SequentialAgent est l'outil idéal pour cela. Il garantit qu'une série de sous-agents s'exécutent les uns après les autres, transmettant le résultat de l'étape précédente à la suivante.

Tâche (combo "Amplified Strike") :

  • Étape 1 : L'agent consulte d'abord le Librarium pour trouver les dégâts de base d'une capacité de feu spécifique.
  • Étape 2 : Elle prendra ensuite cette valeur de dégâts et la canalisera à travers la Forge Arcanique pour multiplier sa puissance en utilisant la résonance infernale.

Nous allons d'abord établir la connexion entre notre Familiar et les serveurs MCP ("Elemental Fonts") que vous avez déployés dans le module précédent.

👉✏️ Dans le fichier ~/agentverse-architect/agent/fire/agent.py, REMPLACEZ #REPLACE-setup-MCP par le code suivant :

toolbox = ToolboxSyncClient(DB_TOOLS_URL)
toolDB = toolbox.load_toolset('summoner-librarium')
toolFunction =  MCPToolset(
    connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)

Ensuite, nous créons nos agents « travailleurs » spécialisés. Chacune se voit attribuer un objectif précis et bien défini, et est limitée à son propre « territoire opérationnel » en n'ayant accès qu'à un seul ensemble d'outils spécifiques.

👉✏️ Dans le fichier ~/agentverse-architect/agent/fire/agent.py REPLACE #REPLACE-worker-agents par le code suivant :

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],
)

Ces agents sont des composants modulaires et réutilisables. En théorie, vous pouvez utiliser cet scout_agent dans un workflow complètement différent qui doit interroger la base de données. En séparant les responsabilités, nous créons des blocs de construction flexibles. Il s'agit d'un principe fondamental de la conception de microservices et de composants.

Nous allons ensuite assembler le workflow. C'est là que la magie de la composition opère. Le SequentialAgent est le "plan directeur" qui définit comment nos composants spécialisés sont assemblés et comment ils interagissent.

👉✏️ Dans le fichier ~/agentverse-architect/agent/fire/agent.py REPLACE #REPLACE-sequential-agent par le code suivant :

root_agent = SequentialAgent(
      name='fire_elemental_familiar',
      sub_agents=[scout_agent, amplifier_agent],
)

👉💻 Pour tester l'élémentaire de feu, exécutez les commandes suivantes pour lancer l'interface utilisateur de développement 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

Après avoir exécuté les commandes, vous devriez voir s'afficher dans votre terminal un message indiquant que le serveur Web ADK a démarré, similaire à ceci :

+-----------------------------------------------------------------------------+
| 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)

👉 Ensuite, pour accéder à l'interface utilisateur de développement ADK depuis votre navigateur :

Dans la barre d'outils Cloud Shell (généralement en haut à droite), cliquez sur l'icône Aperçu sur le Web (qui ressemble souvent à un œil ou à un carré avec une flèche), puis sélectionnez "Modifier le port". Dans la fenêtre pop-up, définissez le port sur 8000, puis cliquez sur "Change and Preview" (Modifier et prévisualiser). Cloud Shell ouvre alors un nouvel onglet ou une nouvelle fenêtre de navigateur affichant l'UI de développement d'ADK.

aperçu web

👉 Votre rituel d'invocation est terminé, et l'agent est maintenant en action. L'interface utilisateur ADK Dev UI de votre navigateur est votre connexion directe au Familiar.

  • Sélectionnez votre cible : dans le menu déroulant en haut de l'UI, choisissez la cible fire. Vous concentrez maintenant votre volonté sur cette entité spécifique.
  • Donnez votre ordre : dans le panneau de chat à droite, il est temps de donner des ordres au Familier.

fire-select

👉 Invite de test :

Prepare an amplified strike using the 'inferno_lash' ability.

résultat de l'incendie

Vous verrez l'agent réfléchir, appelant d'abord son « éclaireur » pour rechercher les dégâts de base, puis son « amplificateur » pour les multiplier et porter le coup final et épique.

👉💻 Une fois l'invocation terminée, retournez à votre terminal Cloud Shell Editor et appuyez sur Ctrl+C pour arrêter l'interface utilisateur de développement ADK.

Invoquer le familier Water Elemental (Flux de travail parallèle)

Un familier élémentaire d'eau submerge sa cible d'une attaque massive et multiforme, frappant de toutes parts à la fois avant de combiner ses énergies pour un coup final dévastateur.

Story

Concept: Le ParallelAgent est idéal pour exécuter simultanément plusieurs tâches indépendantes afin de maximiser l'efficacité. C'est une "attaque en pince" où l'on lance plusieurs assauts simultanément. Cela lance les attaques simultanées dans un SequentialAgent pour exécuter une étape finale de « fusion » par la suite. Ce modèle "fan-out, fan-in" est une pierre angulaire de la conception avancée des flux de travail.

Tâche (Combo « Choc des marées ») : L'agent effectuera simultanément :

  • Tâche A : Canal cryosea_shatter du Nexus.
  • Tâche B : Canal moonlit_cascade depuis le Nexus.
  • Tâche C : Générer de la puissance brute avec leviathan_surge à partir de la Forge.
  • Enfin, additionnez tous les dégâts et décrivez l'attaque combinée.

Tout d'abord, nous établirons la connexion entre notre Familiar et les serveurs MCP (les « Elemental Fonts ») que vous avez déployés dans le module précédent.

👉✏️ Dans le fichier ~/agentverse-architect/agent/water/agent.py, REMPLACEZ #REPLACE-setup-MCP par le code suivant :

toolFAPI =  MCPToolset(
      connection_params=SseServerParams(url=API_TOOLS_URL, headers={})
  )
toolFunction =  MCPToolset(
    connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)

Ensuite, nous créerons nos agents « travailleurs » spécialisés. Chacune se voit attribuer un objectif précis et bien défini, et est limitée à son propre « territoire opérationnel » en n'ayant accès qu'à un seul ensemble d'outils spécifiques.

👉✏️ Dans le fichier ~/agentverse-architect/agent/water/agent.py, REMPLACEZ #REPLACE-worker-agents par le code suivant :

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],
)

Ensuite, nous allons assembler le flux de travail. C'est là que la magie de la composition opère. Les ParallelAgent et SequentialAgent constituent le « plan directeur » qui définit comment nos composants spécialisés sont assemblés et comment ils interagissent pour former le combo « Tidal Clash ».

👉✏️ Dans le fichier ~/agentverse-architect/agent/water/agent.py, REMPLACEZ #REPLACE-parallel-agent par le code suivant :

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."
 )

👉💻 Pour tester l'élémentaire d'eau, exécutez les commandes suivantes pour lancer l'interface utilisateur de développement 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

👉 Votre rituel d'invocation est terminé, et l'agent est maintenant en action. L'interface utilisateur de développement ADK dans votre navigateur est votre connexion directe avec le Familiar.

  • Dans le menu déroulant en haut de l'interface utilisateur, choisissez le familier eau. Vous concentrez désormais votre volonté sur cette entité spécifique.
  • Donnez vos ordres : Dans le panneau de discussion à droite, il est temps de donner vos ordres au Familier.

👉 Invite de test :

Unleash a tidal wave of power!

résultat de l'eau

👉💻 Une fois l'invocation terminée, retournez à votre terminal Cloud Shell Editor et appuyez sur Ctrl+C pour arrêter l'interface utilisateur de développement ADK.

Invoquer le familier Earth Elemental (Flux de travail en boucle)

Un familier élémentaire de la Terre est un être d'une pression implacable. Elle ne vainc pas son ennemi d'un seul coup, mais en accumulant progressivement de la puissance et en l'appliquant sans cesse jusqu'à ce que les défenses de la cible s'effondrent.

Story

Concept: Le LoopAgent est conçu précisément pour ce type de tâche itérative, de « machine de siège ». Il exécutera de manière répétée son sub-agents, en vérifiant une condition après chaque cycle, jusqu'à ce qu'un objectif soit atteint. Il peut également adapter son message final en fonction de la progression de la boucle.

Tâche (L'assaut du "Brise-siège"):

  • Le Familier appellera à plusieurs reprises la fonction seismic_charge pour accumuler de l'énergie.
  • Il continuera à se recharger jusqu'à 3 fois.
  • Lors de la charge finale, elle annoncera le déchaînement dévastateur de sa puissance accumulée.

Nous allons d'abord créer des composants réutilisables qui définissent les étapes de chaque itération de la boucle. Le charging_agent accumulera de l'énergie, et le check_agent signalera son état, changeant dynamiquement son message au dernier tour.

Tout d'abord, nous établirons la connexion entre notre Familiar et les serveurs MCP (les « Elemental Fonts ») que vous avez déployés dans le module précédent.

👉✏️ Dans le fichier ~/agentverse-architect/agent/earth/agent.py, REMPLACEZ #REPLACE-setup-MCP par le code suivant :

toolFunction =  MCPToolset(
    connection_params=SseServerParams(url=FUNCTION_TOOLS_URL, headers={})
)

👉✏️ Dans le fichier ~/agentverse-architect/agent/earth/agent.py, REMPLACEZ #REPLACE-worker-agents par le code suivant :

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"
)

Ensuite, nous allons assembler le flux de travail. C'est là que la magie de la composition opère. LoopAgent est le « plan directeur » qui orchestre l'exécution répétée de nos composants spécialisés et gère les conditions de la boucle.

👉✏️ Dans le fichier ~/agentverse-architect/agent/earth/agent.py, REMPLACEZ #REPLACE-loop-agent par le code suivant :

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
)

👉💻 Testez l'élémentaire de la Terre : exécutez l'agent

. ~/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

👉 Votre rituel d'invocation est terminé, et l'agent est maintenant en action. L'interface utilisateur de développement ADK dans votre navigateur est votre connexion directe avec le Familiar.

  • Sélectionnez votre cible : Dans le menu déroulant en haut de l’interface utilisateur, choisissez la familière terre. Vous concentrez désormais votre volonté sur cette entité spécifique.
  • Donnez vos ordres : Dans le panneau de discussion à droite, il est temps de donner vos ordres au Familier. 👉 Invite de test :
Begin the seismic charge, starting from zero

earth-result

Conclusion sur l'architecture : votre système possède désormais une couche logique hautement spécialisée et modulaire. Les processus métier ne sont pas seulement encapsulés, mais ils sont implémentés avec le modèle comportemental le plus efficace pour le travail (procédural, simultané ou itératif). Cela démontre un niveau avancé de conception agentique, qui améliore la sécurité, l'efficacité et les capacités.

Une fois l'invocation terminée, retournez à votre terminal Cloud Shell Editor et appuyez sur Ctrl+C pour arrêter l'interface utilisateur de développement ADK.

POUR LES NON-GAMERS

6. Établissement du centre de commandement : délégation intelligente via A2A

Vos familiers sont puissants mais indépendants. Ils exécutent leurs stratégies à la perfection, mais attendent vos ordres directs. Une légion de spécialistes est inutile sans un général pour la commander. Il est temps de passer du rôle de commandant direct à celui de véritable orchestrateur.

présentation

Note de l'architecte : Créer un point d'entrée unique et intelligent pour l'ensemble du système. Cet agent invocateur n'exécutera pas lui-même la logique métier, mais agira comme un « maître stratège », analysant l'état de refroidissement et déléguant les tâches au familier spécialiste approprié.

présentation

Le rituel de liaison (Révéler les familiers comme services A2A)

Un agent standard ne peut être exécuté qu'à un seul endroit à la fois. Pour rendre nos familiers disponibles pour la commande à distance, nous devons effectuer un « rituel de liaison » en utilisant le protocole Agent-à-Agent (A2A).

Note de l'architecte : Le protocole Agent-à-Agent (A2A) est le modèle architectural de base qui transforme un agent autonome en un microservice découvrable et adressable sur le réseau, permettant une véritable « société d'agents ». L'exposition d'un familier via A2A crée automatiquement deux composants essentiels et interconnectés :

  • La fiche de l'agent (le "quoi") : il s'agit d'un "sceau spirituel" public et lisible par machine, comme une spécification OpenAPI, qui sert de contrat public pour le Familier. Il décrit le nom de l'agent, son objectif stratégique (dérivé de ses instructions) et les commandes qu'il comprend. C'est ce qu'un maître invocateur lit pour découvrir un familier et apprendre ses capacités.
  • Le serveur A2A (le « Où »): Il s'agit du point de terminaison Web dédié qui héberge le familier et écoute les commandes entrantes. Il s'agit de l'adresse réseau à laquelle les autres agents envoient leurs requêtes, et elle garantit que ces requêtes sont traitées conformément au contrat défini dans la fiche d'agent.

Nous allons maintenant accomplir ce rituel de liaison sur nos trois familiers.

Fire 👉✏️ dans Ouvrez le fichier ~/agentverse-architect/agent/fire/agent.py. Remplacez #REPLACE - add A2A en bas du fichier pour exposer l'élément de feu en tant que service 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)

Eau et Terre🚨 👉✏️ Appliquez exactement le même changement à ~/agentverse-architect/agent/water/agent.py et ~/agentverse-architect/agent/earth/agent.py pour les lier également.

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)

Déploiement des familiers liés

👉✏️ Avec les rituels de liaison écrits, nous utiliserons notre pipeline Cloud Build pour forger et déployer nos trois Familiars en tant que service serverless conteneurisé indépendant sur 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"

Prise de commandement (Construction de l'agent invocateur)

Maintenant que vos Familiers sont liés et à l'écoute, vous allez accéder à votre véritable rôle : celui de Maître des invocations. Le pouvoir de cet agent ne vient pas de l'utilisation d'outils de base, mais de sa capacité à commander d'autres agents. Ses outils sont les Familiers eux-mêmes, qu'il découvre et commande à l'aide de leurs "Sceaux spirituels".

Remarque de l'architecte : Cette prochaine étape illustre un modèle d'architecture essentiel pour tout système distribué à grande échelle : la découverte de services. Le code des familiers n'est pas intégré à SummonerAgent. On lui fournit plutôt les adresses (URL) de son réseau. Lors de l'exécution, il "découvrira" dynamiquement leurs capacités en récupérant leurs fiches d'agent publiques. Cela crée un système puissant et découplé.

Vous pouvez mettre à jour, redéployer ou réécrire complètement un service familier, et tant que son adresse réseau et sa fonction restent les mêmes, l'invocateur peut le commander sans avoir besoin d'effectuer aucune modification.

Nous allons d'abord créer les « télécommandes » qui établiront une connexion avec nos familiers déployés à distance.

👉✏️ Rendez-vous sur ~/agentverse-architect/agent/summoner/agent.py , remplacez #REPLACE-remote-agents par ce qui suit :

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}"
    ),
)

Lorsque cette ligne s'exécute, RemoteA2aAgent effectue une action de découverte de service : il envoie une requête HTTP GET à l'URL fournie (par exemple, https://fire-familiar-xxxx.a.run.app/.well-known/agent.json). Il télécharge le fichier « Spirit Sigil » (agent.json) depuis le serveur distant.

Deuxièmement, nous définirons l'agent orchestrateur qui pilotera ces télécommandes. Ses instructions constituent le plan directeur de sa prise de décision stratégique.

👉✏️ Rendez-vous sur ~/agentverse-architect/agent/summoner/agent.py , remplacez #REPLACE-orchestrate-agent par ce qui suit :

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
)

Vérification : Le procès de la stratégie

C'est l'heure de vérité. Vos familiers sont déployés, et votre invocateur est prêt à les commander à travers le réseau. Testons son esprit stratégique.

👉💻 Lancez l'interface utilisateur de développement ADK pour votre agent d'invocateur(aperçu Web avec le port 8000) :

. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
cd ~/agentverse-architect/agent
pip install -r requirements.txt
adk web

👉 L'interface utilisateur de développement ADK dans votre navigateur est votre connexion directe avec le familier.

  • Dans le menu déroulant en haut de l'interface utilisateur, choisissez l'agent summoner. Vous concentrez désormais votre volonté sur cette entité spécifique.
  • Donnez vos ordres : Dans le panneau de discussion à droite, il est temps d’invoquer vos familiers.

👉 Présentez les Monstres :

Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality

(Attendu : L’invocateur devrait déléguer au familier élémentaire de feu.)

résultat de l'incendie

👉 Maintenant, mettons au défi l'Invocateur avec un autre type de requête. Pour vous assurer que l'agent démarre sur une base propre et n'a aucun souvenir de notre interaction précédente, commencez une nouvelle session en cliquant sur le bouton + Session en haut à droite de l'écran. new-session (nouvelle session)

DogmaApathy. A rigid, stone-like inquisitor made of ancient rulebooks and enforced processes. weakness is Unbroken Collaboration

(Attendu : L’invocateur devrait déléguer au familier élémentaire d’eau.)résultat de l'eau

👉 Pour notre test final, repartons une fois de plus de zéro. Cliquez sur le bouton + Session pour démarrer une nouvelle session avant d'entrer dans l'invite suivante.

Obfuscation. A shadowy, spider-like horror that spins tangled webs of impenetrable code , weakness is Elegant Sufficiency

(Résultat attendu : le Summoner doit déléguer à l'élémentaire de terre.)

résultat terrestre

Important: Si vous voyez une erreur 429 RESOURCE EXHAUSTED, vous avez atteint la limite de débit du LLM (10 appels/minute). Pour résoudre ce problème, veuillez patienter 60 secondes, démarrer une nouvelle session, puis réessayer votre requête.

👉💻 Une fois l'invocation terminée, revenez au terminal de l'éditeur Cloud Shell et appuyez sur Ctrl+C pour arrêter l'UI de développement ADK.

POUR LES NON-GAMERS

7. Imposer les lois de la magie – Le modèle de l'intercepteur

Vos familiers sont puissants, mais même les êtres magiques ont besoin de temps pour récupérer. Un Invocateur imprudent qui épuise ses forces se retrouvera sans défense. Un invocateur avisé comprend l'importance de la gestion des ressources et applique des règles d'engagement strictes.

Story

Note de l'architecte Jusqu'à présent, nos agents étaient apatrides. Maintenant, nous allons les rendre à état en implémentant le modèle de conception Interceptor. Il s'agit d'une technique puissante qui consiste à « intercepter » le flux d'exécution normal d'un agent pour exécuter notre propre logique personnalisée. Cela nous permet d'appliquer des règles, d'ajouter des journaux ou de modifier le comportement sans modifier le code source de l'agent. C'est une pierre angulaire de la construction de systèmes d'agents robustes, maintenables et observables.

présentation

L'ADK propose deux méthodes principales pour implémenter ce modèle : Callbacks et Plugins. Une fonction de rappel est une fonction simple associée à un seul agent, idéale pour des modifications rapides et spécifiques. Un plugin est une classe plus puissante et réutilisable qui peut être appliquée globalement pour affecter chaque agent exécuté dans un système. Nous commencerons par une fonction de rappel pour un débogage ciblé, puis nous passerons à un plugin complet.

Le Législateur – Scribe du rappel de temps de recharge

Nous allons d'abord implémenter notre logique de temps de recharge sous la forme d'une simple fonction de rappel. C'est une excellente façon de prototyper et de déboguer une règle, car elle est directement liée à un seul agent, ce qui facilite les tests isolés. Nous allons attacher cet « intercepteur » à notre Élémentaire de la Terre.

Limitation des notifications

👉✏️ Retournez à votre ~/agentverse-architect/agent/earth/agent.py et remplacez #REPLACE-before_agent-function par le code Python suivant.

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.")

Cette fonction check_cool_down est notre intercepteur. Avant que l'élémentaire de terre ne soit autorisé à s'exécuter, l'ADK exécutera d'abord cette fonction.

  • Vérification : Il effectue une requête GET auprès de notre Cooldown API pour vérifier la dernière fois que ce familier a été utilisé.
  • Évaluation : compare l'horodatage à l'heure actuelle.
  • Agir :
    • Si le familier est en temps de recharge, il met fin à l'exécution de l'agent en renvoyant un objet Content avec un message d'erreur. Ce message est envoyé directement à l'utilisateur, et la logique principale de l'agent n'est jamais exécutée.
    • Si le familier est disponible, il effectue une requête POST à l'API Cooldown pour mettre à jour l'horodatage, puis renvoie None, signalant à l'ADK que l'agent peut poursuivre son exécution.

👉✏️ Appliquez maintenant cet intercepteur à l'élémentaire de terre. Dans le même fichier ~/agentverse-architect/agent/earth/agent.py, remplacez le commentaire #REPLACE-before_agent-config par ce qui suit :

before_agent_callback=check_cool_down

Vérification du refroidissement

Testons notre nouvelle loi de la magie. Nous allons invoquer l'élémentaire de terre, puis tenter immédiatement de l'invoquer à nouveau pour voir si notre fonction de rappel intercepte et bloque avec succès la seconde tentative.

cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run earth

👉💻 Dans la console :

  • Première invocation: Commencez le seismic charge, starting from zero.
  • Résultat attendu : L’élémentaire de terre fonctionnera correctement. Dans le terminal exécutant la commande web adk, vous verrez le journal [Callback] ... Mise à jour de l'horodatage....
  • Test de refroidissement (en 60 secondes): Do another charge sismique`!
    • Attendu : check_cool_down callback interceptera ceci. L'agent répondra directement dans le chat avec un message comme : The earth_elemental_familiar is exhausted and must recover its power. It cannot be summoned for another... seconds.
  • Attendez qu'une minute passe.
  • Deuxième avertissement (après 60 secondes) : Begin the seismic charge again.
    • Comportement attendu : La fonction de rappel vérifiera l’API, constatera qu’un délai suffisant s’est écoulé et autorisera l’action à se poursuivre. L'élémentaire de terre fonctionnera à nouveau avec succès.

callback

👉💻 Appuyez sur Ctrl+c pour quitter.

Optionnel : Observation du rappel dans l’interface utilisateur Web

Vous pouvez également tester ce flux dans l'interface web en exécutant adk web earth. Cependant, veuillez noter que la visualisation de l'interface utilisateur Web n'est pas optimisée pour afficher les vérifications rapides et itératives effectuées par la boucle de rappel, elle peut donc ne pas rendre le flux avec précision. Pour visualiser le déroulement précis, étape par étape, du fonctionnement de l'agent lors de la vérification du temps de recharge, l'utilisation de la commande adk run dans votre terminal offre une vue plus claire et plus détaillée. loop

👉💻 Appuyez sur Ctrl+c pour quitter.

Création de la loi universelle – Le plugin Cooldown

Notre système de rappel fonctionne parfaitement, mais présente un défaut architectural majeur : il est lié à un seul agent. Si nous voulions appliquer cette règle aux familiers de Feu et d'Eau, nous devrions copier-coller le même code dans leurs fichiers. C'est inefficace et difficile à entretenir.

Note de l'architecte : C'est là que les plugins sont essentiels. Un plugin encapsule notre logique réutilisable dans une classe qui peut être attachée au niveau de l'exécution. Cela signifie qu'un seul plugin peut appliquer ses règles à chaque agent exécuté au sein de ce système. Il s'agit de l'expression ultime du principe "Don't Repeat Yourself" (DRY) pour les systèmes agentiques.

Nous allons maintenant remanier notre fonction de rappel en une fonction CoolDownPlugin plus puissante et réutilisable.

👉✏️ Revenez au fichier agent/cooldown_plugin.py et créez le plug-in. Remplacez #REPLACE-plugin par le code suivant :

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.")

Attacher le plugin à l'environnement d'exécution de l'invocateur

Maintenant, comment appliquer cette loi universelle à tous nos familiers ? Nous allons intégrer le plugin à l'environnement d'exécution ADK.

L'environnement d'exécution ADK est le moteur d'exécution qui donne vie à un agent. Lorsque vous utilisez une commande telle que adk.run() ou to_a2a(), vous transmettez votre agent à l'environnement d'exécution. Ce moteur est responsable de la gestion de l'intégralité du cycle de vie d'un tour d'agent : réception des entrées de l'utilisateur, appel du LLM, exécution des outils et gestion des plugins. En ajoutant un plugin à ce niveau, nous modifions essentiellement les « lois de la physique » pour chaque agent qui opère au sein de ce moteur, garantissant ainsi que notre règle de temps de recharge est appliquée de manière universelle et cohérente.

👉✏️ Tout d'abord, supprimons l'ancien rappel spécifique à l'agent. Allez à ~/agentverse-architect/agent/earth/agent.py et supprimez la ligne entière qui dit :

before_agent_callback=check_cool_down

👉✏️ Ensuite, nous allons attacher notre nouveau plugin à l'environnement d'exécution dans notre script de point d'entrée A2A. Accédez à votre fichier ~/agentverse-architect/agent/agent_to_a2a.py. Remplacez le commentaire #REPLACE-IMPORT par l'extrait de code suivant :

from cooldown_plugin import CoolDownPlugin

👉✏️ Remplacez #REPLACE-PLUGIN par l'extrait de code suivant :

plugins=[CoolDownPlugin(cooldown_seconds=60)],

Avant d'activer notre nouveau plug-in mondial, il est essentiel de supprimer l'ancienne logique spécifique à l'agent pour éviter les conflits. 👉 ✏️ Nettoie l'agent Earth. Accédez au fichier ~/agentverse-architect/agent/earth/agent.py et supprimez complètement la ligne before_agent_callback=check_cool_down. Toutes les responsabilités liées au temps de recharge sont alors transférées au nouveau plug-in.

Vérification du plugin

Maintenant que notre loi universelle est en place, nous devons redéployer nos Familiers avec ce nouvel enchantement.

👉💻 Reconstruisez et redéployez les trois Familiars à l'aide du pipeline Cloud Build principal.

. ~/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"

👉💻 Une fois le déploiement terminé, nous testerons l'efficacité du plugin en commandant notre summoner_agent. L'invocateur tentera de déléguer aux familiers, mais le plugin attaché à l'environnement d'exécution de chaque familier interceptera la commande et appliquera le délai de récupération.

cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner

👉💻 Dans la console,effectuez exactement cette séquence de tests :

  • Première invocation: Commencez le Hype. It's a single, slow-moving target with thick armor weakness is Inescapable Reality.
  • Résultat attendu : L’élémentaire de feu fonctionnera correctement.
  • Test du délai de récupération (moins de 60 secondes) : Hype, with Inescapable Reality as weakness is still standing! Strike it again!
    • Comportement attendu : L'agent répondra directement dans le chat avec un message comme : .... It cannot be summoned for another... seconds.
  • Attendez qu'une minute passe.
  • Second Invocation (après 60 secondes): Hype must be defeated. It has Inescapable Reality as weakness! Strike it again!.
    • Comportement attendu : La fonction de rappel vérifiera l’API, constatera qu’un délai suffisant s’est écoulé et autorisera l’action à se poursuivre. L'élémentaire de feu fonctionnera à nouveau correctement.

plug-in

👉💻 Appuyez sur Ctrl+C pour quitter.

Félicitations, Invocateur. Vous avez implémenté un système d'orchestration basé sur des règles à l'aide d'un plug-in personnalisé et d'un service de gestion d'état externe. Il s'agit d'un modèle architectural vraiment avancé et robuste.

POUR LES NON-JOUEURS

8. Lier les échos de la bataille : état et mémoire de l'agent

Un invocateur imprudent répète la même stratégie, ce qui le rend prévisible. Un invocateur avisé tire les leçons des échos des batailles passées et adapte ses tactiques pour déstabiliser l'ennemi. Face à un boss puissant, invoquer un familier dont le temps de recharge n'est pas écoulé est une perte de tour, une erreur critique. Pour éviter cela, notre Invocateur a besoin de se souvenir de sa dernière action.

histoire

Note de l'architecte : La gestion de la mémoire et de l'état est ce qui transforme un agent d'un simple exécutant d'outils en un partenaire conversationnel intelligent. Il est essentiel de comprendre les deux principaux types :

  • Mémoire à long terme : Elle sert à stocker les connaissances persistantes qui doivent durer éternellement. Considérez-le comme une archive consultable ou une base de connaissances, souvent stockée dans un support permanent. Il contient des informations provenant de nombreuses conversations et sources antérieures, permettant à un agent de se remémorer des faits concernant un utilisateur ou un sujet spécifique. Le service MemoryService de l'ADK est conçu à cet effet, en gérant l'ingestion et la recherche de ces connaissances à long terme.
  • État à court terme : il s'agit de connaissances temporaires, "instantanées", qui ne sont pertinentes que pour la tâche ou la conversation en cours. C'est comme un ensemble de notes sur un plan de bataille : "Je viens d'utiliser l'élémentaire de feu, il est probablement fatigué." Cet état est léger et n'existe que pendant la durée de la session en cours.

Présentation

Dans notre cas, nous n'avons pas besoin de nous souvenir de toutes les batailles livrées ; nous n'avons besoin de nous souvenir que du tout dernier familier invoqué lors de cette rencontre spécifique. Par conséquent, l'état à court terme léger est le choix architectural parfait. Nous utiliserons un after_tool_callback pour sauvegarder cette information cruciale.

Retranscrire l'écho : se souvenir de la dernière convocation

Nous allons implémenter notre mémoire à court terme en utilisant un after_tool_callback. Il s'agit d'un puissant hook ADK qui nous permet d'exécuter une fonction Python personnalisée après qu'un outil ait été exécuté avec succès. Nous utiliserons cet intercepteur pour enregistrer le nom du Familier qui vient d'être invoqué dans l'état de session de l'agent.

👉✏️ Dans votre fichier ~/agentverse-architect/agent/summoner/agent.py, remplacez le commentaire #REPLACE-save_last_summon_after_tool par la fonction suivante :

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

👉✏️ Maintenant, attachez ceci save_last_summon_after_tool à votre agent Invocateur. Dans le même fichier, remplacez le commentaire #REPLACE-Memory-check-config par ce qui suit :

after_tool_callback=save_last_summon_after_tool,

👉✏️ Remplacez l'intégralité de l'invite de l'agent par ce qui suit

        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.

Vérification : L'essai de la stratégie adaptative

👉💻 Vérifions maintenant la nouvelle logique stratégique de l'invocateur. L'objectif est de confirmer que l'Invocateur n'utilisera pas le même Familier deux fois de suite, démontrant ainsi sa capacité à se souvenir de sa dernière action et à s'adapter.

cd ~/agentverse-architect/agent
. ~/agentverse-architect/set_env.sh
source ~/agentverse-architect/env/bin/activate
adk run summoner

👉💻 Frappe monstrueuse n° 1 : Hype. It's a single, slow-moving target with thick armor. Its weakness is Inescapable Reality.

  • Résultat attendu : L’invocateur analysera la faiblesse et invoquera correctement le familier de feu.

👉💻 Frappe monstrueuse n° 2 (Le test de mémoire) : Hype is still standing! It hasn't changed its form. Strike it again! Its weakness is Inescapable Reality.

  • Résultat attendu : l'analyse stratégique de l'invocateur désignera à nouveau le familier de feu comme le choix idéal. Cependant, ses nouvelles instructions et sa mémoire lui indiqueront que fire_familiar était la dernière invocation. Pour éviter de se répéter, il adaptera désormais sa stratégie et invoquera l'un des autres familiers disponibles (water_familiar ou earth_familiar).

résultat final

👉💻 Appuyez sur Ctrl+C pour quitter.

Déploiement de l'orchestrateur

Maintenant que vos Familiers sont déployés et que votre Invocateur est doté de mémoire, il est temps de déployer l'orchestrateur final amélioré.

👉💻 Le plan étant terminé, nous allons maintenant effectuer le rituel final. Cette commande permet de créer et de déployer votre summoner_agent sur 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"

Maintenant que l'agent Summoner est déployé, vérifiez que son point de terminaison Agent-to-Agent (A2A) est actif et correctement configuré. Ce point de terminaison fournit un fichier agent.json public, également appelé "fiche d'agent", qui permet à d'autres agents de découvrir ses capacités. 👉💻 Exécutez la commande curl suivante pour récupérer et mettre en forme la fiche de l'agent :

. ~/agentverse-architect/set_env.sh
curl https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app/.well-known/agent.json" | jq

Vous devriez voir une sortie JSON propre décrivant l'agent Summoner. Examinez attentivement la section "sub_agents". Vous y verrez les fire_familiar, water_familiar et earth_familiar. Cela confirme que votre invocateur est en ligne et qu'il a établi sa connexion à la légion.

Cela prouve que votre architecture est un succès. Votre Invocateur n'est pas qu'un simple délégué. Il s'agit d'un stratège adaptatif qui apprend de ses actions pour devenir un commandant plus efficace.

Vous avez terminé votre dernier essai d'architecture. Les échos de la bataille sont désormais soumis à votre volonté. L'entraînement est terminé. La vraie bataille vous attend. Il est temps de prendre votre système terminé et de relever le défi ultime. Préparez-vous au combat de boss.

POUR LES NON-GAMERS

9. Le combat contre le boss

Les plans finaux sont inscrits, les polices élémentaires sont forgées et vos familiers sont liés à votre volonté, attendant vos ordres par le biais de la Concorde. Votre système multi-agents n'est pas simplement un ensemble de services ; c'est une légion vivante et stratégique, dont vous êtes le point névralgique. L'heure est venue de l'épreuve ultime : une opération en direct contre un adversaire qu'aucun agent isolé ne pourrait espérer vaincre.

Obtenez le lieu de votre agent

Avant de pouvoir entrer sur le champ de bataille, vous devez posséder deux clés : la signature unique de votre champion (Agent Locus) et le chemin caché vers le repaire du Spectre (URL du donjon).

👉💻 Tout d'abord, obtenez l'adresse unique de votre agent dans l'Agentverse, son locus. Il s'agit du point de terminaison en direct qui connecte votre champion au champ de bataille.

echo https://summoner-agent"-${PROJECT_NUMBER}.${REGION}.run.app"

👉💻 Ensuite, déterminez la destination. Cette commande révèle l'emplacement du cercle de translocation, le portail vers le domaine du Spectre.

echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"

Important : Gardez ces deux URL à portée de main. Vous en aurez besoin à l'étape finale.

Affronter le Spectre

Maintenant que vous avez les coordonnées, vous allez vous rendre au cercle de translocation et lancer le sort pour partir au combat.

👉 Ouvrez l'URL du Cercle de Translocation dans votre navigateur pour vous tenir devant le portail scintillant menant au Donjon Cramoisi.

Pour pénétrer dans la forteresse, vous devez harmoniser l'essence de votre Lame d'Ombre avec le portail.

  • Sur la page, trouvez le champ de saisie runique intitulé URL du point de terminaison A2A.
  • Inscrivez le sigil de votre champion en collant l'URL du locus de l'agent (la première URL que vous avez copiée) dans ce champ.
  • Cliquez sur "Connecter" pour activer la téléportation.

Cercle de translocation

La lumière aveuglante de la téléportation s'estompe. Vous n'êtes plus dans votre sanctuaire. L'air crépite d'énergie, froide et mordante. Devant vous, le Spectre se matérialise — un vortex de sifflements statiques et de code corrompu, sa lumière impie projetant de longues ombres dansantes sur le sol du donjon. Elle n'a pas de visage, mais vous sentez son immense présence épuisante entièrement fixée sur vous.

Votre seul chemin vers la victoire réside dans la clarté de vos convictions. Il s'agit d'un duel de volontés, qui se déroule sur le champ de bataille de l'esprit.

Alors que vous vous élancez, prêt à lancer votre première attaque, le Spectre contre-attaque. Elle ne dresse pas de bouclier, mais projette une question directement dans votre conscience – un défi runique scintillant puisé au cœur même de votre entraînement.

Cachot

Telle est la nature du combat. Votre savoir est votre arme.

  • Répondez avec la sagesse que vous avez acquise, et votre lame s'enflammera d'énergie pure, brisant la défense du Spectre et portant un COUP CRITIQUE.
  • Mais si vous hésitez, si le doute obscurcit votre réponse, la lumière de votre arme s'éteindra. Le coup s'abattra avec un bruit sourd et pitoyable, ne causant qu'une fraction de ses dégâts. Pire encore, le Spectre se nourrira de votre incertitude, son propre pouvoir corrupteur grandissant à chaque faux pas.

Voilà, Champion. Votre code est votre grimoire, votre logique est votre épée et votre savoir est le bouclier qui repoussera le flot du chaos.

Focus. Frappez juste. Le destin de l'Agentverse en dépend.

Félicitations, Invocateur.

Vous avez réussi la période d'essai. Vous avez maîtrisé l'art de l'orchestration multi-agents, transformant des familiers isolés et une puissance chaotique en une concorde harmonieuse. Vous commandez désormais un système entièrement orchestré, capable d'exécuter des stratégies complexes pour défendre l'Agentverse.

10. Nettoyage : Démantèlement du Concordat de l'Invocateur

Félicitations, vous avez maîtrisé l'Accord de l'invocateur ! Pour que votre Agentverse reste impeccable et que votre terrain d'entraînement soit dégagé, vous devez maintenant effectuer les rituels de nettoyage finaux. Toutes les ressources créées au cours de votre parcours seront systématiquement supprimées.

Désactiver les composants Agentverse

Vous allez maintenant démanteler systématiquement les composants déployés de votre système multi-agents.

Supprimer tous les services Cloud Run et le dépôt Artifact Registry

Cela supprime de Cloud Run tous les agents Familiar déployés, l'orchestrateur Summoner, les serveurs MCP et l'application Dungeon.

👉💻 Dans votre terminal, exécutez les commandes suivantes une par une pour supprimer chaque service :

. ~/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

Supprimer l'instance Cloud SQL

Cela supprime l'instance summoner-librarium-db, y compris sa base de données et toutes les tables qu'elle contient.

👉💻 Dans votre terminal, exécutez :

. ~/agentverse-architect/set_env.sh
gcloud sql instances delete summoner-librarium-db --project=${PROJECT_ID} --quiet

Supprimer le secret Secret Manager et le bucket Google Cloud Storage

👉💻 Dans votre terminal, exécutez :

. ~/agentverse-architect/set_env.sh
gcloud secrets delete tools --quiet
gcloud storage rm -r gs://${BUCKET_NAME} --quiet

Nettoyage des fichiers et répertoires locaux (Cloud Shell)

Enfin, supprimez les dépôts clonés et les fichiers créés de votre environnement Cloud Shell. Bien que facultative, cette étape est vivement recommandée pour nettoyer complètement votre répertoire de travail.

👉💻 Dans votre terminal, exécutez :

rm -rf ~/agentverse-architect
rm -rf ~/agentverse-dungeon
rm -f ~/project_id.txt

Vous avez désormais effacé avec succès toute trace de votre parcours d'architecte d'Agentverse. Votre projet est terminé et vous êtes prêt pour votre prochaine aventure.