Créer des agents IA avec ADK : orchestrer des workflows de graphes

1. Présentation

Pour répondre à une demande de voyage comportant plusieurs contraintes (par exemple, planifier une excursion d'une journée à Kyoto pour 100 $, avec des temples historiques, des ramens locaux et aucun musée d'art moderne), il faut extraire les préférences structurées, rechercher des lieux simultanément, synthétiser un projet détaillé et vérifier le coût total avant de répondre. Dans ADK 1.x, l'orchestration de ces étapes nécessitait d'imbriquer les wrappers SequentialAgent, ParallelAgent et LoopAgent, d'enregistrer chaque sortie intermédiaire dans l'état de la session et d'appeler un appel d'outil LLM supplémentaire juste pour quitter une boucle d'affinage.

Dans cet atelier de programmation, vous allez créer un planificateur de voyage multi-agent sur Agent Platform à l'aide des workflows de graphe (Workflow) d'Agent Development Kit (ADK) 2. En trois étapes progressives, vous allez connecter des nœuds Agent spécialisés (optimisés par gemini-3.8-flash) dans une chaîne d'arêtes séquentielle (node_input), déployer des chercheurs google_search simultanés synchronisés avec JoinNode, et appliquer des règles de budget et des règles exclusives avec un routeur Python déterministe (Event(route=...)) qui ignore l'affinage chaque fois que le brouillon initial passe l'audit.

Prérequis

Objectifs

  • Comment déclarer un pipeline multi-agent dans ADK 2 à l'aide de tuples de périphérie Workflow
  • Comment ADK 2 transmet les sorties directement le long des bords en tant que node_input et lie les clés d'état de session en tant que paramètres de fonction
  • Comment déployer des branches de recherche simultanées et fusionner leurs résultats avec JoinNode
  • Comment router de manière déterministe des cycles de validation à quatre yeux limités en Python avec Event(route=...)
  • Comment inspecter les graphiques de workflows compilés, les chronologies d'exécution parallèle et les deltas d'état dans l'UI Web d'ADK

Ce dont vous avez besoin

  • Un compte Google (utilisez un compte @gmail.com personnel si vous demandez des crédits pour l'atelier)
  • Un lien de crédit d'atelier fourni par votre formateur (ainsi que l'appareil photo d'un téléphone pour scanner le QR code) ou un compte de facturation Cloud actif
  • Google Chrome (nous vous recommandons d'utiliser une fenêtre de navigation privée pour éviter de mélanger vos comptes personnel et professionnel)

2. Profiter de crédits Google Cloud (facultatif)

Si vous participez à un atelier avec un lien de crédit d'événement, demandez votre crédit Google Developer Program pour provisionner un compte de facturation sans carte de crédit.

Demander votre crédit pour l'événement

  1. Ouvrez le lien du crédit de l'atelier dans une fenêtre de navigation privée et connectez-vous avec votre compte @gmail.com.
  2. Sur la page Demander votre avantage, cliquez sur Demander un crédit :

Carte "Profitez de votre avantage" du Google Builders Hub, avec le bouton "Profiter du crédit"

  1. Si vous êtes invité à créer un profil Google Developer Program, remplissez le formulaire.
  2. Lorsque l'option Scanner pour confirmer que vous êtes une personne s'affiche, scannez le QR code avec votre téléphone et effectuez la validation (actualisez la page et cliquez à nouveau sur Demander un crédit si le QR code ne s'affiche pas) :

Boîte de dialogue du QR code "Scannez pour confirmer que vous êtes une personne" du Google Developer Program

  1. Vérifiez que le message Votre demande de crédit pour l'événement a bien été validée ! s'affiche, puis cliquez sur Ouvrir le compte de facturation :

Google Builders Hub affichant le message "Votre demande de crédit pour l'événement a bien été validée" et le bouton "Ouvrir le compte de facturation"

🔍 Vérifiez votre travail

La configuration du compte de facturation prend jusqu'à trois minutes :

  1. Ouvrez Google Cloud Billing (ou copiez l'URL dans votre fenêtre de navigation privée), puis sélectionnez Vos comptes de facturation :
https://console.cloud.google.com/billing
  1. Actualisez la page jusqu'à ce que l'état de votre compte GDP Credit soit Actif :

Gestion des comptes de facturation Google Cloud affichant un compte de facturation de crédit GDP actif

3. Créer un projet Google Cloud (facultatif)

Créez un projet Google Cloud dédié afin que toutes les ressources de cet atelier de programmation restent isolées et faciles à nettoyer.

  1. Ouvrez Créer un projet (ou copiez l'URL dans votre fenêtre de navigation privée) :
https://console.cloud.google.com/projectcreate
  1. Saisissez les détails de votre projet :
    • Nom du projet : par exemple, google-cloud-workshop
    • Compte de facturation (si affiché) : sélectionnez GDP Credit (ou votre compte de facturation actif).
    • Ressource parente : Aucune organisation (ou sélectionnez votre organisation si nécessaire)
  2. Notez l'ID du projet généré sous le nom du projet, puis cliquez sur Créer :

Écran "Créer un projet Google Cloud" affichant le nom du projet, l'ID du projet, la ressource parente et le bouton "Créer"

🔍 Vérifiez votre travail

Cliquez sur Notifications dans la barre d'outils en haut à droite, puis sur Sélectionner un projet une fois la création du projet terminée :

Menu "Notifications" de la console Google Cloud affichant "Créer un projet" et le lien "Sélectionner un projet"

4. Configurer votre environnement

Configurez Google Cloud Shell, activez l'API Agent Platform et créez un environnement virtuel Python 3.12 isolé avec uv.

Configurer Cloud Shell

  1. Cliquez sur Activer Cloud Shell (>_) dans la barre d'outils de la console Google Cloud ou ouvrez directement Google Cloud Shell (ou copiez l'URL dans votre fenêtre de navigation privée) :
https://shell.cloud.google.com/?show=ide,terminal

Bouton "Activer Cloud Shell" dans la barre d'outils de la console Google Cloud

  1. Si vous y êtes invité, cliquez sur Autoriser :

Boîte de dialogue "Autoriser Cloud Shell"

  1. Sélectionnez l'ID de votre projet Google Cloud actif dans le menu numéroté de votre terminal :
unset CLOUDSDK_CORE_PROJECT
PS3="Select your project (e.g. 1): "
select PROJECT_ID in $(gcloud projects list --format="value(projectId)"); do
  [ -n "$PROJECT_ID" ] && gcloud config set project "$PROJECT_ID" && break
done

Un résultat semblable à celui-ci s'affiche (les projets sans tag affichent également une ligne d'informations [environment: untagged]) :

1) google-cloud-workshop-4210
2) my-cloud-project-8812
Select your project (e.g. 1): 1
Updated property [core/project].

Vérifiez que l'ID de projet sélectionné apparaît en jaune dans l'invite Cloud Shell :

Terminal Cloud Shell affichant l'ID du projet sélectionné en jaune

Activer les API requises

Activez l'API Agent Platform pour que vos agents ADK puissent appeler des modèles Gemini :

gcloud services enable aiplatform.googleapis.com

Un résultat semblable à celui-ci s'affiche :

Operation "operations/acat.p2-..." finished successfully.

Créer un environnement virtuel Python et installer ADK

Créez l'espace de travail ~/adk-graph-agents et activez un environnement virtuel Python 3.12 :

cd ~
mkdir -p adk-graph-agents && cd ~/adk-graph-agents

which uv >/dev/null 2>&1 || curl -LsSf https://astral.sh/uv/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"

uv venv .venv --python 3.12
source .venv/bin/activate

Vérifiez que le préfixe (.venv) s'affiche au début de l'invite de votre terminal :

Terminal Cloud Shell affichant le préfixe .venv sur un environnement virtuel Python actif

Installez ADK 2 dans l'environnement virtuel actif :

uv pip install --no-cache "google-adk==2.14.0"

🔍 Vérifiez votre travail

Vérifiez la version de la CLI adk installée :

adk --version

Un résultat semblable à celui-ci s'affiche :

adk, version 2.14.0

5. Créer le squelette du planificateur de voyage

Générez le package de démarrage travel_planner avec adk create et testez la référence par défaut à agent unique dans adk web.

Générer le package de démarrage

Exécutez adk create à partir de ~/adk-graph-agents :

cd ~/adk-graph-agents
adk create travel_planner

Sélectionnez les options suivantes lorsque vous y êtes invité (si vous êtes invité à saisir Enable telemetry? [Y/n]: lors de la première exécution, appuyez sur Entrée ou saisissez n, puis appuyez sur Entrée) :

  1. Choisissez un modèle pour l'agent racine : saisissez 2 pour sélectionner gemini-3.8-flash (l'option 1 sélectionne gemini-3.5-flash), puis appuyez sur Entrée.
  2. Choisissez un backend : saisissez 2 pour sélectionner le backend Agent Platform de Google Cloud (option 2 dans le menu de la CLI ci-dessous), puis appuyez sur Entrée.
  3. Saisissez l'ID du projet Google Cloud : appuyez sur Entrée pour accepter l'ID du projet détecté entre crochets.
  4. Saisissez la région Google Cloud : saisissez global (pour utiliser le point de terminaison Gemini global) et appuyez sur Entrée.

adk create écrit GOOGLE_GENAI_USE_ENTERPRISE=1, l'ID de votre projet et GOOGLE_CLOUD_LOCATION=global dans travel_planner/.env, de sorte que vos identifiants restent intacts lorsque vous remplacez agent.py ultérieurement.

Un résultat semblable à celui-ci s'affiche :

Choose a model for the root agent:
1. gemini-3.5-flash
2. gemini-3.8-flash
3. Other models (fill later)
Choose model (1, 2, 3): 2
1. Google AI
2. Vertex AI
3. Login with Google
Choose a backend (1, 2, 3): 2

You need an existing Google Cloud account and project, check out this link for details:
https://google.github.io/adk-docs/get-started/quickstart/#gemini---google-cloud-vertex-ai

Enter Google Cloud project ID [google-cloud-workshop-4210]:
Enter Google Cloud region [us-central1]: global

Agent created in /home/your_username/adk-graph-agents/travel_planner:
- .env
- .gitignore
- __init__.py
- agent.py

⚠️  WARNING: Secrets (like GOOGLE_API_KEY) are stored in .env.

Next steps:
- Chat with your agent in the terminal: adk run travel_planner
- Or in the browser: adk web .
- Have your coding agent evaluate and deploy it: uvx google-agents-cli setup
  (other install options: https://adk.dev/get-started/agents-cli/)

Ouvrez ~/adk-graph-agents dans l'éditeur de code Cloud Shell :

which cloudshell >/dev/null 2>&1 && cloudshell workspace ~/adk-graph-agents || true

Réactivez votre environnement virtuel dans le terminal actualisé :

cd ~/adk-graph-agents
source .venv/bin/activate

Tester l'agent unique de démarrage

Démarrez l'UI Web ADK pour observer comment un seul agent de démarrage non orchestré répond à une requête de voyage :

cd ~/adk-graph-agents
adk web --allow_origins "*"

Cliquez sur l'icône Aperçu sur le Web dans la barre d'outils Cloud Shell en haut à droite, sélectionnez Modifier le port, saisissez 8000, puis cliquez sur Modifier et prévisualiser :

Boîte de dialogue de configuration du port d'aperçu sur le Web de Cloud Shell définie sur 8000

🔍 Vérifiez votre travail

Sélectionnez travel_planner dans le menu déroulant en haut à gauche de adk web, puis envoyez "Help me plan a trip to Japan" :

UI Web de développement ADK montrant une conversation de base avec un seul agent

Une réponse conversationnelle en une seule passe devrait s'afficher dans le volet de chat (avec un seul appel root_agent dans Événements) :

root_agent -> responds in one pass without structured preference extraction, live search, or budget verification

Appuyez sur Ctrl + C dans votre terminal Cloud Shell pour arrêter adk web avant de modifier des fichiers à l'étape suivante.

6. Créer un workflow de graphe linéaire

Créez votre premier ADK 2 Workflow : une chaîne séquentielle reliant le point d'entrée réservé "START" à user_profiler_agent et itinerary_synthesizer_agent (tout nœud sans arête sortante agit comme un nœud terminal). Chaque périphérie (a, b) exécute automatiquement les nœuds Agent (un alias pour LlmAgent) en mode single_turn isolé et fournit la sortie du nœud a en tant que node_input (le message utilisateur entrant) au nœud b, tandis que {user_preferences} dans une chaîne d'instructions interpole la clé d'état de session correspondante enregistrée via output_key.

Diagramme de l'architecture montrant travel_workflow (Workflow) connectant START à user_profiler_agent et itinerary_synthesizer_agent

Créer les premiers spécialistes

Assurez-vous que adk web est arrêté (Ctrl + C), puis ouvrez un nouveau fichier nommé travel_planner/specialists.py :

cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py

Collez le code suivant dans travel_planner/specialists.py pour définir user_profiler_agent et itinerary_synthesizer_agent (en important google_search au préalable pour l'étape suivante) :

from google.adk import Agent
from google.adk.tools import google_search

MODEL = "gemini-3.8-flash"

# --- Specialist 1: The User Profiler ---
user_profiler_agent = Agent(
    model=MODEL,
    name="user_profiler_agent",
    description="Extracts travel preferences and constraints from user input.",
    instruction="""
        Extract destination, duration (default 1 day), budget, interests, and exclusions.
        Return a single JSON object with keys: "destination", "duration", "budget", "interests", "exclusions".
    """,
    output_key="user_preferences",  # Saved for multi-hop constraints downstream
)

# --- Specialist 2: The Synthesizer ---
itinerary_synthesizer_agent = Agent(
    model=MODEL,
    name="itinerary_synthesizer_agent",
    description="Compiles preferences and research into a final Markdown itinerary.",
    instruction="""
        You are an elite Travel Concierge. Using the incoming input and
        User Preferences ({user_preferences}), write a Markdown itinerary
        with an itemized USD and local currency cost breakdown.
    """,
    output_key="final_itinerary",
)

Définir la chaîne de périphérie séquentielle

Ouvrez un nouveau fichier nommé travel_planner/workflows.py :

cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py

Collez la définition Workflow suivante (où un tuple de trois nœuds ou plus est compilé en une chaîne séquentielle à partir de "START") :

from google.adk import Workflow
from .specialists import (
    itinerary_synthesizer_agent,
    user_profiler_agent,
)

# 1. SEQUENTIAL GRAPH: START -> user_profiler_agent -> itinerary_synthesizer_agent
travel_workflow = Workflow(
    name="travel_workflow",
    description="Orchestrates the end-to-end travel planning process as a graph workflow.",
    edges=[
        ("START", user_profiler_agent, itinerary_synthesizer_agent),
    ],
)

Exposer le workflow en tant que root_agent

Ouvrez travel_planner/agent.py :

cloudshell edit ~/adk-graph-agents/travel_planner/agent.py

Remplacez l'intégralité du contenu de travel_planner/agent.py par ces deux lignes :

from .workflows import travel_workflow

root_agent = travel_workflow

🔍 Vérifiez votre travail

Démarrez adk web à partir de ~/adk-graph-agents :

cd ~/adk-graph-agents
adk web --allow_origins "*"

Ouvrez l'aperçu sur le Web sur le port 8000, cliquez sur + Nouvelle session, puis envoyez :

Help me plan a trip to Kyoto

Dans la vue Événements, vous devriez voir une séquence d'événements semblable à celle-ci :

1. user_profiler_agent -> outputs JSON {"destination": "Kyoto", "duration": "1 day", ...} and writes state["user_preferences"]
2. itinerary_synthesizer_agent -> receives preferences via node_input and outputs the Markdown itinerary

UI Web d'ADK 2.14.0 montrant l'exécution de graphe de START à user_profiler_agent, puis à itinerary_synthesizer_agent, et l'itinéraire généré pour Kyoto

Cliquez sur un événement dans Événements, puis sur l'icône Graphique (account_tree dans la barre d'outils des détails de l'événement) pour inspecter la topologie START -> user_profiler_agent -> itinerary_synthesizer_agent compilée. Ensuite, vérifiez l'onglet État pour vous assurer que user_preferences et final_itinerary sont renseignés.

Appuyez sur Ctrl + C dans votre terminal pour arrêter adk web avant de continuer.

7. Distribution et jointure avec JoinNode

Ancrez l'itinéraire dans les données Web en direct en ajoutant deux spécialistes google_search simultanés (activity_finder_agent et restaurant_finder_agent) et en les synchronisant avec JoinNode :

  • Tuple de distribution : placer (activity_finder_agent, restaurant_finder_agent) dans le tuple de périphérie fournit la sortie de user_profiler_agent en tant que node_input aux deux chercheurs simultanément.
  • Barrière de fan-in (JoinNode) : placer JoinNode(name="research_join") juste après le tuple attend que chaque branche entrante se termine et transmet un dict fusionné ({"activity_finder_agent": ..., "restaurant_finder_agent": ...}) en tant que node_input à itinerary_synthesizer_agent au lieu de déclencher la synthèse deux fois.

Diagramme d'architecture montrant travel_workflow se déployant de user_profiler_agent via node_input vers activity_finder_agent et restaurant_finder_agent en parallèle, fusionnant au niveau de research_join (JoinNode) et transmettant node_input (dict) à itinerary_synthesizer_agent

Ajouter les spécialistes de la recherche

Vérifiez que adk web est arrêté (Ctrl + C), puis ouvrez travel_planner/specialists.py :

cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py

Ajoutez activity_finder_agent et restaurant_finder_agent en bas de travel_planner/specialists.py (aucun des deux n'a besoin de output_key, car research_join transfère les deux sorties directement via node_input) :

# --- Specialist 3: The Activity Finder ---
activity_finder_agent = Agent(
    model=MODEL,
    name="activity_finder_agent",
    description="Finds 3 attractions matching the user's destination and interests.",
    instruction="""
        Using the travel preferences in the input, call google_search to find 3 specific attractions
        (including budget-friendly options).
        Return a JSON list with keys: "attraction_name", "estimated_cost_local", "estimated_cost_usd", "notes".
    """,
    tools=[google_search],
)

# --- Specialist 4: The Restaurant Finder ---
restaurant_finder_agent = Agent(
    model=MODEL,
    name="restaurant_finder_agent",
    description="Finds 3 restaurants matching the destination and budget.",
    instruction="""
        Using the travel preferences in the input, call google_search to find 3 highly-rated restaurants
        across price points.
        Return a JSON list with keys: "restaurant_name", "cuisine", "estimated_cost_local", "estimated_cost_usd".
    """,
    tools=[google_search],
)

Ajouter une distribution et un JoinNode à workflows.py

Ouvrez travel_planner/workflows.py :

cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py

Remplacez l'intégralité du contenu de travel_planner/workflows.py par le graphique de distribution et JoinNode :

from google.adk import Workflow
from google.adk.workflow import JoinNode
from .specialists import (
    activity_finder_agent,
    itinerary_synthesizer_agent,
    restaurant_finder_agent,
    user_profiler_agent,
)

research_join = JoinNode(name="research_join")

# 2. FAN-OUT / FAN-IN GRAPH: Profile -> (Activities || Restaurants) -> Join -> Synthesize
travel_workflow = Workflow(
    name="travel_workflow",
    description="Orchestrates the end-to-end travel planning process as a graph workflow.",
    edges=[
        (
            "START",
            user_profiler_agent,
            (activity_finder_agent, restaurant_finder_agent),
            research_join,
            itinerary_synthesizer_agent,
        ),
    ],
)

🔍 Vérifiez votre travail

Démarrez adk web pour tester la recherche simultanée et la synchronisation JoinNode :

cd ~/adk-graph-agents
adk web --allow_origins "*"

Ouvrez l'aperçu sur le Web sur le port 8000, cliquez sur + Nouvelle session, puis envoyez :

Help me plan a trip to Kyoto focused on historic temples and ramen

Dans la vue Événements, vous devriez voir une séquence d'événements semblable à celle-ci :

1. user_profiler_agent -> emits JSON preferences via node_input
2. activity_finder_agent & restaurant_finder_agent -> invoke google_search concurrently
3. research_join -> merges both researcher outputs into one dict node_input
4. itinerary_synthesizer_agent -> drafts final_itinerary from the merged dict + {user_preferences}

Appuyez sur Ctrl + C dans votre terminal pour arrêter adk web avant de continuer.

8. Cycles de révision des routes

Appliquez des contraintes de budget et des contraintes négatives en ajoutant un itinerary_critic_agent, un itinerary_refiner_agent et deux nœuds de fonction Python déterministes (route_critique et finalize_itinerary) qui renvoient des objets ADK Event :

  • route : sélectionne la clé de branche nommée dans un dictionnaire d'arêtes ({"revise": ..., "approved": ...}) qui s'exécute ensuite.
  • output : transmet une valeur ou une chaîne Python typée le long de l'arête en tant que node_input au nœud suivant sans afficher de message de chat.
  • message et state : message émet du texte visible par l'utilisateur dans la transcription du chat, tandis que state valide les mises à jour de clé-valeur (stateDelta) dans l'état de la session.

Diagramme d'architecture montrant travel_workflow avec itinerary_critic_agent qui alimente route_critique, qui redirige "revise" vers itinerary_refiner_agent (qui boucle vers itinerary_critic_agent) ou "approved" vers finalize_itinerary

Ajouter les spécialistes de la critique et de l'amélioration

Vérifiez que adk web est arrêté (Ctrl + C), puis ouvrez travel_planner/specialists.py :

cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py

Ajoutez itinerary_critic_agent et itinerary_refiner_agent au bas de travel_planner/specialists.py (le raffineur n'a pas besoin d'outil google_search ni exit_loop, car il échange des éléments déjà collectés dans {final_itinerary} et ne s'exécute que lorsque route_critique sélectionne "revise") :

# --- Specialist 5: The Budget & Constraint Critic ---
itinerary_critic_agent = Agent(
    model=MODEL,
    name="itinerary_critic_agent",
    description="Audits the itinerary draft against budget and negative constraints.",
    instruction="""
        Audit the itinerary in the input against User Preferences ({user_preferences}).
        Verify that the USD total stays within the user's budget and no excluded venue types appear.
        If all checks pass, respond EXACTLY with the single word "APPROVED".
        Otherwise, output 1-2 concise revision instructions explaining what to swap or adjust.
    """,
)

# --- Specialist 6: The Itinerary Refiner ---
itinerary_refiner_agent = Agent(
    model=MODEL,
    name="itinerary_refiner_agent",
    description="Revises the itinerary draft using the critic's feedback.",
    instruction="""
        Revise Current Itinerary ({final_itinerary}) using the auditor critique in the input
        so all USD budget and exclusion rules in {user_preferences} pass.
        Output ONLY the updated Markdown itinerary.
    """,
    output_key="final_itinerary",
)

Ajouter route_critique et le cycle

Ouvrez travel_planner/workflows.py :

cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py

Remplacez l'intégralité du contenu de travel_planner/workflows.py par le workflow de graphe complet :

from google.adk import Event, Workflow
from google.adk.workflow import JoinNode
from .specialists import (
    activity_finder_agent, itinerary_critic_agent, itinerary_refiner_agent,
    itinerary_synthesizer_agent, restaurant_finder_agent, user_profiler_agent,
)

MAX_REVISIONS = 2
research_join = JoinNode(name="research_join")


def route_critique(node_input: str, revision_count: int = 0):
    """Routes to 'approved' when constraints pass, or 'revise' up to MAX_REVISIONS."""
    approved = node_input.strip().rstrip(".").upper() == "APPROVED"
    if approved or revision_count >= MAX_REVISIONS:
        return Event(route="approved", output=approved)
    return Event(
        route="revise", output=node_input, state={"revision_count": revision_count + 1}
    )


def finalize_itinerary(node_input: bool, final_itinerary: str, revision_count: int = 0):
    """Emits the verified itinerary and resets revision_count for the next turn."""
    status = (
        f"Itinerary approved after {revision_count} revision(s)."
        if node_input
        else f"Max revisions ({revision_count}) reached; returning best-effort draft."
    )
    return Event(
        message=f"{status}\n\n{final_itinerary}",
        output=final_itinerary,
        state={"revision_count": 0},
    )


travel_workflow = Workflow(
    name="travel_workflow",
    description="Orchestrates the end-to-end travel planning process as a graph workflow.",
    edges=[
        (
            "START",
            user_profiler_agent,
            (activity_finder_agent, restaurant_finder_agent),
            research_join,
            itinerary_synthesizer_agent,
            itinerary_critic_agent,
            route_critique,
        ),
        (route_critique, {"revise": itinerary_refiner_agent, "approved": finalize_itinerary}),
        (itinerary_refiner_agent, itinerary_critic_agent),
    ],
)

🔍 Vérifiez votre travail

Vérifiez que travel_planner/workflows.py se compile correctement et affiche les arêtes du graphe orienté :

cd ~/adk-graph-agents && source .venv/bin/activate
python3 -c "from travel_planner.agent import root_agent; print('\n'.join(f'{e.from_node.name} -> {e.to_node.name} (route={e.route})' for e in root_agent.graph.edges))"

Un résultat semblable à celui-ci s'affiche :

__START__ -> user_profiler_agent (route=None)
user_profiler_agent -> activity_finder_agent (route=None)
user_profiler_agent -> restaurant_finder_agent (route=None)
activity_finder_agent -> research_join (route=None)
restaurant_finder_agent -> research_join (route=None)
research_join -> itinerary_synthesizer_agent (route=None)
itinerary_synthesizer_agent -> itinerary_critic_agent (route=None)
itinerary_critic_agent -> route_critique (route=None)
route_critique -> itinerary_refiner_agent (route=revise)
route_critique -> finalize_itinerary (route=approved)
itinerary_refiner_agent -> itinerary_critic_agent (route=None)

Ensuite, démarrez adk web pour tester l'approbation immédiate et les révisions déclenchées par le budget :

adk web --allow_origins "*"

Ouvrez l'aperçu sur le Web sur le port 8000, cliquez sur + New Session (+ Nouvelle session), puis envoyez le prompt à contraintes multiples sur Kyoto :

Design a full-day itinerary for Kyoto with a total budget of $100. My main interests are historical landmarks, temples, and authentic local cuisine. Please do not include any modern art museums or galleries.

Pour voir la boucle route="revise" en action, envoyez un prompt complémentaire avec un budget serré de 15 $ :

Now design a full-day Kyoto itinerary with paid temple admissions, lunch, and dinner on a strict total budget of $15 USD.

Dans la vue Événements, vous devriez voir une séquence d'exécution semblable à celle-ci :

1. user_profiler_agent -> writes JSON constraints to state["user_preferences"]
2. (activity_finder_agent, restaurant_finder_agent) -> run google_search concurrently -> research_join
3. itinerary_synthesizer_agent -> writes initial draft to state["final_itinerary"]
4. itinerary_critic_agent -> outputs "APPROVED" (or revision instructions when over budget)
5. route_critique -> emits route="approved" (skipping refiner) or route="revise" -> itinerary_refiner_agent -> itinerary_critic_agent
6. finalize_itinerary -> emits "Itinerary approved after N revision(s)." (or max-revisions notice) and resets revision_count=0

Appuyez sur Ctrl + C dans votre terminal pour arrêter adk web.

9. Dépannage

Le menu déroulant des agents est vide dans adk web

  • Cause : adk web a été démarré dans travel_planner/ au lieu du répertoire parent ~/adk-graph-agents, ou la session Cloud Shell a redémarré.
  • Solution : Appuyez sur Ctrl + C, revenez au répertoire parent et redémarrez avec cd ~/adk-graph-agents && source .venv/bin/activate && adk web --allow_origins "*".

404 NOT_FOUND erreur de modèle

  • Cause : Vous avez appuyé sur Entrée pour accepter la région us-central1 par défaut lors de l'exécution de adk create au lieu de saisir global.
  • Solution : ouvrez ~/adk-graph-agents/travel_planner/.env et assurez-vous que GOOGLE_CLOUD_LOCATION=global est défini.

ERROR: [Errno 98] address already in use sur le port 8000

  • Cause : un serveur adk web précédent est toujours en cours d'exécution dans Cloud Shell.
  • Solution : Appuyez sur Ctrl + C dans le terminal actif ou arrêtez le processus existant avec pkill -f "adk web" avant de redémarrer adk web.

10. Effectuer un nettoyage

Supprimez l'espace de travail local et, si vous le souhaitez, désactivez l'API ou supprimez un projet d'atelier dédié.

Supprimer les fichiers du projet local

Supprimez le répertoire ~/adk-graph-agents et l'environnement virtuel :

cd ~
rm -rf ~/adk-graph-agents

Désactiver l'API Agent Platform (facultatif)

Désactivez l'API Agent Platform si vous n'en avez plus besoin dans ce projet :

gcloud services disable aiplatform.googleapis.com --quiet

🔍 Vérifiez votre travail

Vérifiez que ~/adk-graph-agents a bien été supprimé :

test ! -d ~/adk-graph-agents && echo "Workspace ~/adk-graph-agents removed"

Un résultat semblable à celui-ci s'affiche :

Workspace ~/adk-graph-agents removed

11. Félicitations

Vous avez créé un planificateur de voyage multi-agent à l'aide d'ADK 2 Workflow, en unifiant des chaînes séquentielles, une distribution simultanée google_search avec JoinNode et des cycles de vérification conditionnels dans un seul graphe d'arêtes déclaratif.

Bilan de vos réalisations

  • Déclarer un pipeline multi-agent à l'aide d'ADK 2 Workflow(edges=[...])
  • Transmis des données directement entre les nœuds de fonction Agent, JoinNode et Python via node_input et des paramètres liés à l'état, tout en limitant l'état de session au minimum
  • Répartition des branches google_search simultanées et synchronisation avec JoinNode
  • Remplacement de LoopAgent et de l'escalade de boucle basée sur des outils par un routeur Event(route=...) déterministe qui ignore les appels LLM inutiles sur les brouillons approuvés

Étapes suivantes