1. Przegląd
Aby spełnić prośbę o zaplanowanie podróży z wieloma ograniczeniami (np. zaplanowanie jednodniowej wycieczki do Kioto za 100 USD, podczas której można zwiedzić zabytkowe świątynie, zjeść lokalny ramen i nie odwiedzać muzeów sztuki nowoczesnej), trzeba wyodrębnić uporządkowane preferencje, jednocześnie wyszukać miejsca, przygotować szczegółowy projekt i sprawdzić łączny koszt przed udzieleniem odpowiedzi. W pakiecie ADK 1.x koordynowanie tych etapów wymagało zagnieżdżania obiektów opakowujących SequentialAgent, ParallelAgent i LoopAgent, zapisywania wszystkich danych wyjściowych pośrednich w stanie sesji i wywoływania dodatkowego wywołania narzędzia LLM tylko po to, aby wyjść z pętli ulepszania.
W tym ćwiczeniu utworzysz wieloagentowy planer podróży na platformie agentów, korzystając z przepływów pracy grafów (Workflow) pakietu Agent Development Kit (ADK) 2. W 3 kolejnych etapach połączysz specjalistyczne węzły Agent (obsługiwane przez gemini-3.8-flash) w sekwencyjny łańcuch krawędzi (node_input), rozproszysz równoczesne procesy badawcze google_search zsynchronizowane z JoinNode oraz wymusisz stosowanie reguł budżetowych i reguł wykluczających za pomocą deterministycznego routera Pythona (Event(route=...)), który pomija ulepszanie, gdy wstępna wersja robocza przejdzie kontrolę.
Wymagania wstępne
- podstawowa znajomość programowania w Pythonie,
- Znajomość pojęć związanych z generatywną AI i podstaw pracy z agentami AI.
Czego się nauczysz
- Jak zadeklarować potok wieloagentowy w ADK 2 przy użyciu krotek krawędzi
Workflow - Jak ADK 2 przekazuje dane wyjściowe bezpośrednio wzdłuż krawędzi jako
node_inputi wiąże klucze stanu sesji jako parametry funkcji - Jak rozgałęziać równoległe gałęzie badań i scalać ich wyniki za pomocą
JoinNode - Jak deterministycznie kierować ograniczone cykle maker-checker w Pythonie za pomocą
Event(route=...) - jak sprawdzać skompilowane wykresy przepływu pracy, osie czasu wykonywania równoległego i delty stanu w interfejsie internetowym ADK.
Wymagania
- konto Google (jeśli chcesz otrzymać punkty za warsztaty, użyj osobistego konta
@gmail.com); - link do środków na warsztaty od instruktora (oraz aparat w telefonie do zeskanowania kodu QR) lub aktywne konto rozliczeniowe Cloud.
- Google Chrome (zalecamy używanie okna incognito, aby uniknąć mieszania kont osobistych i służbowych).
2. Odbierz środki na Google Cloud (opcjonalnie)
Jeśli uczestniczysz w warsztatach z linkiem do środków na wydarzenie, odbierz środki w ramach programu Google Developer Program, aby utworzyć konto rozliczeniowe bez karty kredytowej.
Odbierz środki na wydarzenie
- Otwórz link do środków na warsztaty w oknie incognito i zaloguj się na konto
@gmail.com. - W sekcji Odbierz korzyści kliknij Odbierz środki:

- Jeśli pojawi się prośba o utworzenie profilu w programie Google Developer Program, wypełnij formularz.
- Gdy pojawi się komunikat Zeskanuj, aby potwierdzić, że jesteś człowiekiem, zeskanuj kod QR telefonem i dokończ weryfikację (jeśli kod QR się nie pojawi, odśwież stronę i ponownie kliknij Odbierz środki):

- Sprawdź, czy pojawił się komunikat Udało Ci się odebrać środki na wydarzenie, a następnie kliknij Otwórz konto rozliczeniowe:

🔍 Sprawdź swoją pracę
Konfigurowanie konta rozliczeniowego zajmuje do 3 minut:
- Otwórz Rozliczenia usługi Google Cloud (lub skopiuj adres URL do okna incognito) i wybierz Twoje konta rozliczeniowe:
https://console.cloud.google.com/billing
- Odświeżaj stronę, dopóki konto
GDP Creditnie będzie miało stanu Aktywne:

3. Tworzenie projektu Google Cloud (opcjonalnie)
Utwórz dedykowany projekt Google Cloud, aby wszystkie zasoby z tego ćwiczenia były odizolowane i łatwe do usunięcia.
- Otwórz stronę Utwórz projekt (lub skopiuj adres URL do okna incognito):
https://console.cloud.google.com/projectcreate
- Wpisz szczegóły projektu:
- Nazwa projektu: na przykład
google-cloud-workshop. - Konto rozliczeniowe (jeśli jest widoczne): wybierz
GDP Credit(lub aktywne konto rozliczeniowe). - Zasób nadrzędny: Brak organizacji (lub wybierz organizację, jeśli jest to wymagane)
- Nazwa projektu: na przykład
- Zanotuj wygenerowany identyfikator projektu pod nazwą projektu, a następnie kliknij Utwórz:

🔍 Sprawdź swoją pracę
Na pasku narzędzi w prawym górnym rogu kliknij Powiadomienia, a po zakończeniu tworzenia projektu kliknij Wybierz projekt:

4. Konfigurowanie środowiska
Skonfiguruj Google Cloud Shell, włącz interfejs Agent Platform API i utwórz odizolowane środowisko wirtualne Python 3.12 za pomocą uv.
Konfigurowanie Cloud Shell
- Kliknij Aktywuj Cloud Shell (
>_) na pasku narzędzi konsoli Google Cloud lub otwórz Google Cloud Shell bezpośrednio (albo skopiuj adres URL do okna incognito):
https://shell.cloud.google.com/?show=ide,terminal

- Jeśli pojawi się prośba o autoryzację, kliknij Autoryzuj:

- Wybierz aktywny identyfikator projektu Google Cloud z menu numerycznego w terminalu:
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
Dane wyjściowe powinny być podobne do tych (projekty bez tagów zawierają też wiersz informacyjny [environment: untagged]):
1) google-cloud-workshop-4210 2) my-cloud-project-8812 Select your project (e.g. 1): 1 Updated property [core/project].
Sprawdź, czy wybrany identyfikator projektu jest podświetlony na żółto w promptu Cloud Shell:

Włącz wymagane interfejsy API
Włącz Agent Platform API, aby agenty ADK mogły wywoływać modele Gemini:
gcloud services enable aiplatform.googleapis.com
Dane wyjściowe powinny być podobne do tych:
Operation "operations/acat.p2-..." finished successfully.
Tworzenie środowiska wirtualnego Pythona i instalowanie pakietu ADK
Utwórz obszar roboczy ~/adk-graph-agents i aktywuj środowisko wirtualne Pythona 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
Sprawdź, czy na początku promptu w terminalu pojawia się prefiks (.venv):

Zainstaluj ADK 2 w aktywnym środowisku wirtualnym:
uv pip install --no-cache "google-adk==2.14.0"
🔍 Sprawdź swoją pracę
Sprawdź zainstalowaną wersję interfejsu wiersza poleceń adk:
adk --version
Dane wyjściowe powinny być podobne do tych:
adk, version 2.14.0
5. Tworzenie szkieletu planera podróży
Wygeneruj pakiet startowy travel_planner za pomocą adk create i przetestuj domyślny punkt odniesienia z jednym agentem w adk web.
Wygeneruj pakiet startowy
Uruchom adk create z ~/adk-graph-agents:
cd ~/adk-graph-agents
adk create travel_planner
Gdy pojawi się prośba, wybierz te opcje (jeśli przy pierwszym uruchomieniu pojawi się prośba o Enable telemetry? [Y/n]:, naciśnij Enter lub wpisz n i naciśnij Enter):
- Wybierz model agenta głównego: wpisz
2, aby wybraćgemini-3.8-flash(opcja1wybieragemini-3.5-flash), i naciśnij Enter. - Wybierz backend: wpisz
2, aby wybrać backend Agent Platform Google Cloud (opcja2w menu interfejsu wiersza poleceń poniżej), i naciśnij Enter. - Enter Google Cloud project ID (Wpisz identyfikator projektu Google Cloud): naciśnij Enter, aby zaakceptować wykryty identyfikator projektu w nawiasach.
- Enter Google Cloud region (Wpisz region Google Cloud): wpisz
global(aby użyć globalnego punktu końcowego Gemini) i naciśnij Enter.
adk create zapisuje GOOGLE_GENAI_USE_ENTERPRISE=1, identyfikator projektu i GOOGLE_CLOUD_LOCATION=global w travel_planner/.env, dzięki czemu dane logowania pozostają nienaruszone, gdy później zastąpisz agent.py.
Dane wyjściowe powinny być podobne do tych:
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/)
Otwórz plik ~/adk-graph-agents w edytorze kodu Cloud Shell:
which cloudshell >/dev/null 2>&1 && cloudshell workspace ~/adk-graph-agents || true
Ponownie aktywuj środowisko wirtualne w ponownie załadowanym terminalu:
cd ~/adk-graph-agents
source .venv/bin/activate
Testowanie początkowego pojedynczego agenta
Uruchom interfejs internetowy ADK, aby zobaczyć, jak pojedynczy, niezarządzany agent początkowy odpowiada na prompta dotyczącego podróży:
cd ~/adk-graph-agents
adk web --allow_origins "*"
Kliknij ikonę Podgląd w przeglądarce na pasku narzędzi Cloud Shell w prawym górnym rogu, wybierz Zmień port, wpisz 8000 i kliknij Zmień i wyświetl podgląd:

🔍 Sprawdź swoją pracę
Wybierz travel_planner w menu w lewym górnym rogu adk web i wyślij "Help me plan a trip to Japan":

W panelu czatu powinna pojawić się odpowiedź konwersacyjna (z jednym wywołaniem root_agent w sekcji Zdarzenia):
root_agent -> responds in one pass without structured preference extraction, live search, or budget verification
Zanim przejdziesz do edytowania plików w następnym kroku, naciśnij Ctrl + C w terminalu Cloud Shell, aby zatrzymać adk web.
6. Tworzenie przepływu pracy z wykresem liniowym
Utwórz pierwszy ADK 2 Workflow: sekwencyjny łańcuch łączący zarezerwowany punkt wejścia "START" z user_profiler_agent i itinerary_synthesizer_agent (każdy węzeł bez krawędzi wychodzących działa jako węzeł końcowy). Każda krawędź (a, b) automatycznie uruchamia węzły Agent (alias dla LlmAgent) w odizolowanym trybie single_turn i dostarcza dane wyjściowe węzła a jako node_input (przychodząca wiadomość użytkownika) do węzła b, podczas gdy {user_preferences} w ciągu instrukcji interpoluje pasujący klucz stanu sesji zapisany za pomocą output_key.

Tworzenie początkowych specjalistów
Upewnij się, że usługa adk web jest zatrzymana (Ctrl + C), a następnie otwórz nowy plik o nazwie travel_planner/specialists.py:
cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py
Wklej ten kod do pliku travel_planner/specialists.py, aby zdefiniować user_profiler_agent i itinerary_synthesizer_agent (importując google_search na potrzeby następnego kroku):
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",
)
Definiowanie sekwencyjnego łańcucha krawędzi
Otwórz nowy plik o nazwie travel_planner/workflows.py:
cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py
Wklej tę definicję Workflow (gdzie krotka składająca się z co najmniej 3 węzłów kompiluje się w łańcuch sekwencyjny z "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),
],
)
Udostępnij przepływ pracy jako root_agent
Otwórz travel_planner/agent.py:
cloudshell edit ~/adk-graph-agents/travel_planner/agent.py
Zastąp całą zawartość pliku travel_planner/agent.py tymi 2 wierszami:
from .workflows import travel_workflow
root_agent = travel_workflow
🔍 Sprawdź swoją pracę
Uruchom adk web z ~/adk-graph-agents:
cd ~/adk-graph-agents
adk web --allow_origins "*"
Otwórz podgląd w przeglądarce na porcie 8000, kliknij + Nowa sesja i wyślij:
Help me plan a trip to Kyoto
W widoku Zdarzenia powinna być widoczna sekwencja zdarzeń podobna do tej:
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

Kliknij dowolne zdarzenie w sekcji Zdarzenia, a następnie kliknij ikonę Wykres (account_tree na pasku narzędzi szczegółów zdarzenia), aby sprawdzić skompilowaną topologię START -> user_profiler_agent -> itinerary_synthesizer_agent. Następnie sprawdź kartę Stan, aby upewnić się, że pola user_preferences i final_itinerary są wypełnione.
Zanim przejdziesz dalej, naciśnij Ctrl + C w terminalu, aby zatrzymać adk web.
7. Rozgałęzianie i łączenie za pomocą węzła JoinNode
Oprzyj plan podróży na danych z internetu, dodając 2 specjalistów google_search (activity_finder_agent i restaurant_finder_agent) i synchronizując ich z JoinNode:
- Krotka rozsyłania: umieszczenie
(activity_finder_agent, restaurant_finder_agent)w krotce krawędzi powoduje, że dane wyjścioweuser_profiler_agentsą dostarczane jakonode_inputdo obu badaczy jednocześnie. - Bariera fan-in (
JoinNode): umieszczenieJoinNode(name="research_join")zaraz po krotce powoduje, że system czeka, aż każda gałąź przychodząca zostanie ukończona, i przekazuje jedną scaloną wartośćdict({"activity_finder_agent": ..., "restaurant_finder_agent": ...}) jakonode_inputdoitinerary_synthesizer_agentzamiast dwukrotnego uruchamiania syntezy.

Dołącz specjalistów ds. badań
Sprawdź, czy usługa adk web jest zatrzymana (Ctrl + C), a następnie otwórz travel_planner/specialists.py:
cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py
Dołącz activity_finder_agent i restaurant_finder_agent na dole pliku travel_planner/specialists.py (żaden z nich nie potrzebuje output_key, ponieważ research_join przekazuje oba wyjścia bezpośrednio przez 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],
)
Dodawanie rozgałęzienia i węzła JoinNode do workflows.py
Otwórz travel_planner/workflows.py:
cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py
Zastąp całą zawartość pliku travel_planner/workflows.py wykresem fan-out i 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,
),
],
)
🔍 Sprawdź swoją pracę
Uruchom adk web, aby przetestować wyszukiwanie równoczesne i synchronizację JoinNode:
cd ~/adk-graph-agents
adk web --allow_origins "*"
Otwórz podgląd w przeglądarce na porcie 8000, kliknij + Nowa sesja i wyślij:
Help me plan a trip to Kyoto focused on historic temples and ramen
W widoku Zdarzenia powinna być widoczna sekwencja zdarzeń podobna do tej:
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}
Zanim przejdziesz dalej, naciśnij Ctrl + C w terminalu, aby zatrzymać adk web.
8. Cykle sprawdzania tras
Wymuś ograniczenia budżetu i ograniczenia ujemne, dodając węzeł itinerary_critic_agent, węzeł itinerary_refiner_agent i 2 węzły deterministycznej funkcji Pythona (route_critique i finalize_itinerary), które zwracają obiekty ADK Event:
route: wybiera, który nazwany klucz gałęzi w krawędzi słownika ({"revise": ..., "approved": ...}) zostanie uruchomiony jako następny.output: przekazuje wpisaną wartość lub ciąg znaków w Pythonie wzdłuż krawędzi jakonode_inputdo następnego węzła bez renderowania wiadomości na czacie.messageistate:messageemituje tekst widoczny dla użytkownika w transkrypcji czatu, astatezatwierdza aktualizacje klucz-wartość (stateDelta) w stanie sesji.

Dołączanie specjalistów od krytyki i ulepszania
Sprawdź, czy usługa adk web jest zatrzymana (Ctrl + C), a następnie otwórz travel_planner/specialists.py:
cloudshell edit ~/adk-graph-agents/travel_planner/specialists.py
Dołącz itinerary_critic_agent i itinerary_refiner_agent na dole travel_planner/specialists.py (rafiner nie potrzebuje narzędzia google_search ani exit_loop, ponieważ zamienia elementy zebrane już w {final_itinerary} i działa tylko wtedy, gdy route_critique wybierze "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",
)
Dodaj route_critique i cykl
Otwórz travel_planner/workflows.py:
cloudshell edit ~/adk-graph-agents/travel_planner/workflows.py
Zastąp całą zawartość pliku travel_planner/workflows.py pełnym przepływem pracy grafu:
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),
],
)
🔍 Sprawdź swoją pracę
Sprawdź, czy travel_planner/workflows.py kompiluje się bez błędów i wyświetla krawędzie grafu skierowanego:
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))"
Dane wyjściowe powinny być podobne do tych:
__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)
Następnie uruchom adk web, aby przetestować zarówno natychmiastowe zatwierdzanie, jak i zmiany wywołane przez budżet:
adk web --allow_origins "*"
Otwórz podgląd w przeglądarce na porcie 8000, kliknij + Nowa sesja i wyślij prompta z wieloma ograniczeniami dotyczącego Kioto:
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.
Aby zobaczyć, jak działa pętla route="revise", wyślij kolejnego prompta z ograniczonym budżetem 15 USD:
Now design a full-day Kyoto itinerary with paid temple admissions, lunch, and dinner on a strict total budget of $15 USD.
W widoku Zdarzenia powinna być widoczna sekwencja wykonywania podobna do tej:
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
W terminalu naciśnij Ctrl + C, aby zatrzymać adk web.
9. Rozwiązywanie problemów
Menu agenta jest puste w: adk web
- Przyczyna: polecenie
adk webzostało uruchomione w katalogutravel_planner/zamiast w katalogu nadrzędnym~/adk-graph-agentslub sesja Cloud Shell została uruchomiona ponownie. - Rozwiązanie: naciśnij
Ctrl + C, wróć do katalogu nadrzędnego i ponownie uruchom poleceniecd ~/adk-graph-agents && source .venv/bin/activate && adk web --allow_origins "*".
404 NOT_FOUND błąd modelu
- Przyczyna: podczas
adk createnaciśnięto Enter, aby zaakceptować domyślny regionus-central1, zamiast wpisaćglobal. - Rozwiązanie: otwórz
~/adk-graph-agents/travel_planner/.envi upewnij się, że ustawionoGOOGLE_CLOUD_LOCATION=global.
ERROR: [Errno 98] address already in use na porcie 8000
- Przyczyna: poprzedni serwer
adk webnadal działa w Cloud Shell. - Rozwiązanie: naciśnij
Ctrl + Cw aktywnym terminalu lub zatrzymaj istniejący proces za pomocąpkill -f "adk web", zanim ponownie uruchomiszadk web.
10. Czyszczenie danych
Usuń lokalny obszar roboczy i opcjonalnie wyłącz interfejs API lub usuń dedykowany projekt warsztatowy.
Usuwanie lokalnych plików projektu
Usuń katalog ~/adk-graph-agents i środowisko wirtualne:
cd ~
rm -rf ~/adk-graph-agents
Wyłączanie interfejsu Agent Platform API (opcjonalnie)
Wyłącz Agent Platform API, jeśli nie potrzebujesz już tego interfejsu w tym projekcie:
gcloud services disable aiplatform.googleapis.com --quiet
🔍 Sprawdź swoją pracę
Potwierdź, że usunięto ~/adk-graph-agents:
test ! -d ~/adk-graph-agents && echo "Workspace ~/adk-graph-agents removed"
Dane wyjściowe powinny być podobne do tych:
Workspace ~/adk-graph-agents removed
11. Gratulacje
Udało Ci się utworzyć wieloagentowy system planowania podróży za pomocą pakietu ADK 2 Workflow, łącząc sekwencyjne łańcuchy, równoległe rozgałęzianie google_search z JoinNode oraz warunkowe cykle weryfikacji w jednym deklaratywnym grafie krawędziowym.
osiągnięcia,
- Zadeklarowano potok wieloagentowy za pomocą ADK 2
Workflow(edges=[...]) - Przekazywanie danych bezpośrednio między węzłami funkcji
Agent,JoinNodei Python za pomocą parametrównode_inputi parametrów powiązanych ze stanem przy zachowaniu minimalnego stanu sesji. - Rozgałęziono równoległe gałęzie
google_searchi zsynchronizowano je zJoinNode - Zastąpiono
LoopAgenti eskalację pętli opartą na narzędziach deterministycznym routeremEvent(route=...), który pomija niepotrzebne wywołania LLM w zatwierdzonych wersjach roboczych.
Dalsze kroki
- Poznaj systemy wieloagentowe w pakiecie ADK.
- Dołącz do programu GEAR (Gemini Enterprise Agent Ready) i programu Get Certified, aby wziąć udział w warsztatach praktycznych i ścieżkach szkoleniowych.