Dans ce blog, je vous expliquerai comment créer un assistant de voyage multi-agents doté d'une intelligence artificielle à l'aide du nouveau kit de développement d'agent (ADK) open-source de Google. Kit de développement d'agents (ADK) de Google et la technologie A2A (Agent-to-Agent) (Agent-to-Agent).
Nous utiliserons plusieurs agents pour gérer les vols, les hôtels et les recommandations d'activités, en communiquant via des API REST et des serveurs FastAPI. Enfin, nous terminerons le tout avec un frontend Streamlit propre pour une expérience utilisateur intuitive.
Nous tenons nos lecteurs informés des dernières nouveautés en matière d'IA en leur envoyant The Median, notre lettre d'information gratuite du vendredi qui analyse les principaux sujets de la semaine. Abonnez-vous et restez à la pointe de la technologie en quelques minutes par semaine :
Qu'est-ce que le kit de développement d'agents (ADK) de Google ?
L'ADK de Google est un cadre modulaire, prêt à la production, pour la construction d'agents alimentés par LLM. Il s'agit de la même boîte à outils qui alimente les agents dans les produits Google, tels qu'Agentspace et Customer Engagement Suite. Maintenant en libre accèsil aide les développeurs à créer des applications multi-agents puissantes, flexibles et interopérables.
Pourquoi utiliser le kit de développement de l'agent (ADK) ?
ADK offre la flexibilité de Python avec des structures intégrées pour la gestion des états, les rappels, le streaming et les entrées/sorties structurées. Jetons un coup d'œil à ses principales caractéristiques :
Multi-agent by design: ADK peut composer des agents dans des flux de travail parallèles, séquentiels ou hiérarchiques.
Modèle-agnostic: Il fonctionne avec Gemini, GPT-4o, Claude, Mistral et d'autres via LiteLlm.
Modulaire et évolutif : L'utilisateur peut définir des agents spécialisés et déléguer intelligemment en utilisant l'orchestration intégrée.
Prêt pour la diffusion en continu : Il prend en charge l'interaction en temps réel, y compris l'audio/vidéo bidirectionnelle.
Outillage intégré : Il prend en charge le CLI local et l'interface web pour le débogage et l'évaluation.
Soutien au déploiement : ADK conteneurise et déploie facilement les agents dans tous les environnements.
Qu'est-ce que le protocole Agent2Agent (A2A) de Google ?
Le protocole Agent2Agent (A2A) est une norme ouverte et neutre développée par Google pour faciliter la communication et la collaboration entre les agents d'intelligence artificielle sur diverses plateformes et cadres.
Les agents ADK exposent un point d'accès HTTP standard /run et des métadonnées via .well-known/agent.json. Cela permet de découvrir les agents et de faciliter la communication entre eux (ou même avec des orchestrateurs externes comme LangGraph ou CrewAI).
Bien qu'optionnel, l'ajout du fichier de métadonnées A2A rend vos agents interopérables avec l'écosystème plus large d'outils d'agents et d'orchestrateurs.
Aperçu du projet : Planificateur de voyage alimenté par l'IA avec ADK et A2A
Ce projet construit un planificateur de voyage qui :
Prend en entrée la destination, les dates et le budget.
Appelle trois agents distincts :
flight_agent: Recommande des options de vol.
stay_agent: Trouvez des hôtels dans les limites de votre budget.
activities_agent: Suggère des activités attrayantes.
Il utilise ensuite un site central ( host_agent ) pour orchestrer toutes les demandes.
Enfin, il utilise une interface utilisateur Streamlit pour l'interaction avec l'utilisateur.
Tous les agents sont hébergés sur des serveurs FastAPI distincts et exposent un point final /run. La communication se fait par l'intermédiaire du client partagé compatible A2A.
Note : Ce projet s'exécute entièrement sur votre machine locale pour plus de simplicité, mais vous pouvez facilement déployer chaque agent et l'interface utilisateur sur des plateformes cloud telles que Render, Railway ou Google Cloud Run pour un accès évolutif.
Étape 1 : Conditions préalables
Commençons par installer les bibliothèques suivantes :
Ensuite, configurez votre clé API OpenAI - n'hésitez pas à utiliser un autre fournisseur de modèle. Pour apprendre à configurer votre clé API OpenAI, je vous recommande ce tutoriel d'introduction à l'API GPT-4o.
Avant de pouvoir construire des agents intelligents, nous devons définir un langage commun pour qu'ils puissent communiquer entre eux. Dans notre configuration, cela se fait à l'aide de :
Un schéma partagé pour l'entrée (défini par Pydantic)
Un utilitaire client REST pour appeler les agents
Un wrapper de serveur REST pour standardiser le point de terminaison /run à travers tous les agents.
Ceux-ci sont placés dans les dossiers shared/ et common/ afin de préserver la modularité du code. Examinons chacun d'entre eux.
Création d'un shared/schemas.py fichier
Nous définissons un schéma TravelRequest en utilisant Pydantic. Cela permet de s'assurer que tous les agents sont d'accord sur la structure des demandes entrantes, qui comprend la destination, les dates de voyage et le budget de l'utilisateur.
from pydantic import BaseModel
classTravelRequest(BaseModel):
destination:str
start_date:str
end_date:str
budget:floatPropulsé par
Cette classe aide à :
Maintenir la cohérence des données saisies par tous les agents.
Ajout d'une validation automatique avec FastAPI.
Simplifier la réutilisation du code.
Création d'un common/a2a_client.py fichier
Cet utilitaire asynchrone léger permet à n'importe quel agent (en particulier l'hôte) d'invoquer un autre agent utilisant le protocole A2A en appelant le point de terminaison /run.
Cet utilitaire envoie de manière asynchrone une requête POST au point de terminaison /run d'un autre agent en utilisant httpx. Il renvoie la réponse JSON analysée et soulève une erreur si la demande échoue.
Nous utiliserons cet utilitaire dans notre agent hôte pour appeler les services flight_agent, stay_agent et activities_agent.
Création d'un common/a2a_server.py fichier
Au lieu d'écrire une route FastAPI personnalisée pour chaque agent, nous la généralisons en utilisant la fonction create_app(agent), qui gère :
Servir l'agent sur /run
Réception d'une demande de voyage
Renvoi d'une réponse structurée
from fastapi import FastAPI
import uvicorn
defcreate_app(agent):
app = FastAPI()@app.post("/run")asyncdefrun(payload:dict):returnawait agent.execute(payload)return appPropulsé par
Cet utilitaire crée une application FastAPI avec une route standard /run qui délègue l'exécution à l'agent fourni. Il garantit une interface cohérente d'agent à agent (A2A) pour tous les services utilisant une entrée JSON structurée.
Ensemble, ces composants partagés rendent notre système multi-agents plus facile à entretenir, plus réutilisable et plus conforme à la philosophie A2A de Google, à savoir une messagerie inter-agents simple et structurée.
Étape 3 : Construire le système multi-agent avec ADK et A2A
Maintenant que nous avons mis en place les contrats et les services communs, commençons à construire les agents individuels. Pour transformer ce système en un véritable système modulaire et multi-agents, nous utiliserons le protocole A2A de Google, une simple interface basée sur HTTP qui permet aux agents de communiquer de manière cohérente et interopérable.
A2A (Agent-to-Agent) permet une coordination plug-and-play entre les agents, qu'il s'agisse d'agents locaux de Python ou d'agents hébergés sur des réseaux. Chaque agent expose un point de terminaison /run avec un schéma commun et agit comme un service.
Dans notre démo, nous avons quatre agents :
host_agent: Orchestrer tous les autres agents
flight_agent: Recherche de vols adaptés
stay_agent: Proposer un hébergement
activities_agent: Recommande de s'engager dans des activités locales
Tous les agents sont structurés de la même manière, avec 3 fichiers et un sous-dossier :
agents/
├── host_agent/
│ │ ├── agent.py # Optional if host logic is minimal
│ │ ├── task_manager.py # Calls other agents and aggregates responses
│ │ ├── __main__.py # Starts FastAPI app via common/a2a_server.py
│ │ └── .well-known/
│ │ └── agent.json # A2A Agent Card metadata
├── flight_agent/
├── stay_agent/
└── activities_agent/Propulsé par
Chaque agent utilise google.adk.agents.Agent, un modèle LiteLlm et Runner pour l'exécution. Commencez par créer les fichiers suivants dans le dossier activities_agent et répétez l'opération pour flight_agent et stay_agent.
Création d'un agent.py fichier
Définissons maintenant la logique de notre site activities_agent, qui sera chargé de générer des expériences locales attrayantes sur la base de l'itinéraire de voyage de l'utilisateur.
Étape 1 : Importations
Nous commençons par importer les modules essentiels pour configurer et faire fonctionner notre agent.
from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
import jsonPropulsé par
Cet agent utilise les composants de Google ADK tels que Agent, ' Runner, ' et LiteLlm et gère l'état à l'aide de InMemorySessionService.. La bibliothèque Types est utilisée pour construire des invites structurées.
Étape 2 : Agent d'activités
Nous allons maintenant instancier l'agent lui-même à l'aide de la classe Agent d'ADK.
activities_agent = Agent(
name="activities_agent",
model=LiteLlm("openai/gpt-4o"),
description="Suggests interesting activities for the user at a destination.",
instruction=("Given a destination, dates, and budget, suggest 2-3 engaging tourist or cultural activities. ""For each activity, provide a name, a short description, price estimate, and duration in hours. ""Respond in plain English. Keep it concise and well-formatted."))Propulsé par
Le paramètre instruction définit l'invite système qui guide le comportement du LLM. Bien que cet exemple utilise un anglais simple, vous pouvez adapter l'instruction pour renvoyer un JSON structuré afin de faciliter l'analyse.
Étape 3 : Gestion des sessions
Ensuite, pour garder une trace des interactions de l'utilisateur, nous configurons un cursus ainsi que des informations de session.
Le site Runner gère l'exécution de l'agent pour une session d'application donnée. La classe InMemorySessionService stocke le contexte dans la mémoire. Ensuite, nous définissons les identifiants de l'utilisateur et de la session. Toutefois, en production, ces derniers peuvent être dynamiques ou spécifiques à l'utilisateur. Cela permet de s'assurer qu'une nouvelle session ADK existe avant d'envoyer des invites à l'agent LLM.
Étape 4 : Exécution de la logique de l'agent
La fonction execute() traite les demandes entrantes, crée une invite, invoque le modèle et analyse la sortie.
asyncdefexecute(request):
session_service.create_session(
app_name="activities_app",
user_id=USER_ID,
session_id=SESSION_ID
)
prompt =(f"User is flying to {request['destination']} from {request['start_date']} to {request['end_date']}, "f"with a budget of {request['budget']}. Suggest 2-3 activities, each with name, description, price estimate, and duration. "f"Respond in JSON format using the key 'activities' with a list of activity objects.")
message = types.Content(role="user", parts=[types.Part(text=prompt)])asyncfor event in runner.run_async(user_id=USER_ID, session_id=SESSION_ID, new_message=message):if event.is_final_response():
response_text = event.content.parts[0].text
try:
parsed = json.loads(response_text)if"activities"in parsed andisinstance(parsed["activities"],list):return{"activities": parsed["activities"]}else:print("'activities' key missing or not a list in response JSON")return{"activities": response_text}# fallback to raw textexcept json.JSONDecodeError as e:print("JSON parsing failed:", e)print("Response content:", response_text)return{"activities": response_text}# fallback to raw textPropulsé par
La fonction execute() construit dynamiquement une invite à l'aide des paramètres de la demande entrante tels que la destination, les dates et le budget. Voici ce qui se passe sous le capot :
L'invite demande au modèle de renvoyer un objet JSON structuré contenant une liste d'activités.
Un objet Content est construit et transmis à ADK Runner, qui attend de manière asynchrone la réponse finale du modèle à l'aide d'un générateur de flux.
Une fois la réponse finale reçue, l'agent extrait le texte brut et tente de l'analyser en JSON.
Si l'analyse réussit et que la clé d'activité attendue existe, les données structurées sont renvoyées.
Si la clé est manquante ou malformée, la solution de repli consiste à renvoyer la réponse en texte brut afin que l'interface utilisateur dispose toujours d'une sortie utilisable.
Cette double approche garantit une dégradation progressive lorsque le LLM renvoie du texte brut au lieu de JSON structuré.
Cette stratégie améliore la robustesse et l'expérience de l'utilisateur, en particulier lorsque les résultats du modèle varient légèrement en raison de la température ou d'une interprétation rapide.
Création d'un task_manager.py fichier
Après avoir défini la logique de execute() à l'intérieur de agent.py, nous la connectons maintenant à la configuration du serveur compatible ADK à l'aide de task_manager.py.
from.agent import execute
asyncdefrun(payload):returnawait execute(payload)Propulsé par
Ce fichier agit comme une enveloppe mince autour de la fonction execute() définie précédemment. Il met la méthode run() à la disposition des modules externes, en particulier le script du serveur dans __main__.py.
Création d'un __main__.py fichier
Le fichier __main__.py lance un serveur FastAPI sur le port 8003, qui sert l'agent au point de terminaison /run.
from common.a2a_server import create_app
from.task_manager import run
app = create_app(agent=type("Agent",(),{"execute": run}))if __name__ =="__main__":import uvicorn
uvicorn.run(app, port=8003)Propulsé par
Voici ce qui se passe :
Le site create_app() (tiré de common/a2a_server.py) intègre notre agent dans une interface FastAPI standard compatible avec A2A.
Nous construisons dynamiquement un objet avec une méthode execute() afin qu'ADK puisse invoquer run() correctement.
Cette séparation nous permet de maintenir des interfaces API sans état tout en réutilisant la logique de base de l'agent.
Création d'un .well-known/agent.json fichier
Nous utilisons ce fichier JSON pour décrire l'identité et l'objectif de l'agent conformément au protocole A2A (Agent-to-Agent).
{"name":"activity_agent","description":"Agent providing activity details."}Propulsé par
Note : Bien que le fichier .well-known/agent.json ne soit pas directement utilisé par nos agents dans ce projet, il adhère à la spécification A2A et est important pour la découverte, l'introspection et la compatibilité future avec des orchestrateurs tels que LangGraph, CrewAI ou le registre d'agents de Google.
La même logique est utilisée pour flight_agent et stay_agent.
Étape 4 : Coordination avec host_agent
Le site host_agent joue le rôle de planificateur central pour la démonstration. Le site host_agent illustre le modèle de contrôleur dans les systèmes multi-agents. Il sépare la prise de décision et l'exécution, permettant à chaque agent en aval de se concentrer sur sa niche tout en centralisant la logique de coordination. Cela simplifie non seulement les tests et la mise à l'échelle, mais reflète également l'architecture réelle des microservices dans les systèmes distribués.
Il envoie la même charge utile aux trois agents à l'aide de leurs API /run et fusionne les résultats. Ajoutons les fichiers suivants au dossier host_agent.
Création d'un agent.py fichier
Commençons par les importations de base.
from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import typesPropulsé par
Ce bloc d'importation apporte tous les éléments de base nécessaires pour définir et exécuter un agent basé sur LLM à l'aide de Google ADK : la classe Agent, le wrapper LLM léger, Runner pour gérer l'exécution et la gestion de la session en mémoire.
host_agent = Agent(
name="host_agent",
model=LiteLlm("openai/gpt-4o"),
description="Coordinates travel planning by calling flight, stay, and activity agents.",
instruction="You are the host agent responsible for orchestrating trip planning tasks. ""You call external agents to gather flights, stays, and activities, then return a final result.")
session_service = InMemorySessionService()
runner = Runner(
agent=host_agent,
app_name="host_app",
session_service=session_service
)
USER_ID ="user_host"
SESSION_ID ="session_host"Propulsé par
Le code ci-dessus définit un agent ADK de haut niveau chargé de coordonner l'ensemble du plan de voyage. Bien que nous n'invoquions pas de sous-agents du LLM dans cette implémentation, l'invite du système établit le rôle pour une extension future où le LLM pourrait potentiellement gérer l'utilisation d'outils et le méta-raisonnement.
asyncdefexecute(request):# Ensure session exists
session_service.create_session(
app_name="host_app",
user_id=USER_ID,
session_id=SESSION_ID
)
prompt =(f"Plan a trip to {request['destination']} from {request['start_date']} to {request['end_date']} "f"within a total budget of {request['budget']}. Call the flights, stays, and activities agents for results.")
message = types.Content(role="user", parts=[types.Part(text=prompt)])asyncfor event in runner.run_async(user_id=USER_ID, session_id=SESSION_ID, new_message=message):if event.is_final_response():return{"summary": event.content.parts[0].text}Propulsé par
Cette fonction execute() sert de point d'entrée principal au LLM de l'agent hôte. Il :
Initialise une session (pour la prise en charge de la mémoire si nécessaire)
Construit dynamiquement une invite pour l'utilisateur
L'envoie au modèle en utilisant la fonction runner.run_async() d'ADK. method
Enfin, attend et extrait la réponse finale
Création d'un task_manager.py fichier
Le gestionnaire de tâches exécute la logique d'orchestration en appelant des agents distants et en gérant l'ensemble du processus de planification des déplacements. Pour la mise en œuvre pratique, nous définissons les URL de service pour chaque agent enfant. Ces points d'accès sont conformes au schéma JSON A2A /run protocol and expect a shared TravelRequest`.
from common.a2a_client import call_agent
FLIGHT_URL ="http://localhost:8001/run"
STAY_URL ="http://localhost:8002/run"
ACTIVITIES_URL ="http://localhost:8003/run"Propulsé par
Nous définissons maintenant la charge utile.
asyncdefrun(payload):#Print what the host agent is sendingprint("Incoming payload:", payload)
flights =await call_agent(FLIGHT_URL, payload)
stay =await call_agent(STAY_URL, payload)
activities =await call_agent(ACTIVITIES_URL, payload)# Log outputsprint("flights:", flights)print("stay:", stay)print("activities:", activities)# Ensure all are dicts before access
flights = flights ifisinstance(flights,dict)else{}
stay = stay ifisinstance(stay,dict)else{}
activities = activities ifisinstance(activities,dict)else{}return{"flights": flights.get("flights","No flights returned."),"stay": stay.get("stays","No stay options returned."),"activities": activities.get("activities","No activities found.")}Propulsé par
Cette fonction utilise la fonction d'aide call_agent() pour envoyer la charge utile à chaque service en aval et enregistre les entrées et les sorties à des fins de visibilité pendant le développement. C'est dans ce fichier que se trouve la véritable logique d'orchestration.
Création d'un __main__.py fichier
Le fichier __main__.py sert de point d'entrée au serveur FastAPI qui enveloppe l'agent hôte.
from common.a2a_server import create_app
from.task_manager import run
app = create_app(agent=type("Agent",(),{"execute": run}))if __name__ =="__main__":import uvicorn
uvicorn.run(app, port=8000)Propulsé par
Le fichier principal effectue les opérations suivantes :
Il utilise create_app() à partir de common/a2a_server.py pour générer une application FastAPI avec un point de terminaison standardisé /run.
Ensuite, il transmet un objet simple de type agent avec une méthode execute() qui délègue en interne à la fonction task_manager.run().
Enfin, il démarre le serveur FastAPI à l'aide de uvicorn sur un port spécifié (généralement 8000).
L'interface de l'agent hôte est ainsi alignée sur celle des autres agents en aval, ce qui permet de maintenir la cohérence du système.
Création d'un .well-known/agent.json fichier
Ce fichier fonctionne comme un modèle multi-agents classique dans lequel un nœud central délègue et compose des tâches.
{"name":"host_agent","description":"Coordinates travel planning among specialized agents."}Propulsé par
Bien que facultatif, il est conseillé de l'inclure dans tous les répertoires d'agents, comme expliqué précédemment.
Étape 5 : Construire l'interface utilisateur avec Streamlit
Enfin, créons une application simple où les utilisateurs peuvent entrer leurs préférences et recevoir un itinéraire structuré. Commencez par créer un fichier travel_ui.py dans le répertoire racine et ajoutez-y le code suivant.
import streamlit as st
import requestsPropulsé par
Nous importons des bibliothèques de base comme Streamlit et des demandes d'assistance pour l'interface utilisateur.
st.set_page_config(page_title="ADK-Powered Travel Planner", page_icon="✈️")
st.title("🌍 ADK-Powered Travel Planner")
origin = st.text_input("Where are you flying from?", placeholder="e.g., New York")
destination = st.text_input("Destination", placeholder="e.g., Paris")
start_date = st.date_input("Start Date")
end_date = st.date_input("End Date")
budget = st.number_input("Budget (in USD)", min_value=100, step=50)if st.button("Plan My Trip ✨"):ifnotall([origin, destination, start_date, end_date, budget]):
st.warning("Please fill in all the details.")else:
payload ={"origin": origin,"destination": destination,"start_date":str(start_date),"end_date":str(end_date),"budget": budget
}
response = requests.post("http://localhost:8000/run", json=payload)if response.ok:
data = response.json()
st.subheader("✈️ Flights")
st.markdown(data["flights"])
st.subheader("🏨 Stays")
st.markdown(data["stay"])
st.subheader("🗺️ Activities")
st.markdown(data["activities"])else:
st.error("Failed to fetch travel plan. Please try again.")Propulsé par
L'application Streamlit fournit une interface utilisateur conviviale pour interagir avec le planificateur de voyage multi-agents construit à l'aide d'ADK. Voici quelques points abordés dans le code ci-dessus.
Il utilise text_input, date_input, et number_input pour collecter l'origine, la destination, les dates et le budget.
Lorsque vous cliquez sur "Planifier mon voyage", le système valide les données saisies afin de s'assurer qu'aucun champ n'est laissé vide.
S'il est valide, il construit une charge utile JSON et envoie une requête POST à l'adresse host_agent. http://localhost:8000/run.
Le site host_agent invoque tous les agents enfants (vol, séjour, activité), regroupe leurs réponses et renvoie un plan de voyage unifié.
La réponse est analysée et affichée à l'aide de la méthode st.markdown() sous des en-têtes distincts pour les vols, les séjours et les activités.
Si le backend échoue, un message d'erreur de secours est affiché à l'aide de st.error().
Maintenant, exécutez la commande suivante dans votre terminal local :
uvicorn agents.host_agent.__main__:app --port8000&
uvicorn agents.flight_agent.__main__:app --port8001&
uvicorn agents.stay_agent.__main__:app --port8002&
uvicorn agents.activities_agent.__main__:app --port8003&
streamlit run travel_ui.pyPropulsé par
Lorsqu'un utilisateur clique sur "Planifier mon voyage", l'agent hôte prend le relais, active les agents et affiche les résultats dans l'interface utilisateur :
La structure globale de vos fichiers devrait ressembler à ceci :
Et c'est tout ! J'ai rassemblé tout ce que nous avons construit dans ce projet GitHub.
Conclusion
Avec seulement quelques applications FastAPI et des agents ADK, nous avons créé un planificateur de voyage collaboratif :
Communique via le protocole A2A
Utilise des agents LLM pour les vols, les séjours et les activités
Agrégation et affichage des résultats dans une interface utilisateur Streamlit propre.
Même si tous les agents utilisent le même modèle sous le capot, ce système a un comportement multi-agents, c'est-à-dire que les agents ont des rôles distincts, des responsabilités isolées et une communication structurée.
Je suis experte Google Developers en ML (Gen AI), triple experte Kaggle et ambassadrice Women Techmakers, avec plus de trois ans d’expérience dans la tech. J’ai cofondé une startup dans le domaine de la santé en 2020 et je poursuis actuellement un master en informatique à Georgia Tech, avec une spécialisation en apprentissage automatique.
Découvrez les principaux types d'agents d'intelligence artificielle, comment ils interagissent avec les environnements et comment ils sont utilisés dans les différents secteurs d'activité. Comprendre les agents réflexes simples, les agents basés sur un modèle, les agents basés sur un but, les agents basés sur l'utilité, les agents d'apprentissage, etc.
L'essor du développement de l'intelligence artificielle (IA) a entraîné une augmentation notable de la demande en matière de calcul, d'où la nécessité de disposer de solutions matérielles robustes. Les unités de traitement graphique (GPU) et les unités de traitement tensoriel (TPU) sont devenues des technologies essentielles pour répondre à ces demandes.
Apprenez l'essentiel de l'architecture d'un entrepôt de données, des composants clés aux meilleures pratiques, pour construire un système de données évolutif et efficace !
Apprenez à utiliser JSON en Python, notamment la sérialisation, la désérialisation, le formatage, l'optimisation des performances, la gestion des API, ainsi que les limites et les alternatives de JSON.
Dans ce blog, je vous expliquerai comment créer un assistant de voyage multi-agents doté d'une intelligence artificielle à l'aide du nouveau kit de développement d'agent (ADK) open-source de Google. Kit de développement d'agents (ADK) de Google et la technologie A2A (Agent-to-Agent) (Agent-to-Agent).
Nous utiliserons plusieurs agents pour gérer les vols, les hôtels et les recommandations d'activités, en communiquant via des API REST et des serveurs FastAPI. Enfin, nous terminerons le tout avec un frontend Streamlit propre pour une expérience utilisateur intuitive.
Nous tenons nos lecteurs informés des dernières nouveautés en matière d'IA en leur envoyant The Median, notre lettre d'information gratuite du vendredi qui analyse les principaux sujets de la semaine. Abonnez-vous et restez à la pointe de la technologie en quelques minutes par semaine :
Qu'est-ce que le kit de développement d'agents (ADK) de Google ?
L'ADK de Google est un cadre modulaire, prêt à la production, pour la construction d'agents alimentés par LLM. Il s'agit de la même boîte à outils qui alimente les agents dans les produits Google, tels qu'Agentspace et Customer Engagement Suite. Maintenant en libre accèsil aide les développeurs à créer des applications multi-agents puissantes, flexibles et interopérables.
Pourquoi utiliser le kit de développement de l'agent (ADK) ?
ADK offre la flexibilité de Python avec des structures intégrées pour la gestion des états, les rappels, le streaming et les entrées/sorties structurées. Jetons un coup d'œil à ses principales caractéristiques :
LiteLlm.Qu'est-ce que le protocole Agent2Agent (A2A) de Google ?
Le protocole Agent2Agent (A2A) est une norme ouverte et neutre développée par Google pour faciliter la communication et la collaboration entre les agents d'intelligence artificielle sur diverses plateformes et cadres.
Les agents ADK exposent un point d'accès HTTP standard
/runet des métadonnées via.well-known/agent.json. Cela permet de découvrir les agents et de faciliter la communication entre eux (ou même avec des orchestrateurs externes comme LangGraph ou CrewAI).Bien qu'optionnel, l'ajout du fichier de métadonnées A2A rend vos agents interopérables avec l'écosystème plus large d'outils d'agents et d'orchestrateurs.
Aperçu du projet : Planificateur de voyage alimenté par l'IA avec ADK et A2A
Ce projet construit un planificateur de voyage qui :
flight_agent: Recommande des options de vol.stay_agent: Trouvez des hôtels dans les limites de votre budget.activities_agent: Suggère des activités attrayantes.host_agent) pour orchestrer toutes les demandes.Tous les agents sont hébergés sur des serveurs FastAPI distincts et exposent un point final
/run. La communication se fait par l'intermédiaire du client partagé compatible A2A.Note : Ce projet s'exécute entièrement sur votre machine locale pour plus de simplicité, mais vous pouvez facilement déployer chaque agent et l'interface utilisateur sur des plateformes cloud telles que Render, Railway ou Google Cloud Run pour un accès évolutif.
Étape 1 : Conditions préalables
Commençons par installer les bibliothèques suivantes :
Ensuite, configurez votre clé API OpenAI - n'hésitez pas à utiliser un autre fournisseur de modèle. Pour apprendre à configurer votre clé API OpenAI, je vous recommande ce tutoriel d'introduction à l'API GPT-4o.
Étape 2 : Schéma et utilitaires partagés
Avant de pouvoir construire des agents intelligents, nous devons définir un langage commun pour qu'ils puissent communiquer entre eux. Dans notre configuration, cela se fait à l'aide de :
/runà travers tous les agents.Ceux-ci sont placés dans les dossiers
shared/etcommon/afin de préserver la modularité du code. Examinons chacun d'entre eux.Création d'un
shared/schemas.pyfichierNous définissons un schéma
TravelRequesten utilisant Pydantic. Cela permet de s'assurer que tous les agents sont d'accord sur la structure des demandes entrantes, qui comprend la destination, les dates de voyage et le budget de l'utilisateur.Cette classe aide à :
Création d'un
common/a2a_client.pyfichierCet utilitaire asynchrone léger permet à n'importe quel agent (en particulier l'hôte) d'invoquer un autre agent utilisant le protocole A2A en appelant le point de terminaison
/run.Cet utilitaire envoie de manière asynchrone une requête POST au point de terminaison
/rund'un autre agent en utilisanthttpx. Il renvoie la réponse JSON analysée et soulève une erreur si la demande échoue.Nous utiliserons cet utilitaire dans notre agent hôte pour appeler les services
flight_agent,stay_agentetactivities_agent.Création d'un
common/a2a_server.pyfichierAu lieu d'écrire une route FastAPI personnalisée pour chaque agent, nous la généralisons en utilisant la fonction
create_app(agent), qui gère :/runCet utilitaire crée une application FastAPI avec une route standard
/runqui délègue l'exécution à l'agent fourni. Il garantit une interface cohérente d'agent à agent (A2A) pour tous les services utilisant une entrée JSON structurée.Ensemble, ces composants partagés rendent notre système multi-agents plus facile à entretenir, plus réutilisable et plus conforme à la philosophie A2A de Google, à savoir une messagerie inter-agents simple et structurée.
Étape 3 : Construire le système multi-agent avec ADK et A2A
Maintenant que nous avons mis en place les contrats et les services communs, commençons à construire les agents individuels. Pour transformer ce système en un véritable système modulaire et multi-agents, nous utiliserons le protocole A2A de Google, une simple interface basée sur HTTP qui permet aux agents de communiquer de manière cohérente et interopérable.
A2A (Agent-to-Agent) permet une coordination plug-and-play entre les agents, qu'il s'agisse d'agents locaux de Python ou d'agents hébergés sur des réseaux. Chaque agent expose un point de terminaison
/runavec un schéma commun et agit comme un service.Dans notre démo, nous avons quatre agents :
host_agent: Orchestrer tous les autres agentsflight_agent: Recherche de vols adaptésstay_agent: Proposer un hébergementactivities_agent: Recommande de s'engager dans des activités localesTous les agents sont structurés de la même manière, avec 3 fichiers et un sous-dossier :
Chaque agent utilise
google.adk.agents.Agent, un modèleLiteLlmetRunnerpour l'exécution. Commencez par créer les fichiers suivants dans le dossieractivities_agentet répétez l'opération pourflight_agentetstay_agent.Création d'un
agent.pyfichierDéfinissons maintenant la logique de notre site
activities_agent, qui sera chargé de générer des expériences locales attrayantes sur la base de l'itinéraire de voyage de l'utilisateur.Étape 1 : Importations
Nous commençons par importer les modules essentiels pour configurer et faire fonctionner notre agent.
Cet agent utilise les composants de Google ADK tels que
Agent, 'Runner, ' etLiteLlmet gère l'état à l'aide deInMemorySessionService.. La bibliothèqueTypesest utilisée pour construire des invites structurées.Étape 2 : Agent d'activités
Nous allons maintenant instancier l'agent lui-même à l'aide de la classe Agent d'ADK.
Le paramètre instruction définit l'invite système qui guide le comportement du LLM. Bien que cet exemple utilise un anglais simple, vous pouvez adapter l'instruction pour renvoyer un JSON structuré afin de faciliter l'analyse.
Étape 3 : Gestion des sessions
Ensuite, pour garder une trace des interactions de l'utilisateur, nous configurons un cursus ainsi que des informations de session.
Le site
Runnergère l'exécution de l'agent pour une session d'application donnée. La classeInMemorySessionServicestocke le contexte dans la mémoire. Ensuite, nous définissons les identifiants de l'utilisateur et de la session. Toutefois, en production, ces derniers peuvent être dynamiques ou spécifiques à l'utilisateur. Cela permet de s'assurer qu'une nouvelle session ADK existe avant d'envoyer des invites à l'agent LLM.Étape 4 : Exécution de la logique de l'agent
La fonction
execute()traite les demandes entrantes, crée une invite, invoque le modèle et analyse la sortie.La fonction
execute()construit dynamiquement une invite à l'aide des paramètres de la demande entrante tels que la destination, les dates et le budget. Voici ce qui se passe sous le capot :Contentest construit et transmis à ADK Runner, qui attend de manière asynchrone la réponse finale du modèle à l'aide d'un générateur de flux.Cette stratégie améliore la robustesse et l'expérience de l'utilisateur, en particulier lorsque les résultats du modèle varient légèrement en raison de la température ou d'une interprétation rapide.
Création d'un
task_manager.pyfichierAprès avoir défini la logique de
execute()à l'intérieur deagent.py, nous la connectons maintenant à la configuration du serveur compatible ADK à l'aide detask_manager.py.Ce fichier agit comme une enveloppe mince autour de la fonction
execute()définie précédemment. Il met la méthoderun()à la disposition des modules externes, en particulier le script du serveur dans__main__.py.Création d'un
__main__.pyfichierLe fichier
__main__.pylance un serveur FastAPI sur le port 8003, qui sert l'agent au point de terminaison/run.Voici ce qui se passe :
create_app()(tiré de common/a2a_server.py) intègre notre agent dans une interface FastAPI standard compatible avec A2A.execute()afin qu'ADK puisse invoquerrun()correctement.Création d'un
.well-known/agent.jsonfichierNous utilisons ce fichier JSON pour décrire l'identité et l'objectif de l'agent conformément au protocole A2A (Agent-to-Agent).
Note : Bien que le fichier
.well-known/agent.jsonne soit pas directement utilisé par nos agents dans ce projet, il adhère à la spécification A2A et est important pour la découverte, l'introspection et la compatibilité future avec des orchestrateurs tels que LangGraph, CrewAI ou le registre d'agents de Google.La même logique est utilisée pour
flight_agentetstay_agent.Étape 4 : Coordination avec
host_agentLe site
host_agentjoue le rôle de planificateur central pour la démonstration. Le sitehost_agentillustre le modèle de contrôleur dans les systèmes multi-agents. Il sépare la prise de décision et l'exécution, permettant à chaque agent en aval de se concentrer sur sa niche tout en centralisant la logique de coordination. Cela simplifie non seulement les tests et la mise à l'échelle, mais reflète également l'architecture réelle des microservices dans les systèmes distribués.Il envoie la même charge utile aux trois agents à l'aide de leurs API
/runet fusionne les résultats. Ajoutons les fichiers suivants au dossierhost_agent.Création d'un
agent.pyfichierCommençons par les importations de base.
Ce bloc d'importation apporte tous les éléments de base nécessaires pour définir et exécuter un agent basé sur LLM à l'aide de Google ADK : la classe
Agent, le wrapper LLM léger,Runnerpour gérer l'exécution et la gestion de la session en mémoire.Le code ci-dessus définit un agent ADK de haut niveau chargé de coordonner l'ensemble du plan de voyage. Bien que nous n'invoquions pas de sous-agents du LLM dans cette implémentation, l'invite du système établit le rôle pour une extension future où le LLM pourrait potentiellement gérer l'utilisation d'outils et le méta-raisonnement.
Cette fonction
execute()sert de point d'entrée principal au LLM de l'agent hôte. Il :methodCréation d'un
task_manager.pyfichierLe gestionnaire de tâches exécute la logique d'orchestration en appelant des agents distants et en gérant l'ensemble du processus de planification des déplacements. Pour la mise en œuvre pratique, nous définissons les URL de service pour chaque agent enfant. Ces points d'accès sont conformes au schéma JSON A2A /run
protocol and expect a sharedTravelRequest`.Nous définissons maintenant la charge utile.
Cette fonction utilise la fonction d'aide
call_agent()pour envoyer la charge utile à chaque service en aval et enregistre les entrées et les sorties à des fins de visibilité pendant le développement. C'est dans ce fichier que se trouve la véritable logique d'orchestration.Création d'un
__main__.pyfichierLe fichier
__main__.pysert de point d'entrée au serveur FastAPI qui enveloppe l'agent hôte.Le fichier principal effectue les opérations suivantes :
create_app()à partir decommon/a2a_server.pypour générer une application FastAPI avec un point de terminaison standardisé/run.execute()qui délègue en interne à la fonctiontask_manager.run().uvicornsur un port spécifié (généralement 8000).L'interface de l'agent hôte est ainsi alignée sur celle des autres agents en aval, ce qui permet de maintenir la cohérence du système.
Création d'un
.well-known/agent.jsonfichierCe fichier fonctionne comme un modèle multi-agents classique dans lequel un nœud central délègue et compose des tâches.
Bien que facultatif, il est conseillé de l'inclure dans tous les répertoires d'agents, comme expliqué précédemment.
Étape 5 : Construire l'interface utilisateur avec Streamlit
Enfin, créons une application simple où les utilisateurs peuvent entrer leurs préférences et recevoir un itinéraire structuré. Commencez par créer un fichier
travel_ui.pydans le répertoire racine et ajoutez-y le code suivant.Nous importons des bibliothèques de base comme Streamlit et des demandes d'assistance pour l'interface utilisateur.
L'application Streamlit fournit une interface utilisateur conviviale pour interagir avec le planificateur de voyage multi-agents construit à l'aide d'ADK. Voici quelques points abordés dans le code ci-dessus.
text_input,date_input, etnumber_inputpour collecter l'origine, la destination, les dates et le budget.host_agent.http://localhost:8000/run.host_agentinvoque tous les agents enfants (vol, séjour, activité), regroupe leurs réponses et renvoie un plan de voyage unifié.st.markdown()sous des en-têtes distincts pour les vols, les séjours et les activités.st.error().Maintenant, exécutez la commande suivante dans votre terminal local :
Lorsqu'un utilisateur clique sur "Planifier mon voyage", l'agent hôte prend le relais, active les agents et affiche les résultats dans l'interface utilisateur :
La structure globale de vos fichiers devrait ressembler à ceci :
Et c'est tout ! J'ai rassemblé tout ce que nous avons construit dans ce projet GitHub.
Conclusion
Avec seulement quelques applications FastAPI et des agents ADK, nous avons créé un planificateur de voyage collaboratif :
Même si tous les agents utilisent le même modèle sous le capot, ce système a un comportement multi-agents, c'est-à-dire que les agents ont des rôles distincts, des responsabilités isolées et une communication structurée.
Voici quelques ressources pour commencer :