Creazione di agenti AI con ADK: orchestrazione dei workflow degli agenti

1. Panoramica

Per soddisfare una richiesta di viaggio con più vincoli (ad esempio, progettare un itinerario di un'intera giornata a Kyoto con un budget inferiore a 100 $incentrato su templi storici e cucina locale, senza gallerie d'arte moderna), è necessario estrarre i vincoli, ricercare attrazioni e ristoranti contemporaneamente, assemblare un programma dettagliato e verificare il piano finale. Affidarsi a un singolo agente monolitico con molti strumenti può comportare il salto dei passaggi di verifica o la violazione delle esclusioni, pertanto l'orchestrazione coordina i sub-agenti specializzati tramite controller di workflow deterministici.

In questa terza parte della serie Creazione di agenti AI con ADK, creerai un pianificatore di viaggi multi-agente autonomo su Agent Platform utilizzando i controller del workflow di Agent Development Kit (ADK) 2 (SequentialAgent, ParallelAgent e LoopAgent). In tre fasi progressive (senza la necessità di configurare l'area di lavoro della Parte 1 o della Parte 2), coordinerai sei agenti specializzati basati su gemini-3.8-flash con stato della sessione condiviso (output_key), esecuzione simultanea di google_search e un ciclo di perfezionamento iterativo maker-checker.

Prerequisiti

Cosa imparerai

  • Come creare un progetto ADK 2 multi-agente da zero
  • Come progettare un team di agenti specializzati che condividono lo stato della sessione utilizzando output_key
  • Come utilizzare SequentialAgent per eseguire sub-agenti in una pipeline deterministica passo passo
  • Come utilizzare ParallelAgent per eseguire contemporaneamente agenti di ricerca indipendenti per una latenza inferiore
  • Come utilizzare l'escalation di LoopAgent e ToolContext per implementare un ciclo di perfezionamento iterativo del controllo del creatore
  • Come combinare pattern sequenziali, paralleli e in loop in un workflow multi-agente gerarchico

Cosa serve

  • Un Account Google (utilizza un account @gmail.com personale se richiedi i crediti per il workshop)
  • Un link per i crediti del workshop fornito dall'insegnante (oltre alla fotocamera dello smartphone per scansionare il codice QR) o un account di fatturazione Cloud attivo
  • Google Chrome (è consigliata una finestra Incognito per evitare di combinare account personali e di lavoro)

2. (Facoltativo) Richiedi crediti Google Cloud

Se partecipi a un workshop con un link ai crediti per l'evento, richiedi il tuo credito del Google Developer Program per eseguire il provisioning di un account di fatturazione senza carta di credito.

Richiedi il tuo credito per l'evento

  1. Apri il link dei crediti del workshop in una finestra di navigazione in incognito e accedi con il tuo account @gmail.com.
  2. In Richiedi il tuo vantaggio, fai clic su Richiedi credito:

Scheda Richiedi il tuo vantaggio di Google Builders Hub con il pulsante Richiedi credito

  1. Se ti viene chiesto di creare un profilo Google Developer Program, compila il modulo.
  2. Quando viene visualizzato il messaggio Scansiona per verificare che sei un essere umano, scansiona il codice QR con lo smartphone e completa la verifica (aggiorna la pagina e fai di nuovo clic su Richiedi credito se il codice QR non viene visualizzato):

Finestra di dialogo del codice QR Scansiona per verificare che sei un essere umano del Google Developer Program

  1. Verifica che venga visualizzato il messaggio Hai richiesto correttamente il tuo credito per l'evento, quindi fai clic su Apri account di fatturazione:

Google Builders Hub che mostra il messaggio "Hai richiesto correttamente il tuo credito per l'evento" e il pulsante Apri account di fatturazione

🔍 Controlla il tuo lavoro

La configurazione dell'account di fatturazione richiede fino a 3 minuti:

  1. Apri Fatturazione Cloud (o copia l'URL nella finestra di navigazione in incognito) e seleziona I tuoi account di fatturazione:
https://console.cloud.google.com/billing
  1. Aggiorna la pagina finché lo stato del tuo account GDP Credit non diventa Attivo:

Gestione dell'account di fatturazione Google Cloud che mostra un account di fatturazione con credito GDP attivo

3. Crea un progetto Google Cloud (facoltativo)

Crea un progetto Google Cloud dedicato in modo che tutte le risorse di questo codelab rimangano isolate e facili da eliminare.

  1. Apri Crea un progetto (o copia l'URL nella finestra Incognito):
https://console.cloud.google.com/projectcreate
  1. Inserisci i dettagli del progetto:
    • Nome progetto: ad esempio google-cloud-workshop
    • Account di fatturazione (se visualizzato): seleziona GDP Credit (o il tuo account di fatturazione attivo)
    • Risorsa padre: Nessuna organizzazione (o la tua organizzazione, se necessario)
  2. Prendi nota dell'ID progetto generato sotto il nome del progetto, quindi fai clic su Crea:

Schermata Crea un progetto Google Cloud che mostra il nome del progetto, l'ID progetto, la risorsa principale e il pulsante Crea

🔍 Controlla il tuo lavoro

Fai clic su Notifiche nella barra degli strumenti in alto a destra e poi su Seleziona progetto al termine della creazione del progetto:

Menu Notifiche della console Google Cloud che mostra Crea progetto e il link Seleziona progetto

4. Configura l'ambiente

Configura Google Cloud Shell, abilita l'API Agent Platform e crea un ambiente virtuale Python 3.12 isolato con uv.

Configura Cloud Shell

  1. Fai clic su Attiva Cloud Shell (>_) nella barra degli strumenti della console Google Cloud o apri direttamente Google Cloud Shell (o copia l'URL nella finestra Incognito):
https://shell.cloud.google.com/?show=ide,terminal

Pulsante Attiva Cloud Shell nella barra degli strumenti della console Google Cloud

  1. Fai clic su Autorizza, se richiesto:

Finestra di dialogo Autorizza Cloud Shell

  1. Seleziona l'ID progetto Google Cloud attivo dal menu numerato nel terminale:
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

Dovresti visualizzare un output simile al seguente (per i progetti senza tag viene stampata anche una riga informativa [environment: untagged]):

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

Verifica che l'ID progetto selezionato sia evidenziato in giallo nel prompt di Cloud Shell:

Terminale Cloud Shell che mostra l'ID progetto selezionato evidenziato in giallo

Abilita le API richieste

Abilita l'API Agent Platform in modo che i tuoi agenti ADK possano richiamare i modelli Gemini:

gcloud services enable aiplatform.googleapis.com

Dovresti visualizzare un output simile al seguente:

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

Crea un ambiente virtuale Python e installa l'ADK

Crea l'area di lavoro ~/adk-agents e attiva un ambiente virtuale Python 3.12:

cd ~
mkdir -p adk-agents && cd ~/adk-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

Verifica che il prefisso (.venv) venga visualizzato all'inizio del prompt del terminale:

Terminale Cloud Shell che mostra il prefisso .venv in un ambiente virtuale Python attivo

Installa ADK 2 nell'ambiente virtuale attivo:

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

🔍 Controlla il tuo lavoro

Verifica la versione installata della CLI adk:

adk --version

Dovresti visualizzare un output simile al seguente:

adk, version 2.14.0

5. Crea l'agente di pianificazione dei viaggi

Con l'ambiente pronto, utilizza il comando adk create integrato di ADK per generare i file di avvio per il pacchetto dell'agente travel_planner.

Genera il pacchetto iniziale

Esegui adk create dalla directory ~/adk-agents:

cd ~/adk-agents
adk create travel_planner

Quando richiesto nel terminale, seleziona le seguenti opzioni di configurazione (se alla prima esecuzione viene visualizzato Enable telemetry? [Y/n]:, premi Invio o digita n e premi Invio):

  1. Scegli un modello per l'agente root: digita 2 per selezionare gemini-3.8-flash (l'opzione 1 seleziona gemini-3.5-flash) e premi Invio.
  2. Scegli un backend: digita 2 per selezionare il backend Agent Platform di Google Cloud (opzione 2 nel menu dell'interfaccia a riga di comando di seguito) e premi Invio.
  3. Inserisci l'ID progetto Google Cloud: conferma l'ID progetto mostrato tra parentesi premendo Invio.
  4. Inserisci la regione Google Cloud: digita global e premi Invio.

adk create scrive GOOGLE_GENAI_USE_ENTERPRISE=1, l'ID progetto e GOOGLE_CLOUD_LOCATION=global in travel_planner/.env, in modo che le credenziali rimangano configurate quando aggiorni agent.py in un secondo momento.

🔍 Controlla il tuo lavoro

Dovresti visualizzare un output simile al seguente:

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

Apri la cartella corrente nell'editor di codice di Cloud Shell per ispezionare e modificare i file insieme al terminale:

which cloudshell >/dev/null 2>&1 && cloudshell workspace ~/adk-agents || true
cd ~/adk-agents
source .venv/bin/activate

Testa l'agente singolo predefinito

Prima di creare workflow multi-agente, avvia la UI di sviluppo dell'ADK per osservare come l'agente singolo predefinito risponde a una query generica di pianificazione di un viaggio:

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

Apri l'interfaccia utente di sviluppo nel browser utilizzando l'Anteprima web di Cloud Shell:

  1. Fai clic sull'icona Anteprima web nella barra degli strumenti in alto a destra di Cloud Shell.
  2. Seleziona Cambia porta, inserisci 8000 e fai clic su Cambia e visualizza anteprima.

Finestra di dialogo di configurazione della porta di Anteprima web di Cloud Shell impostata su 8000

Una volta caricata l'interfaccia utente web dell'ADK, invia un saluto come "hello, what can you do?" o "Help me plan a trip to Japan":

UI web di sviluppo ADK che mostra una conversazione di base con un singolo agente

Tieni presente che il singolo root_agent risponde direttamente in un unico passaggio senza estrazione strutturata delle preferenze, ricerca sul web in tempo reale o verifica del budget.

Al termine del test, premi Ctrl + C nel terminale Cloud Shell per arrestare il server adk web e tornare al prompt dei comandi.

6. Crea un workflow SequentialAgent

Ora creerai il tuo primo pattern di orchestrazione: un workflow lineare basato su SequentialAgent. In una pipeline sequenziale, i sub-agenti vengono eseguiti in un ordine rigoroso. Il primo specialista estrae i parametri strutturati e li salva nello stato della sessione condivisa utilizzando output_key="user_preferences", mentre il secondo specialista legge {user_preferences} dallo stato condiviso per creare la bozza dell'itinerario.

Diagramma dell'architettura che mostra root_agent che delega a master_travel_agent (SequentialAgent), che esegue user_profiler_agent seguito da itinerary_synthesizer_agent tramite lo stato della sessione condivisa

Crea gli specialisti iniziali (specialists.py)

Apri un nuovo file denominato specialists.py all'interno di travel_planner/:

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

Incolla il seguente codice in travel_planner/specialists.py per definire user_profiler_agent e itinerary_synthesizer_agent (importando ToolContext e google_search in anticipo per i passaggi successivi):

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

# --- Specialist 1: The User Profiler ---
user_profiler_agent = Agent(
    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",  # Saves output to state['user_preferences']
)

# --- Specialist 2: The Synthesizer ---
itinerary_synthesizer_agent = Agent(
    name="itinerary_synthesizer_agent",
    description="Compiles preferences and research into a final Markdown itinerary.",
    instruction="""
        You are an elite Travel Concierge. Write a Markdown itinerary with an itemized USD and local currency cost breakdown using:
        - User Preferences: {user_preferences}
        - Activities (if available): {activity_recommendations?}
        - Restaurants (if available): {restaurant_recommendations?}
    """,
    output_key="final_itinerary",
)

Collega la pipeline sequenziale (workflows.py)

Crea un nuovo file denominato workflows.py all'interno di travel_planner/ per orchestrare gli specialisti:

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

Aggiungi la seguente definizione SequentialAgent a travel_planner/workflows.py:

from google.adk.agents import SequentialAgent
from .specialists import (
    user_profiler_agent,
    itinerary_synthesizer_agent,
)

# 1. SEQUENTIAL PHASE: A linear two-step workflow
master_travel_agent = SequentialAgent(
    name="master_travel_agent",
    description="Orchestrates the end-to-end travel planning process for trip and itinerary requests.",
    sub_agents=[
        user_profiler_agent,         # Step 1: Extract constraints into user_preferences
        itinerary_synthesizer_agent,  # Step 2: Draft itinerary from user_preferences
    ],
)

Collega il workflow a root_agent (agent.py)

Ora registra master_travel_agent come subagente di root_agent. Apri travel_planner/agent.py:

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

Sostituisci i contenuti di travel_planner/agent.py con il seguente codice:

from google.adk import Agent
from .workflows import master_travel_agent

MODEL = "gemini-3.8-flash"

root_agent = Agent(
    model=MODEL,
    name="root_agent",
    description="A helpful assistant for user questions.",
    instruction=(
        "Greet the user and delegate any travel or trip planning requests "
        "to master_travel_agent."
    ),
    sub_agents=[master_travel_agent],
)

🔍 Controlla il tuo lavoro

Avvia l'interfaccia utente web dell'ADK dal terminale:

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

Apri l'anteprima web sulla porta 8000 e inserisci il prompt:

Help me plan a trip to Kyoto

Dovresti vedere un output simile al seguente flusso di esecuzione nella visualizzazione Eventi:

1. root_agent -> calls transfer_to_agent(agent_name="master_travel_agent")
2. user_profiler_agent -> outputs JSON {"destination": "Kyoto", "duration": "1 day", ...} to state['user_preferences']
3. itinerary_synthesizer_agent -> reads {user_preferences} and outputs the formatted Markdown itinerary

Interfaccia web di ADK 2.14.0 che mostra il grafico di esecuzione da root_agent a master_travel_agent, user_profiler_agent e itinerary_synthesizer_agent insieme all'itinerario di Kyoto generato

Fai clic su un badge evento (o sul chip State: final_itinerary) e passa alla scheda Stato nel riquadro di controllo a sinistra per verificare che user_preferences e final_itinerary siano entrambi compilati nello stato della sessione.

Al termine dell'ispezione della traccia, premi Ctrl + C nel terminale per interrompere adk web.

7. Esegui ricerche con ParallelAgent

Sebbene il flusso di lavoro sequenziale separi chiaramente l'estrazione delle preferenze dalla stesura dell'itinerario, i suoi consigli si basano ancora esclusivamente sulle conoscenze di addestramento statiche del modello. Puoi basare l'itinerario su dati web in tempo reale aggiungendo due ricercatori dedicati basati sullo strumento google_search integrato:

  • activity_finder_agent: trova tre attrazioni specifiche che corrispondono alla destinazione e agli interessi dell'utente, insieme ai prezzi stimati dei biglietti.
  • restaurant_finder_agent: trova 3 ristoranti locali con valutazioni elevate e il loro costo stimato a persona.

Poiché la ricerca di attrazioni e quella di ristoranti non dipendono l'una dall'altra, eseguirle una dopo l'altra è una perdita di tempo. Invece, racchiuderai entrambi i ricercatori all'interno di un ParallelAgent (parallel_research_agent) in modo che l'ADK esegua entrambi i workflow della Ricerca Google contemporaneamente e compili {activity_recommendations?} e {restaurant_recommendations?} prima di passare a itinerary_synthesizer_agent.

Diagramma dell'architettura che mostra master_travel_agent che esegue user_profiler_agent nella fase 1, parallel_research_agent (ParallelAgent con activity_finder_agent e restaurant_finder_agent) nella fase 2 e itinerary_synthesizer_agent nella fase 3

Aggiungi gli specialisti della ricerca parallela a specialists.py

Apri travel_planner/specialists.py:

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

Aggiungi i seguenti due specialisti della Ricerca Google in fondo a travel_planner/specialists.py (subito sotto itinerary_synthesizer_agent):

# --- Specialist 3: The Activity Finder ---
activity_finder_agent = Agent(
    name="activity_finder_agent",
    description="Finds 3 attractions matching the user's destination and interests.",
    instruction="""
        Based on {user_preferences}, use 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],
    output_key="activity_recommendations",
)

# --- Specialist 4: The Restaurant Finder ---
restaurant_finder_agent = Agent(
    name="restaurant_finder_agent",
    description="Finds 3 restaurants matching the destination and budget.",
    instruction="""
        Based on {user_preferences}, use 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],
    output_key="restaurant_recommendations",
)

Inserisci ParallelAgent in workflows.py

Apri travel_planner/workflows.py:

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

Aggiorna travel_planner/workflows.py per definire parallel_research_agent utilizzando ParallelAgent e posizionalo tra user_profiler_agent e itinerary_synthesizer_agent:

from google.adk.agents import ParallelAgent, SequentialAgent
from .specialists import (
    activity_finder_agent,
    itinerary_synthesizer_agent,
    restaurant_finder_agent,
    user_profiler_agent,
)

# Parallel branch: Run activity and restaurant research simultaneously
parallel_research_agent = ParallelAgent(
    name="parallel_research_agent",
    description="Runs activity and restaurant research concurrently.",
    sub_agents=[
        activity_finder_agent,
        restaurant_finder_agent,
    ],
)

# Master pipeline: Profile -> Parallel Research -> Synthesize
master_travel_agent = SequentialAgent(
    name="master_travel_agent",
    description="Orchestrates the end-to-end travel planning process for trip and itinerary requests.",
    sub_agents=[
        user_profiler_agent,          # Step 1: Extract constraints
        parallel_research_agent,      # Step 2: Research activities & restaurants in parallel
        itinerary_synthesizer_agent,  # Step 3: Synthesize into an itinerary
    ],
)

🔍 Controlla il tuo lavoro

Avvia di nuovo adk web per testare la pipeline di ricerca parallela:

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

Nell'interfaccia utente di Anteprima web, invia il prompt:

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

Dovresti vedere un output simile alla seguente sequenza nella visualizzazione Eventi:

1. user_profiler_agent -> writes state['user_preferences']
2. parallel_research_agent -> fans out concurrently:
   - activity_finder_agent invokes google_search -> writes state['activity_recommendations']
   - restaurant_finder_agent invokes google_search -> writes state['restaurant_recommendations']
3. itinerary_synthesizer_agent -> merges all three state keys into state['final_itinerary']
  1. Visualizzazione Tracce: fai clic su Tracce nella parte superiore del riquadro della conversazione (accanto a Eventi) ed esamina il tuo turno. Vedrai intervalli di tempo sovrapposti per activity_finder_agent e restaurant_finder_agent in parallel_research_agent, dimezzando quasi la latenza totale della ricerca sul web rispetto all'esecuzione sequenziale.
  2. Scheda Stato: fai clic sulla scheda Stato nel riquadro di controllo a sinistra per esaminare il dizionario della sessione live (user_preferences, activity_recommendations, restaurant_recommendations e final_itinerary).

Al termine del test, premi Ctrl + C nel terminale per interrompere adk web.

8. Perfeziona le bozze con LoopAgent

Anche con i risultati di Cerca dal vivo, la bozza iniziale prodotta da itinerary_synthesizer_agent potrebbe superare il budget totale dell'utente o includere accidentalmente una categoria esclusa (ad esempio una galleria d'arte moderna quando l'utente ha chiesto di non includerla).

Per garantire la conformità ai vincoli, aggiungerai un loop di perfezionamento maker-checker alla fine della pipeline utilizzando LoopAgent:

  1. itinerary_critic_agent (The Checker): controlla {final_itinerary} rispetto a {user_preferences}. Somma i costi stimati, controlla ogni vincolo negativo e scrive istruzioni di revisione specifiche in critique_feedback o risponde con la frase esatta "APPROVED".
  2. itinerary_refiner_agent (The Maker / Exiter): legge {critique_feedback}. Se la critica è uguale a "APPROVED", richiama lo strumento exit_loop (tool_context.actions.escalate = True) per uscire immediatamente da LoopAgent. In caso contrario, rivede {final_itinerary} per risolvere i problemi segnalati e sovrascrive final_itinerary per il passaggio successivo.

Diagramma dell'architettura che mostra master_travel_agent con Stage 4 refinement_loop_agent (LoopAgent) che passa da itinerary_critic_agent a itinerary_refiner_agent finché non viene chiamato exit_loop

Aggiungi exit_loop, Critic e Refiner a specialists.py

Apri travel_planner/specialists.py:

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

Aggiungi lo strumento exit_loop (ToolContext), itinerary_critic_agent e itinerary_refiner_agent alla fine di travel_planner/specialists.py:

def exit_loop(tool_context: ToolContext) -> dict:
    """Call ONLY when the critique is APPROVED to exit the refinement loop."""
    print(f"[Tool Call] exit_loop triggered by {tool_context.agent_name}")
    tool_context.actions.escalate = True
    return {"status": "approved", "message": "Itinerary approved. Exiting refinement loop."}


# --- Specialist 5: The Budget & Constraint Critic (Inside LoopAgent) ---
itinerary_critic_agent = Agent(
    name="itinerary_critic_agent",
    include_contents="none",
    description="Audits the itinerary draft against budget and negative constraints.",
    instruction="""
        Audit Current Itinerary ({final_itinerary}) 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.
    """,
    output_key="critique_feedback",
)

# --- Specialist 6: The Itinerary Refiner / Exiter (Inside LoopAgent) ---
itinerary_refiner_agent = Agent(
    name="itinerary_refiner_agent",
    include_contents="none",
    description="Refines the itinerary from critique feedback, or calls exit_loop when APPROVED.",
    instruction="""
        Review Auditor Critique ({critique_feedback}) for Current Itinerary ({final_itinerary}).
        If the critique is EXACTLY "APPROVED", call `exit_loop` immediately and return the itinerary unchanged.
        Otherwise, revise the draft using {activity_recommendations} and {restaurant_recommendations}
        so all USD budget and exclusion rules pass, and output ONLY the updated Markdown itinerary.
    """,
    tools=[exit_loop],
    output_key="final_itinerary",
)

Aggiungi LoopAgent a: workflows.py

Apri travel_planner/workflows.py:

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

Aggiorna travel_planner/workflows.py per aggregare itinerary_critic_agent e itinerary_refiner_agent in un LoopAgent (max_iterations=3) e aggiungilo come quarta fase di master_travel_agent:

from google.adk.agents import LoopAgent, ParallelAgent, SequentialAgent
from .specialists import (
    activity_finder_agent,
    itinerary_critic_agent,
    itinerary_refiner_agent,
    itinerary_synthesizer_agent,
    restaurant_finder_agent,
    user_profiler_agent,
)

# Stage 2: Parallel research branch
parallel_research_agent = ParallelAgent(
    name="parallel_research_agent",
    description="Runs activity and restaurant research concurrently.",
    sub_agents=[
        activity_finder_agent,
        restaurant_finder_agent,
    ],
)

# Stage 4: Iterative Maker-Checker refinement loop
refinement_loop_agent = LoopAgent(
    name="refinement_loop_agent",
    description="Iteratively audits and refines the itinerary until constraints and budget are approved.",
    sub_agents=[
        itinerary_critic_agent,
        itinerary_refiner_agent,
    ],
    max_iterations=3,
)

# Master pipeline: Profile -> Parallel Research -> Synthesize -> Refinement Loop
master_travel_agent = SequentialAgent(
    name="master_travel_agent",
    description="Orchestrates the end-to-end travel planning process for trip and itinerary requests.",
    sub_agents=[
        user_profiler_agent,          # Stage 1: Extract constraints
        parallel_research_agent,      # Stage 2: Research activities & restaurants in parallel
        itinerary_synthesizer_agent,  # Stage 3: Draft initial itinerary
        refinement_loop_agent,        # Stage 4: Audit and refine until approved
    ],
)

🔍 Controlla il tuo lavoro

Avvia adk web per testare il workflow multi-agente completo:

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

Apri l'interfaccia utente di Anteprima web sulla porta 8000, avvia una Nuova sessione e testa l'intero sistema con questo prompt con più vincoli su 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.

Dovresti vedere un output simile alla seguente sequenza di esecuzione nella visualizzazione Eventi e nei log del terminale:

1. user_profiler_agent -> writes JSON with destination="Kyoto", budget="$100", exclusions=["modern art museums", "galleries"]
2. parallel_research_agent -> runs activity_finder_agent and restaurant_finder_agent in parallel
3. itinerary_synthesizer_agent -> produces initial draft in state['final_itinerary']
4. refinement_loop_agent:
   - itinerary_critic_agent -> audits USD budget and exclusions -> outputs "APPROVED" (or revision notes)
   - itinerary_refiner_agent -> triggers [Tool Call] exit_loop triggered by itinerary_refiner_agent and outputs the approved itinerary
  1. Visualizzazione Eventi: fai clic su un chip evento da itinerary_critic_agent o itinerary_refiner_agent per esaminare il relativo payload nella scheda Informazioni a sinistra. Quando itinerary_refiner_agent richiama exit_loop, esamina l'evento per vedere actions.escalate: true, l'indicatore che indica a LoopAgent di interrompere l'iterazione prima di raggiungere max_iterations=3.
  2. Scheda State (Stato): fai clic sulla scheda State (Stato) per osservare l'aggiornamento di state['critique_feedback'] e state['final_itinerary'] nei vari passaggi. Se la bozza iniziale superava $100 USD, critique_feedback contiene le istruzioni di revisione del revisore nel passaggio 1 prima che final_itinerary venga aggiornato con alternative a costo inferiore e critique_feedback cambi in "APPROVED" nel passaggio 2.

Al termine del test, premi Ctrl + C nel terminale per interrompere adk web.

9. Esegui la pulizia

Elimina i file di progetto locali

Per rimuovere la directory del progetto adk-agents e l'ambiente virtuale dalla cartella home di Cloud Shell, esegui:

cd ~
rm -rf ~/adk-agents

Disabilita l'API Agent Platform

Se non hai più bisogno dell'API Agent Platform abilitata nel tuo progetto, disabilitala con gcloud:

gcloud services disable aiplatform.googleapis.com --quiet

(Facoltativo) Elimina l'intero progetto Google Cloud

PROJECT_ID=$(gcloud config get-value project)
gcloud projects delete "$PROJECT_ID" --quiet

🔍 Controlla il tuo lavoro

Verifica che ~/adk-agents sia stato rimosso:

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

Dovresti visualizzare un output simile al seguente:

Workspace ~/adk-agents removed

10. Complimenti

Complimenti! Hai creato un sistema multi-agente gerarchico con Google Agent Development Kit (ADK) che coordina un team di sei agenti specializzati in workflow sequenziali, paralleli e con loop iterativi.

Risultati ottenuti

  • Comunicazione strutturata tra agenti tramite lo stato della sessione condivisa (injection di template output_key e {state_variable})
  • Creazione di una pipeline deterministica passo passo utilizzando SequentialAgent
  • Esecuzione simultanea di agenti di ricerca indipendenti della Ricerca Google utilizzando ParallelAgent
  • Implementato un ciclo di verifica automatizzato maker-checker utilizzando LoopAgent e tool_context.actions.escalate = True

Passaggi successivi