Cómo crear agentes de IA con el ADK: Organiza flujos de trabajo de grafos

1. Descripción general

Cumplir con una solicitud de viaje con múltiples restricciones (como planificar un viaje de un día de USD 100 en Kioto con templos históricos, ramen local y ningún museo de arte moderno) requiere extraer preferencias estructuradas, investigar lugares de forma simultánea, sintetizar un borrador detallado y auditar el costo total antes de responder. En ADK 1.x, organizar esas etapas requería anidar los wrappers SequentialAgent, ParallelAgent y LoopAgent, guardar cada resultado intermedio en el estado de la sesión y realizar una llamada adicional a la herramienta de LLM solo para salir de un bucle de perfeccionamiento.

En este codelab, crearás un planificador de viajes de varios agentes en Agent Platform con flujos de trabajo de grafos (Workflow) del Kit de desarrollo de agentes (ADK) 2. En tres etapas progresivas, conectarás nodos de Agent especializados (con la tecnología de gemini-3.8-flash) en una cadena de bordes secuencial (node_input), distribuirás investigadores de google_search simultáneos sincronizados con JoinNode y aplicarás reglas de presupuesto y exclusión con un enrutador de Python determinista (Event(route=...)) que omite el perfeccionamiento cada vez que el borrador inicial pasa la auditoría.

Requisitos previos

Qué aprenderá

  • Cómo declarar una canalización multiagente en ADK 2 con tuplas de borde Workflow
  • Cómo el ADK 2 pasa los resultados directamente a lo largo de las aristas como node_input y vincula las claves de estado de la sesión como parámetros de función
  • Cómo distribuir ramas de investigación simultáneas y combinar sus resultados con JoinNode
  • Cómo enrutar ciclos de creador-verificador limitados de forma determinística en Python con Event(route=...)
  • Cómo inspeccionar grafos de flujos de trabajo compilados, cronogramas de ejecución paralela y diferencias de estado en la IU web del ADK

Requisitos

  • Una Cuenta de Google (usa una cuenta personal de @gmail.com si reclamas créditos del taller)
  • Un vínculo de crédito para el taller que te haya proporcionado el instructor (además de la cámara de un teléfono para escanear el código QR) o una cuenta de Facturación de Cloud activa
  • Google Chrome (se recomienda usar una ventana de incógnito para evitar mezclar cuentas personales y laborales)

2. Reclama créditos de Google Cloud (opcional)

Si asistes a un taller con un vínculo de crédito para el evento, reclama tu crédito de Google Developer Program para aprovisionar una cuenta de facturación sin tarjeta de crédito.

Reclama tu crédito para el evento

  1. Abre el vínculo de crédito del taller en una ventana de incógnito y accede con tu cuenta de @gmail.com.
  2. En Reclama tu beneficio, haz clic en Reclamar crédito:

Tarjeta Reclama tu beneficio de Google Builders Hub que muestra el botón Reclamar crédito

  1. Si se te solicita que crees un perfil del Programa para desarrolladores de Google, completa el formulario.
  2. Cuando aparezca Escanea para verificar que eres una persona, escanea el código QR con tu teléfono y completa la verificación (actualiza la página y vuelve a hacer clic en Reclamar crédito si no aparece el código QR):

Diálogo del código QR de Escanea para verificar que eres una persona de Google Developer Program

  1. Confirma que aparezca el mensaje Successfully claimed your event credit! y, luego, haz clic en Open Billing Account:

Google Builders Hub mostrando el mensaje Successfully claimed your event credit y el botón Open Billing Account

🔍 Revisa tu trabajo

La configuración de la cuenta de facturación tarda hasta 3 minutos:

  1. Abre la Facturación de Google Cloud (o copia la URL en tu ventana de incógnito) y selecciona Tus cuentas de facturación:
https://console.cloud.google.com/billing
  1. Actualiza hasta que tu cuenta de GDP Credit muestre el estado Activa:

Administración de la cuenta de Facturación de Google Cloud que muestra una cuenta de facturación de crédito de GDP activa

3. Crea un proyecto de Google Cloud (opcional)

Crea un proyecto de Google Cloud dedicado para que todos los recursos de este codelab permanezcan aislados y sean fáciles de limpiar.

  1. Abre Crear un proyecto (o copia la URL en tu ventana de incógnito):
https://console.cloud.google.com/projectcreate
  1. Ingresa los detalles de tu proyecto:
    • Nombre del proyecto: Por ejemplo, google-cloud-workshop
    • Cuenta de facturación (si se muestra): Selecciona GDP Credit (o tu cuenta de facturación activa).
    • Recurso superior: Sin organización (o selecciona tu organización si es necesario)
  2. Anota el ID del proyecto generado que aparece debajo del nombre del proyecto y, luego, haz clic en Crear:

Pantalla de creación de un proyecto de Google Cloud en la que se muestra el nombre del proyecto, el ID del proyecto, el recurso superior y el botón Crear

🔍 Revisa tu trabajo

Haz clic en Notificaciones en la barra de herramientas de la esquina superior derecha y, luego, en Seleccionar proyecto una vez que finalice la creación del proyecto:

Menú Notificaciones de la consola de Google Cloud que muestra Crear proyecto y el vínculo Seleccionar proyecto

4. Configura tu entorno

Configurar Google Cloud Shell, habilitar la API de Agent Platform y crear un entorno virtual aislado de Python 3.12 con uv

Configura Cloud Shell

  1. Haz clic en Activar Cloud Shell (>_) en la barra de herramientas de la consola de Google Cloud o abre Google Cloud Shell directamente (o copia la URL en tu ventana de incógnito):
https://shell.cloud.google.com/?show=ide,terminal

Botón Activar Cloud Shell en la barra de herramientas de la consola de Google Cloud

  1. Haz clic en Autorizar cuando se te solicite:

Cuadro de diálogo Autorizar Cloud Shell

  1. Selecciona el ID del proyecto de Google Cloud activo en el menú numerado de la 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

Deberías ver un resultado similar al siguiente (los proyectos sin etiquetas también imprimen una línea 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 que el ID del proyecto que seleccionaste aparezca destacado en amarillo en el mensaje de Cloud Shell:

Terminal de Cloud Shell que muestra el ID del proyecto seleccionado destacado en amarillo

Habilita las APIs obligatorias

Habilita la API de Agent Platform para que tus agentes de ADK puedan invocar modelos de Gemini:

gcloud services enable aiplatform.googleapis.com

Deberías ver un resultado similar a este:

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

Crea un entorno virtual de Python e instala el ADK

Crea el espacio de trabajo de ~/adk-graph-agents y activa un entorno virtual de 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

Confirma que el prefijo (.venv) aparezca al principio del mensaje de la terminal:

Terminal de Cloud Shell que muestra el prefijo .venv en un entorno virtual de Python activo

Instala el ADK 2 dentro del entorno virtual activo:

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

🔍 Revisa tu trabajo

Verifica la versión instalada de la CLI de adk:

adk --version

Deberías ver un resultado similar a este:

adk, version 2.14.0

5. Crea la estructura del planificador de viajes

Genera el paquete de inicio travel_planner con adk create y prueba el modelo de referencia predeterminado de un solo agente en adk web.

Genera el paquete de inicio

Ejecuta adk create desde ~/adk-graph-agents:

cd ~/adk-graph-agents
adk create travel_planner

Selecciona las siguientes opciones cuando se te solicite (si se te solicita Enable telemetry? [Y/n]: en la primera ejecución, presiona Intro o escribe n y presiona Intro):

  1. Elige un modelo para el agente raíz: Escribe 2 para seleccionar gemini-3.8-flash (la opción 1 selecciona gemini-3.5-flash) y presiona Intro.
  2. Elige un backend: Escribe 2 para seleccionar el backend de Agent Platform de Google Cloud (opción 2 en el menú de la CLI que aparece a continuación) y presiona Intro.
  3. Ingresa el ID del proyecto de Google Cloud: Presiona Intro para aceptar el ID del proyecto detectado entre corchetes.
  4. Ingresa la región de Google Cloud: Escribe global (para usar el extremo global de Gemini) y presiona Intro.

adk create escribe GOOGLE_GENAI_USE_ENTERPRISE=1, el ID del proyecto y GOOGLE_CLOUD_LOCATION=global en travel_planner/.env, por lo que tus credenciales permanecen intactas cuando reemplazas agent.py más adelante.

Deberías ver un resultado similar a este:

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

Abre ~/adk-graph-agents en el editor de código de Cloud Shell:

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

Vuelve a activar tu entorno virtual en la terminal que se volvió a cargar:

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

Prueba el agente único inicial

Inicia la IU web del ADK para observar cómo un solo agente de inicio sin organización responde a una instrucción de viaje:

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

Haz clic en el ícono de Vista previa en la Web en la barra de herramientas de Cloud Shell, en la esquina superior derecha, selecciona Cambiar puerto, ingresa 8000 y haz clic en Cambiar y obtener vista previa:

Diálogo de configuración del puerto de la vista previa en la Web de Cloud Shell establecido en 8000

🔍 Revisa tu trabajo

Selecciona travel_planner en el menú desplegable de la esquina superior izquierda de adk web y envía "Help me plan a trip to Japan":

IU web de desarrollo del ADK que muestra una conversación básica con un solo agente

Deberías ver una respuesta conversacional de un solo paso en el panel de chat (con una sola invocación de root_agent en Eventos):

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

Presiona Ctrl + C en la terminal de Cloud Shell para detener adk web antes de editar archivos en el siguiente paso.

6. Crea un flujo de trabajo de grafo lineal

Crea tu primer ADK 2 Workflow: una cadena secuencial que conecte el punto de entrada reservado "START" con user_profiler_agent y itinerary_synthesizer_agent (cualquier nodo sin bordes salientes actúa como un nodo terminal). Cada borde (a, b) ejecuta automáticamente los nodos Agent (un alias para LlmAgent) en modo single_turn aislado y entrega el resultado del nodo a como node_input (el mensaje entrante del usuario) al nodo b, mientras que {user_preferences} en una cadena de instrucciones interpola la clave de estado de la sesión coincidente guardada a través de output_key.

Diagrama de arquitectura que muestra travel_workflow (Workflow) que conecta START con user_profiler_agent y itinerary_synthesizer_agent

Crea los especialistas iniciales

Asegúrate de que adk web esté detenido (Ctrl + C) y, luego, abre un archivo nuevo llamado travel_planner/specialists.py:

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

Pega el siguiente código en travel_planner/specialists.py para definir user_profiler_agent y itinerary_synthesizer_agent (importando google_search por adelantado para el siguiente paso):

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",
)

Define la cadena de bordes secuenciales

Abre un archivo nuevo llamado travel_planner/workflows.py:

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

Pega la siguiente definición de Workflow (en la que una tupla de 3 o más nodos se compila en una cadena secuencial 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),
    ],
)

Expón el flujo de trabajo como root_agent

Abre travel_planner/agent.py:

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

Reemplaza todo el contenido de travel_planner/agent.py por estas dos líneas:

from .workflows import travel_workflow

root_agent = travel_workflow

🔍 Revisa tu trabajo

Inicia adk web desde ~/adk-graph-agents:

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

Abre la vista previa en la Web en el puerto 8000, haz clic en + Nueva sesión y envía lo siguiente:

Help me plan a trip to Kyoto

En la vista Eventos, deberías ver una secuencia de eventos similar a la siguiente:

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

IU web de ADK 2.14.0 que muestra la ejecución por grafos de START a user_profiler_agent a itinerary_synthesizer_agent y el itinerario de Kioto generado

Haz clic en cualquier evento de Eventos y, luego, en el ícono de Gráfico (account_tree en la barra de herramientas de detalles del evento) para inspeccionar la topología de START -> user_profiler_agent -> itinerary_synthesizer_agent compilada. Luego, revisa la pestaña Estado para verificar que user_preferences y final_itinerary estén propagados.

Presiona Ctrl + C en la terminal para detener adk web antes de continuar.

7. Distribución y unión con JoinNode

Para fundamentar el itinerario en datos web en tiempo real, agrega dos especialistas de google_search simultáneos (activity_finder_agent y restaurant_finder_agent) y sincronízalos con JoinNode:

  • Tupla de distribución: Colocar (activity_finder_agent, restaurant_finder_agent) dentro de la tupla de borde entrega el resultado de user_profiler_agent como node_input a ambos investigadores de forma simultánea.
  • Barrera de distribución de entrada (JoinNode): Colocar JoinNode(name="research_join") justo después de la tupla espera hasta que cada rama entrante se complete y pase un dict ({"activity_finder_agent": ..., "restaurant_finder_agent": ...}) combinado como node_input a itinerary_synthesizer_agent en lugar de activar la síntesis dos veces.

Diagrama de arquitectura que muestra travel_workflow que se extiende desde user_profiler_agent a través de node_input hasta activity_finder_agent y restaurant_finder_agent en paralelo, se combina en research_join (JoinNode) y pasa node_input (dict) a itinerary_synthesizer_agent

Agrega los especialistas en investigación

Confirma que adk web se haya detenido (Ctrl + C) y, luego, abre travel_planner/specialists.py:

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

Agrega activity_finder_agent y restaurant_finder_agent a la parte inferior de travel_planner/specialists.py (ninguno necesita output_key porque research_join reenvía ambos resultados directamente a través de 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],
)

Agrega fan-out y JoinNode a workflows.py

Abre travel_planner/workflows.py:

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

Reemplaza todo el contenido de travel_planner/workflows.py por el grafo de distribución ramificada y 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,
        ),
    ],
)

🔍 Revisa tu trabajo

Inicia adk web para probar la búsqueda simultánea y la sincronización de JoinNode:

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

Abre la vista previa en la Web en el puerto 8000, haz clic en + Nueva sesión y envía lo siguiente:

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

En la vista Eventos, deberías ver una secuencia de eventos similar a la siguiente:

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}

Presiona Ctrl + C en la terminal para detener adk web antes de continuar.

8. Ciclos de revisión de rutas

Aplica restricciones de presupuesto y negativas agregando un itinerary_critic_agent, un itinerary_refiner_agent y dos nodos de función de Python determinísticos (route_critique y finalize_itinerary) que devuelvan objetos Event del ADK:

  • route: Selecciona qué clave de rama con nombre en un borde de dict ({"revise": ..., "approved": ...}) se ejecuta a continuación.
  • output: Pasa un valor o una cadena de Python con tipo a lo largo de la arista como node_input al siguiente nodo sin renderizar un mensaje de chat.
  • message y state: message emite texto visible para el usuario en la transcripción del chat, mientras que state confirma las actualizaciones de pares clave-valor (stateDelta) en el estado de la sesión.

Diagrama de arquitectura que muestra travel_workflow con itinerary_critic_agent que alimenta route_critique, que enruta 'revise' a itinerary_refiner_agent (que vuelve a itinerary_critic_agent) o 'approved' a finalize_itinerary

Agrega los especialistas de crítica y perfeccionamiento

Confirma que adk web se haya detenido (Ctrl + C) y, luego, abre travel_planner/specialists.py:

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

Agrega itinerary_critic_agent y itinerary_refiner_agent al final de travel_planner/specialists.py (el refinador no necesita ninguna herramienta google_search ni exit_loop porque intercambia elementos que ya se recopilaron en {final_itinerary} y solo se ejecuta cuando route_critique selecciona "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",
)

Agrega route_critique y el ciclo

Abre travel_planner/workflows.py:

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

Reemplaza todo el contenido de travel_planner/workflows.py por el flujo de trabajo de grafo completo:

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),
    ],
)

🔍 Revisa tu trabajo

Verifica que travel_planner/workflows.py se compile de forma correcta y que imprima los bordes del grafo dirigido:

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

Deberías ver un resultado similar a este:

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

A continuación, inicia adk web para probar la aprobación inmediata y las revisiones activadas por el presupuesto:

adk web --allow_origins "*"

Abre la vista previa en la Web en el puerto 8000, haz clic en + Nueva sesión y envía la instrucción de Kioto con varias restricciones:

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.

Para ver el bucle route="revise" en acción, envía una instrucción de seguimiento con un presupuesto ajustado de USD 15:

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

En la vista Eventos, deberías ver una secuencia de ejecución similar a la siguiente:

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

Presiona Ctrl + C en la terminal para detener adk web.

9. Solución de problemas

El menú desplegable de agentes está vacío en adk web

  • Causa: Se inició adk web dentro de travel_planner/ en lugar del directorio superior ~/adk-graph-agents, o se reinició la sesión de Cloud Shell.
  • Solución: Presiona Ctrl + C, vuelve al directorio superior y reinicia con cd ~/adk-graph-agents && source .venv/bin/activate && adk web --allow_origins "*".

404 NOT_FOUND error del modelo

  • Causa: Presionaste Intro para aceptar la región predeterminada us-central1 durante adk create en lugar de escribir global.
  • Solución: Abre ~/adk-graph-agents/travel_planner/.env y asegúrate de que GOOGLE_CLOUD_LOCATION=global esté configurado.

ERROR: [Errno 98] address already in use en el puerto 8000

  • Causa: Un servidor adk web anterior aún se está ejecutando en Cloud Shell.
  • Solución: Presiona Ctrl + C en la terminal activa o detén el proceso existente con pkill -f "adk web" antes de volver a iniciar adk web.

10. Limpia

Quita el espacio de trabajo local y, de manera opcional, inhabilita la API o borra un proyecto de taller dedicado.

Borra los archivos del proyecto local

Quita el directorio ~/adk-graph-agents y el entorno virtual:

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

Inhabilita la API de Agent Platform (opcional)

Inhabilita la API de Agent Platform si ya no la necesitas en este proyecto:

gcloud services disable aiplatform.googleapis.com --quiet

🔍 Revisa tu trabajo

Confirma que se haya quitado ~/adk-graph-agents:

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

Deberías ver un resultado similar a este:

Workspace ~/adk-graph-agents removed

11. Felicitaciones

Creaste un planificador de viajes multiagente con ADK 2 Workflow, unificando cadenas secuenciales, distribución simultánea de google_search con JoinNode y ciclos condicionales de creador-verificador en un solo grafo de bordes declarativo.

Qué lograste

  • Declarar una canalización multiagente con el ADK 2 Workflow(edges=[...])
  • Pasaste datos directamente entre los nodos de funciones de Agent, JoinNode y Python a través de node_input y parámetros vinculados al estado, a la vez que mantuviste el estado de la sesión al mínimo.
  • Se distribuyeron ramas google_search simultáneas y se sincronizaron con JoinNode
  • Se reemplazó el escalamiento de bucle basado en herramientas y LoopAgent por un router Event(route=...) determinista que omite las llamadas innecesarias al LLM en los borradores aprobados.

Próximos pasos