ADK ile Yapay Zeka Ajanları Oluşturma: Grafik İş Akışlarını Yönetme

1. Genel Bakış

Birden fazla kısıtlamanın olduğu bir seyahat isteğini yerine getirmek (ör. Kyoto'da tarihi tapınakları ve yerel ramen restoranlarını içeren, ART Museum'ların olmadığı 100 dolarlık bir günlük gezi planlamak) için yapılandırılmış tercihleri ayıklamak, mekanları aynı anda araştırmak, ayrıntılı bir taslak oluşturmak ve yanıt vermeden önce toplam maliyeti denetlemek gerekir. ADK 1.x'te bu aşamaları yönetmek için SequentialAgent, ParallelAgent ve LoopAgent sarmalayıcılarını iç içe yerleştirmek, her ara çıkışı oturum durumuna kaydetmek ve yalnızca bir iyileştirme döngüsünden çıkmak için fazladan bir LLM aracı çağrısı yapmak gerekiyordu.

Bu codelab'de, Agent Development Kit (ADK) 2 grafik iş akışlarını (Workflow) kullanarak Agent Platform'da birden fazla temsilci içeren bir seyahat planlayıcı oluşturacaksınız. Üç aşamada, uzman Agent düğümlerini (gemini-3.8-flash tarafından desteklenir) sıralı bir kenar zincirine (node_input) bağlayacak, JoinNode ile senkronize edilmiş eşzamanlı google_search araştırmacıları dağıtacak ve ilk taslak denetimi geçtiğinde iyileştirmeyi atlayan deterministik bir Python yönlendiricisi (Event(route=...)) ile bütçe ve hariç tutma kurallarını uygulayacaksınız.

Ön koşullar

Öğrenecekleriniz

  • Workflow kenar demetlerini kullanarak ADK 2'de çoklu temsilci ardışık düzeni tanımlama
  • ADK 2, çıkışları kenarlar boyunca doğrudan node_input olarak nasıl iletir ve oturum durumu anahtarlarını işlev parametreleri olarak nasıl bağlar?
  • JoinNode ile eşzamanlı araştırma dallarını dağıtma ve çıktılarını birleştirme
  • Event(route=...) ile Python'da sınırlı yapıcı-kontrolör döngülerini deterministik olarak yönlendirme
  • ADK Web kullanıcı arayüzünde derlenmiş iş akışı grafiklerini, paralel yürütme zaman çizelgelerini ve durum deltalarını inceleme

İhtiyacınız olanlar

  • Google Hesabı (Atölye kredisi talep ediyorsanız kişisel @gmail.com hesabı kullanın)
  • Eğitmeninizden aldığınız atölye kredisi bağlantısı (ve QR kodunu taramak için telefon kamerası) veya etkin bir Cloud Faturalandırma Hesabı
  • Google Chrome (Kişisel hesaplar ile iş hesaplarının karışmaması için gizli pencere kullanılması önerilir.)

2. Google Cloud kredilerini kullanma (isteğe bağlı)

Etkinlik kredisi bağlantısı içeren bir atölyeye katılıyorsanız kredi kartı olmadan faturalandırma hesabı oluşturmak için Google Developer Program kredinizi kullanın.

Etkinlik kredinizi alma

  1. Atölye kredisi bağlantısını gizli pencerede açın ve @gmail.com hesabınızla oturum açın.
  2. Avantajınızı Kullanın sayfasında Krediyi Kullan'ı tıklayın:

Google Builders Hub'da "Kredinizi alın" düğmesini gösteren "Avantajınızı alın" kartı

  1. Google Developer Program profili oluşturmanız istenirse formu doldurun.
  2. Gerçek Kişi Olduğunuzu Doğrulamak İçin Tarayın ifadesi göründüğünde QR kodunu telefonunuzla tarayın ve doğrulamayı tamamlayın (QR kodu görünmüyorsa sayfayı yenileyip Krediyi Al'ı tekrar tıklayın):

Google Developer Program'da gerçek bir kişi olduğunuzu doğrulamak için QR kodunu tarayın iletişim kutusu

  1. Etkinlik kredinizi başarıyla kullandınız ifadesinin göründüğünü onaylayın, ardından Faturalandırma Hesabını Aç'ı tıklayın:

Google Builders Hub'da "Etkinlik kredinizi başarıyla kullandınız" mesajı ve "Faturalandırma Hesabını Aç" düğmesi gösteriliyor.

🔍 Çalışmanızı kontrol edin

Faturalandırma hesabı kurulumu 3 dakika kadar sürer:

  1. Google Cloud Billing'i açın (veya URL'yi gizli pencerenize kopyalayın) ve Faturalandırma hesaplarınız'ı seçin:
https://console.cloud.google.com/billing
  1. GDP Credit hesabınızın durumu Etkin olarak gösterilene kadar sayfayı yenileyin:

Etkin bir GDP Kredisi faturalandırma hesabını gösteren Google Cloud Faturalandırma Hesabı yönetimi

3. Google Cloud projesi oluşturma (isteğe bağlı)

Bu codelab'deki tüm kaynakların izole kalması ve kolayca temizlenebilmesi için özel bir Google Cloud projesi oluşturun.

  1. Proje Oluşturma sayfasını açın (veya URL'yi gizli pencerenize kopyalayın):
https://console.cloud.google.com/projectcreate
  1. Proje ayrıntılarınızı girin:
    • Proje adı: Örneğin, google-cloud-workshop
    • Faturalandırma hesabı (gösteriliyorsa): GDP Credit (veya etkin faturalandırma hesabınızı) seçin.
    • Üst kaynak: Kuruluş yok (veya gerekirse kuruluşunuzu seçin)
  2. Proje adının altında oluşturulan Proje Kimliği'ni not edin ve Oluştur'u tıklayın:

Proje adı, proje kimliği, üst kaynak ve Oluştur düğmesinin gösterildiği Google Cloud projesi oluşturma ekranı

🔍 Çalışmanızı kontrol edin

Sağ üstteki araç çubuğunda Bildirimler'i tıklayın ve proje oluşturma işlemi tamamlandığında Proje Seç'i tıklayın:

Proje Oluştur ve Proje Seç bağlantısını gösteren Google Cloud Console Bildirimler menüsü

4. Ortamınızı ayarlama

Google Cloud Shell'i yapılandırın, Agent Platform API'yi etkinleştirin ve uv ile izole bir Python 3.12 sanal ortamı oluşturun.

Cloud Shell'i yapılandırma

  1. Google Cloud konsolu araç çubuğunda Cloud Shell'i etkinleştir'i (>_) tıklayın veya doğrudan Google Cloud Shell'i açın (ya da URL'yi gizli pencerenize kopyalayın):
https://shell.cloud.google.com/?show=ide,terminal

Google Cloud Console araç çubuğundaki Cloud Shell'i etkinleştir düğmesi

  1. İstenirse Authorize'ı (Yetkilendir) tıklayın:

Cloud Shell'i yetkilendirme iletişim kutusu

  1. Terminalinizdeki numaralı menüden etkin Google Cloud proje kimliğinizi seçin:
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

Aşağıdakine benzer bir çıkış görürsünüz (etiketlenmemiş projeler de bilgilendirici bir [environment: untagged] satırı yazdırır):

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

Seçtiğiniz proje kimliğinin Cloud Shell isteminde sarı renkle vurgulandığını doğrulayın:

Seçilen proje kimliğinin sarı renkle vurgulandığı Cloud Shell terminali

Gerekli API'leri etkinleştirme

ADK temsilcilerinizin Gemini modellerini çağırabilmesi için Agent Platform API'yi etkinleştirin:

gcloud services enable aiplatform.googleapis.com

Şuna benzer bir çıkış alırsınız:

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

Python sanal ortamı oluşturma ve ADK'yi yükleme

~/adk-graph-agents çalışma alanını oluşturun ve Python 3.12 sanal ortamını etkinleştirin:

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

Terminal isteminizin başında (.venv) ön ekinin göründüğünü doğrulayın:

Etkin bir Python sanal ortamında .venv ön ekini gösteren Cloud Shell terminali

Etkin sanal ortamda ADK 2'yi yükleyin:

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

🔍 Çalışmanızı kontrol edin

Yüklü adk CLI sürümünü doğrulayın:

adk --version

Şuna benzer bir çıkış alırsınız:

adk, version 2.14.0

5. Seyahat planlayıcıyı oluşturma

adk create ile başlangıç travel_planner paketini oluşturun ve adk web'da varsayılan tek temsilci referansını test edin.

Başlangıç paketini oluşturma

~/adk-graph-agents becerisinden adk create dosyasını çalıştır:

cd ~/adk-graph-agents
adk create travel_planner

İstendiğinde aşağıdaki seçenekleri belirleyin (ilk çalıştırmada Enable telemetry? [Y/n]: ile istenirse Enter tuşuna basın veya n yazıp Enter tuşuna basın):

  1. Kök temsilci için bir model seçin: gemini-3.8-flash modelini seçmek için 2 yazın (1 seçeneği gemini-3.5-flash modelini seçer) ve Enter tuşuna basın.
  2. Arka uç seçin: Google Cloud Agent Platform arka ucunu seçmek için 2 yazın (aşağıdaki CLI menüsünde 2 seçeneği) ve Enter tuşuna basın.
  3. Enter Google Cloud project ID (Google Cloud proje kimliğini girin): Parantez içinde algılanan proje kimliğinizi kabul etmek için Enter tuşuna basın.
  4. Enter Google Cloud region (Google Cloud bölgesini girin): global yazın (global Gemini uç noktasını kullanmak için) ve Enter tuşuna basın.

adk create, GOOGLE_GENAI_USE_ENTERPRISE=1, proje kimliğiniz ve GOOGLE_CLOUD_LOCATION=global değerlerini travel_planner/.env dosyasına yazar. Böylece daha sonra agent.py dosyasını değiştirdiğinizde kimlik bilgileriniz bozulmaz.

Şuna benzer bir çıkış alırsınız:

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

Cloud Shell kod düzenleyicide ~/adk-graph-agents dosyasını açın:

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

Yeniden yüklenen terminalde sanal ortamınızı yeniden etkinleştirin:

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

Başlangıç seviyesindeki tek temsilciyi test etme

Tek bir düzenlenmemiş başlangıç temsilcisinin seyahat istemine nasıl yanıt verdiğini görmek için ADK Web kullanıcı arayüzünü başlatın:

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

Cloud Shell'in sağ üst kısmındaki araç çubuğunda Web Önizlemesi simgesini tıklayın, Bağlantı Noktasını Değiştir'i seçin, 8000 değerini girin ve Değiştir ve Önizle'yi tıklayın:

Cloud Shell web önizlemesi bağlantı noktası yapılandırma iletişim kutusu 8000 olarak ayarlanmış

🔍 Çalışmanızı kontrol edin

adk web uygulamasının sol üstteki açılır listesinden travel_planner'ı seçin ve "Help me plan a trip to Japan" komutunu gönderin:

Temel bir tek temsilcili görüşmeyi gösteren ADK Development Web UI

Sohbet panelinde tek adımlı bir sohbet yanıtı (Etkinlikler'de tek bir root_agent çağrısı ile) görürsünüz:

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

Bir sonraki adımda dosyaları düzenlemeden önce adk web işlemini durdurmak için Cloud Shell terminalinizde Ctrl + C tuşlarına basın.

6. Doğrusal grafik iş akışı oluşturma

İlk ADK 2'nizi oluşturun Workflow: Ayrılmış "START" giriş noktasını user_profiler_agent ve itinerary_synthesizer_agent'ye bağlayan sıralı bir zincir (giden kenarı olmayan tüm düğümler, terminal düğümü olarak işlev görür). Her uç (a, b), izole single_turn modunda Agent (LlmAgent için bir takma ad) düğümlerini otomatik olarak çalıştırır ve a düğümünün çıkışını node_input (gelen kullanıcı mesajı) olarak b düğümüne iletir. Talimat dizesindeki {user_preferences} ise output_key aracılığıyla kaydedilen eşleşen oturum durumu anahtarını ekler.

START'ı user_profiler_agent ve itinerary_synthesizer_agent'a bağlayan travel_workflow'u (iş akışı) gösteren mimari diyagramı

İlk uzmanları oluşturma

adk web uygulamasının durdurulduğundan (Ctrl + C) emin olun, ardından travel_planner/specialists.py adlı yeni bir dosya açın:

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

user_profiler_agent ve itinerary_synthesizer_agent öğelerini tanımlamak için aşağıdaki kodu travel_planner/specialists.py dosyasına yapıştırın (sonraki adım için google_search öğesini önceden içe aktarın):

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

Sıralı kenar zincirini tanımlama

travel_planner/workflows.py adlı yeni bir dosya açın:

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

Aşağıdaki Workflow tanımını yapıştırın (3 veya daha fazla düğümden oluşan bir grup, "START"'den sıralı bir zincir halinde derlenir):

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

İş akışını root_agent olarak göster

travel_planner/agent.py uygulamasını açın:

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

travel_planner/agent.py dosyasının tüm içeriğini şu iki satırla değiştirin:

from .workflows import travel_workflow

root_agent = travel_workflow

🔍 Çalışmanızı kontrol edin

adk web uygulamasını ~/adk-graph-agents cihazından başlat:

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

8000 bağlantı noktasında Web Önizlemesi'ni açın, + New Session'ı (Yeni Oturum) tıklayın ve şunu gönderin:

Help me plan a trip to Kyoto

Etkinlikler görünümünde şuna benzer bir etkinlik sırası görürsünüz:

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

ADK 2.14.0 web kullanıcı arayüzünde, START'tan user_profiler_agent'a ve itinerary_synthesizer_agent'a grafik yürütme ve oluşturulan Kyoto seyahat planı gösteriliyor.

Events (Etkinlikler) bölümünde herhangi bir etkinliği tıklayın ve derlenen START -> user_profiler_agent -> itinerary_synthesizer_agent topolojisini incelemek için Graph (Grafik) simgesini (etkinlik ayrıntıları araç çubuğunda account_tree) tıklayın. Ardından user_preferences ve final_itinerary değerlerinin doldurulduğunu doğrulamak için State (Durum) sekmesini kontrol edin.

Devam etmeden önce adk web işlemini durdurmak için terminalinizde Ctrl + C tuşlarına basın.

7. JoinNode ile dağıtma ve birleştirme

İki eşzamanlı google_search uzmanı (activity_finder_agent ve restaurant_finder_agent) ekleyip bunları JoinNode ile senkronize ederek seyahat planını canlı web verilerine dayandırın:

  • Fan-out tuple: (activity_finder_agent, restaurant_finder_agent)'yi edge tuple'ın içine yerleştirmek, user_profiler_agent'nin çıkışını her iki araştırmacıya da aynı anda node_input olarak iletir.
  • Fan-in engeli (JoinNode): JoinNode(name="research_join") öğesini demetin hemen arkasına yerleştirmek, sentezi iki kez tetiklemek yerine her gelen dal tamamlanana kadar bekler ve birleştirilmiş bir dict ({"activity_finder_agent": ..., "restaurant_finder_agent": ...}) öğesini node_input olarak itinerary_synthesizer_agent öğesine iletir.

travel_workflow'un user_profiler_agent'tan node_input aracılığıyla activity_finder_agent ve restaurant_finder_agent'a paralel olarak dağıldığını, research_join'de (JoinNode) birleştiğini ve node_input'u (dict) itinerary_synthesizer_agent'a ilettiğini gösteren mimari diyagramı

Araştırma uzmanlarını ekleme

adk web uygulamasının durdurulduğunu (Ctrl + C) onaylayın, ardından travel_planner/specialists.py uygulamasını açın:

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

travel_planner/specialists.py dosyasının altına activity_finder_agent ve restaurant_finder_agent satırlarını ekleyin (research_join, her iki çıkışı da doğrudan node_input üzerinden ilettiği için ikisinde de output_key gerekmez):

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

workflows.py için fan-out ve JoinNode ekleyin

travel_planner/workflows.py uygulamasını açın:

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

travel_planner/workflows.py dosyasının tüm içeriğini, fan-out ve JoinNode grafiğiyle değiştirin:

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

🔍 Çalışmanızı kontrol edin

Eşzamanlı arama ve JoinNode senkronizasyonunu test etmek için adk web başlatın:

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

8000 bağlantı noktasında Web Önizlemesi'ni açın, + New Session'ı (Yeni Oturum) tıklayın ve şunu gönderin:

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

Etkinlikler görünümünde şuna benzer bir etkinlik sırası görürsünüz:

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}

Devam etmeden önce adk web işlemini durdurmak için terminalinizde Ctrl + C tuşlarına basın.

8. Rota revizyon döngüleri

ADK Event nesneleri döndüren bir itinerary_critic_agent, bir itinerary_refiner_agent ve iki deterministik Python işlev düğümü (route_critique ve finalize_itinerary) ekleyerek bütçe ve negatif kısıtlamaları uygulayın:

  • route: Bir sözlük kenarındaki ({"revise": ..., "approved": ...}) hangi adlandırılmış dal anahtarının bir sonraki adımda çalıştırılacağını seçer.
  • output: Yazılan bir Python değerini veya dizesini, sohbet mesajı oluşturmadan bir sonraki düğüme node_input olarak iletir.
  • message ve state: message, sohbet transkriptinde kullanıcı tarafından görülebilen metinler yayınlar. state ise anahtar/değer çifti güncellemelerini (stateDelta) oturum durumuna kaydeder.

travel_workflow'u gösteren mimari diyagram. itinerary_critic_agent, route_critique'i besler. route_critique, "revise" (düzenle) seçeneğini itinerary_refiner_agent'a (itinerary_critic_agent'a geri döner) veya "approved" (onaylandı) seçeneğini finalize_itinerary'ye yönlendirir.

Eleştirmen ve iyileştirici uzmanları ekleme

adk web uygulamasının durdurulduğunu (Ctrl + C) onaylayın, ardından travel_planner/specialists.py uygulamasını açın:

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

travel_planner/specialists.py öğesinin altına itinerary_critic_agent ve itinerary_refiner_agent ekleyin (arıtıcı, {final_itinerary} öğesinde toplanmış öğeleri değiştirdiği ve yalnızca route_critique, "revise" öğesini seçtiğinde çalıştığı için google_search veya exit_loop aracına ihtiyaç duymaz):

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

route_critique ve döngüyü ekleyin

travel_planner/workflows.py uygulamasını açın:

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

travel_planner/workflows.py dosyasının tüm içeriğini tam grafik iş akışıyla değiştirin:

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

🔍 Çalışmanızı kontrol edin

travel_planner/workflows.py öğesinin sorunsuz bir şekilde derlendiğini ve yönlendirilmiş grafik kenarlarını yazdırdığını doğrulayın:

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

Şuna benzer bir çıkış alırsınız:

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

Ardından, hem anında onayı hem de bütçeyle tetiklenen düzeltmeleri test etmek için adk web uygulamasını başlatın:

adk web --allow_origins "*"

8000 bağlantı noktasında Web Preview'u (Web Önizlemesi) açın, + New Session'ı (Yeni Oturum) tıklayın ve çoklu kısıtlama içeren Kyoto istemini gönderin:

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.

route="revise" döngüsünün nasıl çalıştığını görmek için 15 ABD doları bütçeli bir takip istemi gönderin:

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

Events (Etkinlikler) görünümünde şuna benzer bir yürütme sırası görürsünüz:

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

adk web işlemini durdurmak için terminalinizde Ctrl + C tuşuna basın.

9. Sorun giderme

adk web içinde temsilci açılır listesi boş.

  • Nedeni: adk web, üst ~/adk-graph-agents dizini yerine travel_planner/ içinde başlatıldı veya Cloud Shell oturumu yeniden başlatıldı.
  • Düzeltme: Ctrl + C tuşuna basın, ana dizine dönün ve cd ~/adk-graph-agents && source .venv/bin/activate && adk web --allow_origins "*" ile yeniden başlatın.

404 NOT_FOUND model hatası

  • Nedeni: adk create sırasında global yazmak yerine Enter tuşuna basarak varsayılan us-central1 bölgesini kabul ettiniz.
  • Düzeltme: ~/adk-graph-agents/travel_planner/.env dosyasını açın ve GOOGLE_CLOUD_LOCATION=global değerinin ayarlandığından emin olun.

8000 bağlantı noktasında ERROR: [Errno 98] address already in use

  • Nedeni: Önceki bir adk web sunucusu Cloud Shell'de hâlâ çalışıyor.
  • Düzeltme: Etkin terminalde Ctrl + C tuşuna basın veya adk web komutunu tekrar çalıştırmadan önce pkill -f "adk web" komutuyla mevcut işlemi durdurun.

10. Temizleme

Yerel çalışma alanını kaldırın ve isteğe bağlı olarak API'yi devre dışı bırakın veya özel bir atölye projesini silin.

Yerel proje dosyalarını silme

~/adk-graph-agents dizinini ve sanal ortamı kaldırın:

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

Agent Platform API'yi devre dışı bırakma (isteğe bağlı)

Bu projede artık ihtiyacınız yoksa Agent Platform API'yi devre dışı bırakın:

gcloud services disable aiplatform.googleapis.com --quiet

🔍 Çalışmanızı kontrol edin

~/adk-graph-agents adlı kullanıcının kaldırıldığını onaylayın:

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

Şuna benzer bir çıkış alırsınız:

Workspace ~/adk-graph-agents removed

11. Tebrikler

ADK 2 Workflow kullanarak birden fazla temsilci içeren bir seyahat planlayıcı oluşturdunuz. Bu planlayıcıda sıralı zincirleri, JoinNode ile eşzamanlı google_search fan-out'u ve koşullu yapıcı-kontrolör döngülerini tek bir açıklayıcı kenar grafiğinde birleştirdiniz.

Başarılarınız

  • ADK 2 kullanarak çoklu aracı ardışık düzeni tanımlama Workflow(edges=[...])
  • Oturum durumunu minimum düzeyde tutarken node_input ve duruma bağlı parametreler aracılığıyla verileri doğrudan Agent, JoinNode ve Python işlev düğümleri arasında aktardık.
  • Eşzamanlı google_search dalı dağıttı ve bunları JoinNode ile senkronize etti
  • LoopAgent ve araca dayalı döngü ilerletme, onaylanmış taslaklarda gereksiz LLM çağrılarını atlayan deterministik bir Event(route=...) yönlendiriciyle değiştirildi.

Sonraki adımlar