Lesson 12 — Tutoriels pas à pas

12-1-1. Déployer les agents dans le projet des agents : méthode **shell** (commandes)

38 min read

This content is not translated yet. Showing the original version.

Le but : mettre en ligne un, deux ou tous les agents dans le projet des agents aiml-gemini-ent-exp-0zga, les tester, et savoir où les voir dans la console Google Cloud.

Pas encore d'app Gemini Enterprise. On ne fait que les agents. Les relier à une app viendra plus tard (12-1, A5 et A6).

Les autres méthodes, même résultat : 12-1-2 Terraform · 12-1-3 Console.

Agents dans le projet de l'app (cas 12-2) ? Tout est identique : mettez le projet de l'app dans PROJET_AGENTS et NUM_AGENTS, et utilisez config/12-2-agents-dans-projet-app.env.

Testé en vrai (10 octobre 2026, projet de test) : toutes les commandes de ce guide, dans l'ordre, pour l'agent meteo, puis pour un 2e agent taille ajouté ensuite. Cloud Run, Agent Runtime, Agent Registry, tests, puis nettoyage. Le 11 octobre : construction des images par Cloud Build, sans Docker sur le poste (compte agents-build-sa), service déployé depuis cette image et testé. Dans les résultats, le nom et le numéro du projet de test sont remplacés par les vôtres.


Sommaire

  1. Les mots à connaître
  2. Ce que vous allez créer, et où le voir
  3. Préparer votre poste (une fois)
  4. Le fichier de configuration : quoi écrire, ligne par ligne
  5. Se connecter, vérifier le projet et vos droits
  6. Vérifier et activer les API
  7. Model Armor : le filtre de sécurité (une fois) — avant : deux façons de faire, avec ou sans script
  8. Cloud Run (A2A) : un agent, puis plusieurs
  9. Agent Runtime : un agent, puis plusieurs
  10. Agent Registry : le catalogue des agents
  11. Dialogflow : un agent conversationnel sans code (option)
  12. Vérification finale
  13. Ajouter un agent plus tard, en retirer un
  14. Tout nettoyer
  15. Ce qui peut arriver

0. Les mots à connaître

MotEn clair
ProjetL'espace Google Cloud où tout est créé et facturé. Ici : aiml-gemini-ent-exp-0zga (numéro 433175138344).
AgentUn programme Python (dossier agents/trio/<clé>_agent/) qui répond aux questions avec Gemini et ses outils (des fonctions Python).
Clé d'un agentSon nom court : meteo, redaction, traduction, taille, retour, identite. Liste complète : agents/trio/catalogue.json.
Cloud RunLe service Google qui fait tourner un conteneur (une image) et lui donne une adresse https://…run.app.
A2AAgent-to-Agent : le protocole ouvert que parlent nos agents sur Cloud Run (celui que Gemini Enterprise utilise).
Carte d'agentUn petit JSON qui décrit l'agent : nom, description, adresse, compétences. Servie par l'agent sur /.well-known/agent-card.json.
ImageLe paquet « code + Python + bibliothèques » que Cloud Run fait tourner. Rangée dans Artifact Registry.
Agent RuntimeL'hébergement géré d'agents de Google (dans Vertex AI). On lui envoie le code ; il gère tout, sessions comprises.
Agent RegistryLe catalogue des agents du projet : qui existe, où, ce qu'il sait faire.
DialogflowUn agent conversationnel construit à la souris (sans Python).
Model ArmorLe filtre de sécurité : bloque injections, contenus dangereux, liens malveillants, dans les questions et les réponses.
Compte de serviceL'identité d'un agent (comme un compte utilisateur, mais pour un programme). Un par agent.
RôleUn droit donné à un compte : roles/aiplatform.user = « peut appeler Gemini ».
APIUn service Google à activer dans le projet avant de s'en servir (Cloud Run, Vertex AI…).

1. Ce que vous allez créer, et où le voir

 Votre poste                          Projet des agents aiml-gemini-ent-exp-0zga
 ┌───────────────────┐               ┌───────────────────────────────────────────────────────────────┐
 │ agents/trio/      │  image        │ Artifact Registry  agents-shell/meteo:v1                       │
 │   meteo_agent/    │ ────────────▶ │ Cloud Run          meteo-a2a-shell   (privé, protocole A2A)    │
 │   taille_agent/   │               │   identité         meteo-a2a-shell-sa                          │
 │   commun.py       │  code         │ Agent Runtime      meteo-shell       (hébergement géré)        │
 │ config/…env       │ ────────────▶ │   identité         meteo-shell-sa                              │
 └───────────────────┘               │ Agent Registry     les agents ci-dessus (catalogue)            │
                                     │ Model Armor        agents-prompt-shield, agents-response-shield│
                                     └───────────────────────────────────────────────────────────────┘

Deux façons d'héberger un agent. Faites l'une, l'autre ou les deux (les noms ne se gênent pas) :

Cloud Run (A2A)Agent Runtime
C'est quoiVotre conteneur, sur l'hébergement « serveur » de GoogleL'hébergement d'agents géré par Google
Ce qui est créé par agentUne image, un compte de service + 3 rôles, un service Cloud Run, une entrée Agent RegistryUn compte de service + 3 rôles, un agent Agent Runtime (inscrit seul dans Agent Registry)
Nom (agent meteo)meteo-a2a-shellmeteo-shell
Pour Gemini Enterprise, plus tardMode « Agent personnalisé via A2A »Mode « Agent personnalisé via Agent Runtime »
Durée de déploiement3 à 5 min (construction de l'image)3 à 5 min

Où le voir dans la console (console.cloud.google.com, projet aiml-gemini-ent-exp-0zga choisi en haut) : tapez le nom dans la barre de recherche 🔎.

Quoi🔎 RechercherPuis
Les API activées« API et services »API et services activés
Les comptes de service« Comptes de service »La liste ; un clic → onglet Autorisations
Les rôles donnés« IAM »Filtrer sur le nom du compte
Les filtres Model Armor« Model Armor »Templates, région eu
Les constructions d'images« Cloud Build »Historique, région europe-west1 : chaque construction et son journal
Les images« Artifact Registry »Dépôt agents-shell → une image par agent
Les agents Cloud Run« Cloud Run »Services → meteo-a2a-shell → URL, Révisions, Journaux, Sécurité
Les agents Agent Runtime« Agent Runtime »Déploiements → meteo-shell → Playground (tester), Sessions, Journaux
Le catalogue« Agent Registry »Région europe-west1 → la liste des agents
Dialogflow« Conversational Agents »L'agent → Tester l'agent
Les erreurs« Journaux » (Logs Explorer)Filtrer par service

2. Préparer votre poste (une fois)

OutilInstaller (Mac, Homebrew)Vérifier
gcloud (la ligne de commande Google Cloud)brew install --cask google-cloud-sdk puis gcloud components install betagcloud version
uv (Python 3.12 à 3.14)brew install uvuv --version

Pas besoin de Docker. Les images des agents sont construites dans Google Cloud (Cloud Build) : votre poste envoie seulement le code (quelques dizaines de Ko). Tout se fait depuis un terminal Linux ou Mac, ou depuis Cloud Shell (le terminal intégré à la console). Sur Linux, gcloud s'installe avec le guide officiel « Install the gcloud CLI » (paquet google-cloud-cli) ; uv avec curl -LsSf https://astral.sh/uv/install.sh | sh.

Le dossier du projet et son Python :

cd ~/Desktop/09-agents-multi-projets-gemini-enterprise
uv venv -p '>=3.12' .venv && source .venv/bin/activate
uv pip install -r agents/trio/requirements.txt
python scripts/test_trio.py

Résultat obtenu : tests trio OK (9 scénarios, 6 agents). Votre invite commence par (.venv) : c'est le Python du projet. Dans chaque nouveau terminal, refaites cd … et source .venv/bin/activate.

Quelle version de Python ? 3.12, 3.13 ou 3.14 (testé : 3.12 et 3.14.6, tests et serveur A2A compris). -p '>=3.12' prend celle déjà installée sur votre poste, sans rien télécharger. Les apostrophes sont nécessaires (sinon le terminal lit > comme une redirection). Les agents déployés, eux, tournent toujours en Python 3.12 (image Cloud Run, Agent Runtime) : votre version locale n'y change rien.

Mac Acme : Failed building wheel for watchdog (unknown architecture arm64e.x1-macos)

google-adk demande le paquet watchdog. Pour Python 3.14 sur Mac, il n'existe pas en version déjà compilée, et sa compilation échoue avec les outils du poste. On ne peut rien y changer, mais on n'en a pas besoin : il ne sert qu'à adk web. Installez la liste prête, sans watchdog (mêmes paquets, versions figées, tous déjà compilés pour Mac et Python 3.14 : rien n'est construit) :

rm -rf .venv
python3 -m venv .venv && source .venv/bin/activate
pip install --no-deps -r agents/trio/requirements-poste.txt
python scripts/test_trio.py

Résultat obtenu (Python 3.14, python -m venv, pip) : tests trio OK (9 scénarios, 6 agents). Les scripts, le serveur A2A et adk run fonctionnent ; seul adk web a besoin de watchdog. Pour tester un agent sur le poste, à la place de adk web :

cd agents/trio && PROMPT_TEMPLATE= RESPONSE_TEMPLATE= LOCAL_DEV=1 adk run taille_agent

Résultat obtenu : Running agent taille_agent, type exit to exit., puis vous tapez votre question ; réponse [taille_agent]: Pour votre tour de poitrine de 98 cm, je vous conseille une veste en taille M…. exit pour quitter. Le déploiement n'est pas concerné : Cloud Run et Agent Runtime utilisent requirements.txt dans Google Cloud.

Si l'installation ne démarre pas, ou bloque (réseau d'entreprise) :

Ce que vous voyezCauseQue faire
uv venv reste bloqué, ou Downloading cpython-3.12… sans finIl cherche à télécharger un Python (ancienne commande -p 3.12, alors que vous avez 3.14), et le réseau le bloqueuv venv -p '>=3.12' .venv (prend votre Python) ; ou sans uv : python3 -m venv .venv
invalid peer certificate: UnknownIssuer, certificate verify failedLe proxy de l'entreprise inspecte le trafic (certificat interne)uv pip install --native-tls -r agents/trio/requirements.txt (utilise les certificats du système) ; ou export UV_NATIVE_TLS=1
Failed to fetch … / délai dépassé vers pypi.orgAccès direct à PyPI interdit, miroir interne obligatoireuv pip install --index-url <URL du miroir PyPI interne> -r agents/trio/requirements.txt (demander l'URL à l'équipe poste de travail / Artifactory) ; ou export UV_INDEX_URL=…
Building wheel for … failedPas de paquet tout prêt pour votre version de Python ou votre machineEssayer uv venv -p 3.12 .venv si 3.12 est installé (brew install python@3.12), puis réinstaller
command not found: uvuv absentbrew install uv, ou sans uv : python3 -m venv .venv && source .venv/bin/activate && pip install -r agents/trio/requirements.txt

L'erreur exacte est la dernière ligne rouge affichée : elle dit laquelle de ces situations est la vôtre.


3. Le fichier de configuration : quoi écrire, ligne par ligne

Toutes les commandes lisent leurs valeurs dans un seul fichier : config/12-1-agents-dans-projet-exp.env. Ouvrez-le dans un éditeur (VS Code, TextEdit…) et remplissez-le ainsi :

# Projet de l'app Gemini Enterprise : PAS ENCORE D'APP -> on laisse vide
PROJET_APP=
NUM_APP=
APP_ID=
GE_LOCATION=eu

# Projet des agents
PROJET_AGENTS=aiml-gemini-ent-exp-0zga
NUM_AGENTS=433175138344
REGION=europe-west1

# Les agents à déployer
AGENTS="meteo"

PUBLIER=non
AGENTS_OAUTH=""
GROUPE_UTILISATEURS=
DOSSIER=~/Desktop/09-agents-multi-projets-gemini-enterprise
LigneCe que c'estOù le trouverIci
PROJET_APP, NUM_APP, APP_IDLe projet et l'app Gemini Enterprise—Vides (pas encore d'app)
GE_LOCATIONOù vivent les filtres Model Armor (et plus tard l'app) : eu, us ou global—eu
PROJET_AGENTSL'ID du projet des agents (pas son nom affiché)Console → sélecteur de projet en haut → colonne IDaiml-gemini-ent-exp-0zga
NUM_AGENTSSon numéroMême écran, colonne Numéro, ou Accueil → Informations sur le projet433175138344
REGIONOù tournent les agents. Doit aller avec GE_LOCATION : eu → europe-…—europe-west1
AGENTSQuels agents déployer : leurs clés, séparées par des espaces. Vide = tousagents/trio/catalogue.json"meteo" (un seul)
PUBLIERAjouter les agents à l'app ?—non (pas d'app)
AGENTS_OAUTHAgents qui agissent avec le compte de l'utilisateur (12-3, partie C)—""
GROUPE_UTILISATEURSLe groupe qui utilisera les agents dans l'app—vide pour l'instant
DOSSIEROù est le dossier sur votre poste—le chemin du dossier

Exemples pour AGENTS :

Vous voulezÉcrivez
un seul agentAGENTS="meteo"
deux agentsAGENTS="meteo taille"
certainsAGENTS="meteo traduction retour"
tous les agents du catalogueAGENTS=""

Charger la configuration dans le terminal (à refaire dans chaque nouveau terminal, et après chaque modification du fichier) :

source scripts/config.sh config/12-1-agents-dans-projet-exp.env

Résultat obtenu :

== Configuration chargée : config/12-1-agents-dans-projet-exp.env
   App Gemini Enterprise : (pas encore : agents seuls)   (projet -, numéro -, eu)
   Projet des agents     : aiml-gemini-ent-exp-0zga (numéro 433175138344), région europe-west1   [même projet que l'app : non]
   Agents à déployer     : meteo
   Compte de l'app       : (aucun : pas encore d'app, aucun droit donné)
   Terraform             : espace « scenario-12-1 », publication dans l'app : non
   Dossier               : /Users/<vous>/Desktop/09-agents-multi-projets-gemini-enterprise
   OK

À vérifier : la dernière ligne est OK, et « Agents à déployer » montre vos agents. Sinon le script dit quoi corriger, par exemple ATTENTION : agent « metoe » absent de agents/trio/catalogue.json (faute de frappe).

Ce que fait ce script : il crée dans le terminal des variables ($PROJET_AGENTS, $REGION, $AGENTS_LISTE…) que les commandes suivantes utilisent. $AGENTS_LISTE = vos agents (ou tous si AGENTS est vide). Toujours avec source, jamais derrière un | : sinon les variables disparaissent.


4. Se connecter, vérifier le projet et vos droits

gcloud auth login                        # ouvre le navigateur : votre compte Google
gcloud auth application-default login    # une 2e fois : pour les scripts Python
gcloud projects describe $PROJET_AGENTS --format='value(projectNumber)'

Résultat attendu : 433175138344. Un autre numéro → corriger NUM_AGENTS, recharger (source …).

Vos droits sur le projet des agents :

gcloud projects get-iam-policy $PROJET_AGENTS --flatten=bindings \
  --filter="bindings.members:user:$(gcloud config get-value account 2>/dev/null)" --format="value(bindings.role)"

Il faut roles/owner, ou ces rôles : aiplatform.admin, run.admin, artifactregistry.admin, iam.serviceAccountAdmin, iam.serviceAccountUser, resourcemanager.projectIamAdmin, serviceusage.serviceUsageAdmin, modelarmor.admin, agentregistry.admin, cloudbuild.builds.editor, storage.admin (+ dialogflow.admin pour la partie 10). Un rôle reçu via un groupe n'apparaît pas ici : vérifiez dans la console (🔎 « IAM »).

La vraie vérification (recommandée) : ce script demande à Google, permission par permission, ce que vous pouvez faire. Il compte aussi les rôles reçus par un groupe et les rôles propres à l'organisation. Lecture seule :

./scripts/verifier_droits.sh

Résultat obtenu :

== Vos droits sur aiml-gemini-ent-exp-0zga (rôles directs, de groupe et personnalisés compris)
  OK        Activer les API (12-1-1 partie 5)
  OK        Créer les comptes de service des agents
  …
  OK        Déclarer les agents Cloud Run dans Agent Registry (partie 9)
  OK        Agent Dialogflow (partie 10, option)

Tout est en place.

Une ligne MANQUANT donne le rôle à demander (ex. → demander roles/agentregistry.admin). Pour une étape optionnelle (Agent Registry, Dialogflow), on peut aussi simplement la passer.


5. Vérifier et activer les API

Une API doit être activée dans le projet avant qu'on s'en serve. Ce script vérifie chacune et active seulement celles qui manquent :

./scripts/verifier_api.sh $PROJET_AGENTS cloudresourcemanager.googleapis.com serviceusage.googleapis.com iam.googleapis.com \
  aiplatform.googleapis.com agentregistry.googleapis.com modelarmor.googleapis.com logging.googleapis.com \
  run.googleapis.com artifactregistry.googleapis.com cloudbuild.googleapis.com

Résultat obtenu :

OK        cloudresourcemanager.googleapis.com
OK        serviceusage.googleapis.com
OK        iam.googleapis.com
OK        aiplatform.googleapis.com
OK        agentregistry.googleapis.com
OK        modelarmor.googleapis.com
OK        logging.googleapis.com
OK        run.googleapis.com
OK        artifactregistry.googleapis.com
OK        cloudbuild.googleapis.com
rien à activer

S'il en manque : MANQUANTE cloudbuild.googleapis.com puis activées : cloudbuild.googleapis.com (1 à 2 minutes). Une API tout juste activée peut refuser la première commande (PERMISSION_DENIED) : attendez 1 minute et relancez.

APIÀ quoi elle sert iciNécessaire pour
cloudresourcemanager, serviceusageLire le projet, activer les autres APITout
iamCréer les comptes de service, donner des rôlesTout
aiplatformGemini (le modèle) et Agent RuntimeTout
modelarmorLe filtre de sécuritéTout
loggingLes journauxTout
agentregistryLe catalogue des agentsAgent Registry
runCloud RunCloud Run
artifactregistryRanger les imagesCloud Run
cloudbuildConstruire les images dans Google Cloud (pas de Docker sur votre poste)Cloud Run
dialogflowDialogflowPartie 10 seulement

Dans la console : 🔎 « API et services » → API et services activés : elles sont dans la liste.


Deux façons de faire les parties 6 à 9

Tout ce qui suit lit le fichier de configuration (partie 3) : les agents à déployer sont ceux de la ligne AGENTS.

Façon 1 : le script (le plus simple)Façon 2 : les commandes une à une
Ce que vous tapezUne commande par étapeLes blocs de commandes ci-dessous
Les agentsCeux de AGENTS (ou la clé donnée : … cloudrun taille)Vous les nommez vous-même avec K=… dans le terminal
Ce que vous voyezChaque commande lancée, précédée de ▶Les commandes que vous collez
RelancerSans danger : ce qui existe est gardé, rien n'est créé deux foisÀ vous de ne pas recréer

Façon 1, configuration chargée (source scripts/config.sh …), dans le dossier du projet :

./scripts/deployer_shell.sh preparer      # partie 6 et 7.1, une fois : filtres, dépôt d'images, compte de construction
./scripts/deployer_shell.sh cloudrun      # partie 7 : chaque agent de AGENTS sur Cloud Run (image, compte, service)
./scripts/deployer_shell.sh runtime       # partie 8 : chaque agent de AGENTS sur Agent Runtime
./scripts/deployer_shell.sh registre      # partie 9 : déclarer les agents Cloud Run dans Agent Registry
./scripts/deployer_shell.sh tester        # 3 à 5 minutes après : tester tout ce qui est déployé
./scripts/deployer_shell.sh carte         # TOUT ce qu'il faut coller dans Gemini Enterprise : carte-K.json, chemin Agent Runtime…

Un seul agent sans toucher au fichier : ajoutez sa clé, ex. ./scripts/deployer_shell.sh cloudrun taille.

carte écrit carte-<clé>.json (agents Cloud Run, au format Google) et affiche la fiche de chaque agent déployé : nom, description, carte sur une ligne, chemin Agent Runtime, étape Authentification, questions proposées, droits de l'app. Ne crée rien chez Google. Agents avec OAuth (oauth, puis carte avec CLIENT_ID=…) : 12-1-8, partie 4 bis.

Résultat obtenu (cloudrun taille, extrait) :

== taille (Cloud Run)   image europe-west1-docker.pkg.dev/aiml-gemini-ent-exp-0zga/agents-shell/taille:v1   adresse https://taille-a2a-shell-433175138344.europe-west1.run.app
-- 1/3 l'image, construite par Cloud Build (environ 1 min 20 s)
▶ gcloud builds submit --region=europe-west1 --project=aiml-gemini-ent-exp-0zga --service-account=… --config=01-bis-cloud-run-a2a/cloudbuild.yaml --substitutions=_AGENT_DIR=taille_agent,_IMAGE=… .
85d9aa15-…  2026-10-11T10:39:13+00:00  1M23S  gs://…  europe-west1-docker.pkg.dev/…/agents-shell/taille:v1  SUCCESS
-- 2/3 son compte de service et ses 3 rôles (Gemini, journaux, Model Armor)
▶ gcloud iam service-accounts create taille-a2a-shell-sa --project=aiml-gemini-ent-exp-0zga --display-name=Agent taille (Cloud Run A2A, méthode shell)
  taille-a2a-shell-sa : roles/aiplatform.user
  taille-a2a-shell-sa : roles/logging.logWriter
  taille-a2a-shell-sa : roles/modelarmor.user
-- 3/3 le service Cloud Run (privé)
▶ gcloud run deploy taille-a2a-shell --image=… --no-allow-unauthenticated --env-vars-file=env-taille.yaml …
Service URL: https://taille-a2a-shell-433175138344.europe-west1.run.app

Attendez 3 à 5 minutes (droits des nouveaux comptes), puis : ./scripts/deployer_shell.sh tester taille

Et tester taille : OK : les agents répondent en A2A v0.3, avec mémoire de conversation (Cloud Run), puis -> outil : taille_vetement({'mesure_cm': 98, 'type_vetement': 'haut'}) et la réponse (Agent Runtime). Relancé une 2e fois : compte … : existe déjà, déjà déployé, déjà déclaré : rien n'est recréé.

Ensuite, la carte de chaque agent pour Gemini Enterprise : 7.6. Les parties 6 à 9 ci-dessous détaillent ce que fait le script (façon 2) : à lire pour comprendre, ou à suivre à la main.


6. Model Armor : le filtre de sécurité (une fois)

Deux templates (modèles de filtre) : un pour les questions, un pour les réponses. Tous les agents les partagent : on les crée une fois, quel que soit le nombre d'agents.

for T in prompt response; do
gcloud model-armor templates create agents-$T-shield --location=$GE_LOCATION --project=$PROJET_AGENTS \
  --pi-and-jailbreak-filter-settings-enforcement=enabled --pi-and-jailbreak-filter-settings-confidence-level=medium-and-above \
  --malicious-uri-filter-settings-enforcement=enabled --basic-config-filter-enforcement=enabled \
  --rai-settings-filters='[{"filterType":"HATE_SPEECH","confidenceLevel":"MEDIUM_AND_ABOVE"},{"filterType":"HARASSMENT","confidenceLevel":"MEDIUM_AND_ABOVE"},{"filterType":"SEXUALLY_EXPLICIT","confidenceLevel":"MEDIUM_AND_ABOVE"},{"filterType":"DANGEROUS","confidenceLevel":"MEDIUM_AND_ABOVE"}]' \
  --template-metadata-log-operations
done
gcloud model-armor templates list --location=$GE_LOCATION --project=$PROJET_AGENTS --format="value(name)"

for T in prompt response; do … done est une boucle : la commande est lancée deux fois, avec T=prompt puis T=response. Elle crée donc agents-prompt-shield et agents-response-shield.

Résultat obtenu :

Created template [agents-prompt-shield].
Created template [agents-response-shield].
projects/aiml-gemini-ent-exp-0zga/locations/eu/templates/agents-prompt-shield
projects/aiml-gemini-ent-exp-0zga/locations/eu/templates/agents-response-shield

Leurs chemins sont déjà dans $PROMPT_TEMPLATE et $RESPONSE_TEMPLATE (le script de configuration les a calculés). Déjà créés (ALREADY_EXISTS) ? Rien à faire, passez à la suite.

Dans la console : 🔎 « Model Armor » → Templates → les deux, région eu.


7. Cloud Run (A2A) : un agent, puis plusieurs

7.1 Le dépôt d'images et le compte qui construit (une fois)

Une image est le paquet « code + Python + bibliothèques » que Cloud Run fait tourner. On la fait construire par Cloud Build, un service de Google : votre poste envoie le code, Google construit l'image et la range dans un dépôt (Artifact Registry). Il faut donc, une fois :

gcloud artifacts repositories create agents-shell --repository-format=docker --location=$REGION --project=$PROJET_AGENTS
gcloud iam service-accounts create agents-build-sa --project=$PROJET_AGENTS --display-name="Construction des images des agents (Cloud Build)"
for R in storage.objectViewer artifactregistry.writer logging.logWriter; do
  gcloud projects add-iam-policy-binding $PROJET_AGENTS --condition=None --role=roles/$R \
    --member=serviceAccount:agents-build-sa@$PROJET_AGENTS.iam.gserviceaccount.com >/dev/null && echo "  agents-build-sa : roles/$R"
done
LigneCe qu'elle fait
repositories create agents-shellLe dépôt où ranger les images (--repository-format=docker est le format standard des images, pas besoin du logiciel Docker)
service-accounts create agents-build-saLe compte qui construit les images. Pourquoi un compte à nous : celui que Cloud Build utilise par défaut n'a souvent aucun droit (vérifié : … does not have storage.objects.get access)
storage.objectViewerLire le code que vous envoyez
artifactregistry.writerRanger l'image dans le dépôt
logging.logWriterÉcrire le journal de construction

Résultat obtenu :

Created repository [agents-shell].
Created service account [agents-build-sa].
  agents-build-sa : roles/storage.objectViewer
  agents-build-sa : roles/artifactregistry.writer
  agents-build-sa : roles/logging.logWriter

Attendez 1 à 2 minutes avant la première construction : les droits d'un compte neuf mettent ce temps à s'appliquer.

7.2 Déployer UN agent

Dans le dossier du projet (cd $DOSSIER), en changeant seulement la 1re ligne si vous voulez un autre agent :

K=meteo                                                                    # ← la clé de l'agent
IMAGE=$REGION-docker.pkg.dev/$PROJET_AGENTS/agents-shell/$K:v1             # où ranger son image
SA=$K-a2a-shell-sa@$PROJET_AGENTS.iam.gserviceaccount.com                  # son identité
URL=https://$K-a2a-shell-$NUM_AGENTS.$REGION.run.app                       # son adresse, connue d'avance

Où les mettre ? Nulle part dans un fichier : copiez-collez ces 4 lignes dans le terminal, comme les commandes précédentes, puis Entrée. Elles ne créent rien : elles nomment les choses, et les commandes suivantes s'en servent ($IMAGE, $SA, $URL). Elles disparaissent si vous ouvrez un nouveau terminal : recollez-les alors.

Vérifiez avant de continuer :

echo "K=$K  IMAGE=$IMAGE  URL=$URL"

Attendu : K=meteo IMAGE=europe-west1-docker.pkg.dev/aiml-gemini-ent-exp-0zga/agents-shell/meteo:v1 URL=https://meteo-a2a-shell-433175138344.europe-west1.run.app. Si IMAGE= est vide, les 4 lignes n'ont pas été collées dans ce terminal (sinon : invalid image name "" à l'étape a).

a) L'image de l'agent, construite par Cloud Build (code commun + le dossier de CET agent seulement) :

gcloud builds submit --region=$REGION --project=$PROJET_AGENTS \
  --service-account=projects/$PROJET_AGENTS/serviceAccounts/agents-build-sa@$PROJET_AGENTS.iam.gserviceaccount.com \
  --config=01-bis-cloud-run-a2a/cloudbuild.yaml --substitutions=_AGENT_DIR=${K}_agent,_IMAGE=$IMAGE .
MorceauSens
gcloud builds submit … .Envoie le dossier courant (le point final) à Cloud Build. Le fichier .gcloudignore du projet filtre : seul le code des agents part, jamais .venv ni l'état Terraform
--region=$REGIONLa construction a lieu en Europe (europe-west1)
--service-account=…agents-build-sa…Construire avec notre compte (7.1)
--config=01-bis-cloud-run-a2a/cloudbuild.yamlLa recette de construction (elle utilise 01-bis-cloud-run-a2a/Dockerfile)
_AGENT_DIR=meteo_agentNe mettre que cet agent dans l'image
_IMAGE=$IMAGELe nom de l'image, dans le dépôt agents-shell

Résultat obtenu (environ 1 min 20 s) :

Creating temporary archive of 20 file(s) totalling 61.4 KiB before compression.
Uploading tarball of [.] to [gs://aiml-gemini-ent-exp-0zga_cloudbuild/source/….tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/aiml-gemini-ent-exp-0zga/locations/europe-west1/builds/1092987d-…].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds;region=europe-west1/1092987d-…?project=433175138344 ].
…
ID          CREATE_TIME                DURATION  SOURCE   IMAGES                                                                    STATUS
1092987d-…  2026-10-10T22:22:46+00:00  1M21S     gs://…   europe-west1-docker.pkg.dev/aiml-gemini-ent-exp-0zga/agents-shell/meteo:v1  SUCCESS

À vérifier : le dernier mot est SUCCESS. 20 file(s) totalling 61.4 KiB : seul le code est envoyé. FAILURE : ouvrez le lien Logs are available at (ou 🔎 « Cloud Build » → Historique) pour lire l'erreur.

b) Son compte de service et ses 3 rôles :

gcloud iam service-accounts create $K-a2a-shell-sa --project=$PROJET_AGENTS --display-name="Agent $K (Cloud Run A2A, méthode shell)"
for R in aiplatform.user logging.logWriter modelarmor.user; do
  gcloud projects add-iam-policy-binding $PROJET_AGENTS --condition=None --role=roles/$R --member=serviceAccount:$SA >/dev/null \
    && echo "  $K-a2a-shell-sa : roles/$R"
done
RôlePourquoi
aiplatform.userAppeler Gemini
logging.logWriterÉcrire ses journaux
modelarmor.userUtiliser les filtres de la partie 6

Résultat obtenu :

Created service account [meteo-a2a-shell-sa].
  meteo-a2a-shell-sa : roles/aiplatform.user
  meteo-a2a-shell-sa : roles/logging.logWriter
  meteo-a2a-shell-sa : roles/modelarmor.user

c) Ses réglages, puis le service :

python3 scripts/carte_a2a.py $K $URL --env-yaml > env-$K.yaml
gcloud run deploy $K-a2a-shell --image=$IMAGE --region=$REGION --project=$PROJET_AGENTS \
  --service-account=$SA --no-allow-unauthenticated --env-vars-file=env-$K.yaml \
  --memory=1Gi --cpu=1 --min-instances=0 --max-instances=1 --quiet

La 1re ligne écrit env-meteo.yaml, les variables d'environnement du service :

VariableValeurRôle
AGENTmeteo_agentQuel agent ce service fait tourner
AGENT_CARDla carte A2A (JSON), avec $URLCe que l'agent montre de lui-même
GOOGLE_CLOUD_PROJECTaiml-gemini-ent-exp-0zgaOù appeler Gemini
MODELgemini-3.5-flashLe modèle
PROMPT_TEMPLATE, RESPONSE_TEMPLATEles chemins de la partie 6Les filtres Model Armor
Option de gcloud run deploySens
--no-allow-unauthenticatedPrivé : seuls les comptes autorisés peuvent l'appeler (vous, et plus tard l'app)
--min-instances=0S'éteint quand personne ne l'utilise (rien à payer) ; la 1re réponse prend alors ~20 s
--max-instances=1Une seule copie : la mémoire des conversations est dans le conteneur

Résultat obtenu :

Deploying container to Cloud Run service [meteo-a2a-shell] in project [aiml-gemini-ent-exp-0zga] region [europe-west1]
Deploying new service...
Creating Revision...done
Routing traffic.....done
Done.
Service [meteo-a2a-shell] revision [meteo-a2a-shell-00001-8xs] has been deployed and is serving 100 percent of traffic.
Service URL: https://meteo-a2a-shell-433175138344.europe-west1.run.app

À vérifier : Service URL est exactement $URL (la carte de l'agent contient cette adresse).

7.3 Tester l'agent

Attendez 3 à 5 minutes (les rôles du nouveau compte mettent ce temps à s'appliquer), puis :

URL=$URL ./01-bis-cloud-run-a2a/test.sh $K

Le script parle à l'agent comme le fera Gemini Enterprise (protocole A2A) : il lit sa carte, pose une question, puis une 2e dans la même conversation.

Résultat obtenu (agent taille) :

== taille  carte : taille_agent (A2A 0.3)
   Q1 > Je fais 98 cm de tour de poitrine, quelle taille de veste ?
   R1 < Pour votre tour de poitrine de 98 cm, je vous conseille la taille M (ou L pour plus d'aisance).
        L'essai en magasin reste cependant le moyen le plus sûr de trouver la coupe idéale pour votre veste.
   Q2 > Peux-tu résumer ta réponse en une phrase ?
   R2 < Pour un tour de poitrine de 98 cm, je vous conseille la taille M ou L (pour plus d'aisance), sachant que l'essai en magasin reste le plus sûr.

OK : les agents répondent en A2A v0.3, avec mémoire de conversation

Dans la console : 🔎 « Cloud Run » → Services → meteo-a2a-shell :

  • l'URL en haut ;
  • Révisions : la version en ligne ;
  • Journaux : chaque appel ;
  • Sécurité : l'authentification requise ;
  • Modifier et déployer une nouvelle révision → Variables et secrets : les variables du tableau ci-dessus.

7.4 Plusieurs agents

Façon 1, un par un : refaites 7.2 et 7.3 en changeant seulement K=… (ex. K=taille). Les étapes 6 et 7.1 ne se refont pas.

Façon 2, d'un coup : mettez les clés dans le fichier de configuration (ex. AGENTS="meteo taille retour"), rechargez-le (source scripts/config.sh …), puis :

for K in $(echo $AGENTS_LISTE); do
  IMAGE=$REGION-docker.pkg.dev/$PROJET_AGENTS/agents-shell/$K:v1
  SA=$K-a2a-shell-sa@$PROJET_AGENTS.iam.gserviceaccount.com
  URL=https://$K-a2a-shell-$NUM_AGENTS.$REGION.run.app
  gcloud builds submit --region=$REGION --project=$PROJET_AGENTS \
    --service-account=projects/$PROJET_AGENTS/serviceAccounts/agents-build-sa@$PROJET_AGENTS.iam.gserviceaccount.com \
    --config=01-bis-cloud-run-a2a/cloudbuild.yaml --substitutions=_AGENT_DIR=${K}_agent,_IMAGE=$IMAGE .
  gcloud iam service-accounts create $K-a2a-shell-sa --project=$PROJET_AGENTS --display-name="Agent $K (Cloud Run A2A, méthode shell)"
  for R in aiplatform.user logging.logWriter modelarmor.user; do
    gcloud projects add-iam-policy-binding $PROJET_AGENTS --condition=None --role=roles/$R --member=serviceAccount:$SA >/dev/null \
      && echo "  $K-a2a-shell-sa : roles/$R"
  done
  python3 scripts/carte_a2a.py $K $URL --env-yaml > env-$K.yaml
  gcloud run deploy $K-a2a-shell --image=$IMAGE --region=$REGION --project=$PROJET_AGENTS \
    --service-account=$SA --no-allow-unauthenticated --env-vars-file=env-$K.yaml \
    --memory=1Gi --cpu=1 --min-instances=0 --max-instances=1 --quiet
done

Comment lire cette boucle : for K in meteo taille retour; do … done lance le bloc une fois par agent, avec K qui vaut meteo, puis taille, puis retour. $(echo $AGENTS_LISTE) donne la liste de votre fichier (cette écriture marche dans bash et dans zsh, le terminal des Mac).

Un agent déjà déployé dans la liste ? La création de son compte dit already exists (sans effet). Le reste redéploie la même version : sans danger, mais inutile. Mettez plutôt seulement les nouveaux dans la liste.

Puis tester tous les agents :

for K in $(echo $AGENTS_LISTE); do URL=https://$K-a2a-shell-$NUM_AGENTS.$REGION.run.app ./01-bis-cloud-run-a2a/test.sh $K; done

Tous les agents du catalogue : AGENTS="", recharger, même boucle (6 agents : 20 à 30 minutes).

7.5 Nouvelle version du code d'un agent

Modifiez agents/trio/meteo_agent/agent.py, puis refaites 7.2 a) avec :v2 au lieu de :v1 et 7.2 c) (seulement la commande gcloud run deploy). La même adresse sert la nouvelle version. Les autres agents ne sont pas touchés : chacun a sa propre image.

7.6 La carte de l'agent (pour Gemini Enterprise)

La carte est ce que vous collerez dans Gemini Enterprise (Agents → + Ajouter un agent → Agent personnalisé via A2A) : un JSON qui dit le nom, la description, l'adresse et les compétences de l'agent. Elle sert aussi à déclarer l'agent dans Agent Registry (partie 9).

L'écrire dans un fichier, dans le dossier du projet (configuration chargée) :

K=meteo
python3 scripts/carte_a2a.py $K https://$K-a2a-shell-$NUM_AGENTS.$REGION.run.app > carte-$K.json
python3 -m json.tool --no-ensure-ascii carte-$K.json        # l'afficher, lisible

Résultat obtenu :

{
    "protocolVersion": "0.3",
    "name": "meteo_agent",
    "description": "Météo réelle d'une ville (jusqu'à 7 jours) et équipement conseillé pour faire du sport dehors.",
    "url": "https://meteo-a2a-shell-433175138344.europe-west1.run.app",
    "preferredTransport": "JSONRPC",
    "version": "1.0.0",
    "capabilities": { "streaming": true },
    "defaultInputModes": ["text/plain"],
    "defaultOutputModes": ["text/plain"],
    "skills": [
        { "id": "meteo", "name": "Météo d'une ville", "description": "…", "tags": ["météo", "prévisions"],
          "examples": ["Quel temps à Chamonix demain ?"] },
        { "id": "equipement", "name": "Quoi porter", "description": "…", "tags": ["équipement", "sport"],
          "examples": ["Je cours à Lille demain matin, quoi porter ?"] }
    ]
}
ChampSens
protocolVersion: "0.3"La version d'A2A que Gemini Enterprise attend
urlL'adresse du service : exactement la Service URL de 7.2 c)
name, descriptionCe que l'app affiche ; viennent de agents/trio/catalogue.json
skillsLes compétences et leurs exemples de questions

À coller dans Gemini Enterprise : tout le contenu de carte-meteo.json (cat carte-meteo.json : une seule ligne, plus facile à copier sans rien couper).

La vérifier sur l'agent en ligne (c'est la même, servie par l'agent lui-même) :

curl -s -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
  https://$K-a2a-shell-$NUM_AGENTS.$REGION.run.app/.well-known/agent-card.json | python3 -m json.tool --no-ensure-ascii

Résultat obtenu : les mêmes champs, plus un champ supportedInterfaces ajouté par la bibliothèque A2A (sans effet). Pour Gemini Enterprise, utilisez carte-meteo.json : c'est exactement le format de la documentation Google.

Pour l'ajouter à l'app plus tard (quand elle existera), il faudra aussi donner à l'app le droit d'appeler ce service (roles/run.invoker), puis la coller : 12-1, A5 et A6. Ou, en une commande : ./scripts/add_agent_to_ge.sh a2a carte-meteo.json "Météo & équipement (A2A shell)" (le script donne aussi ce droit).


8. Agent Runtime : un agent, puis plusieurs

Ici, pas d'image : on envoie le code à Google, qui l'installe et le fait tourner.

8.1 Déployer UN agent

K=meteo                                                          # ← la clé de l'agent
SA=$K-shell-sa@$PROJET_AGENTS.iam.gserviceaccount.com
gcloud iam service-accounts create $K-shell-sa --project=$PROJET_AGENTS --display-name="Agent $K (Agent Runtime, méthode shell)"
for R in aiplatform.user logging.logWriter modelarmor.user; do
  gcloud projects add-iam-policy-binding $PROJET_AGENTS --condition=None --role=roles/$R --member=serviceAccount:$SA >/dev/null \
    && echo "  $K-shell-sa : roles/$R"
done
DESC=$(python3 -c "import json; print(json.load(open('agents/trio/catalogue.json'))['$K']['description'])")
python scripts/deployer_agent_runtime.py --projet $PROJET_AGENTS --region $REGION --agent ${K}_agent --nom $K-shell \
  --description "$DESC" --compte-service $SA \
  --env PROMPT_TEMPLATE=$PROMPT_TEMPLATE --env RESPONSE_TEMPLATE=$RESPONSE_TEMPLATE
MorceauSens
DESC=$(python3 …)Lit la description de l'agent dans le catalogue
--agent meteo_agentLe dossier de l'agent (son point d'entrée : meteo_agent/agent.py, objet agent_runtime_app)
--nom meteo-shellSon nom dans Agent Runtime et dans Agent Registry
--compte-serviceSon identité
--env PROMPT_TEMPLATE=…Ses filtres Model Armor

Résultat obtenu :

Created service account [meteo-shell-sa].
  meteo-shell-sa : roles/aiplatform.user
  meteo-shell-sa : roles/logging.logWriter
  meteo-shell-sa : roles/modelarmor.user
opération : projects/100000000002/locations/europe-west1/reasoningEngines/5685752748113395712/operations/4990073393119232000
  en cours… 0 s
  …
déployé : projects/100000000002/locations/europe-west1/reasoningEngines/5685752748113395712

Notez le nom après déployé : : c'est le nom de ressource de l'agent (Gemini Enterprise le demandera).

8.2 Tester l'agent

Attendez 3 à 5 minutes, puis :

AGENT_NAME=projects/$NUM_AGENTS/locations/$REGION/reasoningEngines/5685752748113395712 \
  python scripts/query.py - "Je cours à Lille demain matin, quoi porter ?"

(Remplacez le nombre par votre nom de ressource.) Résultat obtenu (agent taille, « Mon pied mesure 27 cm, quelle pointure pour courir ? ») :

  -> outil : pointure({'longueur_pied_cm': 27, 'activite': 'course'})
agent : Pour la course à pied avec un pied de 27 cm, je vous conseille une pointure **42 EUR** (une marge est ajoutée car le pied gonfle).
N'oubliez pas que l'essai en magasin reste le moyen le plus sûr de trouver chaussure à votre pied !

La ligne -> outil : montre l'outil Python que l'agent a appelé, avec ses arguments.

Retrouver le nom de ressource plus tard :

curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://$REGION-aiplatform.googleapis.com/v1/projects/$PROJET_AGENTS/locations/$REGION/reasoningEngines" \
  | python3 -c 'import json,sys; [print(e["displayName"], e["name"]) for e in json.load(sys.stdin).get("reasoningEngines",[])]'

Dans la console : 🔎 « Agent Runtime » → Déploiements → meteo-shell :

  • Playground : tester à la souris ;
  • Sessions : les conversations ;
  • Journaux ;
  • le nom de ressource en haut.

8.3 Plusieurs agents

Un par un : refaites 8.1 et 8.2 avec un autre K. D'un coup, avec la liste du fichier :

for K in $(echo $AGENTS_LISTE); do
  SA=$K-shell-sa@$PROJET_AGENTS.iam.gserviceaccount.com
  gcloud iam service-accounts create $K-shell-sa --project=$PROJET_AGENTS --display-name="Agent $K (Agent Runtime, méthode shell)"
  for R in aiplatform.user logging.logWriter modelarmor.user; do
    gcloud projects add-iam-policy-binding $PROJET_AGENTS --condition=None --role=roles/$R --member=serviceAccount:$SA >/dev/null \
      && echo "  $K-shell-sa : roles/$R"
  done
  DESC=$(python3 -c "import json; print(json.load(open('agents/trio/catalogue.json'))['$K']['description'])")
  python scripts/deployer_agent_runtime.py --projet $PROJET_AGENTS --region $REGION --agent ${K}_agent --nom $K-shell \
    --description "$DESC" --compte-service $SA \
    --env PROMPT_TEMPLATE=$PROMPT_TEMPLATE --env RESPONSE_TEMPLATE=$RESPONSE_TEMPLATE
done

Un agent déjà déployé (même nom) n'est pas recréé : le script répond existe déjà : projects/… et passe. Pour une nouvelle version : le supprimer d'abord (13 ou python scripts/nettoyer.py --agent <clé> --types runtime --supprimer), puis relancer. Pour une nouvelle version du code d'un agent : supprimez l'ancien (13) puis redéployez, ou utilisez Terraform (12-1-2), qui met à jour sur place.


9. Agent Registry : le catalogue des agents

  • Agents Agent Runtime : inscrits automatiquement. Rien à faire.
  • Agents Cloud Run : on les déclare avec leur carte. Pour un agent :
K=meteo
python3 scripts/carte_a2a.py $K https://$K-a2a-shell-$NUM_AGENTS.$REGION.run.app > carte-$K.json
NOM=$(python3 -c "import json; print(json.load(open('agents/trio/catalogue.json'))['$K']['nom_affiche'])")
gcloud agent-registry services create $K-a2a-shell --location=$REGION --project=$PROJET_AGENTS \
  --display-name="$NOM" --description="$(python3 -c "import json; print(json.load(open('carte-$K.json'))['description'])")" \
  --agent-spec-type=A2A_AGENT_CARD --agent-spec-content="$(cat carte-$K.json)"

Résultat obtenu : Created service [meteo-a2a-shell]. Pour plusieurs : même bloc dans for K in $(echo $AGENTS_LISTE); do … done, ou en changeant K.

Voir le catalogue :

gcloud agent-registry agents list --location=$REGION --project=$PROJET_AGENTS --format="table(displayName,agentId)"

Résultat obtenu (après meteo et taille, Cloud Run et Agent Runtime) :

DISPLAY_NAME     AGENT_ID
meteo_agent      urn:agent:projects-433175138344:…:agentregistry:services:meteo-a2a-shell
taille_agent     urn:agent:projects-433175138344:…:agentregistry:services:taille-a2a-shell
meteo-shell      urn:agent:projects-433175138344:…:aiplatform:reasoningEngines:5685752748113395712
taille-shell     urn:agent:projects-433175138344:…:aiplatform:reasoningEngines:8117696546893463552

Les lignes agentregistry:services sont les agents Cloud Run (déclarés) ; aiplatform:reasoningEngines, ceux d'Agent Runtime (inscrits seuls). Une ligne Workspace Agent peut apparaître : c'est un agent de Google, ignorez-la.

Dans la console : 🔎 « Agent Registry » → région europe-west1 → la liste ; un clic → la carte et les compétences.


10. Dialogflow : un agent conversationnel sans code (option)

C'est quoi, et faut-il le faire ?

  • Dialogflow (« Conversational Agents » dans la console) est un autre type d'agent, qui n'a rien à voir avec nos agents Python (météo, taille…).
  • Il se construit à la souris :
    • des intentions : « l'utilisateur veut un horaire » → telle réponse ;
    • des pages : un parcours guidé, étape par étape ;
    • ou un playbook génératif : des consignes en langage naturel.
  • Utile pour un parcours guidé : accueil en magasin, orientation, FAQ.
  • Optionnel : si vous n'en avez pas besoin, passez à la partie 11.

Ce qu'on fait ici :

  1. créer un agent Dialogflow vide ;
  2. vérifier qu'il répond ;
  3. noter son nom, que Gemini Enterprise demandera plus tard.

Son contenu se construit ensuite dans la console.

10.1 Activer l'API (une fois)

./scripts/verifier_api.sh $PROJET_AGENTS dialogflow.googleapis.com

Attendu : OK dialogflow.googleapis.com (ou activées : dialogflow.googleapis.com).

10.2 Créer l'agent

curl -s -X POST -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "Content-Type: application/json" \
  -H "x-goog-user-project: $PROJET_AGENTS" \
  "https://$REGION-dialogflow.googleapis.com/v3/projects/$PROJET_AGENTS/locations/$REGION/agents" \
  -d '{"displayName":"Accueil magasin (shell)","defaultLanguageCode":"fr","timeZone":"Europe/Paris","description":"Accueil et orientation en magasin"}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["name"])' | tee agent-dialogflow.txt
MorceauSens
curl -s -X POST …/agentsDemande à l'API Dialogflow de créer un agent (il n'y a pas de commande gcloud pour cela)
-H "Authorization: Bearer …"Votre jeton de connexion (gcloud)
-d '{…}'Ce qu'on crée : nom affiché Accueil magasin (shell), langue fr, fuseau Europe/Paris
python3 -c … ["name"]Garde seulement le nom de l'agent dans la réponse
tee agent-dialogflow.txtL'affiche et l'écrit dans le fichier agent-dialogflow.txt (pour la suite)

Résultat obtenu :

projects/aiml-gemini-ent-exp-0zga/locations/europe-west1/agents/02d61b82-3c96-4564-82f2-9aa73a455dcd

Cette ligne est la source de l'agent Dialogflow : c'est ce que Gemini Enterprise demandera (Agent personnalisé via Dialogflow → Source de l'agent Dialogflow). Elle est gardée dans agent-dialogflow.txt.

10.3 Vérifier qu'il répond

AGENT=$(cat agent-dialogflow.txt) ./04-bis-dialogflow/test.sh "Bonjour"

(AGENT=$(cat agent-dialogflow.txt) donne au script le nom écrit à l'étape d'avant.) Résultat obtenu :

  agent pas encore prêt, nouvel essai dans 5 s…
intention : Default Welcome Intent
réponse   : Bonjour !
  • La ligne « pas encore prêt » est normale juste après la création : un agent neuf répond 404 pendant quelques secondes (vérifié : 404 tout de suite, réponse 5 s plus tard). Le script réessaie seul.
  • Default Welcome Intent : l'intention d'accueil que Dialogflow met dans tout agent neuf ; la réponse varie (« Bonjour ! », « Salutations ! »…).
  • ÉCHEC : l'agent … ne répond pas : l'agent n'existe plus (supprimé ?) ou mauvais nom dans agent-dialogflow.txt. Vérifiez la liste :
curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "x-goog-user-project: $PROJET_AGENTS" \
  "https://$REGION-dialogflow.googleapis.com/v3/projects/$PROJET_AGENTS/locations/$REGION/agents" \
  | python3 -c 'import json,sys; [print(a["displayName"], a["name"]) for a in json.load(sys.stdin).get("agents",[])]'

10.4 Lui donner un contenu (console)

🔎 « Conversational Agents » → choisir le projet → région europe-west1 → Accueil magasin (shell). Puis :

  • Flux et Pages : un parcours (ex. « Horaires », « Retours », « Parler à un conseiller ») ;
  • ou Playbooks : des consignes en langage naturel (« Tu accueilles les clients du magasin… »).

À droite, Tester l'agent : posez une question, voyez la réponse.

10.5 Plus tard, dans Gemini Enterprise

  1. L'app → Agents → + Ajouter un agent → Agent personnalisé via Dialogflow.
  2. Remplir :
    • Nom : Accueil magasin ;
    • Description : une phrase ;
    • Source de l'agent Dialogflow : le contenu de agent-dialogflow.txt.
  3. Créer.

Détails : 12-2, A6. Dialogflow dans un autre projet que l'app n'est pas documenté par Google : pour ce mode, l'agent Dialogflow se crée de préférence dans le projet de l'app (12-2).

Supprimer l'agent Dialogflow : python scripts/nettoyer.py --types dialogflow --supprimer (il est reconnu à son nom « Accueil magasin… »), ou :

curl -s -X DELETE -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "x-goog-user-project: $PROJET_AGENTS" \
  "https://$REGION-dialogflow.googleapis.com/v3/$(cat agent-dialogflow.txt)" && rm agent-dialogflow.txt

11. Vérification finale

gcloud run services list --region=$REGION --project=$PROJET_AGENTS --format="table(metadata.name,status.url)"
gcloud iam service-accounts list --project=$PROJET_AGENTS --format="value(email)" | grep shell
gcloud agent-registry agents list --location=$REGION --project=$PROJET_AGENTS --format="table(displayName,agentId)"

Résultat obtenu (meteo et taille) :

NAME              URL
meteo-a2a-shell   https://meteo-a2a-shell-…-ew.a.run.app
taille-a2a-shell  https://taille-a2a-shell-…-ew.a.run.app

(Cloud Run affiche ici une 2e forme d'adresse, …-ew.a.run.app : les deux mènent au même service.)

VérifierAttendu
Un service Cloud Run par agent<clé>-a2a-shell
Deux comptes par agent<clé>-a2a-shell-sa (Cloud Run), <clé>-shell-sa (Agent Runtime)
Le catalogueUne ligne par agent et par hébergement
Les testsOK : … (Cloud Run), une réponse avec -> outil (Agent Runtime)

12. Ajouter un agent plus tard, en retirer un

  • Ajouter un agent existant du catalogue (ex. retour) : K=retour, puis 7.2, 7.3, 8.1, 8.2, 9. Rien d'autre ne bouge.
  • Créer un tout nouvel agent : 12-3, partie 1 (python scripts/nouvel_agent.py …), puis comme ci-dessus.
  • Retirer un agent : le bloc de 13 avec ce seul K.

13. Tout nettoyer

Plus simple : le script de nettoyage. Il fait l'inventaire de tout ce que les guides créent (Cloud Run, Agent Runtime, Agent Registry, Dialogflow, comptes de service et leurs rôles, images, filtres Model Armor) et ne supprime qu'après confirmation :

python scripts/nettoyer.py                         # INVENTAIRE : liste, ne supprime rien
python scripts/nettoyer.py --agent meteo           # seulement ce qui appartient à meteo
python scripts/nettoyer.py --supprimer             # supprime (tapez l'ID du projet pour confirmer)

Ce que Terraform a créé est ignoré (marqué [terraform]) : supprimez-le avec terraform destroy. Testé en vrai : 8 types supprimés, rôles des comptes compris.

À la main, voici ce que fait le script.

Un agent (mettez sa clé dans K) :

K=meteo
R=$(curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://$REGION-aiplatform.googleapis.com/v1/projects/$PROJET_AGENTS/locations/$REGION/reasoningEngines" \
  | python3 -c "import json,sys; print(next((e['name'] for e in json.load(sys.stdin).get('reasoningEngines',[]) if e['displayName']=='$K-shell'), ''))")
[ -n "$R" ] && python scripts/deployer_agent_runtime.py --projet $PROJET_AGENTS --supprimer $R
gcloud agent-registry services delete $K-a2a-shell --location=$REGION --project=$PROJET_AGENTS --quiet
gcloud run services delete $K-a2a-shell --region=$REGION --project=$PROJET_AGENTS --quiet
for SA in $K-shell-sa $K-a2a-shell-sa; do
  for R in aiplatform.user logging.logWriter modelarmor.user; do
    gcloud projects remove-iam-policy-binding $PROJET_AGENTS --condition=None --role=roles/$R \
      --member=serviceAccount:$SA@$PROJET_AGENTS.iam.gserviceaccount.com >/dev/null 2>&1
  done
  gcloud iam service-accounts delete $SA@$PROJET_AGENTS.iam.gserviceaccount.com --project=$PROJET_AGENTS --quiet
done
gcloud artifacts docker images delete $REGION-docker.pkg.dev/$PROJET_AGENTS/agents-shell/$K --delete-tags --quiet
rm -f env-$K.yaml carte-$K.json

Résultat obtenu :

supprimé : projects/100000000002/locations/europe-west1/reasoningEngines/5685752748113395712
Deleted service [meteo-a2a-shell].
Deleted service [meteo-a2a-shell].
deleted service account [meteo-shell-sa@aiml-gemini-ent-exp-0zga.iam.gserviceaccount.com]
deleted service account [meteo-a2a-shell-sa@aiml-gemini-ent-exp-0zga.iam.gserviceaccount.com]

(Deleted service deux fois : l'entrée du catalogue, puis le service Cloud Run.) Plusieurs agents : même bloc dans for K in $(echo $AGENTS_LISTE); do … done (sans la ligne K=meteo).

Ce qui est commun (seulement quand plus aucun agent ne s'en sert) :

for T in agents-prompt-shield agents-response-shield; do gcloud model-armor templates delete $T --location=$GE_LOCATION --project=$PROJET_AGENTS --quiet; done
gcloud artifacts repositories delete agents-shell --location=$REGION --project=$PROJET_AGENTS --quiet
for R in storage.objectViewer artifactregistry.writer logging.logWriter; do
  gcloud projects remove-iam-policy-binding $PROJET_AGENTS --condition=None --role=roles/$R \
    --member=serviceAccount:agents-build-sa@$PROJET_AGENTS.iam.gserviceaccount.com >/dev/null 2>&1
done
gcloud iam service-accounts delete agents-build-sa@$PROJET_AGENTS.iam.gserviceaccount.com --project=$PROJET_AGENTS --quiet
curl -s -X DELETE -H "Authorization: Bearer $(gcloud auth print-access-token)" -H "x-goog-user-project: $PROJET_AGENTS" \
  "https://$REGION-dialogflow.googleapis.com/v3/$(cat agent-dialogflow.txt)" && rm -f agent-dialogflow.txt   # si partie 10

Résultat obtenu : Deleted template [agents-prompt-shield]., Deleted template [agents-response-shield]., Deleted repository [agents-shell].


14. Ce qui peut arriver

Ce que vous voyezCauseQue faire
MANQUANT : … ou ATTENTION : … au chargement de la configurationValeur vide, faute de frappe dans AGENTSCorriger le fichier, recharger
Une commande contient --project= videConfiguration pas chargée dans ce terminalsource scripts/config.sh config/12-1-agents-dans-projet-exp.env
PERMISSION_DENIEDUn rôle vous manquePartie 4
PERMISSION_DENIED à gcloud builds submitAPI Cloud Build ou compte agents-build-sa tout neufs : droits pas encore actifsAttendre 1 à 2 minutes, relancer
does not have storage.objects.get accessConstruction lancée sans --service-account=…agents-build-sa…, ou ce compte n'a pas ses 3 rôlesRefaire 7.1 ; garder l'option --service-account
STATUS … FAILURE (Cloud Build)Erreur pendant la constructionLe lien Logs are available at, ou 🔎 « Cloud Build » → Historique → la construction → journal
Service account … does not exist juste après Created service account […]Un compte tout neuf met quelques secondes à être visible pour IAM : le rôle n'a pas été donnéAttendre 10 s et relancer la boucle des rôles (ou, avec le script, relancer la même commande : il réessaie seul et ne recrée rien)
invalid build: invalid image name ""Les 4 lignes de 7.2 (K=…, IMAGE=…, SA=…, URL=…) n'ont pas été collées dans ce terminalLes coller, vérifier avec echo $IMAGE, relancer
Creating temporary archive of … avec des centaines de fichiersCommande lancée hors du dossier du projetcd $DOSSIER puis relancer (le point final = le dossier courant)
already existsDéjà créé (compte, template, dépôt)Rien à faire
ÉCHEC : réponse bloquée par Model Armor juste après le déploiementRôles du nouveau compte pas encore actifsAttendre 2 à 5 minutes, retester
ÉCHEC : 403 dans test.shVotre compte n'a pas le droit d'appeler le serviceÊtre propriétaire du projet, ou roles/run.invoker sur le service
Error code 13 (Agent Runtime)Erreur interne de GoogleRelancer la commande
Météo : « service météo indisponible (erreur 429) »Le service météo public gratuit limite les appelsRéessayer quelques minutes plus tard : l'agent le dit lui-même, rien de cassé
Service URL différente de $URLNUM_AGENTS fauxCorriger, recharger, redéployer

Journaux : 🔎 « Journaux », ou gcloud logging read 'resource.type="cloud_run_revision" AND severity>=WARNING' --project=$PROJET_AGENTS --freshness=30m --limit=10.

Et après : l'app Gemini Enterprise existe ? Remplissez PROJET_APP, NUM_APP, APP_ID dans le fichier, rechargez, puis 12-1, A5 (droits) et A6 (ajout dans l'app).

Next