Déployer et interroger à distance
Avant de lancer
-
pytestest vert (sinon, inutile de payer un déploiement) -
python local.pyfonctionne avec Vertex AI - vous avez lu la leçon Coûts et nettoyage et vous savez lancer
nettoyer.py
export GOOGLE_GENAI_USE_VERTEXAI=TRUE GOOGLE_CLOUD_PROJECT=votre-projet GOOGLE_CLOUD_LOCATION=europe-west1
python deployer.py # 5 à 15 minutes
python interroger.py # 2 sessions distantes + lecture des souvenirs
python nettoyer.py # supprime tout, puis vérifieLe déploiement
sequenceDiagram participant P as "deployer.py" participant GCS as "Bucket lab-agent-engine-memory-bank-xxxxxx" participant AE as "Agent Engine (europe-west1)" P->>GCS: "création du bucket (label formation-lab)" P->>GCS: "agent_engine.pkl, dependencies.tar.gz, requirements.txt" P->>AE: "create(display_name lab-agent-engine-memory-bank, context_spec)" AE->>AE: "construction du conteneur, installation des dépendances" AE-->>P: "projects/.../reasoningEngines/ID"
Les trois fichiers déposés dans le bucket sont l'agent sérialisé (agent_engine.pkl), le code local nécessaire (dependencies.tar.gz, qui contient agent_memoire.py) et la liste des dépendances.
Dans notre essai du 2026-10-15, le déploiement a pris un peu moins de 5 minutes. Pendant ce temps, rien n'est encore interrogeable : create() rend la main quand le conteneur est prêt.
Que contient dependencies.tar.gz dans le bucket de staging ?
Les bibliothèques PyPI sont installées à distance d'après requirements. dependencies.tar.gz transporte votre propre code (extra_packages), dont l'agent sérialisé a besoin pour être rechargé.
Interroger à distance
client.agent_engines.get(name=...) renvoie un objet dont les méthodes correspondent aux opérations exposées par AdkApp : async_create_session, async_stream_query, async_search_memory…
async def tour(distant, texte: str) -> str:
session = await distant.async_create_session(user_id=UTILISATEUR)
morceaux = []
async for ev in distant.async_stream_query(user_id=UTILISATEUR, session_id=session["id"],
message=texte):
for part in (ev.get("content") or {}).get("parts", []):
if part.get("function_call"):
print(" [outil]", part["function_call"]["name"], part["function_call"]["args"])
if part.get("text"):
morceaux.append(part["text"])
return "".join(morceaux)À distance, les événements arrivent sous forme de dictionnaires (JSON), pas d'objets Event : on lit ev["content"]["parts"].
Entre les deux sessions, on attend que Memory Bank ait fini d'extraire les souvenirs : la génération est asynchrone, elle se fait en arrière-plan après l'appel de add_session_to_memory().
for _ in range(18): # 3 minutes au plus
faits = souvenirs(client, nom) # [m.fact for m in client.agent_engines.memories.list(name=nom)]
if faits:
break
time.sleep(10)Pourquoi interroger.py attend-il avant d'ouvrir la session 2 ?
add_session_to_memory déclenche une génération asynchrone (un LLM extrait et fusionne les faits). En production, quelques secondes séparent en général deux conversations ; dans un test enchaîné, il faut attendre explicitement.
Exercice : chercher dans la mémoire sans passer par l'agent
Écrivez quelques lignes qui interrogent directement la mémoire de Camille avec la question « quel ordinateur ? », sans lancer de conversation.
Voir la solution
AdkApp expose async_search_memory, qui appelle le MemoryService (ici Memory Bank) :
import asyncio, json, vertexai
from deployer import ETAT, PROJET, REGION
async def main():
client = vertexai.Client(project=PROJET, location=REGION)
distant = client.agent_engines.get(name=json.loads(ETAT.read_text())["agent_engine"])
print(await distant.async_search_memory(user_id="camille", query="quel ordinateur ?"))
asyncio.run(main())La recherche est limitée à l'utilisateur et à l'application (app_name) : les souvenirs de Camille ne remontent jamais pour un autre user_id. En production, l'user_id doit venir de l'authentification, jamais d'un champ saisi par l'utilisateur.
Résultat obtenu
Exécution réelle le 2026-10-15 (python interroger.py, agent déployé dans europe-west1, gemini-2.5-flash), environ 1 minute au total :
Session 1 > Bonjour, je suis Camille, je travaille sur le site de Nantes avec un MacBook.
Assistant < Bonjour Camille, je prends note que vous travaillez sur le site de Nantes avec un
MacBook. Comment puis-je vous aider aujourd'hui ?
Souvenirs dans Memory Bank : ['My name is Camille, I work at the Nantes site, and I use a MacBook.']
Session 2 > Mon ordinateur ne démarre plus depuis ce matin. Tu peux créer un ticket ?
[outil] creer_ticket {'priorite': 'haute', 'sujet': "L'ordinateur de Camille (Nantes) ne démarre plus."}
Assistant < Bien sûr, je viens de créer un ticket de support pour votre problème de démarrage
d'ordinateur. Le numéro de votre ticket est IT-46114. Notre équipe va examiner cela
en priorité.Trois observations :
- le sujet du ticket de la session 2 contient « Camille (Nantes) » : l'information vient uniquement de Memory Bank, la session étant neuve ;
- Memory Bank a écrit le souvenir en anglais et à la première personne, alors que la conversation était en français : c'est le comportement par défaut observé ce jour-là ; la configuration de génération (thèmes, exemples) permet de l'orienter ;
- la recherche de l'exercice (
async_search_memory) a renvoyé ce souvenir pourcamille, et une liste vide pour un autre utilisateur (dominique).
Je sais faire
- Déployer un agent ADK sur Agent Engine et retrouver son nom de ressource
- Ouvrir une session distante et lire les événements en streaming
- Lister les souvenirs générés par Memory Bank
- Vérifier qu'une nouvelle session utilise les souvenirs d'une session précédente