Google ADK ve AP2 ile Güvenilir Yardım Kuruluşu Temsilcileri Oluşturma

1. Cömertliği Teşvik Etmek İçin Güven Oluşturma

banner

İlham Anı

Telefonunuz titrer. Yeterli hizmet alamayan topluluklardaki çocukların okumayı öğrenmesine yardımcı olan başarılı bir okuryazarlık programıyla ilgili bir haber görüyorsunuz. Katkıda bulunmak için güçlü bir istek duyarsınız. Tarayıcınızı açıp "çocukların okuma yazma programı bağışları" ifadesini aradığınızı varsayalım.

google arama

Yüzlerce sonuç gösterilir.

İlk bağlantıyı tıkladığınızda Web sitesi profesyonel görünüyor. Finansal bilgilerine gitmek için aşağı kaydırın. "Yönetim giderleri: %28." Duraklatma Bağışladığınız her doların yalnızca 72 senti programı finanse etmek için kullanılır. Bu iyi bir şey mi? Emin değilsiniz.

Başka bir kuruluş deneyin. Bu kişileri hiç duymadınız. Bunlar meşru mu? Kısa bir arama sizi çıkmaz sokağa götürüyor. İki yıl önce açılmış bir Reddit ileti dizisinde bir kullanıcının "Bu bir dolandırıcılık, bağışım hiçbir yere gitmedi." dediğini görüyorsunuz. Başka bir kullanıcı ise "Gerçek işi yapanlar onlar!" diyerek bu kişileri tutkuyla savunuyor. Belirsizlik, hareketsizliğe neden oluyor.

Otuz dakika sonra, çelişkili yorumlar, verimlilik puanları ve IRS kayıtlarından oluşan bir labirentin derinliklerindesiniz ve hâlâ bağış yapmadınız. Cömertliğin ilk kıvılcımı, araştırmanın zorluğuyla yer değiştirdi. Sekme, iyi niyetinizi hatırlatmak için birkaç gün açık kalır ve sonunda siz kapatırsınız.

Bu Kişisel Bir Başarısızlık Değil, Sistemsel Bir Başarısızlıktır

Bu deneyim evrenseldir. Bağış yapma isteği çok olsa da süreç, tereddüt ve şüpheye neden olan engellerle dolu:

  • Araştırma Sürtünmesi: Her hayır kurumu için ayrı bir araştırma yapılması gerekir.
  • Güven Doğrulaması: Yüksek düzeyde etkili kuruluşları verimsiz olanlardan, hatta dolandırıcılık yapanlardan ayırt etmek zordur.
  • Analize Takılıp Kalma: Çok fazla seçenek sunulması karar yorgunluğuna yol açar.
  • Momentum Kaybı: Lojistik yük arttıkça bağış yapma isteği azalır.

Bu sürtünmenin gerçek dünyada şaşırtıcı bir maliyeti vardır. ABD'de bireysel bağışlar çok büyük bir hacme sahip. Giving USA 2024'e göre, yalnızca 2023'te bireysel bağışçılar yaklaşık 374 milyar ABD doları bağışta bulundu. Ancak araştırmalar, arama maliyetleri, psikolojik sürtünme ve zaman kısıtlamaları gibi bağış yapmayı engelleyen faktörlerin, hayır kurumlarına ulaşan bağış miktarını önemli ölçüde azalttığını gösteriyor. Milyonlarca bağışçının katıldığı araştırmalar, online bağış sürecindeki küçük aksaklıkların bile insanların hayırseverlik amaçlarını gerçekleştirmesini engellediğini gösteriyor.

Bu durum, ihtiyaç sahiplerine ulaşmayan milyarlarca dolarlık bağış anlamına geliyor.

The Vision

Farklı bir deneyim hayal edin. 30 dakikalık bir araştırma oturumu yerine şunları söylemeniz yeterlidir:

"Çocuklar için okuma yazma programına 50 TL bağış yapmak istiyorum. Bana yüksek puanlı, verimli ve doğrulanmış bir hayır kurumu bul."

Saniyeler içinde güven veren bir yanıt alırsınız:

yardım kuruluşu sonuç kartı

Yapay zeka bağış aracının vaadi budur. Ancak bu vizyonu gerçekleştirmek için temel bir zorluğu çözmemiz gerekiyor: Özerk bir yapay zeka aracısı parayı yönettiğinde güven isteğe bağlı değildir, temel unsurdur.

  • Kullanıcının yetkilendirdiği işlemleri nasıl kanıtlayabiliriz?
  • Hata yapılırsa kim hesap verir?
  • Bağışçıların, yardım kuruluşlarının ve ödeme ağlarının katılımını nasıl sağlıyoruz?

Bugünkü Göreviniz

Bu atölyede, iki güçlü teknolojiyi birleştirerek güvenilir bir aracı oluşturacaksınız:

Google Agent Development Kit (ADK)

Agent Payments Protocol (AP2)

Rol

Üretim düzeyinde yapay zeka temsilcileri oluşturmak için fabrika

Yapay zeka işlemlerinde güven için mimari plan

Sunduğu bilgiler

• Çoklu aracı düzenleme çerçevesi
• Araç onaylama gibi yerleşik güvenlik özellikleri
• Üretime hazır gözlemlenebilirlik ve izleme
• Karmaşık aracı davranışları için basit Python arayüzü

• Role dayalı güvenlik sınırları
• Doğrulanabilir dijital kimlik bilgileri (zorunlu)
• İzin için kriptografik kanıt
• Hesap verebilirlik için eksiksiz denetim izleri

Daha fazla bilgi

ADK Dokümanları

AP2 Protokolü

Ne Oluşturacaksınız?

mimari

Bu atölye çalışmasının sonunda şunları oluşturmuş olacaksınız:

✅ Özel rollere sahip çoklu temsilci sistemi:

  • Doğrulanmış hayır kurumlarını bulan bir Alışveriş Aracısı
  • Bağlayıcı bağış teklifleri oluşturan bir satıcı temsilcisi
  • Ödemeleri güvenli bir şekilde işleyen bir kimlik bilgisi sağlayıcı
  • Akışın tamamını koordine eden bir düzenleyici

Üç Tür Doğrulanabilir Kimlik Bilgisi:

  • IntentMandate: "Find me an education charity" (Bana bir eğitim hayır kurumu bul)
  • CartMandate: "50 ABD doları Room to Read'e bağışlanacak, satıcı tarafından imzalandı"
  • PaymentMandate: "Simüle edilmiş ödeme üzerinden işleme"

Her Katmanda Güvenlik:

  • Role-based trust boundaries
  • Kullanıcıdan açık rıza alma

Tam Denetim Takibi:

  • Her karar izlenebilir
  • Kaydedilen her izin
  • Her el değiştirme görünür olmalıdır.

🔒 Önemli: Bu, güvenli bir öğrenme ortamıdır

Güven oluşturmaya hazır mısınız?

Sonraki modülde, geliştirme ortamınızı kuracak ve ilk yapay zeka aracınızı oluşturacaksınız. Basit aracıların neden güvenilir olmadığını hızlıca öğrenecek ve atölyenin geri kalanında bu sorunu nasıl düzelteceğinizi öğreneceksiniz.

Öncelikle sorunu ilk elden anlayarak başlayalım.

2. Workspace'inizi hazırlama

The Foundation for Trustworthy Agents

Yapay Zeka Bağış Aracımızı oluşturmadan önce temiz, tutarlı ve doğru şekilde yapılandırılmış bir geliştirme ortamı hazırlamamız gerekir. Bu modül, gerekli tüm araçların ve hizmetlerin yerinde olmasını sağlamaya odaklanmış bir adımdır.

Bu kurulumu başarıyla tamamladığınızda yapılandırma sorunları konusunda endişelenmeden tamamen sonraki modüllerde aracı mantığı oluşturma gibi heyecan verici çalışmalara odaklanabilirsiniz.

Cloud Shell'e erişme

Öncelikle, Google Cloud SDK ve diğer temel araçların önceden yüklendiği tarayıcı tabanlı bir terminal olan Cloud Shell'i açacağız.

Google Cloud Console'un üst kısmında Cloud Shell'i etkinleştir'i (sağ üst gezinme çubuğundaki terminal simgesi) tıklayın.

cloud shell

Google Cloud proje kimliğinizi bulma:

  • Google Cloud Console'u açın: https://console.cloud.google.com
  • Sayfanın üst kısmındaki proje açılır listesinden bu atölye çalışması için kullanmak istediğiniz projeyi seçin.
  • Proje kimliğiniz, kontrol panelindeki Proje bilgileri kartında gösterilir. proje kimliği

Cloud Shell açıldıktan sonra kimliğinizin doğrulandığını onaylayın:

# Check that you are logged in
gcloud auth list

Hesabınız (ACTIVE) olarak listelenir.

Projenizi Yapılandırma

Şimdi Google Cloud projenizi ayarlayalım ve gerekli API'leri etkinleştirelim.

Proje kimliğinizi ayarlama

# Set your project using the auto-detected environment variable in Cloud Shell
gcloud config set project $GOOGLE_CLOUD_PROJECT

# Verify the project has been set
echo "Your active Google Cloud project is: $(gcloud config get-value project)"

Gerekli API'leri etkinleştirme

Temsilcilerinizin çeşitli Google Cloud hizmetlerine erişmesi gerekir:

gcloud services enable \
    aiplatform.googleapis.com \
    secretmanager.googleapis.com \
    cloudtrace.googleapis.com

Bu işlem 1-2 dakika sürebilir. Şunları görürsünüz:

Operation "operations/..." finished successfully.

Bu API'lerin sağladığı olanaklar:

  • aiplatform.googleapis.com: Aracı muhakemesi için Gemini modellerine erişim
  • secretmanager.googleapis.com: API anahtarları için güvenli depolama (üretimle ilgili en iyi uygulama)
  • cloudtrace.googleapis.com: Hesap verebilirlik izimiz için gözlemlenebilirlik

Başlangıç kodunu klonlama

Tüm şablon kodunu ve kaynaklarını içeren atölye deposunu edinin:

git clone https://github.com/ayoisio/adk-ap2-charity-agents
cd adk-ap2-charity-agents
git checkout codelab

Elimizdeki bilgileri doğrulayalım:

ls -la

Aşağıdaki bilgileri görürsünüz:

  • charity_advisor/: Temsilcilerimizi ve araçlarımızı oluşturacağımız yer
  • scripts/ - Test ve doğrulama için yardımcı komut dosyaları
  • deploy.sh - Dağıtım için yardımcı komut dosyası
  • setup.py - Modül kurulumu için yardımcı komut dosyası
  • .env.template - Ortam değişkenleri dosyası

Python ortamını ayarlama

Şimdi projemiz için izole bir Python ortamı oluşturacağız.

Sanal ortam oluşturma ve etkinleştirme

# Create the virtual environment
python3 -m venv venv

# Activate it
source venv/bin/activate

Doğrulama: İsteminizde artık (venv) öneki gösterilmelidir.

Bağımlılıkları yükleme

pip install -r charity_advisor/requirements.txt
pip install -e .

Bu işlemle aşağıdakiler yüklenir:

  • google-adk: Agent Development Kit çerçevesi
  • google-cloud-aiplatform: Vertex AI ve Gemini entegrasyonu
  • ap2: Agent Payments Protocol SDK (GitHub'dan)
  • python-dotenv: Ortam değişkeni yönetimi

-e işareti, adk_ap2_charity_agents modüllerini istediğiniz yerden içe aktarmanıza olanak tanır.

Ortam dosyasını yapılandırma

Şablondan yapılandırmanızı oluşturun:

# Copy the template
cp .env.template .env

# Get your current Project ID
PROJECT_ID=$(gcloud config get-value project)

# Replace the placeholder with your actual project ID
sed -i "s/your-project-id/$PROJECT_ID/g" .env

# Verify the replacement worked
grep GOOGLE_CLOUD_PROJECT .env

Aşağıdaki bilgileri görürsünüz:

GOOGLE_CLOUD_PROJECT=your-actual-project-id

Doğrulama

Her şeyin doğru şekilde yapılandırıldığından emin olmak için doğrulama komut dosyasını çalıştırın:

python scripts/verify_setup.py

Tüm onay işaretlerinin yeşil olması gerekir:

======================================================================
SETUP VERIFICATION
======================================================================

✓ Python version: 3.11.x
✓ google-adk: 1.17.0
✓ google-cloud-aiplatform: 1.111.0+
✓ ap2: 0.1.0
✓ python-dotenv: 1.0.0+
✓ .env file found and contains project ID
✓ Google Cloud project configured: your-project-id

✓ Mock charity database found
✓ Agent templates ready
✓ All directories present

======================================================================
✓ Setup complete! You are ready to build trustworthy agents.
======================================================================

Sorun giderme

Sırada ne var?

Ortamınız artık tamamen hazır. Sahip olduğunuz izinler:

  • ✅ Google Cloud projesi yapılandırıldı
  • ✅ Gerekli API'ler etkinleştirildi
  • ✅ ADK ve AP2 kitaplıkları yüklü
  • ✅ Şablon kodu değiştirilmeye hazır

Bir sonraki modülde, birkaç satır kodla ilk yapay zeka aracınızı oluşturacak ve basit aracıların finansal işlemleri yürütürken neden güvenilir olmadığını öğreneceksiniz.

3. İlk temsilciniz ve güven açığını keşfetme

banner

Fikirden Etkileşime

Önceki modülde geliştirme ortamımızı hazırladık. Şimdi de işin heyecanlı kısmına geçelim. İlk aracımızı oluşturup çalıştıracak, ilk özelliğini ekleyecek ve bu süreçte aracın gerçekten güvenilir olması için çözmemiz gereken temel zorlukları keşfedeceğiz.

Bu modül, "önce" resminizdir. Güvenilir aracıların oluşturulması için LLM'ye araçlara erişim izni vermenin yeterli olmadığını gösteren anı temsil eder.

1. adım: Başlangıç aracısını inceleyin

Öncelikle ilk temsilcimizin şablonuna bakalım. Bu dosya, sonraki adımlarda tamamlayacağımız yer tutucular içeren temel bir yapı içerir.

👉 Dosyayı açın .

charity_advisor/simple_agent/agent.py

düzenleyicinizde

Şunları görürsünüz:

"""
A simple agent that can research charities using Google Search.
"""

# MODULE_3_STEP_2_IMPORT_COMPONENTS


simple_agent = Agent(
    name="SimpleAgent",
    model="gemini-2.5-flash",
    
    # MODULE_3_STEP_3_WRITE_INSTRUCTION
    instruction="""""",
    
    # MODULE_3_STEP_4_ADD_TOOLS
    tools=[]
)

Yer tutucu yorumların MODULE_3_STEP_X_DESCRIPTION şeklinde bir kalıbı izlediğini fark edeceksiniz. Temsilcimizi kademeli olarak oluşturmak için bu işaretçilerin yerini alacağız.

2. adım: Gerekli bileşenleri içe aktarın

Agent sınıfını örnekleyebilmemiz veya google_search aracını kullanabilmemiz için bunları dosyamıza aktarmamız gerekir.

👉 Bul:

# MODULE_3_STEP_2_IMPORT_COMPONENTS

👉 Tek satırı şununla değiştirin:

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

Artık dosyamızda Agent sınıfı ve google_search aracı kullanılabilir.

3. adım: Aracı Talimatı'nı yazın

Talimat, ajanın "iş tanımıdır". Büyük dil modeline araçlarını ne zaman ve nasıl kullanacağını söyler. Ajanımızı hayır kurumu bilgilerini aramaya yönlendiren bir istem yazalım.

👉 Bul:

# MODULE_3_STEP_3_WRITE_INSTRUCTION
instruction="""""",

👉 Bu iki satırı şununla değiştirin:

instruction="""You are a helpful research assistant. When a user asks you to find information about charities,
use the google_search tool to find the most relevant and up-to-date results from the web.
Synthesize the search results into a helpful summary.""",

4. adım: Arama aracını ekleyin

Araçsız bir temsilci yalnızca bir sohbetçidir. Ajanımıza ilk özelliğini, yani web'de arama yapma özelliğini verelim.

👉 Bul:

# MODULE_3_STEP_4_ADD_TOOLS
tools=[]

👉 Bu iki satırı şununla değiştirin:

tools=[google_search]

5. adım: Temsilcinizi doğrulayın

Test etmeden önce tüm parçaların yerinde olduğunu doğrulayalım.

👉 Tam

charity_advisor/simple_agent/agent.py

dosyası artık tam olarak şu şekilde görünmelidir:

"""
A simple agent that can research charities using Google Search.
"""

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


simple_agent = Agent(
    name="SimpleAgent",
    model="gemini-2.5-flash",
    instruction="""You are a helpful research assistant. When a user asks you to find information about charities,
use the google_search tool to find the most relevant and up-to-date results from the web.
Synthesize the search results into a helpful summary.""",
    tools=[google_search]
)

6. adım: Aracı test edin - Güven boşluklarını ortaya çıkarma

Temsilcimiz tamamen yapılandırıldığına göre şimdi onu test edip davranışını analiz edelim. Basit aracıların finansal kararlar söz konusu olduğunda neden güvenilir olmadığını bu noktada keşfederiz.

1. Test: Keşif Sorunu

👉 Cloud Shell terminalinizde aşağıdaki komutu çalıştırın:

adk run charity_advisor/simple_agent

Şuna benzer bir çıkış görürsünüz:

INFO:google.adk.agents:Loading agent from charity_advisor/simple_agent
INFO:google.adk.agents:Agent 'SimpleAgent' ready

[user]:

[user]: istemi artık girişinizi bekliyor.

👉 [user]: isteminde şunu yazın:

Can you find me a verified, highly-rated charity for children's literacy?

👉 Enter tuşuna basın ve yanıtı inceleyin.

Bir süre sonra aracı, arama sonuçlarını aşağıdaki gibi bir yanıtta sentezleyecektir:

Web'de yapılan bir aramaya göre, çocukların okuryazarlığı konusunda saygın bazı yardım kuruluşları Reading Is Fundamental ve Room to Read'dir. Durumlarını ve puanlarını doğrulamak için genellikle Charity Navigator ve GuideStar gibi kaynaklar önerilir. Ayrıca Reddit gibi forumlarda, kullanıcıların çeşitli küçük ve yerel okuma yazma programlarıyla ilgili kişisel deneyimlerini paylaştığı birçok online tartışma buldum.

Bunu analiz edelim. Temsilci sorunumuzu çözdü mü?

Hayır. 1. modülde açıkladığımız insan deneyimini mükemmel bir şekilde kopyaladı. "Google'da arama" sürecini başarıyla otomatikleştirerek "analiz felci" sorununu bize geri verdi.

Bu durum, ilk güven açığını ortaya çıkarır: yetkili verilerin eksikliği.

Temsilci, açık web'de arama yapıyor. Bu şu anlama gelir:

  • ✅ Sonuçlar hızlı bir şekilde bulundu (kullanıcı deneyimi iyileştirildi).
  • ❌ Yüksek puanlı kuruluşları Reddit tartışmalarıyla (güvenilir olmayan kaynaklar) karıştırıyor.
  • ❌ İyice incelenmiş hayır kurumları ile olası dolandırıcılıklar arasında ayrım yapamaz (doğrulama yok).
  • ❌ Yeni sağladığı bilgileri doğrulamamızı bizden istiyor (sorumluluğu bize yüklüyor).

2. Test: Yürütme Sorunu

Şimdi de çok önemli olan ikinci teste geçelim. [user]: isteminde bağışı tamamlamayı deneyin:

Okay, please donate $50 to Room to Read for me.

Temsilci, sınırlamayı kabul ederek özür dileyerek yanıt verir:

Bağış yapmak istediğinizi belirtmişsiniz. Bu harika! Ancak ben bir araştırma asistanıyım ve finansal işlemleri gerçekleştirme veya ödemeleri işleme yeteneğine sahip değilim. Bağış yapmak için doğrudan Room to Read'in resmi web sitesini ziyaret etmeniz gerekir.

Bu da ikinci ve eşit derecede önemli bir "Aha!" anıdır.

Temsilci, doğru hayır kurumunu bulma konusunda güvenilir olmamasının yanı sıra henüz bağış yapma konusunda da güvenilir değildir.

👉 Basın

Ctrl+C

simgesini tıklayın.

İki Boşluğun Görselleştirilmesi

güven sorunu

Öğrendikleriniz

Bu modülde, ilk yapay zeka aracınızı başarıyla oluşturup donattınız. Bu şekilde, güvenilir bir sistem oluşturmanın iki temel zorluğunu ortaya çıkarmış olursunuz.

Uzmanlaşılan Temel Kavramlar

The Agent Class: (Temsilci Sınıfı)

  • ADK'nın temel yapı taşı
  • LLM akıl yürütmesini (beyin) araçlarla (eller) birleştirir.
  • Model, talimat ve araçlarla yapılandırılmış

Klasör Tabanlı Yapı:

  • Her aracı kendi klasöründe bulunur.
  • ADK, agent_folder/agent.py için arama yapar
  • adk run agent_folder ile koşma

Araç Listesi:

  • Temsilci özelliklerini tanımlar
  • LLM, araçları ne zaman ve nasıl kullanacağına karar verir.
  • Farklı işlemler için birden fazla araç içerebilir.

Talimat istemi:

  • İş tanımı gibi temsilcinin davranışını yönlendirir.
  • Rolü, tetikleyicileri, işlemleri ve çıkış biçimini belirtir.
  • Güvenilir araç kullanımı için kritik öneme sahiptir.

Güven Sorunu:

  • Keşif boşluğu: İncelenmemiş kaynaklar, karışık kalite
  • Yürütme açığı: Güvenli özellik yok, izin yok, denetim izi yok

Sonraki Adımlar

Bir sonraki modülde, AP2'nin role dayalı mimarisini uygulayarak çözümü oluşturmaya başlayacağız.

İlk aracıyı oluşturalım ve rol ayrımını uygulamalı olarak görelim.

4. Alışveriş Ajanı'nı oluşturma - Rol tabanlı keşif

banner

Güvenin Temeli: Rol Ayrımı

Son modülde, basit ve genel amaçlı bir aracının iki açıdan başarısız olduğunu öğrendiniz: Güvenilir keşif sağlayamıyor ve güvenli işlemler gerçekleştiremiyor. Şimdi, Agent Payments Protocol'deki ilk ilkeyi (role-based architecture) uygulayarak bu sorunları çözmeye başlayacağız.

Kod yazmaya başlamadan önce bu ilkenin neden önemli olduğunu anlayalım.

AP2 İlkesi: Rol Ayrımı

"Her Şeyi Yapan" Temsilcilerle İlgili Sorun

Finans danışmanınız, muhasebeciniz ve yatırım aracınız olması için bir kişiyi işe aldığınızı düşünün. Kolay mı? Evet. Güvenli mi? Kesinlikle hayır. Bu durumda, ilgili konuğa şu seçenek sunulur:

  • Yatırım hedefleriniz (danışman rolü)
  • Hesaplarınıza erişim (muhasebeci rolü)
  • Paranızı taşıma yetkisi (aracı rolü)

Bu kişinin hesabı ele geçirilirse veya bu kişi bir hata yaparsa her şey risk altında olur.

AP2'nin çözümü: Bir temsilci, bir iş

AP2, güven sınırları oluşturmak için sorumlulukların ayrılması ilkesini uygular:

mimari

Bu neden önemli?

  • Sınırlı etki alanı: Alışveriş Temsilcisi'nin güvenliği ihlal edilirse saldırgan, ödeme kimlik bilgilerine erişemez.
  • Gizlilik: Yeterlilik Belgesi Sağlayıcı, alışveriş görüşmenizi hiçbir zaman görmez.
  • Uygunluk: Ödeme verileri yalıtıldığında PCI-DSS şartlarını karşılamak daha kolaydır.
  • Sorumluluk: Her adım için net sorumluluk

Temsilciler Nasıl İletişim Kurar: Durumu Paylaşılan Not Defteri Olarak Kullanma

Aracılar birbirlerinin verilerine doğrudan erişemediğinden paylaşılan durum üzerinden iletişim kurar. Bunu, tüm temsilcilerin yazabileceği ve okuyabileceği bir beyaz tahta olarak düşünebilirsiniz:

# Shopping Agent writes:
state["intent_mandate"] = {
    "natural_language_description": "Donate $50 to Room to Read",
    "merchants": ["Room to Read"],
    "intent_expiry": "2024-11-07T15:32:16Z",
    "amount": 50.0
}

# Merchant Agent reads:
intent = state["intent_mandate"]
charity_name = intent["merchants"][0]
amount = intent["amount"]
# Creates CartMandate based on IntentMandate...

# Credentials Provider reads:
cart_mandate = state["cart_mandate"]
# Processes payment...

Bu sayede, iş birliğini mümkün kılarken güven sınırlarını koruruz.

İlk Ajanımız: Alışveriş Ajanı

Alışveriş Aracısı'nın sorumluluğu basit ve odaklanmıştır:

  1. Güvenilir veritabanımızı sorgulamak için find_charities aracını kullanın.
  2. Kullanıcıya seçenekler sunma
  3. IntentMandate oluşturmak ve durumu kaydetmek için save_user_choice aracını kullanın.
  4. Bir sonraki temsilciye (satıcı) yönlendirme

Bu kadar basit. Ödeme işleme ve alışveriş sepeti oluşturma yok. Yalnızca keşif ve aktarım.

Adım adım ilerleyelim.

1. adım: Giriş Doğrulama Yardımcısı'nı ekleyin

Üretim araçları oluştururken giriş doğrulaması çok önemlidir. Hayır kurumu verilerini duruma kaydetmeden önce doğrulayan bir yardımcı işlev oluşturalım.

👉

charity_advisor/tools/charity_tools.py

En üstte find_charities işlevinin (zaten tamamlanmış) olduğunu görürsünüz. Aşağı kaydırarak şunları bulabilirsiniz:

# MODULE_4_STEP_1_ADD_VALIDATION_HELPER

👉 Tek satırı şununla değiştirin:

def _validate_charity_data(charity_name: str, charity_ein: str, amount: float) -> tuple[bool, str]:
    """
    Validates charity selection data before saving to state.
    
    This helper function performs basic validation to ensure data quality
    before it gets passed to other agents in the pipeline.
    
    Args:
        charity_name: Name of the selected charity
        charity_ein: Employer Identification Number (should be format: XX-XXXXXXX)
        amount: Donation amount in USD
        
    Returns:
        (is_valid, error_message): Tuple where is_valid is True if all checks pass,
                                    and error_message contains details if validation fails
    """
    # Validate charity name
    if not charity_name or not charity_name.strip():
        return False, "Charity name cannot be empty"
    
    # Validate EIN format (should be XX-XXXXXXX)
    if not charity_ein or len(charity_ein) != 10 or charity_ein[2] != '-':
        return False, f"Invalid EIN format: {charity_ein}. Expected format: XX-XXXXXXX"
    
    # Validate amount
    if amount <= 0:
        return False, f"Donation amount must be positive, got: ${amount}"
    
    if amount > 1_000_000:
        return False, f"Donation amount exceeds maximum of $1,000,000: ${amount}"
    
    # All checks passed
    return True, ""

2. adım: IntentMandate Creation Helper'ı ekleyin

Şimdi de AP2 IntentMandate yapısını oluşturan yardımcıyı oluşturalım. Bu, AP2'deki üç doğrulanabilir kimlik bilgisinden biridir.

👉 Aynı dosyada şunları bulabilirsiniz:

# MODULE_4_STEP_2_ADD_INTENTMANDATE_CREATION_HELPER

👉 Tek satırı şununla değiştirin:

def _create_intent_mandate(charity_name: str, charity_ein: str, amount: float) -> dict:
    """
    Creates an IntentMandate - AP2's verifiable credential for user intent.
    
    This function uses the official Pydantic model from the `ap2` package
    to create a validated IntentMandate object before converting it to a dictionary.
    
    Args:
        charity_name: Name of the selected charity
        charity_ein: Employer Identification Number
        amount: Donation amount in USD
        
    Returns:
        Dictionary containing the IntentMandate structure per AP2 specification
    """
    from datetime import datetime, timedelta, timezone
    from ap2.types.mandate import IntentMandate
    
    # Set the expiry for the intent
    expiry = datetime.now(timezone.utc) + timedelta(hours=1)
    
    # Step 1: Instantiate the Pydantic model with official AP2 fields
    intent_mandate_model = IntentMandate(
        user_cart_confirmation_required=True,
        natural_language_description=f"Donate ${amount:.2f} to {charity_name}",
        merchants=[charity_name],
        skus=None,
        requires_refundability=False,
        intent_expiry=expiry.isoformat()
    )
    
    # Step 2: Convert the validated model to a dictionary for state storage
    intent_mandate_dict = intent_mandate_model.model_dump()
    
    # Step 3: Add the codelab's custom fields to the dictionary
    timestamp = datetime.now(timezone.utc)
    intent_mandate_dict.update({
        "timestamp": timestamp.isoformat(),
        "intent_id": f"intent_{charity_ein.replace('-', '')}_{int(timestamp.timestamp())}",
        "charity_ein": charity_ein,
        "amount": amount,
        "currency": "USD"
    })
    
    return intent_mandate_dict

3. adım: State Handoff Tool'u IntentMandate ile oluşturun

Şimdi de IntentMandate'i oluşturan ve durumu kaydeden aracı oluşturalım.

👉 Aynı dosyada,

save_user_choice

işlevini kullanmanız gerekir. Bul:

# MODULE_4_STEP_3_COMPLETE_SAVE_TOOL

👉 Tek satırı şununla değiştirin:

    # Validate inputs before creating IntentMandate
    is_valid, error_message = _validate_charity_data(charity_name, charity_ein, amount)
    if not is_valid:
        logger.error(f"Validation failed: {error_message}")
        return {"status": "error", "message": error_message}
    
    # Create AP2 IntentMandate using our updated helper function
    intent_mandate = _create_intent_mandate(charity_name, charity_ein, amount)
    
    # Write the IntentMandate to shared state for the next agent
    tool_context.state["intent_mandate"] = intent_mandate
    
    logger.info(f"Successfully created IntentMandate and saved to state")
    logger.info(f"Intent ID: {intent_mandate['intent_id']}")
    logger.info(f"Intent expires: {intent_mandate['intent_expiry']}")
    
    # Return success confirmation
    return {
        "status": "success",
        "message": f"Created IntentMandate: ${amount:.2f} donation to {charity_name} (EIN: {charity_ein})",
        "intent_id": intent_mandate["intent_id"],
        "expiry": intent_mandate["intent_expiry"]
    }

4. adım: Görüntüleme Biçimlendirme Yardımcısı'nı ekleyin

Aracı oluşturmadan önce, yardım kuruluşu verilerini kullanıcı dostu bir şekilde görüntülemek için bir yardımcı daha ekleyelim.

👉 Aşağı kaydırarak şunları bulun:

# MODULE_4_STEP_4_ADD_FORMATTING_HELPER

👉 Tek satırı şununla değiştirin:

def _format_charity_display(charity: dict) -> str:
    """
    Formats a charity dictionary into a user-friendly display string.
    
    This helper function demonstrates how to transform structured data
    into readable text for the user.
    
    Args:
        charity: Dictionary containing charity data (name, ein, mission, rating, efficiency)
        
    Returns:
        Formatted string suitable for display to the user
    """
    name = charity.get('name', 'Unknown')
    ein = charity.get('ein', 'N/A')
    mission = charity.get('mission', 'No mission statement available')
    rating = charity.get('rating', 0.0)
    efficiency = charity.get('efficiency', 0.0)
    
    # Format efficiency as percentage
    efficiency_pct = int(efficiency * 100)
    
    # Build formatted string
    display = f"""
**{name}** (EIN: {ein})
⭐ Rating: {rating}/5.0
💰 Efficiency: {efficiency_pct}% of funds go to programs
📋 Mission: {mission}
    """.strip()
    
    return display

5. adım: Alışveriş Ajanı'nı oluşturun - Bileşenleri içe aktarın

Araçlarımız tamamlandığına ve sağlam olduğuna göre, bunları kullanacak temsilciyi oluşturalım.

👉

charity_advisor/shopping_agent/agent.py

Yer tutucu yorumlar içeren bir şablon görürsünüz. Adım adım ilerleyelim.

👉 Bul:

# MODULE_4_STEP_5_IMPORT_COMPONENTS

👉 Tek satırı şununla değiştirin:

from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.charity_tools import find_charities, save_user_choice

6. adım: Aracı Talimatı'nı yazın

Talimat, aracının iş açıklamasını ve iş akışını tanımladığımız yerdir. Bu çok önemlidir. Kötü yazılmış bir talimat, güvenilmez davranışlara yol açar.

👉 Bul:

# MODULE_4_STEP_6_WRITE_INSTRUCTION
instruction="""""",

👉 Bu iki satırı şununla değiştirin:

    instruction="""You are a research specialist helping users find verified charities.

Your workflow:

1. When the user describes what cause they want to support (e.g., "education", "health", "environment"),
   use the find_charities tool to search our vetted database.

2. Present the results clearly. The tool returns formatted charity information that you should
   show to the user.

3. When the user selects a charity and specifies an amount, use the save_user_choice tool
   to create an IntentMandate and record their decision. You MUST call save_user_choice with:
   - charity_name: The exact name of the chosen charity
   - charity_ein: The EIN of the chosen charity  
   - amount: The donation amount in dollars (as a number, not a string)

4. After successfully saving, inform the user:
   - That you've created an IntentMandate (mention the intent ID if provided)
   - When the intent expires
   - That you're passing their request to the secure payment processor

IMPORTANT BOUNDARIES:
- Your ONLY job is discovery and creating the IntentMandate
- You do NOT process payments
- You do NOT see the user's payment methods
- You do NOT create cart offers (that's the Merchant Agent's job)
- After calling save_user_choice, your work is done

WHAT IS AN INTENTMANDATE:
An IntentMandate is a structured record of what the user wants to do. It includes:
- Natural language description ("Donate $50 to Room to Read")
- Which merchants can fulfill it
- When the intent expires
- Whether user confirmation is required

This is the first of three verifiable credentials in our secure payment system.

If the user asks you to do anything related to payment processing, politely explain that
you don't have that capability and that their request will be handled by the appropriate
specialist agent.""",

7. adım: Temsilciye araç ekleyin

Şimdi temsilciye her iki araca da erişim izni verelim.

👉 Bul:

# MODULE_4_STEP_7_ADD_TOOLS

👉 Bu iki satırı şununla değiştirin:

    tools=[
        FunctionTool(func=find_charities),
        FunctionTool(func=save_user_choice)
    ]

8. adım: Temsilcinizi doğrulayın

Her şeyin doğru şekilde bağlandığından emin olalım.

👉 Tam

charity_advisor/shopping_agent/agent.py

artık şu şekilde görünmelidir:

"""
Shopping Agent - Finds charities from a trusted database and saves the user's choice.
This agent acts as our specialized "Research Analyst."
"""

from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.charity_tools import find_charities, save_user_choice


shopping_agent = Agent(
    name="ShoppingAgent",
    model="gemini-2.5-pro",
    description="Finds and recommends vetted charities from a trusted database, then creates an IntentMandate capturing the user's donation intent.",
    instruction="""You are a research specialist helping users find verified charities.

Your workflow:

1. When the user describes what cause they want to support (e.g., "education", "health", "environment"),
   use the find_charities tool to search our vetted database.

2. Present the results clearly. The tool returns formatted charity information that you should
   show to the user.

3. When the user selects a charity and specifies an amount, use the save_user_choice tool
   to create an IntentMandate and record their decision. You MUST call save_user_choice with:
   - charity_name: The exact name of the chosen charity
   - charity_ein: The EIN of the chosen charity  
   - amount: The donation amount in dollars (as a number, not a string)

4. After successfully saving, inform the user:
   - That you've created an IntentMandate (mention the intent ID if provided)
   - When the intent expires
   - That you're passing their request to the secure payment processor

IMPORTANT BOUNDARIES:
- Your ONLY job is discovery and creating the IntentMandate
- You do NOT process payments
- You do NOT see the user's payment methods
- You do NOT create cart offers (that's the Merchant Agent's job)
- After calling save_user_choice, your work is done

WHAT IS AN INTENTMANDATE:
An IntentMandate is a structured record of what the user wants to do. It includes:
- Natural language description ("Donate $50 to Room to Read")
- Which merchants can fulfill it
- When the intent expires
- Whether user confirmation is required

This is the first of three verifiable credentials in our secure payment system.

If the user asks you to do anything related to payment processing, politely explain that
you don't have that capability and that their request will be handled by the appropriate
specialist agent.""",
    tools=[
        FunctionTool(func=find_charities),
        FunctionTool(func=save_user_choice)
    ]
)

Mükemmel! Aşağıdakileri kullanarak üretime hazır, AP2 uyumlu bir aracı oluşturdunuz:

  • Giriş doğrulaması
  • AP2 Pydantic modellerini kullanarak uygun IntentMandate oluşturma
  • Biçimlendirilmiş çıkış
  • Net rol sınırları
  • Ayrıntılı talimatlar
  • Hata işleme

9. adım: Alışveriş Ajanı'nı test edin

Aracımızın doğru çalıştığını, uygun IntentMandate'ler oluşturduğunu ve sınırlarına uyduğunu doğrulayalım.

👉 Cloud Shell terminalinizde şunu çalıştırın:

adk run charity_advisor/shopping_agent

[user]: istemi gösterilir.

1. Test: Güvenilir veritabanıyla Discovery

👉 Tür:

I want to donate to an education charity. What are my options?

Bir süre sonra temsilci yanıt verir. _format_charity_display yardımcımız sayesinde sonuçlar güzel bir şekilde biçimlendiriliyor:

Veritabanımızda 3 doğrulanmış eğitim hayır kurumu buldum:

Room to Read (EIN: 77-0479905)
⭐ Puan: 4,9/5,0
💰 Verimlilik: Fonların% 88'i programlara gider
📋 Misyon: Eğitimde okuryazarlığa ve cinsiyet eşitliğine odaklanarak düşük gelirli topluluklardaki milyonlarca çocuğun hayatını dönüştürmek.

Teach For America (EIN: 13-3541913)
⭐ Puan: 4,7/5,0
💰 Verimlilik: Fonların% 81'i programlara aktarılıyor
📋 Misyon: Zorluklarla karşılaşan çocukların eğitim fırsatlarını genişletmek için çalışır.

Tech Education Alliance (EIN: 45-2345678)
⭐ Puan: 4,8/5,0
💰 Verimlilik: Fonların% 92'si programlara aktarılıyor
📋 Misyon: Bilgisayar bilimleri eğitimini yeterli hizmet alamayan okullara ulaştırmak.

Hangi hayır kurumunu desteklemek ve ne kadar bağış yapmak istiyorsunuz?

Bunu, 3. modüldeki basit aracıyla karşılaştırın. Bu araç, size doğrulanmamış Google sonuçları veriyordu. Güvenilmeyen ve güvenilen keşif arasındaki fark budur.

2. Test: Kullanıcı Seçimini Kaydetme ve IntentMandate Oluşturma

👉 Tür:

I'll donate $50 to Room to Read.

Temsilcinin save_user_choice aracını doğru parametrelerle çağırdığını görmelisiniz. AP2 modellerini kullanarak IntentMandate oluşturma özelliğimiz sayesinde daha yapılandırılmış bir yanıt görürsünüz:

Mükemmel! Bağışınız için bir bağış niyet beyanı oluşturdum:

Amaç Ayrıntıları:

  • Niyet kimliği: intent_774795905_1730927536
  • Tutar: 50,00 ABD doları, Room to Read'e (EIN: 77-0479905)
  • Geçerlilik süresi: 2024-11-07T15:32:16Z (1 saat içinde)

Bu IntentMandate, bağış yapma niyetinizi yakalar ve işlemin güvenli bir şekilde işlenmesini sağlamak için kısıtlamalar içerir. Resmi bir teklif oluşturmak ve bağışınızı tamamlamak için bu bilgileri güvenli ödeme işleyicimize iletiyorum.

Kamera arkasında birkaç şey oldu:

  1. _validate_charity_data() girişleri doğruladı
  2. _create_intent_mandate(), yapıyı oluşturmak için AP2 Pydantic modelini kullandı:
   # Created and validated via Pydantic
   intent_mandate_model = IntentMandate(
       user_cart_confirmation_required=True,
       natural_language_description="Donate $50.00 to Room to Read",
       merchants=["Room to Read"],
       skus=None,
       requires_refundability=False,
       intent_expiry="2024-11-07T15:32:16Z"
   )
   
   # Converted to dict and extended with custom fields
   intent_mandate_dict = intent_mandate_model.model_dump()
   intent_mandate_dict.update({
       "charity_ein": "77-0479905",
       "amount": 50.0,
       "currency": "USD"
   })
  1. Araç, yalnızca IntentMandate'i paylaşılan duruma yazdı:
   state["intent_mandate"] = intent_mandate_dict
  1. LLM'ye amaç ayrıntılarını içeren bir başarı mesajı döndürüldü.
  2. LLM, son kullanıcı mesajını oluşturdu

Bu IntentMandate artık Merchant Agent (Modül 5) tarafından alınmaya hazır. Satıcı, IntentMandate'ten hayır kurumunun adını ve tutarını çıkarır ve süresinin dolmadığını doğrular.

3. Test: Doğrulama İşlemi

Doğrulama yardımcımızın hatalı girişi yakaladığını doğrulayalım.

👉 Tür:

I'll donate -$25 to Room to Read.

Temsilci, geçersiz tutarı yakalamalıdır:

Bir sorunla karşılaştım: Bağış tutarı pozitif olmalıdır, alınan değer: $-25.0

Lütfen pozitif bir bağış tutarı belirtin. Sizin için IntentMandate oluşturacağım.

Bu, savunma amaçlı programlamanın uygulamadaki halidir. _validate_charity_data yardımcı aracımız, geçersiz verilerin sisteme girip hatalı bir IntentMandate oluşturmasını engelledi.

4. Test: Güven sınırını doğrulama

👉 Temsilciden ödemeyi işlemesini isteyin:

Now process my credit card payment.

Ajan, rol sınırına uyarak reddetmelidir:

Ödemeleri işleme yeteneğim yok. Bu, görevimin bir parçası değil. İşim, doğrulanmış yardım kuruluşlarını bulmanıza ve bağış yapma amacınızı yansıtan IntentMandate'i oluşturmanıza yardımcı olmaktır.

IntentMandate'iniz oluşturuldu ve güvenli ödeme işleyicimize iletildi. Satıcı temsilcisi resmi bir teklif (CartMandate) oluşturur. Ardından, kimlik bilgisi sağlayıcı, açık izninizle gerçek ödemeyi işler.

Bu, güven sınırının işleyiş şeklidir. Aracı, ödeme verilerini işlemeye yetkili olmadığını biliyor ve talimatı, kullanıcılara bu durumu açıklarken IntentMandate kavramını da öğretmesi için açıkça yönlendiriyor.

👉 Basın

Ctrl+C

simgesini tıklayın.

Az Önce Oluşturduğunuz

AP2 Pydantic modellerini kullanarak uygun IntentMandate oluşturma ile AP2 mimarisinin ilk bölümünü başarıyla uyguladınız.

Uzmanlaşılan Temel Kavramlar

Role-Based Architecture: (Role Tabanlı Mimari)

  • Her temsilcinin net bir şekilde tanımlanmış bir işi vardır.
  • Temsilciler, doğrudan erişim yerine paylaşılan durum üzerinden iletişim kurar.
  • Güven sınırları, güvenlik ihlalinin etkisini sınırlar

IntentMandate (AP2 Credential #1):

  • Doğrulama için resmi AP2 Pydantic modelleri kullanılarak oluşturuldu
  • Kullanıcı niyetinin yapılandırılmış şekilde yakalanması
  • Güvenlik için geçerlilik süresi içerir (tekrar oynatma saldırılarını önler).
  • Kısıtlamaları (satıcılar, geri ödeme, onay) belirtir.
  • İnsanlar için doğal dil açıklaması
  • Temsilciler için makine tarafından okunabilir
  • Model, sözlüğe dönüştürülmeden önce doğrulanır.

Durumu Paylaşılan Anı Olarak Kaydetme:

  • tool_context.state, tüm temsilcilerin erişebileceği "not defteri"dir.
  • Duruma yazma = doğrulanabilir kimlik bilgilerini kullanıma sunma
  • Durumdan okuma = kimlik bilgilerini kullanma ve doğrulama
  • Aşağı akış aracıları, kimlik bilgilerinden ihtiyaç duyduklarını ayıklar.

FunctionTool:

  • Python işlevlerini LLM tarafından çağrılabilir araçlara dönüştürür.
  • LLM'nin anlaması için docstring'lere ve tür ipuçlarına dayanır.
  • İşlemleri otomatik olarak başlatır.
  • Araçların birleştirilebilirliği: Küçük ve odaklanmış araçlar > tek bir araç

Temsilci Talimatları:

  • Adım adım iş akışı açıklaması
  • Açık sınırlar ("YAPMAYIN...")
  • Hataları önlemek için parametre spesifikasyonları
  • Teknik tanımlar (IntentMandate nedir?)
  • Sıra dışı durumlarla başa çıkma (ne zaman ne söylemelisiniz?)

Sonraki Adımlar

Bir sonraki modülde, IntentMandate'i almak ve ikinci doğrulanabilir kimlik bilgisi olan CartMandate'i oluşturmak için Merchant Agent'ı oluşturacağız.

Alışveriş Temsilcisi, kullanıcının amacını son kullanma tarihiyle birlikte yakalayan bir IntentMandate oluşturdu. Şimdi bu yeterlilik belgesini okuyacak, süresinin dolmadığını doğrulayacak ve "Ben, satıcı, bu fiyata uyacağım ve bu ürünleri teslim edeceğim." yazan resmi ve imzalı bir teklif oluşturacak bir temsilciye ihtiyacımız var.

Merchant Agent'ı oluşturalım ve ikinci AP2 kimlik bilgisinin nasıl çalıştığını görelim.

5. Satıcı aracısını oluşturma - Bağlayıcı teklifler ve CartMandate

banner

Keşiften Bağlılığa

Önceki modülde, doğrulanmış hayır kurumlarını bulan ve kullanıcının amacını yakalayan bir IntentMandate oluşturan uzman bir alışveriş aracısı oluşturmuştunuz. Şimdi bu IntentMandate'i alıp resmi ve bağlayıcı bir teklif oluşturacak bir temsilciye ihtiyacımız var.

Bu noktada AP2'nin ikinci temel ilkesi olan CartMandate aracılığıyla doğrulanabilir kimlik bilgileri devreye girer.

AP2 İlkesi: Sepet Zorunluluğu ve Bağlayıcı Teklifler

Neden satıcı rolüne ihtiyacımız var?

4. modülde Alışveriş Temsilcisi bir IntentMandate oluşturup bunu şu duruma kaydetti:

state["intent_mandate"] = {
    "natural_language_description": "Donate $50 to Room to Read",
    "merchants": ["Room to Read"],
    "amount": 50.0,
    "intent_expiry": "2024-11-07T15:32:16Z"
}

Ancak bu yalnızca kullanıcı niyetiyle ilgilidir. Ödeme işlenmeden önce şunlara ihtiyacımız var:

  • Ödeme sistemlerinin anlayabileceği resmi bir teklif yapısı
  • Satıcının bu fiyata uyacağını gösteren kanıt
  • İşlem ortasında değiştirilemeyen bağlayıcı bir taahhüt
  • Amacın geçerlilik süresinin dolmadığını doğrulama

Bu, satıcı temsilcisinin görevidir.

CartMandate nedir?

CartMandate, AP2'nin bağlayıcı teklif olarak kullanılan "dijital alışveriş sepeti" için kullandığı terimdir. W3C PaymentRequest standardına göre yapılandırılmıştır. Bu nedenle:

  • Biçim, dünya genelindeki ödeme işleyiciler tarafından tanınır.
  • Tüm işlem ayrıntılarını standart bir şekilde içerir.
  • Özgünlüğü kanıtlamak için kriptografik olarak imzalanabilir.

Bunu bir yüklenicinin yazılı teklifi gibi düşünebilirsiniz:

  • ❌ Sözlü: "Evet, bu işi yaklaşık elli liraya yapabilirim."
  • ✅ Yazılı teklif: Kalem kalem maliyetler, toplam, imza, tarih

Yazılı fiyat teklifi bağlayıcıdır. CartMandate, bunun dijital karşılığıdır.

sepete ekleme amacı

CartMandate'in yapısı

AP2'deki bir CartMandate'in belirli bir iç içe yerleştirilmiş yapısı vardır:

cart_mandate = {
    "contents": {  # ← AP2 wrapper
        "id": "cart_xyz123",
        "cart_expiry": "2024-11-07T15:47:16Z",
        "merchant_name": "Room to Read",
        "user_cart_confirmation_required": False,
        
        "payment_request": {  # ← W3C PaymentRequest nested inside
            "method_data": [...],
            "details": {...},
            "options": {...}
        }
    },
    "merchant_authorization": "SIG_a3f7b2c8"  # ← Merchant signature
}

Üç ana bileşen:

1. contents: Şunları içeren alışveriş sepeti sarmalayıcısı:

  • Alışveriş sepeti kimliği ve son kullanma tarihi
  • Satıcının adı
  • W3C PaymentRequest

2. payment_request (içeriklerde) - Ne satın alınıyor:

  • method_data: Kabul edilen ödeme türleri
  • Ayrıntılar: Öğeler ve toplam
  • seçenekler: Kargo, ödeyen bilgileriyle ilgili koşullar

3. merchant_authorization: Kriptografik imza

Satıcı İmzaları: Taahhüt Kanıtı

Satıcı imzası çok önemlidir. Bu, aşağıdakileri kanıtlar:

  • Bu teklif, yetkili bir satıcıdan gelmiştir
  • Satıcı, bu fiyatı kabul etmeyi taahhüt eder.
  • Teklif, oluşturulduktan sonra değiştirilmemiş olmalıdır.

Üretim ortamında bu, PKI (Ortak Anahtar Altyapısı) veya JWT (JSON Web Jetonları) kullanılarak oluşturulan bir şifreleme imzası olur. Eğitim amaçlı atölye çalışmamızda bunu SHA-256 karmasıyla simüle edeceğiz.

# Production (real signature):
signature = sign_with_private_key(cart_data, merchant_private_key)

# Workshop (simulated signature):
cart_hash = hashlib.sha256(cart_json.encode()).hexdigest()
signature = f"SIG_{cart_hash[:16]}"

Misyonumuz: Satıcı Temsilcisi'ni geliştirme

Satıcı temsilcisi:

  1. Eyaletten gelen IntentMandate'i okuma (Alışveriş Ajanı'nın yazdığı)
  2. Intent'in süresinin dolmadığını doğrulayın.
  3. Bağış yapılan kuruluşun adını, tutarı ve diğer ayrıntıları çıkarma
  4. AP2 Pydantic modellerini kullanarak W3C uyumlu bir PaymentRequest yapısı oluşturma
  5. AP2'nin CartMandate with expiry (Son kullanma tarihi olan alışveriş sepeti zorunluluğu) ile sarmalayın.
  6. Simüle edilmiş satıcı imzası ekleme
  7. Kimlik bilgisi sağlayıcı için CartMandate'i eyalete yazma (sonraki modül)

Adım adım ilerleyelim.

1. adım: Geçerlilik Bitiş Tarihi Doğrulama Yardımcısı'nı ekleyin

Öncelikle, satıcıyla ilgili araçlar dosyasını ayarlayalım ve IntentMandate geçerlilik bitimini doğrulamak için bir yardımcı ekleyelim.

👉

charity_advisor/tools/merchant_tools.py

Geçerlilik bitiş tarihi doğrulamasını ekleyelim:

👉 Bul:

# MODULE_5_STEP_1_ADD_EXPIRY_VALIDATION_HELPER

👉 Tek satırı şununla değiştirin:

def _validate_intent_expiry(intent_expiry_str: str) -> tuple[bool, str]:
    """
    Validates that the IntentMandate hasn't expired.
    
    This is a critical security check - expired intents should not be processed.
    
    Args:
        intent_expiry_str: The ISO 8601 timestamp string from the IntentMandate.
        
    Returns:
        (is_valid, error_message): Tuple indicating if intent is still valid.
    """
    try:
        # The .replace('Z', '+00:00') is for compatibility with older Python versions
        expiry_time = datetime.fromisoformat(intent_expiry_str.replace('Z', '+00:00'))
        now = datetime.now(timezone.utc)
        
        if expiry_time < now:
            return False, f"IntentMandate expired at {intent_expiry_str}"
        
        time_remaining = expiry_time - now
        logger.info(f"IntentMandate valid. Expires in {time_remaining.total_seconds():.0f} seconds")
        
        return True, ""
        
    except (ValueError, TypeError) as e:
        return False, f"Invalid intent_expiry format: {e}"

2. adım: İmza Oluşturma Yardımcısı'nı ekleyin

Şimdi de simüle edilmiş satıcı imzası oluşturan bir yardımcı oluşturalım.

👉 Bul:

# MODULE_5_STEP_2_ADD_SIGNATURE_HELPER

👉 Tek satırı şununla değiştirin:

def _generate_merchant_signature(cart_contents: CartContents) -> str:
    """
    Generates a simulated merchant signature for the CartMandate contents.
    
    In production, this would use PKI or JWT with the merchant's private key.
    For this codelab, we use a SHA-256 hash of the sorted JSON representation.
    
    Args:
        cart_contents: The Pydantic model of the cart contents to sign.
        
    Returns:
        Simulated signature string (format: "SIG_" + first 16 chars of hash).
    """
    # Step 1: Dump the Pydantic model to a dictionary. The `mode='json'` argument
    # ensures that complex types like datetimes are serialized correctly.
    cart_contents_dict = cart_contents.model_dump(mode='json')
    
    # Step 2: Use the standard json library to create a stable, sorted JSON string.
    # separators=(',', ':') removes whitespace for a compact and canonical representation.
    cart_json = json.dumps(cart_contents_dict, sort_keys=True, separators=(',', ':'))
    
    # Step 3: Generate SHA-256 hash.
    cart_hash = hashlib.sha256(cart_json.encode('utf-8')).hexdigest()
    
    # Step 4: Create signature in a recognizable format.
    signature = f"SIG_{cart_hash[:16]}"
    
    logger.info(f"Generated merchant signature: {signature}")
    return signature

3A adımı: Araç imzasını oluşturma ve kurulum

Şimdi ana aracı oluşturmaya başlayalım. Bu planı dört alt adımda kademeli olarak oluşturacağız. İlk olarak işlev imzası ve ilk kurulum.

👉 Bul:

# MODULE_5_STEP_3A_CREATE_TOOL_SIGNATURE

👉 Tek satırı şununla değiştirin:

async def create_cart_mandate(tool_context: Any) -> Dict[str, Any]:
    """
    Creates a W3C PaymentRequest-compliant CartMandate from the IntentMandate.
    
    This tool reads the IntentMandate from shared state, validates it, and
    creates a formal, signed offer using the official AP2 Pydantic models.
    
    Returns:
        Dictionary containing status and the created CartMandate.
    """
    logger.info("Tool called: Creating CartMandate from IntentMandate")
    
    # MODULE_5_STEP_3B_ADD_VALIDATION_LOGIC

3B adımı: Doğrulama mantığı ekleyin

Şimdi de AP2 Pydantic modellerini kullanarak IntentMandate'i okuyup doğrulama ve ihtiyacımız olan verileri çıkarma mantığını ekleyelim.

👉 Bul:

# MODULE_5_STEP_3B_ADD_VALIDATION_LOGIC

👉 Tek satırı şununla değiştirin:

    # 1. Read IntentMandate dictionary from state
    intent_mandate_dict = tool_context.state.get("intent_mandate")
    if not intent_mandate_dict:
        logger.error("No IntentMandate found in state")
        return {
            "status": "error",
            "message": "No IntentMandate found. Shopping Agent must create intent first."
        }
    
    # 2. Parse dictionary into a validated Pydantic model
    try:
        intent_mandate_model = IntentMandate.model_validate(intent_mandate_dict)
    except Exception as e:
        logger.error(f"Could not validate IntentMandate structure: {e}")
        return {"status": "error", "message": f"Invalid IntentMandate structure: {e}"}
    
    # 3. Validate that the intent hasn't expired (CRITICAL security check)
    is_valid, error_message = _validate_intent_expiry(intent_mandate_model.intent_expiry)
    if not is_valid:
        logger.error(f"IntentMandate validation failed: {error_message}")
        return {"status": "error", "message": error_message}
    
    # 4. Extract data. Safely access standard fields from the model, and
    # custom fields (like 'amount') from the original dictionary.
    charity_name = intent_mandate_model.merchants[0] if intent_mandate_model.merchants else "Unknown Charity"
    amount = intent_mandate_dict.get("amount", 0.0)
    
    # MODULE_5_STEP_3C_CREATE_CARTMANDATE_STRUCTURE

3C adımı: CartMandate yapısını oluşturun

Şimdi W3C uyumlu PaymentRequest yapısını oluşturalım ve Pydantic modellerini kullanarak AP2 CartMandate'e sarmalayalım.

👉 Bul:

# MODULE_5_STEP_3C_CREATE_CARTMANDATE_STRUCTURE

👉 Tek satırı şununla değiştirin:

    # 5. Build the nested Pydantic models for the CartMandate
    timestamp = datetime.now(timezone.utc)
    cart_id = f"cart_{hashlib.sha256(f'{charity_name}{timestamp.isoformat()}'.encode()).hexdigest()[:12]}"
    cart_expiry = timestamp + timedelta(minutes=15)
    
    payment_request_model = PaymentRequest(
        method_data=[PaymentMethodData(
            supported_methods="CARD",
            data={"supported_networks": ["visa", "mastercard", "amex"], "supported_types": ["debit", "credit"]}
        )],
        details=PaymentDetailsInit(
            id=f"order_{cart_id}",
            display_items=[PaymentItem(
                label=f"Donation to {charity_name}",
                amount=PaymentCurrencyAmount(currency="USD", value=amount)  # Pydantic v2 handles float -> str conversion
            )],
            total=PaymentItem(
                label="Total Donation",
                amount=PaymentCurrencyAmount(currency="USD", value=amount)
            )
        ),
        options=PaymentOptions(request_shipping=False)
    )
    
    cart_contents_model = CartContents(
        id=cart_id,
        cart_expiry=cart_expiry.isoformat(),
        merchant_name=charity_name,
        user_cart_confirmation_required=False,
        payment_request=payment_request_model
    )
    
    # MODULE_5_STEP_3D_ADD_SIGNATURE_AND_SAVE

3D adımı: İmzayı ekleyin ve durumu kaydedin

Son olarak, Pydantic modelimizi kullanarak CartMandate'i imzalayalım ve bir sonraki aracı için durumu kaydedelim.

👉 Bul:

# MODULE_5_STEP_3D_ADD_SIGNATURE_AND_SAVE

👉 Tek satırı şununla değiştirin:

    # 6. Generate signature from the validated Pydantic model
    signature = _generate_merchant_signature(cart_contents_model)
    
    # 7. Create the final CartMandate model, now including the signature
    cart_mandate_model = CartMandate(
        contents=cart_contents_model,
        merchant_authorization=signature
    )
    
    # 8. Convert the final model to a dictionary for state storage and add the custom timestamp
    cart_mandate_dict = cart_mandate_model.model_dump(mode='json')
    cart_mandate_dict["timestamp"] = timestamp.isoformat()
    
    # 9. Write the final dictionary to state
    tool_context.state["cart_mandate"] = cart_mandate_dict
    
    logger.info(f"CartMandate created successfully: {cart_id}")
    
    return {
        "status": "success",
        "message": f"Created signed CartMandate {cart_id} for ${amount:.2f} donation to {charity_name}",
        "cart_id": cart_id,
        "cart_expiry": cart_expiry.isoformat(),
        "signature": signature
    }

4. adım: Satıcı aracısını oluşturun - Bileşenleri içe aktarın

Şimdi bu aracı kullanacak temsilciyi oluşturalım.

👉

charity_advisor/merchant_agent/agent.py

Yer tutucu işaretleri içeren bir şablon görürsünüz. İhtiyacımız olanları içe aktararak başlayalım.

👉 Bul:

# MODULE_5_STEP_4_IMPORT_COMPONENTS

👉 Tek satırı şununla değiştirin:

from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.merchant_tools import create_cart_mandate

5. adım: Satıcı temsilcisi talimatını yazın

Şimdi, temsilciye aracını ne zaman ve nasıl kullanacağını söyleyen talimatı yazalım.

👉 Bul:

# MODULE_5_STEP_5_WRITE_INSTRUCTION
instruction="""""",

👉 Bu iki satırı şununla değiştirin:

    instruction="""You are a merchant specialist responsible for creating formal, signed offers (CartMandates).

Your workflow:

1. Read the IntentMandate from shared state.
   The IntentMandate was created by the Shopping Agent and contains:
   - merchants: List of merchant names
   - amount: Donation amount
   - charity_ein: Tax ID
   - intent_expiry: When the intent expires

2. Use the create_cart_mandate tool to create a W3C PaymentRequest-compliant CartMandate.
   This tool will:
   - Validate the IntentMandate hasn't expired (CRITICAL security check)
   - Extract the charity name and amount from the IntentMandate
   - Create a structured offer with payment methods, transaction details, and merchant info
   - Generate a merchant signature to prove authenticity
   - Save the CartMandate to state for the payment processor

3. After creating the CartMandate, inform the user:
   - That you've created a formal, signed offer
   - The cart ID
   - When the cart expires (15 minutes)
   - That you're passing it to the secure payment processor

IMPORTANT BOUNDARIES:
- Your ONLY job is creating signed CartMandates from valid IntentMandates
- You do NOT process payments
- You do NOT see the user's payment methods or credentials
- You do NOT interact with payment networks
- You MUST validate that the IntentMandate hasn't expired before creating a cart
- After calling create_cart_mandate, your work is done

WHAT IS A CARTMANDATE:
A CartMandate is a binding commitment that says:
"I, the merchant, commit to accepting $X for this charity donation, and I prove it with my signature."

This commitment is structured using the W3C PaymentRequest standard and includes:
- Payment methods accepted (card, bank transfer)
- Transaction details (amount, charity name)
- Cart expiry (15 minutes from creation)
- Merchant signature (proof of commitment)

This is the second of three verifiable credentials in our secure payment system.""",

6. adım: Merchant Agent'a araç ekleyin

👉 Bul:

# MODULE_5_STEP_6_ADD_TOOLS
tools=[],

👉 Bu iki satırı şununla değiştirin:

    tools=[
        FunctionTool(func=create_cart_mandate)
    ],

7. adım: Complete Merchant Agent'ı doğrulayın

Her şeyin doğru şekilde bağlandığını onaylayalım.

👉 Tam

charity_advisor/merchant_agent/agent.py

artık şu şekilde görünmelidir:

"""
Merchant Agent - Creates W3C-compliant CartMandates with merchant signatures.
This agent acts as our "Contract Creator."
"""

from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.merchant_tools import create_cart_mandate


merchant_agent = Agent(
    name="MerchantAgent",
    model="gemini-2.5-flash",
    description="Creates formal, signed CartMandates for charity donations following W3C PaymentRequest standards.",
    tools=[
        FunctionTool(func=create_cart_mandate)
    ],
    instruction="""You are a merchant specialist responsible for creating formal, signed offers (CartMandates).

Your workflow:

1. Read the IntentMandate from shared state.
   The IntentMandate was created by the Shopping Agent and contains:
   - merchants: List of merchant names
   - amount: Donation amount
   - charity_ein: Tax ID
   - intent_expiry: When the intent expires

2. Use the create_cart_mandate tool to create a W3C PaymentRequest-compliant CartMandate.
   This tool will:
   - Validate the IntentMandate hasn't expired (CRITICAL security check)
   - Extract the charity name and amount from the IntentMandate
   - Create a structured offer with payment methods, transaction details, and merchant info
   - Generate a merchant signature to prove authenticity
   - Save the CartMandate to state for the payment processor

3. After creating the CartMandate, inform the user:
   - That you've created a formal, signed offer
   - The cart ID
   - When the cart expires (15 minutes)
   - That you're passing it to the secure payment processor

IMPORTANT BOUNDARIES:
- Your ONLY job is creating signed CartMandates from valid IntentMandates
- You do NOT process payments
- You do NOT see the user's payment methods or credentials
- You do NOT interact with payment networks
- You MUST validate that the IntentMandate hasn't expired before creating a cart
- After calling create_cart_mandate, your work is done

WHAT IS A CARTMANDATE:
A CartMandate is a binding commitment that says:
"I, the merchant, commit to accepting $X for this charity donation, and I prove it with my signature."

This commitment is structured using the W3C PaymentRequest standard and includes:
- Payment methods accepted (card, bank transfer)
- Transaction details (amount, charity name)
- Cart expiry (15 minutes from creation)
- Merchant signature (proof of commitment)

This is the second of three verifiable credentials in our secure payment system."""
)

Kontrol noktası: Artık Pydantic modellerini kullanarak uygun AP2 CartMandate oluşturma özelliğine sahip eksiksiz bir Merchant Agent'ınız var.

8. adım: Satıcı aracısını test edin

Şimdi de aracımızın, imzalarla birlikte alışveriş sepeti yetkilerini doğru şekilde oluşturduğunu ve geçerlilik süresini doğruladığını kontrol edelim.

Test kurulumu: Test komut dosyasını çalıştırma

👉 Cloud Shell terminalinizde şunu çalıştırın:

python scripts/test_merchant.py

Beklenen çıkış:

======================================================================
MERCHANT AGENT TEST
======================================================================

Simulated IntentMandate from Shopping Agent:
  charity: Room to Read
  amount: $50.00
  expiry: 2024-11-07T16:32:16Z

----------------------------------------------------------------------
Merchant Agent Response:
----------------------------------------------------------------------
Perfect! I've received your IntentMandate and created a formal, signed offer (CartMandate) for your donation.

**CartMandate Details:**
- **Cart ID**: cart_3b4c5d6e7f8a
- **Donation Amount**: $50.00 to Room to Read
- **Payment Methods Accepted**: Credit/debit cards (Visa, Mastercard, Amex) or bank transfer
- **Cart Expires**: 2024-11-07T15:47:16Z (in 15 minutes)
- **Merchant Signature**: SIG_a3f7b2c8d9e1f4a2

This signed CartMandate proves my commitment to accept this donation amount. I'm now passing this to the secure payment processor to complete your transaction.

======================================================================
CARTMANDATE CREATED:
======================================================================
  ID: cart_3b4c5d6e7f8a
  Amount: 50.00
  Merchant: Room to Read
  Expires: 2024-11-07T15:47:16Z
  Signature: SIG_a3f7b2c8d9e1f4a2
======================================================================

2. Test: W3C Uygunluğunu Doğrulama

CartMandate yapımızın hem AP2 hem de W3C PaymentRequest standartlarına tamamen uygun olduğunu doğrulayalım.

👉 Doğrulama komut dosyasını çalıştırın:

python scripts/validate_cartmandate.py

Beklenen çıkış:

======================================================================
AP2 & W3C PAYMENTREQUEST VALIDATION
======================================================================
✅ CartMandate is AP2 and W3C PaymentRequest compliant

Structure validation passed:
  ✓ AP2 'contents' wrapper present
  ✓ AP2 'merchant_authorization' signature present
  ✓ cart_expiry present
  ✓ payment_request nested inside contents
  ✓ method_data present and valid
  ✓ details.total.amount present with currency and value
  ✓ All required W3C PaymentRequest fields present
======================================================================

Az Önce Oluşturduğunuz

Uygun yapı, geçerlilik süresi doğrulama ve satıcı imzaları için Pydantic modellerini kullanarak AP2'nin CartMandate'ini başarıyla uyguladınız.

Uzmanlaşılan Temel Kavramlar

CartMandate (AP2 Credential #2):

  • Resmi AP2 Pydantic modelleri kullanılarak oluşturuldu
  • İçerik sarmalayıcı içeren AP2 yapısı
  • W3C PaymentRequest iç içe yerleştirilmiş
  • Sepet geçerlilik süresi (amaçlanandan daha kısa)
  • Bağlayıcı taahhüt için satıcı imzası
  • Model doğrulama, spesifikasyonlara uygunluğu sağlar

Geçerlilik Bitiş Tarihi Doğrulaması:

  • Eyalet tarafından verilen Reading IntentMandate
  • Yapı IntentMandate.model_validate() ile doğrulanıyor
  • ISO 8601 zaman damgalarını ayrıştırma
  • Mevcut zamanla karşılaştırma
  • Eski işlemeyi önleyen güvenlik özelliği

Satıcı imzası:

  • Gerçekliği ve bağlılığı kanıtlar
  • Doğrulanmış Pydantic modelinden oluşturuldu
  • Standart gösterim için model_dump(mode='json') kullanır.
  • Eğitim için SHA-256 ile simüle edildi
  • Üretimde PKI/JWT kullanılıyor
  • Sözlükleri değil, içerik modelini imzalar.

W3C PaymentRequest:

  • AP2'nin PaymentRequest Pydantic modeli kullanılarak oluşturulmuştur.
  • Ödeme verileri için endüstri standardı
  • AP2 yapısı içine yerleştirilmiş
  • method_data, details, options öğelerini içerir.
  • Birlikte çalışabilirliği etkinleştirir

Modellerle Kimlik Bilgisi Zinciri:

  • Alışveriş → IntentMandate (doğrulanmış)
  • Satıcı, IntentMandate → CartMandate (her iki model de doğrulandı) okur.
  • Kimlik bilgisi sağlayıcı, CartMandate → PaymentMandate'i okur.
  • Her adımda önceki kimlik bilgisi Pydantic kullanılarak doğrulanır.

Model Odaklı Geliştirme:

  • model_validate() üzerinden giriş doğrulaması
  • Tür güvenli yapı
  • model_dump() ile otomatik serileştirme
  • Üretime hazır kalıplar

Sonraki Adımlar

Bir sonraki modülde, ödemeleri güvenli bir şekilde işlemek için Kimlik Bilgisi Sağlayıcı'yı oluşturacağız.

Satıcı Temsilcisi, AP2 modellerini kullanarak son kullanma tarihi olan bağlayıcı bir teklif oluşturdu. Şimdi bu CartMandate'i okuyacak, kullanıcı izni alacak ve ödemeyi gerçekleştirecek bir aracıya ihtiyacımız var.

Kimlik bilgisi sağlayıcıyı oluşturalım ve AP2 kimlik bilgisi zincirini tamamlayalım.

6. Kimlik bilgisi sağlayıcıyı oluşturma - Güvenli ödeme yürütme

banner

Bağlayıcı Tekliften Ödeme Yürütmeye

5. modülde, IntentMandates'i okuyan, geçerlilik sürelerinin dolmadığını doğrulayan ve satıcı imzalarıyla bağlayıcı CartMandates oluşturan bir uzman olan Satıcı Ajanı'nı oluşturmuştunuz. Şimdi bu CartMandate'i alıp gerçek ödemeyi gerçekleştirecek bir temsilciye ihtiyacımız var.

Bu noktada, AP2'nin üçüncü ve son ilkesi olan PaymentMandate aracılığıyla güvenli ödeme yürütme devreye girer.

AP2 İlkesi: Ödeme Yetkisi ve Ödeme Yürütme

Neden kimlik bilgisi sağlayıcı rolüne ihtiyacımız var?

5. modülde, satıcı temsilcisi bir CartMandate oluşturup durumu şu şekilde kaydediyor:

state["cart_mandate"] = {
    "contents": {
        "id": "cart_abc123",
        "cart_expiry": "2025-11-07:15:47:16Z",
        "payment_request": {
            "details": {
                "total": {
                    "amount": {"currency": "USD", "value": "50.00"}
                }
            }
        }
    },
    "merchant_authorization": "SIG_a3f7b2c8"
}

Ancak bu yalnızca bağlayıcı bir tekliftir. Ödemenin gerçekleştirilebilmesi için şunlara ihtiyacımız var:

  • Sepetin süresinin dolmadığını doğrulama
  • Ödemeye devam etmek için kullanıcı izni
  • Ödeme işleminin yürütülmesine izin veren bir kimlik bilgisi
  • Gerçek ödeme işleme (veya atölyemiz için simülasyon)

Bu, kimlik bilgisi sağlayıcının görevidir.

PaymentMandate nedir?

PaymentMandate, ödemenin gerçekleştirilmesine izin veren nihai yetkilendirme için AP2'nin kullandığı terimdir. AP2 zincirindeki üçüncü ve son doğrulanabilir kimlik bilgisidir.

Üç kimlik bilgisini, sözleşme imzalama süreci gibi düşünebilirsiniz:

  • IntentMandate: "Bunu satın almak istiyorum" (Niyet mektubu)
  • CartMandate: "Ben, satıcı olarak bu fiyata satış yapmayı teklif ediyorum" (Yazılı fiyat teklifi)
  • PaymentMandate: "Ödeme yöntemimden ödeme alınmasına izin veriyorum" (İmzalı sözleşme)

Ödeme yalnızca üç kimlik bilgisi de mevcut olduğunda yapılabilir.

tam kimlik bilgisi zinciri

Ödeme Talimatının Yapısı

AP2'deki bir PaymentMandate'in belirli bir yapısı vardır:

payment_mandate = {
    "payment_mandate_contents": {  # ← AP2 wrapper
        "payment_mandate_id": "payment_xyz123",
        "payment_details_id": "cart_abc123",  # Links to CartMandate
        "user_consent": True,
        "consent_timestamp": "2025-11-07T15:48:00Z",
        "amount": {
            "currency": "USD",
            "value": "50.00"
        },
        "merchant_name": "Room to Read"
    },
    "agent_present": True,  # Human-in-the-loop flow
    "timestamp": "2025-11-07T15:48:00Z"
}

Temel bileşenler:

1. payment_mandate_contents: Aşağıdaki bilgileri içeren yetkilendirme sarmalayıcısı:

  • payment_mandate_id: Benzersiz tanımlayıcı
  • payment_details_id: CartMandate'e geri bağlantı verir.
  • user_consent: Kullanıcının onaylayıp onaylamadığı
  • tutar: Ödeme tutarı (CartMandate'den çıkarılır)

2. agent_present: Bu, insan müdahalesi gerektiren bir akış mı?

3. timestamp: Yetkilendirmenin oluşturulduğu zaman

Misyonumuz: Kimlik bilgisi sağlayıcıyı oluşturmak

Kimlik bilgisi sağlayıcı:

  1. Eyalet tarafından verilen CartMandate'i okuyun (Satıcı Temsilcisi'nin yazdığı)
  2. AP2 Pydantic modellerini kullanarak sepetin süresinin dolmadığını doğrulayın.
  3. İç içe yerleştirilmiş yapıdan ödeme ayrıntılarını ayıklama
  4. AP2 modellerini kullanarak kullanıcı izniyle PaymentMandate oluşturma
  5. Ödeme işlemini simüle etme (üretimde gerçek ödeme API'si çağrılır)
  6. PaymentMandate ve ödeme sonucunu duruma yazma

Adım adım ilerleyelim.

1. adım: Alışveriş sepeti geçerlilik süresi doğrulama yardımcısını ekleyin

Öncelikle, 5. modülde IntentMandate'in geçerlilik süresini doğruladığımız gibi CartMandate'in geçerlilik süresinin dolmadığını doğrulayan bir yardımcı oluşturalım.

👉

charity_advisor/tools/payment_tools.py

Geçerlilik bitiş tarihi doğrulamasını ekleyelim:

👉 Bul:

# MODULE_6_STEP_1_ADD_CART_EXPIRY_VALIDATION_HELPER

👉 Tek satırı şununla değiştirin:

def _validate_cart_expiry(cart: CartMandate) -> tuple[bool, str]:
    """
    Validates that the CartMandate hasn't expired.
    
    This is a critical security check - expired carts should not be processed.
    
    Args:
        cart: The Pydantic CartMandate model to validate.
        
    Returns:
        (is_valid, error_message): Tuple indicating if cart is still valid.
    """
    try:
        expiry_str = cart.contents.cart_expiry
        expiry_time = datetime.fromisoformat(expiry_str.replace('Z', '+00:00'))
        now = datetime.now(timezone.utc)
        
        if expiry_time < now:
            return False, f"CartMandate expired at {expiry_str}"
        
        time_remaining = expiry_time - now
        logger.info(f"CartMandate valid. Expires in {time_remaining.total_seconds():.0f} seconds")
        
        return True, ""
        
    except (ValueError, TypeError, AttributeError) as e:
        return False, f"Invalid cart_expiry format or structure: {e}"

2. adım: PaymentMandate Creation Helper'ı ekleyin

Şimdi resmi AP2 Pydantic modellerini kullanarak PaymentMandate yapısını oluşturan bir yardımcı oluşturalım.

👉 Bul:

# MODULE_6_STEP_2_ADD_PAYMENT_MANDATE_CREATION_HELPER

👉 Tek satırı şununla değiştirin:

def _create_payment_mandate(cart: CartMandate, consent_granted: bool) -> dict:
    """
    Creates a PaymentMandate using the official AP2 Pydantic models.
    
    It links to the CartMandate and includes user consent status.
    
    Args:
        cart: The validated Pydantic CartMandate model being processed.
        consent_granted: Whether the user has consented to the payment.
        
    Returns:
        A dictionary representation of the final, validated PaymentMandate.
    """
    timestamp = datetime.now(timezone.utc)
    
    # Safely extract details from the validated CartMandate model
    cart_id = cart.contents.id
    merchant_name = cart.contents.merchant_name
    total_item = cart.contents.payment_request.details.total
    
    # Create the nested PaymentResponse model for the mandate
    payment_response_model = PaymentResponse(
        request_id=cart_id,
        method_name="CARD",  # As per the simulated flow
        details={"token": "simulated_payment_token_12345"}
    )
    
    # Create the PaymentMandateContents model
    payment_mandate_contents_model = PaymentMandateContents(
        payment_mandate_id=f"payment_{hashlib.sha256(f'{cart_id}{timestamp.isoformat()}'.encode()).hexdigest()[:12]}",
        payment_details_id=cart_id,
        payment_details_total=total_item,
        payment_response=payment_response_model,
        merchant_agent=merchant_name,
        timestamp=timestamp.isoformat()
    )
    
    # Create the top-level PaymentMandate model
    # In a real system, a user signature would be added to this model
    payment_mandate_model = PaymentMandate(
        payment_mandate_contents=payment_mandate_contents_model
    )
    
    # Convert the final Pydantic model to a dictionary for state storage
    final_dict = payment_mandate_model.model_dump(mode='json')
    
    # Add any custom/non-standard fields required by the codelab's logic to the dictionary
    # The spec does not have these fields, but your original code did. We add them
    # back to ensure compatibility with later steps.
    final_dict['payment_mandate_contents']['user_consent'] = consent_granted
    final_dict['payment_mandate_contents']['consent_timestamp'] = timestamp.isoformat() if consent_granted else None
    final_dict['agent_present'] = True
    
    return final_dict

3A adımı: Araç imzasını oluşturma ve kurulum

Şimdi ana aracı kademeli olarak oluşturmaya başlayalım. İlk olarak işlev imzası ve ilk kurulum.

👉 Bul:

# MODULE_6_STEP_3A_CREATE_TOOL_SIGNATURE

👉 Tek satırı şununla değiştirin:

async def create_payment_mandate(tool_context: Any) -> Dict[str, Any]:
    """
    Creates a PaymentMandate and simulates payment processing using Pydantic models.
    
    This tool now reads the CartMandate from state, parses it into a validated model,
    and creates a spec-compliant PaymentMandate.
    """
    logger.info("Tool called: Creating PaymentMandate and processing payment")
    
    # MODULE_6_STEP_3B_VALIDATE_CARTMANDATE

3B adımı: CartMandate'i doğrulayın

Şimdi de AP2 Pydantic modellerini kullanarak CartMandate'i okuma ve doğrulama, son kullanma tarihini kontrol etme mantığını ekleyelim.

👉 Bul:

# MODULE_6_STEP_3B_VALIDATE_CARTMANDATE

👉 Tek satırı şununla değiştirin:

    # 1. Read CartMandate dictionary from state
    cart_mandate_dict = tool_context.state.get("cart_mandate")
    if not cart_mandate_dict:
        logger.error("No CartMandate found in state")
        return { "status": "error", "message": "No CartMandate found. Merchant Agent must create cart first." }
    
    # 2. Parse dictionary into a validated Pydantic model
    try:
        cart_model = CartMandate.model_validate(cart_mandate_dict)
    except Exception as e:
        logger.error(f"Could not validate CartMandate structure: {e}")
        return {"status": "error", "message": f"Invalid CartMandate structure: {e}"}
    
    # 3. Validate that the cart hasn't expired using the Pydantic model
    is_valid, error_message = _validate_cart_expiry(cart_model)
    if not is_valid:
        logger.error(f"CartMandate validation failed: {error_message}")
        return {"status": "error", "message": error_message}
    
    # MODULE_6_STEP_3C_EXTRACT_PAYMENT_DETAILS

3C adımı: Ödeme ayrıntılarını iç içe yerleştirilmiş yapıdan ayıklayın

Şimdi, ihtiyacımız olan ödeme ayrıntılarını çıkarmak için doğrulanmış CartMandate modelinde gezinelim.

👉 Bul:

# MODULE_6_STEP_3C_EXTRACT_PAYMENT_DETAILS

👉 Tek satırı şununla değiştirin:

    # 4. Safely extract data from the validated model
    cart_id = cart_model.contents.id
    merchant_name = cart_model.contents.merchant_name
    amount_value = cart_model.contents.payment_request.details.total.amount.value
    currency = cart_model.contents.payment_request.details.total.amount.currency
    consent_granted = True  # Assume consent for this codelab flow
    
    # MODULE_6_STEP_3D_CREATE_PAYMENTMANDATE_AND_SIMULATE

3D adımı: Ödeme yetkisi oluşturma ve ödemeyi simüle etme

Son olarak, Pydantic tabanlı yardımcı programımızı kullanarak PaymentMandate'i oluşturalım, ödeme işlemeyi simüle edelim ve her şeyi duruma kaydedelim.

👉 Bul:

# MODULE_6_STEP_3D_CREATE_PAYMENTMANDATE_AND_SIMULATE

👉 Tek satırı şununla değiştirin:

    # 5. Create the spec-compliant PaymentMandate using the validated CartMandate model
    payment_mandate_dict = _create_payment_mandate(cart_model, consent_granted)
    
    # 6. Simulate payment processing
    transaction_id = f"txn_{hashlib.sha256(f'{cart_id}{datetime.now(timezone.utc).isoformat()}'.encode()).hexdigest()[:16]}"
    payment_result = {
        "transaction_id": transaction_id,
        "status": "completed",
        "amount": amount_value,
        "currency": currency,
        "merchant": merchant_name,
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "simulation": True
    }
    
    # 7. Write the compliant PaymentMandate dictionary and result to state
    tool_context.state["payment_mandate"] = payment_mandate_dict
    tool_context.state["payment_result"] = payment_result
    
    logger.info(f"Payment processed successfully: {transaction_id}")
    
    return {
        "status": "success",
        "message": f"Payment of {currency} {amount_value:.2f} to {merchant_name} processed successfully",
        "transaction_id": transaction_id,
        "payment_mandate_id": payment_mandate_dict["payment_mandate_contents"]["payment_mandate_id"]
    }

4. adım: Kimlik bilgisi sağlayıcı aracısını oluşturun - Bileşenleri içe aktarın

Şimdi bu aracı kullanan temsilciyi oluşturalım.

👉

charity_advisor/credentials_provider/agent.py

Yer tutucu işaretleri içeren bir şablon görürsünüz. İhtiyacımız olanları içe aktararak başlayalım.

👉 Bul:

# MODULE_6_STEP_4_IMPORT_COMPONENTS

👉 Tek satırı şununla değiştirin:

from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.payment_tools import create_payment_mandate

5. adım: Kimlik bilgisi sağlayıcı talimatını yazın

Şimdi de temsilciye yol gösterecek talimatı yazalım.

👉 Bul:

# MODULE_6_STEP_5_WRITE_INSTRUCTION
instruction="""""",

👉 Bu iki satırı şununla değiştirin:

    instruction="""You are a payment specialist responsible for securely processing payments with user consent.

Your workflow:

1. Read the CartMandate from shared state.
   The CartMandate was created by the Merchant Agent and has this structure:
   - contents: AP2 wrapper containing:
     - id: Cart identifier
     - cart_expiry: When the cart expires
     - merchant_name: Who is receiving payment
     - payment_request: W3C PaymentRequest with transaction details
   - merchant_authorization: Merchant's signature

2. Extract payment details from the nested structure:
   - Navigate: cart_mandate["contents"]["payment_request"]["details"]["total"]["amount"]
   - This gives you the currency and value

3. **IMPORTANT - Two-Turn Conversational Confirmation Pattern:**
   Before calling create_payment_mandate, you MUST:
   - Present the payment details clearly to the user
   - Ask explicitly: "I'm ready to process a payment of $X to [Charity Name]. Do you want to proceed with this donation?"
   - WAIT for the user's explicit confirmation (e.g., "yes", "proceed", "confirm")
   - ONLY call create_payment_mandate AFTER receiving explicit confirmation
   - If user says "no" or "cancel", DO NOT call the tool

4. After user confirms, use the create_payment_mandate tool to:
   - Validate the CartMandate hasn't expired (CRITICAL security check)
   - Create a PaymentMandate (the third AP2 credential)
   - Simulate payment processing
   - Record the transaction result

5. After processing, inform the user:
   - That payment was processed successfully (this is a simulation)
   - The transaction ID
   - The amount and merchant
   - That this completes the three-agent AP2 credential chain

IMPORTANT BOUNDARIES:
- Your ONLY job is creating PaymentMandates and processing payments
- You do NOT discover charities (that's Shopping Agent's job)
- You do NOT create offers (that's Merchant Agent's job)
- You MUST validate that the CartMandate hasn't expired before processing
- You MUST get explicit user confirmation before calling create_payment_mandate
- In production, this consent mechanism would be even more robust

WHAT IS A PAYMENTMANDATE:
A PaymentMandate is the final credential that authorizes payment execution. It:
- Links to the CartMandate (proving the merchant's offer)
- Records user consent
- Contains payment details extracted from the CartMandate
- Enables the actual payment transaction

This is the third and final verifiable credential in our secure payment system.

THE COMPLETE AP2 CREDENTIAL CHAIN:
1. Shopping Agent creates IntentMandate (user's intent)
2. Merchant Agent reads IntentMandate, creates CartMandate (merchant's binding offer)
3. You read CartMandate, get user confirmation, create PaymentMandate (authorized payment execution)

Each credential:
- Has an expiry time (security feature)
- Links to the previous credential
- Is validated before the next step
- Creates an auditable chain of trust""",

6. adım: Araçları kimlik bilgisi sağlayıcısına ekleyin

👉 Bul:

# MODULE_6_STEP_6_ADD_TOOLS
tools=[],

👉 Bu iki satırı şununla değiştirin:

    tools=[
        FunctionTool(func=create_payment_mandate)
    ],

7. adım: Complete Credentials Provider'ı doğrulayın

Her şeyin doğru şekilde bağlandığını onaylayalım.

👉 Tam

charity_advisor/credentials_provider/agent.py

artık şu şekilde görünmelidir:

"""
Credentials Provider Agent - Handles payment processing with user consent.
This agent acts as our "Payment Processor."
"""

from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from charity_advisor.tools.payment_tools import create_payment_mandate


credentials_provider = Agent(
    name="CredentialsProvider",
    model="gemini-2.5-flash",
    description="Securely processes payments by creating PaymentMandates and executing transactions with user consent.",
    tools=[
        FunctionTool(func=create_payment_mandate)
    ],
    instruction="""You are a payment specialist responsible for securely processing payments with user consent.

Your workflow:

1. Read the CartMandate from shared state.
   The CartMandate was created by the Merchant Agent and has this structure:
   - contents: AP2 wrapper containing:
     - id: Cart identifier
     - cart_expiry: When the cart expires
     - merchant_name: Who is receiving payment
     - payment_request: W3C PaymentRequest with transaction details
   - merchant_authorization: Merchant's signature

2. Extract payment details from the nested structure:
   - Navigate: cart_mandate["contents"]["payment_request"]["details"]["total"]["amount"]
   - This gives you the currency and value

3. **IMPORTANT - Two-Turn Conversational Confirmation Pattern:**
   Before calling create_payment_mandate, you MUST:
   - Present the payment details clearly to the user
   - Ask explicitly: "I'm ready to process a payment of $X to [Charity Name]. Do you want to proceed with this donation?"
   - WAIT for the user's explicit confirmation (e.g., "yes", "proceed", "confirm")
   - ONLY call create_payment_mandate AFTER receiving explicit confirmation
   - If user says "no" or "cancel", DO NOT call the tool

4. After user confirms, use the create_payment_mandate tool to:
   - Validate the CartMandate hasn't expired (CRITICAL security check)
   - Create a PaymentMandate (the third AP2 credential)
   - Simulate payment processing
   - Record the transaction result

5. After processing, inform the user:
   - That payment was processed successfully (this is a simulation)
   - The transaction ID
   - The amount and merchant
   - That this completes the three-agent AP2 credential chain

IMPORTANT BOUNDARIES:
- Your ONLY job is creating PaymentMandates and processing payments
- You do NOT discover charities (that's Shopping Agent's job)
- You do NOT create offers (that's Merchant Agent's job)
- You MUST validate that the CartMandate hasn't expired before processing
- You MUST get explicit user confirmation before calling create_payment_mandate
- In production, this consent mechanism would be even more robust

WHAT IS A PAYMENTMANDATE:
A PaymentMandate is the final credential that authorizes payment execution. It:
- Links to the CartMandate (proving the merchant's offer)
- Records user consent
- Contains payment details extracted from the CartMandate
- Enables the actual payment transaction

This is the third and final verifiable credential in our secure payment system.

THE COMPLETE AP2 CREDENTIAL CHAIN:
1. Shopping Agent creates IntentMandate (user's intent)
2. Merchant Agent reads IntentMandate, creates CartMandate (merchant's binding offer)
3. You read CartMandate, get user confirmation, create PaymentMandate (authorized payment execution)

Each credential:
- Has an expiry time (security feature)
- Links to the previous credential
- Is validated before the next step
- Creates an auditable chain of trust"""
)

Kontrol noktası: Artık AP2 Pydantic modellerini kullanarak uygun CartMandate okuma ve PaymentMandate oluşturma işlemlerini gerçekleştiren eksiksiz bir kimlik bilgisi sağlayıcınız var.

8. adım: Kimlik bilgisi sağlayıcıyı test edin

Şimdi de aracımızın ödemeleri doğru şekilde işlediğini ve kimlik bilgisi zincirini tamamladığını doğrulayalım.

👉 Cloud Shell terminalinizde şunu çalıştırın:

python scripts/test_credentials_provider.py

Beklenen çıkış:

======================================================================
CREDENTIALS PROVIDER TEST (MOCK - NO CONFIRMATION)
======================================================================

Simulated CartMandate from Merchant Agent:
  - Cart ID: cart_test123
  - Merchant: Room to Read
  - Amount: $50.00
  - Expires: 2025-11-07T15:47:16Z
  - Signature: SIG_test_signature

Calling Credentials Provider to process payment...
======================================================================
INFO:charity_advisor.tools.payment_tools:Tool called: Creating PaymentMandate and processing payment
INFO:charity_advisor.tools.payment_tools:CartMandate valid. Expires in 900 seconds
INFO:charity_advisor.tools.payment_tools:Payment processed successfully: txn_a3f7b2c8d9e1f4a2

======================================================================
CREDENTIALS PROVIDER RESPONSE:
======================================================================
I've successfully processed your payment. Here are the details:

**Payment Completed** (Simulated)
- Transaction ID: txn_a3f7b2c8d9e1f4a2
- Amount: USD 50.00
- Merchant: Room to Read
- Status: Completed

This completes the three-agent AP2 credential chain:
1.  Shopping Agent created IntentMandate (your intent)
2.  Merchant Agent created CartMandate (binding offer)
3.  Credentials Provider created PaymentMandate (payment authorization)

Your donation has been processed securely through our verifiable credential system.

======================================================================
PAYMENTMANDATE CREATED:
======================================================================
  Payment Mandate ID: payment_3b4c5d6e7f8a
  Linked to Cart: cart_test123
  User Consent: True
  Amount: USD 50.00
  Merchant: Room to Read
  Agent Present: True
======================================================================

======================================================================
PAYMENT RESULT:
======================================================================
  Transaction ID: txn_a3f7b2c8d9e1f4a2
  Status: completed
  Amount: USD 50.00
  Merchant: Room to Read
  Simulation: True
======================================================================

9. adım: Üç aracılı tam işlem hattını test edin

Şimdi üç aracının birlikte çalışmasını test edelim.

👉 Tam ardışık düzen testini çalıştırın:

python scripts/test_full_pipeline.py

Beklenen çıkış:

======================================================================
THREE-AGENT PIPELINE TEST (AP2 CREDENTIAL CHAIN)
======================================================================

[1/3] SHOPPING AGENT - Finding charity and creating IntentMandate...
----------------------------------------------------------------------
✓ IntentMandate created
  - Intent ID: intent_774799058_1730927536
  - Description: Donate $75.00 to Room to Read
  - Merchant: Room to Read
  - Amount: $75.0
  - Expires: 2025-11-07T16:32:16Z

[2/3] MERCHANT AGENT - Reading IntentMandate and creating CartMandate...
----------------------------------------------------------------------
✓ CartMandate created
  - ID: cart_3b4c5d6e7f8a
  - Expires: 2025-11-07T15:47:16Z
  - Signature: SIG_a3f7b2c8d9e1f4a2

[3/3] CREDENTIALS PROVIDER - Creating PaymentMandate and processing...
----------------------------------------------------------------------
NOTE: In the web UI, this would show a confirmation dialog
      For this test, consent is automatically granted
✓ Payment processed (SIMULATED)
  - Transaction ID: txn_a3f7b2c8d9e1f4a2
  - Amount: $75.0
  - Status: completed

======================================================================
COMPLETE AP2 CREDENTIAL CHAIN
======================================================================

✓ Credential 1: IntentMandate (User's Intent)
  - Intent ID: intent_774799058_1730927536
  - Description: Donate $75.00 to Room to Read
  - Expiry: 2025-11-07T16:32:16Z

✓ Credential 2: CartMandate (Merchant's Offer)
  - Cart ID: cart_3b4c5d6e7f8a
  - Cart Expiry: 2025-11-07T15:47:16Z
  - Merchant Signature: SIG_a3f7b2c8d9e1f4a2

✓ Credential 3: PaymentMandate (Payment Execution)
  - Payment Mandate ID: payment_3b4c5d6e7f8a
  - Linked to Cart: cart_3b4c5d6e7f8a
  - Agent Present: True

✓ Transaction Result:
  - Transaction ID: txn_a3f7b2c8d9e1f4a2
  - Simulation: True

======================================================================
✅ COMPLETE PIPELINE TEST PASSED
======================================================================

Bu, AP2 kimlik bilgilerinin tam zincirinin kullanıldığı bir örnektir.

Her temsilci:

  1. Durumdan bir kimlik bilgisi okur.
  2. Pydantic modellerini (yapı + son kullanma tarihi kontrolü) kullanarak doğrular.
  3. AP2 modellerini kullanarak sonraki kimlik bilgisini oluşturur.
  4. Sonraki temsilci için durumu yazar

Az Önce Oluşturduğunuz

Pydantic modelleri ve ödeme simülasyonu kullanarak uygun yapı doğrulama ile AP2 üç aracılı kimlik bilgisi zincirini başarıyla tamamladınız.

Uzmanlaşılan Temel Kavramlar

PaymentMandate (AP2 Credential #3):

  • Resmi AP2 Pydantic modelleri kullanılarak oluşturuldu
  • Ödeme işleminin yürütülmesini yetkilendiren nihai kimlik bilgisi
  • payment_details_id aracılığıyla CartMandate'e bağlantılar
  • Kullanıcı iznini ve zaman damgasını kaydeder.
  • CartMandate'ten alınan ödeme tutarını içerir.
  • Sürecin parçası olan insan için agent_present işareti eklenmiştir.
  • Model doğrulama, spesifikasyonlara uygunluğu sağlar

CartMandate'ten okuma:

  • Yapıyı CartMandate.model_validate() ile doğrulayın
  • Tür güvenli özellik erişimi: cart_model.contents.payment_request.details.total.amount
  • AP2 sarmalayıcısı ile W3C standardı ayrımı arasındaki farkı anlama
  • merchant_name, amount, currency değerlerini modelden güvenli bir şekilde ayıklayın
  • Pydantic, yapı hatalarını otomatik olarak yakalar

Sepet Geçerlilik Süresi Doğrulaması:

  • Doğrulanmış CartMandate Pydantic modelini kabul eder.
  • cart.contents.cart_expiry (özellik erişimi) öğesinden okuma
  • Eski alışveriş sepeti işlemlerini önleyen güvenlik özelliği
  • Amaçtan (1 saat) daha kısa süre (15 dakika)

Ödeme Simülasyonu:

  • Gerçek ödeme işleyicinin eğitim amaçlı taklidi
  • İşlem kimliği oluşturur.
  • Durumda payment_result kaydeder
  • Simülasyon olarak açıkça işaretlenmiş (simulation: True işareti)

Modellerle AP2 Zincirini Tamamlama:

  • Üç aracı, üç kimlik bilgisi, üç Pydantic doğrulaması
  • Her aracı, modelleri kullanarak önceki kimlik bilgilerinin yapısını doğrular.
  • Her kimlik bilgisi, denetleme izi için önceki kimlik bilgisine bağlanır.
  • Duruma dayalı devirler, rol ayrımını korur
  • Zincir boyunca tip güvenliği

Model Odaklı Geliştirme:

  • model_validate() üzerinden giriş doğrulaması
  • İç içe yerleştirilmiş modellerle tür güvenli yapı
  • model_dump(mode='json') ile otomatik serileştirme
  • Başlangıçtan itibaren üretime hazır kalıplar

Sonraki Adımlar

Bir sonraki modülde, üç uzman temsilcinin tümünü koordine eden Orchestrator Agent'ı oluşturacağız.

AP2 Pydantic modellerini kullanarak üç güçlü uzman aracısı oluşturdunuz. Şimdi de bunları sorunsuz bir bağış deneyimi için düzenleyen orkestra şefini oluşturalım.

Orchestrator'ı oluşturalım ve sistemin tamamının işleyişini görelim.

7. Düzenleme: Her Şeyi Bir Araya Getirme

sıralı ardışık düzen

Uzmanlardan Sorunsuz Deneyime

Önceki modüllerde üç uzmanlaşmış aracı oluşturmuştunuz:

  • Alışveriş Ajanı: Hayır kurumlarını bulur, IntentMandate oluşturur.
  • Satıcı Temsilcisi: IntentMandate'ten CartMandate oluşturur.
  • Kimlik bilgisi sağlayıcı: PaymentMandate oluşturur, ödemeyi işler

Bu temsilciler doğal olarak iki aşamaya ayrılır:

  • 1. aşama (Alışveriş): Hayır kurumunu bulup seçmek için çok turlu görüşme
  • 2. Aşama (İşleme): Teklif oluşturma ve ödeme işlemlerinin atomik olarak yürütülmesi

Ancak şu anda bu aşamaları manuel olarak kendiniz yönetmeniz gerekir.

ADK'nin düzenleme kalıpları tam da bu noktada devreye girer.

AP2 İlkesi: Düzenleme, Güven Sınırlarını Uygular

Güvenlik için orkestrasyonun önemi

Düzenleme yalnızca kolaylık sağlamakla ilgili değildir. Aynı zamanda mimari aracılığıyla güven sınırlarını zorlamakla da ilgilidir.

Düzenleme olmadan:

# User could accidentally skip steps or reorder them
shopping_agent.run("Find charity")
# Oops, forgot to create CartMandate!
credentials_provider.run("Process payment")  # No offer to validate!

Düzenleme ile:

# Pipeline enforces correct order
donation_processing_pipeline = SequentialAgent(
    sub_agents=[
        merchant_agent,      # Must run first
        credentials_provider # Must run second
    ]
)
# Steps ALWAYS run in order, no skipping allowed

Sıralı ardışık düzen şunları garanti eder:

  • ✅ IntentMandate, CartMandate'ten önce oluşturulmuş olmalıdır.
  • ✅ Ödeme işlenmeden önce CartMandate oluşturuldu
  • ✅ Her aracı, kendi yalıtılmış bağlamında çalışır.
  • ✅ Durum, kimlik bilgisi zinciri boyunca ilerler.

Misyonumuz: Eksiksiz Sistemi Oluşturmak

İki katman oluşturacağız:

1. Katman: İşleme Ardışık Düzeni (SequentialAgent)

  • Satıcıyı kimlik bilgilerine bağlama → Kimlik bilgileri
  • Bağış kuruluşu seçildikten sonra otomatik olarak sırayla çalışır.
  • Teklif ve ödemenin atomik olarak yürütülmesi

2. Katman: Kök Düzenleyici (kullanıcıya yönelik aracı)

  • Güler yüzlü kişilik
  • Hayır kurumu seçimi için shopping_agent'a yetki verir.
  • IntentMandate oluşturulduktan sonra işleme ardışık düzenine temsilci atar.
  • Konuşma ve aşama geçişlerini yönetir.

Bu iki katmanlı yaklaşım, doğal akışla eşleşir:

  • Alışveriş Aşaması: Çok turlu sohbet (kullanıcı göz atar, soru sorar, karar verir)
  • İşleme Aşaması: Atomik yürütme (teklif → ödeme)

İkisini de oluşturalım.

1. adım: Orkestrasyon bileşenlerini içe aktarın

Öncelikle, gerekli içe aktarma işlemlerini yaparak düzenleme dosyasını oluşturalım.

👉

charity_advisor/agent.py

İçe aktarma işlemlerinden başlayalım:

👉 Bul:

# MODULE_7_STEP_1_IMPORT_COMPONENTS

👉 Tek satırı şununla değiştirin:

from google.adk.agents import Agent, SequentialAgent
from charity_advisor.shopping_agent.agent import shopping_agent
from charity_advisor.merchant_agent.agent import merchant_agent
from charity_advisor.credentials_provider.agent import credentials_provider

2. adım: İşleme hattını oluşturun

Şimdi de teklif oluşturma ve ödeme işlemlerini atomik olarak çalıştıran ardışık düzeni oluşturalım.

👉 Bul:

# MODULE_7_STEP_2_CREATE_SEQUENTIAL_PIPELINE

👉 Bu iki satırı şununla değiştirin:

# Create the donation processing pipeline
# This runs Merchant → Credentials in sequence AFTER charity is selected
donation_processing_pipeline = SequentialAgent(
    name="DonationProcessingPipeline",
    description="Creates signed offer and processes payment after charity is selected",
    sub_agents=[
        merchant_agent,
        credentials_provider
    ]
)

3A Adımı: Kök aracı kurulumu oluşturma

Şimdi her iki aşamayı da düzenleyen, kullanıcıya yönelik aracı oluşturalım. Bu özelliği üç bölüm halinde ele alacağız: kurulum (3A), talimat (3B) ve alt aracıları (3C).

👉 Bul:

# MODULE_7_STEP_3A_CREATE_ROOT_AGENT_SETUP

👉 Tek satırı şununla değiştirin:

# Create the root orchestrator agent
# This is what users interact with directly
root_agent = Agent(
    name="CharityAdvisor",
    model="gemini-2.5-pro",
    description="A friendly charity giving assistant that helps users donate to verified organizations.",
    # MODULE_7_STEP_3B_WRITE_ROOT_AGENT_INSTRUCTION

3B adımı: Kök aracı talimatını yazın

Şimdi, her iki aşamada da yardım danışmanının davranışını yönlendiren talimatı ekleyelim.

👉 Bul:

# MODULE_7_STEP_3B_WRITE_ROOT_AGENT_INSTRUCTION

👉 Tek satırı şununla değiştirin:

    instruction="""You are a helpful and friendly charity giving advisor.

Your workflow has TWO distinct phases:

PHASE 1: CHARITY SELECTION (delegate to shopping_agent)
When a user expresses interest in donating:
1. Delegate to shopping_agent immediately
2. The shopping_agent will:
   - Search for charities matching their cause
   - Present verified options with ratings
   - Engage in conversation (user may ask questions, change their mind)
   - Wait for user to select a specific charity and amount
   - Create an IntentMandate when user decides
3. Wait for shopping_agent to complete

You'll know Phase 1 is complete when shopping_agent's response includes:
- "IntentMandate created" or "Intent ID: intent_xxx" 
- Charity name and donation amount

PHASE 2: PAYMENT PROCESSING (delegate to DonationProcessingPipeline)
After shopping_agent completes:
1. Acknowledge the user's selection naturally:
   "Perfect! Let me process your $X donation to [Charity]..."
2. Delegate to DonationProcessingPipeline
3. The pipeline will automatically:
   - Create signed cart offer (MerchantAgent)
   - Get consent and process payment (CredentialsProvider)
4. After pipeline completes, summarize the transaction

CRITICAL RULES:
- Phase 1 may take multiple conversation turns (this is normal)
- Only proceed to Phase 2 after IntentMandate exists
- Don't rush the user during charity selection
- Don't ask user to "proceed" between phases - transition automatically

EXAMPLE FLOW:
User: "I want to donate to education"
You: [delegate to shopping_agent]
Shopping: "Here are 3 education charities..." [waits]
User: "Tell me more about the first one"
Shopping: "Room to Read focuses on..." [waits]
User: "Great, I'll donate $50 to Room to Read"
Shopping: "IntentMandate created (ID: intent_123)..."
You: "Perfect! Processing your $50 donation to Room to Read..." [delegate to DonationProcessingPipeline]
Pipeline: [creates offer, gets consent, processes payment]
You: "Done! Your donation was processed successfully. Transaction ID: txn_456"

Your personality:
- Warm and encouraging
- Patient during charity selection
- Clear about educational nature
- Smooth transitions between phases""",
# MODULE_7_STEP_3C_ADD_ROOT_AGENT_SUBAGENTS

3C adımı: Alt aracıları ekleyin

Son olarak, yardım danışmanına hem alışveriş aracısına hem de işleme hattına erişim izni verelim ve aracı tanımını kapatalım.

👉 Bul:

# MODULE_7_STEP_3C_ADD_ROOT_AGENT_SUBAGENTS

👉 Tek satırı şununla değiştirin:

    sub_agents=[
        shopping_agent,
        donation_processing_pipeline
    ]
)

4. adım: Sistemi doğrulayın

Orkestrasyonun doğru şekilde bağlandığını onaylayalım.

👉 Tam

charity_advisor/agent.py

artık şu şekilde görünmelidir:

"""
Main orchestration: The donation processing pipeline and root orchestrator agent.
"""

from google.adk.agents import Agent, SequentialAgent
from charity_advisor.shopping_agent.agent import shopping_agent
from charity_advisor.merchant_agent.agent import merchant_agent
from charity_advisor.credentials_provider.agent import credentials_provider

# Create the donation processing pipeline
# This runs Merchant → Credentials in sequence AFTER charity is selected
donation_processing_pipeline = SequentialAgent(
    name="DonationProcessingPipeline",
    description="Creates signed offer and processes payment after charity is selected",
    sub_agents=[
        merchant_agent,
        credentials_provider
    ]
)

# Create the root orchestrator agent
# This is what users interact with directly
root_agent = Agent(
    name="CharityAdvisor",
    model="gemini-2.5-flash",
    description="A friendly charity giving assistant that helps users donate to verified organizations.",
    instruction="""You are a helpful and friendly charity giving advisor.

Your workflow has TWO distinct phases:

PHASE 1: CHARITY SELECTION (delegate to shopping_agent)
When a user expresses interest in donating:
1. Delegate to shopping_agent immediately
2. The shopping_agent will:
   - Search for charities matching their cause
   - Present verified options with ratings
   - Engage in conversation (user may ask questions, change their mind)
   - Wait for user to select a specific charity and amount
   - Create an IntentMandate when user decides
3. Wait for shopping_agent to complete

You'll know Phase 1 is complete when shopping_agent's response includes:
- "IntentMandate created" or "Intent ID: intent_xxx" 
- Charity name and donation amount

PHASE 2: PAYMENT PROCESSING (delegate to DonationProcessingPipeline)
After shopping_agent completes:
1. Acknowledge the user's selection naturally:
   "Perfect! Let me process your $X donation to [Charity]..."
2. Delegate to DonationProcessingPipeline
3. The pipeline will automatically:
   - Create signed cart offer (MerchantAgent)
   - Get consent and process payment (CredentialsProvider)
4. After pipeline completes, summarize the transaction

CRITICAL RULES:
- Phase 1 may take multiple conversation turns (this is normal)
- Only proceed to Phase 2 after IntentMandate exists
- Don't rush the user during charity selection
- Don't ask user to "proceed" between phases - transition automatically

EXAMPLE FLOW:
User: "I want to donate to education"
You: [delegate to shopping_agent]
Shopping: "Here are 3 education charities..." [waits]
User: "Tell me more about the first one"
Shopping: "Room to Read focuses on..." [waits]
User: "Great, I'll donate $50 to Room to Read"
Shopping: "IntentMandate created (ID: intent_123)..."
You: "Perfect! Processing your $50 donation to Room to Read..." [delegate to DonationProcessingPipeline]
Pipeline: [creates offer, gets consent, processes payment]
You: "Done! Your donation was processed successfully. Transaction ID: txn_456"

Your personality:
- Warm and encouraging
- Patient during charity selection
- Clear about educational nature
- Smooth transitions between phases""",
    sub_agents=[
        shopping_agent,
        donation_processing_pipeline
    ]
)

5. adım: Doğrulama geri aramalarıyla güvenliği artırın (isteğe bağlı, 7. adıma geçebilirsiniz)

geri aramalar

SequentialAgent, yürütme sırasını garanti eder. Ancak şu durumlarda ne olur?

  • Alışveriş Ajanı sessizce başarısız oluyor (IntentMandate hiçbir zaman oluşturulmuyor)
  • Alışveriş ile satıcı arasında bir saat geçer (amaç sona erer)
  • Durum bozulur veya temizlenirse
  • Bir kullanıcı, Alışveriş'i atlayarak doğrudan satıcıyı aramaya çalışır.

Geri aramalar mimari zorunluluk ekler. Geri aramalar, bir aracı LLM çağrısını başlatmadan önce ön koşulları doğrular. Bu, derinlemesine savunma anlamına gelir: Araçlar yürütme sırasında doğrular, geri çağırmalar yürütmeden önce doğrular.

Satıcı ve Kimlik Bilgisi Sağlayıcı aracılarımıza doğrulama geri aramaları ekleyelim.

Adım 5A: Satıcı Doğrulaması Ekleme - Geri Arama Türlerini İçe Aktarma

İlk olarak geri çağırmalar için gereken içe aktarmaları ekleyelim.

👉

charity_advisor/merchant_agent/agent.py

Dosyanın üst kısmında, mevcut içe aktarma işlemlerinden sonra şunları ekleyin:

from typing import Optional
from datetime import datetime, timezone
from google.adk.agents.callback_context import CallbackContext
from google.genai.types import Content, Part
import logging

logger = logging.getLogger(__name__)

5B adımı: Amaç doğrulama işlevini oluşturun

Şimdi de satıcı temsilcisi çalışmadan önce IntentMandate'i doğrulayan bir geri çağırma işlevi oluşturalım.

👉 İçinde

charity_advisor/merchant_agent/agent.py

, bu işlevi

merchant_agent = Agent(...)

definition:

def validate_intent_before_merchant(
    callback_context: CallbackContext,
) -> Optional[Content]:
    """
    Validates IntentMandate exists and hasn't expired before Merchant runs.
    
    This callback enforces that the Shopping Agent completed successfully
    before the Merchant Agent attempts to create a CartMandate.
    
    Returns:
        None: Allow Merchant Agent to proceed normally
        Content: Skip Merchant Agent and return error to user
    """
    state = callback_context.state
    
    # Check credential exists
    if "intent_mandate" not in state:
        logger.error("❌ IntentMandate missing - Shopping Agent may have failed")
        return Content(parts=[Part(text=(
            "Error: Cannot create cart. User intent was not properly recorded. "
            "Please restart the donation process."
        ))])
    
    intent_mandate = state["intent_mandate"]
    
    # Validate expiry (critical security check)
    try:
        expiry_time = datetime.fromisoformat(
            intent_mandate["intent_expiry"].replace('Z', '+00:00')
        )
        now = datetime.now(timezone.utc)
        
        if expiry_time < now:
            logger.error(f"❌ IntentMandate expired at {intent_mandate['intent_expiry']}")
            return Content(parts=[Part(text=(
                "Error: Your donation intent has expired. "
                "Please select a charity again to restart."
            ))])
        
        time_remaining = expiry_time - now
        logger.info(f"✓ IntentMandate validated. Expires in {time_remaining.total_seconds():.0f}s")
        
    except (KeyError, ValueError) as e:
        logger.error(f"❌ Invalid IntentMandate structure: {e}")
        return Content(parts=[Part(text=(
            "Error: Invalid intent data. Please restart the donation."
        ))])
    
    # All checks passed - allow Merchant Agent to proceed
    logger.info(f"✓ Prerequisites met for Merchant Agent: {intent_mandate['intent_id']}")
    return None

5C adımı: Geri aramayı satıcı temsilcisine yönlendirin

Şimdi geri aramayı temsilciye bağlayalım.

👉 İçinde

charity_advisor/merchant_agent/agent.py

,

merchant_agent = Agent(...)

definition:

Temsilci tanımında şu satırı bulun:

merchant_agent = Agent(
    name="MerchantAgent",
    model="gemini-2.5-flash",
    description="Creates formal, signed CartMandates for charity donations following W3C PaymentRequest standards.",

Bu satırı

description

line:

    before_agent_callback=validate_intent_before_merchant,

Aracı tanımınız artık şu şekilde görünmelidir:

merchant_agent = Agent(
    name="MerchantAgent",
    model="gemini-2.5-flash",
    description="Creates formal, signed CartMandates for charity donations following W3C PaymentRequest standards.",
    before_agent_callback=validate_intent_before_merchant,
    tools=[
        FunctionTool(func=create_cart_mandate)
    ],
    instruction="""..."""
)

6. adım: Kimlik bilgisi sağlayıcı doğrulaması ekleyin (isteğe bağlı, 7. adıma geçebilirsiniz)

Aynı kalıbı kullanıyoruz. Ödeme adımı için doğrulama ekleyelim.

6A adımı: Geri arama türlerini içe aktarın

👉

charity_advisor/credentials_provider/agent.py

Dosyanın üst kısmında, mevcut içe aktarma işlemlerinden sonra şunları ekleyin:

from typing import Optional
from datetime import datetime, timezone
from google.adk.agents.callback_context import CallbackContext
from google.genai.types import Content, Part
import logging

logger = logging.getLogger(__name__)

6B adımı: Alışveriş sepeti doğrulama işlevini oluşturun

👉 İçinde

charity_advisor/credentials_provider/agent.py

, bu işlevi

credentials_provider = Agent(...)

definition:

def validate_cart_before_payment(
    callback_context: CallbackContext,
) -> Optional[Content]:
    """
    Validates CartMandate exists and hasn't expired before payment processing.
    
    This callback enforces that the Merchant Agent completed successfully
    before the Credentials Provider attempts to process payment.
    
    Returns:
        None: Allow Credentials Provider to proceed
        Content: Skip payment processing and return error
    """
    state = callback_context.state
    
    # Check credential exists
    if "cart_mandate" not in state:
        logger.error("❌ CartMandate missing - Merchant Agent may have failed")
        return Content(parts=[Part(text=(
            "Error: Cannot process payment. Cart was not properly created. "
            "Please restart the donation process."
        ))])
    
    cart_mandate = state["cart_mandate"]
    
    # Validate AP2 structure
    if "contents" not in cart_mandate:
        logger.error("❌ CartMandate missing AP2 contents wrapper")
        return Content(parts=[Part(text=(
            "Error: Invalid cart structure. Please restart."
        ))])
    
    # Validate expiry
    try:
        contents = cart_mandate["contents"]
        expiry_time = datetime.fromisoformat(
            contents["cart_expiry"].replace('Z', '+00:00')
        )
        now = datetime.now(timezone.utc)
        
        if expiry_time < now:
            logger.error(f"❌ CartMandate expired at {contents['cart_expiry']}")
            return Content(parts=[Part(text=(
                "Error: Your cart has expired (15 minute limit). "
                "Please restart the donation to get a fresh offer."
            ))])
        
        time_remaining = expiry_time - now
        logger.info(f"✓ CartMandate validated. Expires in {time_remaining.total_seconds():.0f}s")
        
    except (KeyError, ValueError) as e:
        logger.error(f"❌ Invalid CartMandate structure: {e}")
        return Content(parts=[Part(text=(
            "Error: Invalid cart data. Please restart the donation."
        ))])
    
    # All checks passed - allow payment processing
    logger.info(f"✓ Prerequisites met for Credentials Provider: {contents['id']}")
    return None

6C adımı: Geri aramayı kimlik bilgisi sağlayıcıya ekleyin

👉 İçinde

charity_advisor/credentials_provider/agent.py

,

credentials_provider = Agent(...)

definition:

Temsilci tanımında şu satırı bulun:

credentials_provider = Agent(
    name="CredentialsProvider",
    model="gemini-2.5-flash",
    description="Securely processes payments by creating PaymentMandates and executing transactions with user consent.",

Bu satırı

description

line:

    before_agent_callback=validate_cart_before_payment,

Aracı tanımınız artık şu şekilde görünmelidir:

credentials_provider = Agent(
    name="CredentialsProvider",
    model="gemini-2.5-flash",
    description="Securely processes payments by creating PaymentMandates and executing transactions with user consent.",
    before_agent_callback=validate_cart_before_payment,
    tools=[
        FunctionTool(func=create_payment_mandate)
    ],
    instruction="""..."""
)

7. adım: ADK web kullanıcı arayüzü ile test etme

Şimdi de doğrulama geri aramaları etkin durumdayken tamamen güvenliği artırılmış sistemi test edelim.

👉 Cloud Shell terminalinizde şunu çalıştırın:

adk web

Şuna benzer bir çıkış görürsünüz:

+-----------------------------------------------------------------------------+
| ADK Web Server started                                                      |
|                                                                             |
| For local testing, access at http://localhost:8000.                         |
+-----------------------------------------------------------------------------+

INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)

👉 Ardından, tarayıcınızdan ADK Web kullanıcı arayüzüne erişmek için:

Cloud Shell araç çubuğunda (genellikle sağ üstte) bulunan Web önizlemesi simgesinden (göz veya ok içeren kareye benzer) Bağlantı noktasını değiştir'i seçin. Pop-up pencerede bağlantı noktasını 8000 olarak ayarlayın ve "Değiştir ve Önizle"'yi tıklayın. Ardından Cloud Shell, ADK Web kullanıcı arayüzünü gösteren yeni bir tarayıcı sekmesi açar.

webpreview

👉 Açılır menüden temsilcinizi seçin:

ADK Web kullanıcı arayüzünün üst kısmında bir açılır menü görürsünüz. Listeden charity_advisor'ı seçin.

agent-select

ADK web arayüzünü görürsünüz. Bu arayüzde:

  • Sohbet paneli: Sol tarafta, sohbet için
  • İzleme paneli: Sağ tarafta, gözlemlenebilirlik için (Bunu 9. modülde kullanacağız)

1. Test: Bağış Akışını Tamamlama (Normal Durum)

👉 Sohbet arayüzünde şunu yazın:

I want to donate to an education charity

Akışın tamamını izleyin:

adk web shopping agent

adk web donation processing pipeline

Neler oluyor (sağdaki izleme panelinde görünür):

1. Danışman, ShoppingAgent'a yetki veriyor:

  • ShoppingAgent, eğitim hayır kurumlarını arıyor
  • Ayrıntılarıyla birlikte 3 doğrulanmış seçeneği gösterir.

2. ShoppingAgent ile etkileşimde bulunursunuz (bu işlem birden fazla adım sürebilir):

User: "Tell me more about Room to Read"
Shopping: [explains mission and impact]
User: "I'll donate $50 to Room to Read"

3. ShoppingAgent, IntentMandate oluşturur:

  • Amacı oluşturur ve imzalar.
  • Niyet kimliğiyle onay döndürür.

4. Danışman, işleme aşamasına geçer:

Mükemmel! Room to Read'e yaptığınız 50 ABD doları tutarındaki bağış işleniyor...

5. DonationProcessingPipeline etkinleştirilir:

  • Satıcı geri çağırması, IntentMandate'i doğrular (✓ geçti) ← YENİ!
  • Satıcı temsilcisi, imzalı CartMandate oluşturur
  • Kimlik bilgileri geri çağırma işlevi, CartMandate'i doğrular (✓ geçti) ← YENİ!
  • Kimlik bilgisi sağlayıcı ödemeyi hazırlar

6. Ödeme işlemleri:

  • Kimlik bilgisi sağlayıcı, PaymentMandate oluşturur
  • Ödeme işleme sürecini simüle eder.
  • İade işlem kimliği

7. Danışman özetliyor:

Mükemmel! Bağışınız başarıyla işlendi. 🎉

Ayrıntılar:

  • Tutar: 50,00 ABD doları
  • Hayır kurumu: Room to Read (EIN: 77-0479905)
  • İşlem kimliği: txn_a3f7b2c8d9e1f4a2

2. Test: Geri Aramaların Hataları Yakaladığını Doğrulayın (İsteğe Bağlı Gelişmiş Test)

Geri çağırmaların hataları yakaladığını görmek ister misiniz? Durumu manuel olarak bozmanız (gelişmiş hata ayıklama) gerekir. Ancak üretimde geri çağırmalar şunları yakalar:

  • Alışveriş aracının çalışması başarısız oluyor → Satıcı geri araması engelliyor: "Hata: Sepet oluşturulamıyor..."
  • 2 saat geçer → Satıcı geri araması engellenir: "Hata: Amaç süresi doldu..."
  • Alışveriş sepetinin süresi doluyor → Kimlik bilgileri geri çağırma işlemleri engelleniyor: "Hata: Alışveriş sepetinin süresi doldu (15 dakika sınırı)..."

Bu uç durumlar artık doğrulama geri çağırmalarınız tarafından mimari olarak zorunlu kılınıyor.

Az Önce Oluşturduğunuz

Üç uzmanlaşmış aracı, mimari doğrulama ile sorunsuz ve güvenilir bir sistemde başarıyla düzenlediniz.

Sonraki Adımlar

Güvenilir aracı oluşturmanın teknik temelini tamamladınız:

Kimlik bilgisi zincirini yerel olarak zorunlu kılan, güvenilir ve eksiksiz bir sistem oluşturdunuz. Şimdi de üretim dağıtımı aracılığıyla gerçek kullanıcıların erişimine açalım ve 9. Modül'ü mümkün kılan hesap verebilirlik izini etkinleştirelim.

Güçlendirilmiş temsilcinizi Google Cloud'a dağıtalım.

8. Dağıtım

banner

Güvenilir bağış sisteminiz artık yerel olarak çalışan üç uzman temsilciyle tamamlandı:

Ancak bu yalnızca geliştirme makinenizde çalışır. Bu sistemi gerçek kullanıcılar için faydalı hale getirmek ve güvenilirliği kanıtlayan hesap verebilirlik izlerini yakalamak için sistemi üretime dağıtmanız gerekir.

Bu modülde, gözlemlenebilirlik özelliği ilk günden itibaren etkin olacak şekilde aracınızı Google Cloud'a dağıtma süreci adım adım açıklanmaktadır. Dağıtım sırasında kullanacağınız --trace_to_cloud işareti, 9. modüldeki hesap verebilirlik izinin oluşturulmasını sağlar.

Dağıtım Seçeneklerini Anlama

ADK, birden fazla dağıtım hedefini destekler. Her birinin karmaşıklık, oturum yönetimi, ölçeklendirme ve maliyet açısından farklı özellikleri vardır:

Faktör

Yerel (adk web)

Agent Engine

Cloud Run

Karmaşıklık

Minimal

Düşük

Orta zorlukta

Oturum Kalıcılığı

Yalnızca bellek içi (yeniden başlatıldığında kaybolur)

Vertex AI tarafından yönetilen (otomatik)

Cloud SQL (PostgreSQL) veya bellek içi

Altyapı

Yok (yalnızca geliştirme makinesi)

Tümüyle yönetilen

Kapsayıcı + isteğe bağlı veritabanı

Soğuk Başlatma (Cold Start)

Yok

100-500ms

100-2000ms

Ölçeklendirme

Tek örnek

Otomatik

Otomatik (sıfıra)

Maliyet modeli

Ücretsiz (yerel işlem)

İşleme dayalı

İstek tabanlı + ücretsiz katman

Kullanıcı arayüzü desteği

Evet (yerleşik)

Hayır (yalnızca API)

Evet (--with_ui işaretiyle)

Gözlemlenebilirlik Kurulumu

Yerel iz görüntüleyici

--trace_to_cloud ile otomatik

--trace_to_cloud işareti gerektirir

İdeal kullanım alanları

Geliştirme ve test

Yapımcılar

Yapımcılar

Öneri: Bu güvenilir bağış sistemi için Agent Engine'i birincil üretim dağıtımınız olarak kullanmanızı öneririz. Çünkü Agent Engine:

  • Tümüyle yönetilen altyapı (yönetilecek container yok)
  • VertexAiSessionService üzerinden yerleşik oturum kalıcılığı
  • Soğuk başlatma olmadan otomatik ölçeklendirme
  • Basitleştirilmiş dağıtım (Docker bilgisi gerekmez)
  • Kullanıma hazır Cloud Trace entegrasyonu

Ek seçenek: Google Kubernetes Engine (GKE)

Kubernetes düzeyinde kontrol, özel ağ veya çok hizmetli düzenleme gerektiren ileri düzey kullanıcılar için GKE dağıtımı kullanılabilir. Bu seçenek maksimum esneklik sağlar ancak daha fazla operasyonel uzmanlık (küme yönetimi, manifestler, hizmet hesapları) gerektirir.

GKE dağıtımı bu codelab'de ele alınmamıştır ancak ADK GKE Dağıtım Kılavuzu'nda ayrıntılı olarak açıklanmıştır.

Ön koşullar

1. Google Cloud Proje Kurulumu

Faturalandırmanın etkin olduğu bir Google Cloud projeniz olmalıdır. Hesabınız yoksa:

  1. Proje oluşturma: Google Cloud Console
  2. Faturalandırmayı etkinleştirme: Faturalandırmayı Etkinleştir'i tıklayın.
  3. Proje kimliğinizi (proje adı veya numarası değil) not edin.

2. Yeniden kimlik doğrulama (isteğe bağlı)

Google Cloud ile kimlik doğrulayın:

gcloud auth application-default login
gcloud config set project YOUR_PROJECT_ID

YOUR_PROJECT_ID kısmını, gerçek Google Cloud proje kimliğinizle değiştirin.

Kimlik doğrulamayı onaylayın:

gcloud config get-value project
# Should output: YOUR_PROJECT_ID

3. Ortam Değişkenleri

.env dosyanızı otomatik olarak doldurmak için aşağıdaki komutları kullanın:

# Get your current Project ID
PROJECT_ID=$(gcloud config get-value project)
STAGING_BUCKET_VALUE="gs://${PROJECT_ID}-staging"
ENV_FILE=".env"

# Check if STAGING_BUCKET is already set in the .env file
if grep -q "^STAGING_BUCKET=" "${ENV_FILE}"; then
  # If it exists, replace the line
  # The sed command finds the line starting with STAGING_BUCKET= and replaces the entire line.
  # Using | as a delimiter to avoid issues with slashes in the bucket name.
  sed -i "s|^STAGING_BUCKET=.*|STAGING_BUCKET=${STAGING_BUCKET_VALUE}|" "${ENV_FILE}"
  echo "Updated STAGING_BUCKET in ${ENV_FILE}"
else
  # If it doesn't exist, add it to the end of the file
  echo "STAGING_BUCKET=${STAGING_BUCKET_VALUE}" >> "${ENV_FILE}"
  echo "Added STAGING_BUCKET to ${ENV_FILE}"
fi

# Verify it was added or updated correctly
echo "Current STAGING_BUCKET setting:"
grep "^STAGING_BUCKET=" "${ENV_FILE}"

Aşağıdaki bilgileri görürsünüz:

STAGING_BUCKET=gs://your-actual-project-id-staging

Önemli notlar:

  • YOUR_PROJECT_ID yerine gerçek proje kimliğinizi yazın (veya yukarıdaki komutları kullanın).
  • GOOGLE_CLOUD_LOCATION için desteklenen bir bölge kullanın.
  • Dağıtım komut dosyasını çalıştırdığınızda hazırlama paketi yoksa otomatik olarak oluşturulur.

4. Gerekli API'leri etkinleştirme

Dağıtım sürecinde çeşitli Google Cloud API'lerinin etkinleştirilmesi gerekir. Bu API'leri etkinleştirmek için aşağıdaki komutu çalıştırın:

gcloud services enable \
    aiplatform.googleapis.com \
    storage.googleapis.com \
    cloudbuild.googleapis.com \
    cloudtrace.googleapis.com \
    compute.googleapis.com

Bu komut şunları sağlar:

  • AI Platform API: Agent Engine ve Vertex AI modelleri için
  • Cloud Storage API: Hazırlama paketi için
  • Cloud Build API: Container oluşturma (Cloud Run) için
  • Cloud Trace API: İzlenebilirlik ve hesap verebilirlik izleri için
  • Compute Engine API: Hizmet hesabı yönetimi için

1. adım: Dağıtım altyapısını anlayın

Projenizde tüm dağıtım modlarını işleyen birleşik bir dağıtım komut dosyası (deploy.sh) bulunur.

👉 Dağıtım komut dosyasını inceleyin (isteğe bağlı):

cat deploy.sh

Komut dosyası üç dağıtım modu sunar:

  • ./deploy.sh local - Bellek içi depolama ile yerel olarak çalıştırma
  • ./deploy.sh agent-engine - Vertex AI Agent Engine'e dağıtma (önerilir)
  • ./deploy.sh cloud-run - İsteğe bağlı kullanıcı arayüzüyle Cloud Run'a dağıtma

Arka planda işleyiş şekli:

Agent Engine dağıtımı için komut dosyası şunları yürütür:

adk deploy agent_engine \
  --project=$GOOGLE_CLOUD_PROJECT \
  --region=$GOOGLE_CLOUD_LOCATION \
  --staging_bucket=$STAGING_BUCKET \
  --display_name="Charity Advisor" \
  --trace_to_cloud \
  charity_advisor

Cloud Run dağıtımı için şu komutlar yürütülür:

adk deploy cloud_run \
  --project=$GOOGLE_CLOUD_PROJECT \
  --region=$GOOGLE_CLOUD_LOCATION \
  --service_name="charity-advisor" \
  --app_name="charity_advisor" \
  --with_ui \
  --trace_to_cloud \
  charity_advisor

--trace_to_cloud işareti her iki dağıtım türü için de kritik öneme sahiptir. 9. modülde ele alacağınız hesap verebilirlik izi için Cloud Trace entegrasyonunu etkinleştirir.

2. adım: Agent Engine Sarmalayıcısı'nı hazırlayın

Agent Engine, yönetilen çalışma zamanı için aracınızı sarmalayan belirli bir giriş noktası gerektirir. Bu dosya sizin için oluşturuldu.

👉 İnceleme

charity_advisor/agent_engine_app.py

:

"""Agent Engine application wrapper.

This file prepares the Charity Advisor agent for deployment to Vertex AI Agent Engine.
"""

from vertexai import agent_engines
from .agent import root_agent

# Wrap the agent in an AdkApp object for Agent Engine deployment
app = agent_engines.AdkApp(
    agent=root_agent,
    enable_tracing=True,  # Enables Cloud Trace integration automatically
)

Bu dosya neden gereklidir?

  • Agent Engine, ajanın AdkApp nesnesine sarmalanmasını gerektirir.
  • enable_tracing=True parametresi, Cloud Trace entegrasyonunu otomatik olarak etkinleştirir.
  • Bu sarmalayıcı, dağıtım sırasında ADK CLI tarafından referans alınır.
  • VertexAiSessionService, otomatik oturum kalıcılığı için yapılandırılır.

Agent Engine, yerleşik oturum kalıcılığına sahip, tümüyle yönetilen bir altyapı sağladığı için güvenilir bağış sisteminiz için önerilen üretim dağıtımıdır.

Dağıtımı çalıştırma

Projenizin kök dizininden:

chmod +x deploy.sh
./deploy.sh agent-engine

Dağıtım Aşamaları

Komut dosyasının aşağıdaki aşamaları gerçekleştirmesini izleyin:

Phase 1: API Enablement
   aiplatform.googleapis.com
   storage.googleapis.com
   cloudbuild.googleapis.com
   cloudtrace.googleapis.com
   compute.googleapis.com

Phase 2: IAM Setup
   Getting project number
   Granting Storage Object Admin
   Granting Vertex AI User
   Granting Cloud Trace Agent

Phase 3: Staging Bucket
   Creating gs://your-project-id-staging (if needed)
   Setting permissions

Phase 4: Validation
   Checking agent.py exists
   Verifying root_agent defined
   Checking agent_engine_app.py exists
   Validating requirements.txt

Phase 5: Build & Deploy
   Packaging agent code
   Uploading to staging bucket
   Creating Agent Engine instance
   Configuring session persistence
   Setting up Cloud Trace integration
   Running health checks

Bu işlem, aracı paketleyip Vertex AI altyapısına dağıttığı için 5-10 dakika sürer.

Ajan motoru kimliğinizi kaydetme

Dağıtım başarılı olduğunda:

✅ Agent Engine created successfully!

   Agent Engine ID: 7917477678498709504
   Resource Name: projects/123456789/locations/us-central1/reasoningEngines/7917477678498709504
   Endpoint: https://us-central1-aiplatform.googleapis.com/v1/...

   ⚠️  IMPORTANT: Save the Agent Engine ID from the output above
   Add it to your .env file as:
   AGENT_ENGINE_ID=7917477678498709504

   This ID is required for:
   - Testing the deployed agent
   - Updating the deployment later
   - Accessing logs and traces

.env dosyanızı hemen güncelleyin:

echo "AGENT_ENGINE_ID=7917477678498709504" >> .env

Dağıtılanlar

Agent Engine dağıtımınız artık şunları içeriyor:

✅ Yönetilen çalışma zamanında çalışan
üç aracının tamamı (Alışveriş, Satıcı, Kimlik Bilgileri) ✅
Tam kimlik bilgisi zinciri mantığı (Intent → Sepet → Ödeme yetkileri) ✅
Onay iş akışıyla
kullanıcı rızası mekanizması
VertexAiSessionService aracılığıyla
otomatik oturum kalıcılığı
Google tarafından yönetilen
otomatik ölçeklendirme altyapısı ✅
Tam gözlemlenebilirlik için
Cloud Trace entegrasyonu

4. adım: Dağıtılan aracınızı test edin

Ortamınızı Güncelleme

.env dosyanızın Agent Engine kimliğini içerdiğini doğrulayın:

AGENT_ENGINE_ID=7917477678498709504  # From deployment output
GOOGLE_CLOUD_PROJECT=your-project-id
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://your-project-id-staging

Test komut dosyasını çalıştırma

Projenizde, özellikle Agent Engine dağıtımları için bir test komut dosyası bulunur.

👉 Testi çalıştırın:

python scripts/test_deployed_agent.py

Beklenen Çıkış

Testing Agent Engine deployment...
Project: your-project-id
Location: us-central1
Agent Engine ID: 7917477678498709504
Endpoint: https://us-central1-aiplatform.googleapis.com/v1/...

Creating session...
✓ Session created: 4857885913439920384

Sending donation query...
✓ Response received:
  Event 1: I'll help you donate $50 to a children's education charity...
  Event 2: Here are some highly-rated children's education charities...
  Event 3: Which charity would you like to support?...

✅ Test completed successfully!

Session ID: 4857885913439920384

This donation generated a trace in Cloud Trace.
View it in Module 9: Observability

To view traces:
https://console.cloud.google.com/traces/list?project=your-project-id

Doğrulama kontrol listesi

Testten sonra şunları doğrulayın:

✅ Ajan, sorgulara yanıt veriyor
✅ Üç ajanın tümü sırayla çalışıyor (Alışveriş → Satıcı → Kimlik Bilgileri)
✅ Kullanıcı rızası mekanizması etkinleştiriliyor (onay isteniyor)
✅ Oturum, istekler arasında devam ediyor
✅ Kimlik doğrulama hatası yok
✅ Bağlantı zaman aşımı yok

Hata alırsanız:

  • Ortam değişkenlerinizin doğru şekilde ayarlandığını kontrol edin
  • API'lerin etkinleştirildiğini doğrulayın: gcloud services list --enabled
  • Vertex AI Console'da Agent Engine günlüklerini kontrol etme
  • agent_engine_app.py dosyasının charity_advisor klasörünüzde bulunduğunu doğrulayın.

5. adım: Cloud Run'a dağıtın (isteğe bağlı)

Kolaylaştırılmış üretim dağıtımı için Agent Engine önerilse de Cloud Run daha fazla kontrol olanağı sunar ve ADK web kullanıcı arayüzünü destekler. Bu bölüm isteğe bağlıdır.

Cloud Run'ı Ne Zaman Kullanmalısınız?

Aşağıdaki durumlarda Cloud Run'ı seçin:

  • Kullanıcı etkileşimi için ADK web kullanıcı arayüzü
  • Container ortamı üzerinde tam kontrol
  • Özel veritabanı yapılandırmaları
  • Mevcut Cloud Run hizmetleriyle entegrasyon

Dağıtımı çalıştırma

chmod +x deploy.sh
./deploy.sh cloud-run

Neler değişiyor?

Senaryo otomatik olarak:

  • Aracı kodunuzla Docker container'ı oluşturma
  • Cloud SQL PostgreSQL veritabanı oluşturma (gerekirse)
  • Veritabanı bağlantısını yapılandırma
  • ADK web kullanıcı arayüzü etkinleştirilmiş şekilde dağıtma

Cloud SQL sağlama nedeniyle dağıtım 10-15 dakika sürer.

Oturum Yönetimi:

  • VertexAiSessionService yerine DatabaseSessionService kullanılıyor.
  • .env içinde veritabanı kimlik bilgileri (veya otomatik olarak oluşturulan kimlik bilgileri) gerektirir.
  • Durum, PostgreSQL veritabanında kalıcı olur.

Kullanıcı arayüzü desteği:

  • Web kullanıcı arayüzü: https://charity-advisor-xyz.a.run.app

Cloud Run dağıtımını test etme

--with_ui ile Cloud Run'a dağıtım yaptıysanız doğrudan tarayıcınızda test edebilirsiniz:

  1. Hizmet URL'nize gidin (Dağıtım çıktısında sağlanır)
  2. ADK web arayüzünü görürsünüz. Açılır listeden temsilcinizi seçin.
  3. Test bağışı yapma:
   I want to donate $50 to a children's education charity
  1. Yürütme akışını gözlemleyin:
    • ShoppingAgent, yardım kuruluşlarını bulur ve amacınızı kaydeder
    • MerchantAgent, alışveriş sepeti talimatını oluşturur
    • CredentialsProvider, ödeme yetkisi oluşturur ve onay ister
    • Onayınızın ardından ödeme işlenir.
  2. Yanıtın aşağıdakileri içerdiğini doğrulayın:
    • Bağış kuruluşu önerileri
    • Onay isteği
    • Onaydan sonraki başarı mesajı

Sorun giderme

Sık Karşılaşılan Sorunlar

Sorun: ERROR: GOOGLE_CLOUD_PROJECT is not set

Çözüm: .env dosyanızın doğru proje kimliğine sahip olduğundan emin olun:

GOOGLE_CLOUD_PROJECT=your-actual-project-id

Sorun: Hazırlama paketi otomatik olarak oluşturulmuyor

Çözüm: Komut dosyası, paketi otomatik olarak oluşturmalıdır. Yoksa manuel olarak oluşturun:

gsutil mb -p $GOOGLE_CLOUD_PROJECT -l $GOOGLE_CLOUD_LOCATION $STAGING_BUCKET

Özet

Başarıyla:

deploy.sh
tarafından sağlanan dağıtım altyapısını anladım. ✅ Agent Engine sarmalayıcı yapılandırmasını inceledim.
✅ Güvenilir bağış sisteminizi Agent Engine'e dağıttım (önerilir).
--trace_to_cloud
ile Cloud Trace entegrasyonunu etkinleştirdim.
✅ Temsilcinin erişilebilir ve işlevsel olduğunu doğruladım.
✅ 9. modülde hesap verebilirlik izleri için temel oluşturdum.

Bir sonraki modülde, bu işaretin tam olarak neyin kilidini açtığını göreceksiniz: her bağış, her izin anı ve kimlik bilgisi zincirinin her adımı hakkında tam görünürlük.

9. Gözlemlenebilirlik

banner

grafik izi

1. modülde temel bir sorun hakkında bilgi edindiniz: Bir yapay zeka ajanı parayı yönettiğinde ne olduğunu nasıl kanıtlayabilirsiniz?

Bir kullanıcı şunları iddia edebilir:

  • "Bu yardım kuruluşunu hiç seçmedim!"
  • "Bu ödemeyi ben yapmadım!"
  • "Sistem, iznim olmadan benden ödeme aldı!"

Geleneksel bir kara kutu yapay zeka sisteminde bunun aksini kanıtlamanın bir yolu yoktur. Ancak güvenilir bağış sisteminiz farklıdır. 8. modülde --trace_to_cloud işaretiyle dağıtım yaptınız. Bu nedenle artık her bağış, Cloud Trace'te eksiksiz ve kurcalanmaya karşı korumalı bir denetleme izi oluşturuyor.

Bu modülde, bu izleri okumayı ve kanıt olarak kullanmayı öğreneceksiniz. Öğrenecekleriniz:

  • Üretim izlerini bulmak için Cloud Trace Explorer'da gezinme
  • Yürütme akışını anlamak için şelale görünümünü okuyun
  • Kimlik bilgisi zincirini (Amaç → Sepet → Ödeme talimatları) bulma
  • Zaman damgası kanıtıyla izin anlarını bulma
  • Anlaşmazlık çözümü için izlemeleri kullanma
  • Uygunluk ve denetim için izlemeleri dışa aktarma

Güvenilir sistemleri yetenekli ancak şeffaf olmayan sistemlerden ayıran özellik, adli kesinlikle ne olduğunu kanıtlama yeteneğidir.

İzler ve Kapsamlar

Cloud Trace'te izleri görüntülemeden önce neye baktığınızı anlamanız gerekir.

İz nedir?

İzleme, aracınızın tek bir isteği işlediği zaman çizelgesinin tamamıdır. Kullanıcının sorgu göndermesinden nihai yanıtın iletilmesine kadar her şeyi yakalar.

Her izlemede şunlar gösterilir:

  • İsteğin toplam süresi
  • Yürütülen tüm işlemler
  • İşlemlerin birbirleriyle ilişkisi (üst-alt ilişkileri)
  • Her işlemin başlangıç ve bitiş zamanı
  • Başarı veya başarısızlık durumu

Bağış kuruluşu temsilciniz için: Bir izleme = "Bağış yapmak istiyorum"dan "Ödeme başarılı"ya kadar olan bağış akışının tamamı.

Aralık nedir?

Span, izleme içindeki tek bir iş birimini temsil eder. Kapsamları, bir izlemenin yapı taşları olarak düşünebilirsiniz.

Bağış sisteminizdeki yaygın aralık türleri:

Aralık Türü

Ne Anlama Gelir?

Örnek

agent_run

Temsilcinin yürütülmesi

ShoppingAgent.run, MerchantAgent.run

call_llm

Dil modeline istek gönderme

gemini-2.5-flash hayır kurumu seçme isteği

execute_tool

Araç işlevi yürütme

find_charities, create_payment_mandate

state_read

Oturum belleğinden okuma

Eyaletten intent_mandate alma

state_write

Oturum belleğine yazma

Durumda cart_mandate depolama

Her aralıkta şunlar bulunur:

  • Ad: Hangi işlemi temsil ettiği
  • Ne kadar sürdüğü (başlangıç zamanı → bitiş zamanı)
  • Özellikler: Araç girişleri, model yanıtları, jeton sayıları gibi meta veriler
  • Durum: Başarılı (OK) veya hata (ERROR)
  • Üst-alt ilişkileri: Hangi işlemler hangi işlemleri tetikledi?

Aralıklar nasıl iz oluşturur?

Kapsamlar, nedenselliği göstermek için iç içe yerleştirilir:

Root Span: CharityAdvisor.run (entire request)
  └─ Child: DonationPipeline.run (sequential workflow)
      ├─ Child: ShoppingAgent.run
         ├─ Grandchild: call_llm (Gemini processes charity search)
         ├─ Grandchild: execute_tool (find_charities)
         └─ Grandchild: execute_tool (save_user_choice)
      ├─ Child: MerchantAgent.run
         ├─ Grandchild: call_llm (Gemini generates cart)
         └─ Grandchild: execute_tool (create_cart_mandate)
      └─ Child: CredentialsProvider.run
          ├─ Grandchild: call_llm (Gemini processes payment)
          └─ Grandchild: execute_tool (create_payment_mandate) [CONSENT!]

Bu hiyerarşi, tam olarak ne olduğunu ve hangi sırayla gerçekleştiğini gösterir. Ödeme talimatının, kullanıcının bir hayır kurumu seçmesinden sonra oluşturulan alışveriş sepeti talimatından sonra oluşturulduğunu görebilirsiniz.

1. adım: Cloud Trace Explorer'a erişin

Şimdi de dağıtılan aracınızdaki gerçek izleri görüntüleyelim.

  1. Google Cloud Console'u açın: console.cloud.google.com
  2. En üstteki açılır listeden projenizi seçin (üzerinde çalışıyorsanız önceden seçilmiş olmalıdır).
  3. Cloud Trace Gezgini'ne gidin:

Ne Görüntülüyorsunuz?

İzleme Gezgini, projenizdeki tüm izlerin listesini gösterir:

Sütun

Gösterdiği bilgiler

İstek

HTTP yöntemi ve uç noktası (API istekleri için)

Başlangıç Saati

İsteğin başladığı zaman

Gecikme

İsteğin toplam süresi

Spans

İzdeki işlem sayısı

Her satır, dağıtılan aracınıza yapılan bir tam isteği temsil eder.

Test İzleri Oluşturma (Gerekirse)

Henüz iz görmüyorsanız listenin boş olmasının nedeni şunlar olabilir:

  • Dağıtılan temsilcinize henüz istek gönderilmedi
  • İstekten sonra izlerin görünmesi 1-2 dakika sürer.

Test izi oluşturma:

Cloud Run with UI'ye dağıtım yaptıysanız hizmet URL'nizi ziyaret edin ve tarayıcıda bağış işlemini tamamlayın.

Agent Engine'e dağıtım yaptıysanız 8. modüldeki test komut dosyasını çalıştırın:

python scripts/test_deployed_agent.py

1-2 dakika bekleyin, ardından Cloud Trace Explorer sayfasını yenileyin. Artık izleri görebilirsiniz.

İzleri filtreleme

Belirli izleri bulmak için üstteki filtre seçeneklerini kullanın:

  • Zaman aralığı: Gerekirse "Son bir saat"ten "Son 24 saat"e geçin.
  • Minimum gecikme / Maksimum gecikme: Yavaş istekleri filtreleme
  • İstek filtresi: Belirli işlemlere göre arama yapın (ör. "DonationPipeline")

Bu modülde, üç aracının da çalıştığı tam bağış akışlarını temsil ettikleri için daha uzun süreli izlere (>5 saniye) odaklanın.

2. adım: Tam bir bağış akışını inceleyin

Şelale görünümünü açmak için listedeki herhangi bir izi tıklayın. Temsilci davranışını analiz ederken en çok zaman geçireceğiniz yer burasıdır.

Şelale görünümünü anlama

Şelale görünümü, tüm yürütme zaman çizelgesini gösteren bir Gantt şemasıdır:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
              Timeline (horizontal = time) 
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

invocation                           ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 8.2s
  agent_run: CharityAdvisor          ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 8.1s
    agent_run: DonationPipeline      ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 7.9s
      agent_run: ShoppingAgent       ▓▓▓▓▓▓ 2.1s
        call_llm: gemini-2.5-flash   ▓▓▓▓ 1.2s
        execute_tool: find_charities ▓▓ 0.5s
        execute_tool: save_user_choice  0.3s
      agent_run: MerchantAgent       ▓▓▓ 1.8s
        call_llm: gemini-2.5-flash   ▓▓ 0.9s
        execute_tool: create_cart_mandate  0.7s
      agent_run: CredentialsProvider ▓▓▓▓▓▓▓▓ 4.0s
        call_llm: gemini-2.5-flash   ▓▓ 0.8s
        execute_tool: create_payment_mandate ▓▓▓▓▓ 3.0s [CONSENT]

Grafiği okuma

Her çubuk bir aralığı temsil eder:

  • Yatay konum: Başlangıç zamanı
  • Süre: Ne kadar sürdüğü
  • Girinti: Üst-alt ilişkilerini gösterir.
  • Renk: Normal için genellikle mavi, hatalar için kırmızı

Bu örnek izlemeden elde edilen önemli gözlemler:

Toplam süre: 8,2 saniye
Sıralı yürütme: ShoppingAgent, MerchantAgent başlatılmadan önce tamamlandı
MerchantAgent tamamlandı

önce

CredentialsProvider started
Consent was the longest operation: create_payment_mandate için 3,0 saniye (kullanıcı onayı bekleniyor)
LLM calls are visible: Her aracı bir Gemini isteği gönderdi
Tool calls are captured: Altı aracın tamamı başarıyla çalıştırıldı

Bu görsel, zamanın nerede harcandığını ve işlemlerin hangi sırada yürütüldüğünü anında gösterir.

Ayrıntılar için bir aralığı tıklayın

invocation aralığını (en üstteki kök aralık) tıklayın. Sağ panelde ayrıntılı özellikler gösterilir:

{
  "http.method": "POST",
  "http.status_code": 200,
  "http.url": "https://charity-advisor-xyz.a.run.app/api/run",
  "user_id": "test_user_123",
  "session_id": "4857885913439920384",
  "trace_id": "a1b2c3d4e5f6...",
  "span_id": "1234567890abcdef"
}

Bu özellikler, isteğin tamamı hakkında bağlam bilgisi sağlar.

3. adım: Kimlik bilgisi zincirini bulun

Güvenilir sisteminiz, her adımda yetkilendirmeyi kanıtlamak için kimlik bilgisi zinciri kullanır:

IntentMandate (User chose charity)
    ↓
CartMandate (Merchant created cart, signed IntentMandate)
    ↓
PaymentMandate (Payment provider created payment, signed CartMandate)

İzde her bir zorunluluğu bulalım.

IntentMandate'i bulma

execute_tool: save_user_choice yayını (ShoppingAgent altında) tıklayın.

Özellikler panelinde şunları görürsünüz:

{
  "tool.name": "save_user_choice",
  "tool.input.charity_name": "Save the Children",
  "tool.input.amount": 50,
  "tool.output.status": "success",
  "tool.output.intent_mandate": {
    "charity_name": "Save the Children",
    "amount": 50,
    "timestamp": "2024-11-08T15:30:12.345Z",
    "signature": "a3f7b9c1d2e4..."
  }
}

Bu, aşağıdakileri kanıtlar:

  • ✅ Kullanıcı "Save the Children"ı seçti
  • ✅ Tutar 50 ABD dolarıydı.
  • ✅ Seçim, 15:30:12 UTC'de kaydedildi.
  • ✅ İmza oluşturuldu (üretim ortamında bu işlem kriptografik olur)

IntentMandate artık oturum durumunda ve sonraki temsilciler tarafından kullanılabilir.

CartMandate'i bulma

execute_tool: create_cart_mandate aralığını (MerchantAgent altında) tıklayın.

Özellikler panelinde:

{
  "tool.name": "create_cart_mandate",
  "tool.input.intent_mandate": {
    "charity_name": "Save the Children",
    "amount": 50,
    "signature": "a3f7b9c1d2e4..."
  },
  "tool.output.status": "success",
  "tool.output.cart_mandate": {
    "cart_id": "cart_7893",
    "intent_signature": "a3f7b9c1d2e4...",
    "cart_signature": "e8f2a9b3c7d1...",
    "timestamp": "2024-11-08T15:30:14.789Z"
  }
}

Bu, aşağıdakileri kanıtlar:

  • ✅ MerchantAgent, IntentMandate'i aldı (girişte gösteriliyor)
  • ✅ "cart_7893" kimliğiyle sepet oluşturuldu
  • ✅ Sepet imzası, IntentMandate imzasına (zincir bağlantısı) referans veriyor.
  • ✅ 15:30:14 UTC'de oluşturuldu (intent'ten 2,4 saniye sonra)

CartMandate artık IntentMandate'i referans alarak zinciri oluşturuyor.

Ödeme yetkisini bulma

execute_tool: create_payment_mandate aralığını (CredentialsProvider altında) tıklayın.

Özellikler panelinde:

{
  "tool.name": "create_payment_mandate",
  "tool.input.cart_mandate": {
    "cart_id": "cart_7893",
    "intent_signature": "a3f7b9c1d2e4...",
    "cart_signature": "e8f2a9b3c7d1..."
  },
  "tool.confirmation_required": true,
  "tool.confirmation_timestamp": "2024-11-08T15:30:17.891Z",
  "tool.user_response": "CONFIRMED",
  "tool.wait_duration_ms": 29168,
  "tool.output.status": "success",
  "tool.output.payment_mandate": {
    "payment_id": "pay_9821",
    "cart_signature": "e8f2a9b3c7d1...",
    "payment_signature": "b4c9e2a7f8d3...",
    "timestamp": "2024-11-08T15:30:47.059Z"
  }
}

Bu, zincirin tamamını kanıtlar:

  • ✅ CredentialsProvider, CartMandate'i aldı (giriş bunu gösteriyor)
  • ✅ Ödeme, CartMandate imzasını (zincir bağlantısı) referans alıyor.
  • Onay gerekliydi (confirmation_required: true)
  • Kullanıcı, 15:30:17 UTC'de onayladı
  • ✅ Kullanıcı kararı için sistem 29,2 saniye bekledi.
  • ✅ Ödeme, onaydan sonra oluşturuldu (zaman damgası: 15:30:47)

Zinciri Görselleştirme

İzleme, kimlik bilgisi zincirinin doğru şekilde yürütüldüğünü kanıtlar:

15:30:12 UTC  IntentMandate created (signature: a3f7...)
                  
15:30:14 UTC  CartMandate created (references: a3f7...)
                  
15:30:17 UTC  User consent requested
                  
15:30:47 UTC  PaymentMandate created (references: e8f2...)

Her talimat, bir öncekinin imzasını referans alır. Bu, kurcalamaya karşı korumalıdır. İmzaların eşleştiğini kontrol ederek zinciri doğrulayabilirsiniz.

4. adım: Performansı ve darboğazları analiz etme

Cloud Trace yalnızca ne olduğunu kanıtlamakla kalmaz, zamanın nerede harcandığını da gösterir. Böylece optimizasyon yapabilirsiniz.

Kritik yolu belirleme

Şelale görünümünde, dikey yığındaki en uzun aralıkları bulun. Bunlar, performansınızdaki darboğazları gösterir.

Örnek izlememizden:

Total: 8.2 seconds

Breakdown:
  - ShoppingAgent:         2.1s (26%)
  - MerchantAgent:         1.8s (22%)
  - CredentialsProvider:   4.0s (49%)  ← Bottleneck
  - Other overhead:        0.3s (3%)

Önemli analiz: Kimlik bilgisi sağlayıcı, toplam sürenin% 49'unu oluşturuyor. Neden?

CredentialsProvider aralığını ayrıntılı inceleyin:

CredentialsProvider: 4.0s
  - call_llm:              0.8s (20%)
  - create_payment_mandate: 3.0s (75%)  ← User consent wait
  - Other:                 0.2s (5%)

3 saniyelik gecikme beklenir ve iyidir.Kullanıcı, onaylamadan önce düşünür. Bu bir performans sorunu değil, kullanıcıların bilinçli rızasının kanıtıdır.

Büyük dil modeli maliyetlerini izleme

Jeton kullanımını görmek için herhangi bir call_llm aralığını tıklayın:

{
  "llm.model": "gemini-2.5-flash",
  "llm.usage.prompt_tokens": 487,
  "llm.usage.completion_tokens": 156,
  "llm.usage.total_tokens": 643,
  "llm.response_time_ms": 1243
}

Bu API'yi kullanarak:

  • İstek başına maliyeti izleme (jeton sayısı × model fiyatlandırması)
  • Gereksiz yere uzun istemleri belirleme
  • Model performansını karşılaştırma (Flash ve Pro)
  • Gecikmeye karşı kalite için optimizasyon

Örnek hesaplama:

Gemini 2.5 Flash pricing (as of Nov 2024):
  Input:  $0.075 per 1M tokens
  Output: $0.30 per 1M tokens

This request:
  Input:  487 tokens × $0.075 / 1M = $0.000037
  Output: 156 tokens × $0.30 / 1M  = $0.000047
  Total:                            = $0.000084 (~$0.00008)

For 10,000 donations/month:
  10,000 × 3 agents × $0.00008 = $2.40/month in LLM costs

Bu ayrıntılı görünürlük, model seçimiyle ilgili veriye dayalı kararlar almanıza yardımcı olur.

İzler Arasında Karşılaştırma

Birden fazla iz için filtreleme ve süreleri karşılaştırma:

Trace 1: 8.2s  (with consent wait: 3.0s)
Trace 2: 12.5s (with consent wait: 7.8s)  ← User took longer
Trace 3: 5.1s  (with consent wait: 0.2s)  ← User clicked fast
Trace 4: 6.3s  (with consent wait: 1.5s)

Analiz: Çoğu varyasyon, sistem performansından değil kullanıcı karar verme süresinden kaynaklanır. Temel aracı yürütme (izin hariç) yaklaşık 5 saniye sürer.

Bu, sistemin güvenilir bir şekilde çalıştığını gösterir.

Üretim sistemlerinde, kullanıcılar şikayet etmeden önce sorunları yakalamak için uyarılar ayarlayın.

Yüksek hata oranları hakkında uyarı

İzlerin% 5'inden fazlasında hata olduğunda uyarı oluşturma:

  1. Cloud Monitoring'e gidin.
  2. "Uyarılar""Politika Oluştur"'u tıklayın.
  3. Yapılandırma:
    Resource: Cloud Trace Span
    Metric: Span error count
    Condition: Rate > 5% over 5 minutes
    Notification: Email your-team@example.com
    

Yüksek Gecikme Uyarısı

P95 gecikmesi 15 saniyeyi aştığında uyarı oluşturma:

Resource: Cloud Trace
Metric: Span duration (95th percentile)
Condition: > 15000ms for 5 minutes
Notification: PagerDuty

Bu sayede, performans düşüşü kullanıcı deneyimini etkilemeden önce tespit edilebilir.

Onay olmadan ödeme işlemi yapıldığında uyarı oluşturma:

Resource: Cloud Trace Span
Filter: tool.name="create_payment_mandate" AND tool.confirmation_required!=true
Condition: Any match
Notification: Critical alert to security team

Bu, bir güvenlik ihlali algılayıcısıdır. Tetiklenirse kullanıcı rızası mekanizmanızda bir sorun var demektir.

Öğrendikleriniz

Cloud Trace ile artık şunları nasıl yapacağınızı biliyorsunuz:

✅ Üretim izlerini bulmak için Cloud Trace Explorer'da gezinin.
✅ Tam yürütme akışını görmek için basamaklı görünümü okuyun.
✅ Kimlik bilgisi zincirini IntentMandate → CartMandate → PaymentMandate üzerinden izleyin. ✅ Anlaşmazlık çözümü için izleri kanıt olarak kullanın.
✅ Darboğazları belirlemek için performansı analiz edin.
LLM maliyetlerini ayrıntılı düzeyde izleyin.

Bu Durumun Farkı

Aynı "Bunu hiç yetkilendirmedim!" şikayetini ele alan iki sistemi karşılaştırın:

Gözlemlenebilirliği Olmayan Sistem

User: "I never authorized that $50 donation!"
You:  "Our logs show the transaction completed successfully."
User: "But I didn't approve it!"
You:  "The system requires confirmation before processing."
User: "I never saw any confirmation!"
You:  "..." [no way to prove what happened]

Result: Refund issued, trust lost, user never returns.

Cloud Trace ile Sistem

User: "I never authorized that $50 donation!"
You:  "Let me pull up the trace from your session..."
      [Shows waterfall with consent span]
You:  "Here's the evidence:
       - 15:30:17 UTC: System asked for confirmation
       - Message shown: 'You are about to donate $50...'
       - 15:30:47 UTC: You clicked 'CONFIRM'
       - Wait time: 29.2 seconds
       
       The system waited almost 30 seconds for your decision.
       Here's the exact timestamp of your confirmation."
       
User: "Oh... I remember now. My mistake. Sorry!"

Result: Trust preserved, no refund needed, user continues using service.

Hesap verebilirlik izlerinin gücü budur. "Bize güvenin"den "Size tam olarak ne olduğunu gösterelim"e geçersiniz.

Sonraki Adımlar

Güvenilir aracı oluşturmanın teknik temelini tamamladınız:

1-6. Modüller: Güvenilir bir mimari tasarlama (roller, kimlik bilgileri, izin)
7. Modül: Karmaşık iş akışlarını düzenleme (SequentialAgent)
8. Modül: Gözlemlenebilirlik etkinleştirilmiş şekilde dağıtma
9. Modül: Hesap verebilirlik izlerini okumayı ve kullanmayı öğrenme

Oluşturduğunuz mimari (rol ayrımı, kimlik bilgisi zincirleri, kullanıcı rızası mekanizmaları, tam gözlemlenebilirlik) doğrudan gerçek para, gerçek veriler ve gerçek sonuçlar içeren canlı sürüm sistemlerine aktarılır.

10. Yolculuğunuzun Aşamaları

Oluşturduklarınız

Bu atölyeye "Parayla ilgili konularda gerçekten güvenebileceğim yapay zeka temsilcilerini nasıl oluşturabilirim?" sorusuyla başladınız.

Artık cevabı biliyorsunuz.

Nereden başladığınız (3. Modül):

simple_agent = Agent(
    model="gemini-2.5-flash",
    instruction="Find charities and donate",
    tools=[google_search]
)

Şu an bulunduğunuz nokta (10. Modül):

  • ✅ Rol ayrımı olan üç uzman temsilci
  • ✅ Üç doğrulanabilir kimlik bilgisi (Niyet → Alışveriş sepeti → Ödeme yetkileri)
  • ✅ Her adımda geçerlilik süresi doğrulamasıyla kimlik bilgisi zincirini tamamlama
  • ✅ Zaman damgası kanıtı içeren açık rıza mekanizması
  • ✅ Gözlemlenebilirlik ile Agent Engine'e üretim dağıtımı
  • ✅ Cloud Trace'te tam hesap verebilirlik izi
  • ✅ Anlaşmazlık çözümü için adli kanıtlar

Atölye ve Üretim: Aradaki Fark

Sisteminizde doğru mimari ve kalıplar gösteriliyor ancak gerçek para ve gerçek kullanıcılar için yükseltilmesi gereken eğitici basitleştirmeler kullanılıyor.

Tam olarak nelerin basitleştirildiği ve üretim için gerekenler aşağıda açıklanmıştır:

Bileşen

Atölye Uygulaması

Prodüksiyon Şartları

İmzalar

Gösterim için SHA-256 karmaları (SIG_abc123)

PKI veya özel anahtarlarla JWT kullanılarak oluşturulan gerçek kriptografik imzalar

Ödeme İşleme

Simülasyonu yapılan iadeler (simulation: True işareti)

Gerçek ödeme API'leriyle (Stripe, PayPal, Square) entegrasyon

Kullanıcı Kimlik Doğrulaması

Örtülü güven (giriş yapılması gerekmez)

OAuth 2.0, WebAuthn veya oturum yönetimi

Gizli Anahtar Yönetimi

.env dosyasındaki ortam değişkenleri

Şifrelemeyle Google Secret Manager veya Cloud KMS

Charity Database (Hayır Kurumu Veritabanı)

9 hayır kurumunu içeren sahte JSON dosyası

Canlı API entegrasyonu (IRS Tax Exempt Organization Search, Charity Navigator API)

Hata İşleme

Hata mesajlarıyla temel try-catch

Eksponansiyel geri yükleme, devre kesiciler ve geçersiz ileti kuyruklarıyla yeniden deneme mantığı

Test

Komut dosyalarıyla manuel doğrulama

CI/CD ile kapsamlı birim/entegrasyon/E2E test paketi

Oturum Kalıcılığı

Bellek içi (yerel) veya otomatik (Agent Engine)

Yedekleme ve olağanüstü durum kurtarma özelliklerine sahip üretim veritabanı

Hız sınırlaması

Yok (eğitim ortamı)

Kullanıcı başına hız sınırlamaları, IP tabanlı sınırlama, kötüye kullanım tespiti

Ustalaştığınız Temel Mimari Kalıplar

Bu atölyede öğrendiğiniz kalıplar üretim kalıplarıdır. Bu kişilerden şüphe etmeyin.

Rol Ayrımı (AP2 1. İlkesi)

Her temsilcinin NET bir görevi vardır ve YALNIZCA ihtiyacı olan bilgileri görür. Bir aracı tehlikeye girse bile saldırgan diğer aracıların verilerine erişemez. Bu durum, etki alanını sınırlar.

Bunu kullanan üretim sistemleri: Ödeme işleme, belge iş akışları, onay zincirleri, doğrulama kapıları içeren çok adımlı formlar.

Doğrulanabilir Kimlik Bilgileri (AP2 2. İlkesi)

Her kimlik bilgisinin süre sonu vardır, önceki kimlik bilgisine referans verir ve bir sonraki adımdan önce doğrulama gerektirir. Bu işlem, kurcalamaya karşı korumalı bir denetim zinciri oluşturur.

Üretim değeri: Ne zaman, ne olduğu ve hangi sırayla gerçekleştiğine dair eksiksiz kanıt. Anlaşmazlık çözümü ve düzenleyici kurumun belirlediği kurallara uygunluk için gereklidir.

Kullanıcının işlemi onayladığını gösteren zaman damgası. İtiraz edilemez.

Üretim değeri: Finansal işlemler için yasal zorunluluktur. Hem kullanıcıyı hem de şirketi korur.

Sıralı Düzenleme (ADK Kalıbı)

Doğru yürütme sırasını zorunlu kılar. Adımların atlanmasını önler. Her temsilcinin önceki temsilcinin çıktısını görmesini sağlar.

Üretim değeri: Kullanıcıların anında sonuç beklediği, insan etkileşimli sistemler için idealdir. Bu, bağış akışları, ödeme süreçleri ve onay zincirleri için doğru kalıptır.

Tam gözlemlenebilirlik (OpenTelemetry + Cloud Trace)

Her karar, araç çağrısı, izin anı ve kimlik bilgisi aktarımı otomatik olarak kaydedilir.

Gerçek değer: Anlaşmazlıklar için adli kanıt. Performans optimizasyonu verileri. Uygunluk denetim izleri. Üretim sorunlarında hassas bir şekilde hata ayıklama yapın.

Sürekli öğrenme kaynakları

ADK Belgeleri:

AP2 ve İlgili Standartlar:

Google Cloud Hizmetleri:

Temizleme Kaynakları

Devam eden ödemelerden kaçınmak için dağıtımınızı silin:

Agent Engine: Agent Engine dokümanlarındaki adımları uygulayın.

Cloud Run (yayınlandıysa):

gcloud run services delete charity-advisor \
    --region=$GOOGLE_CLOUD_LOCATION

Depolama paketleri:

gsutil -m rm -r gs://$GOOGLE_CLOUD_PROJECT-staging
gsutil -m rm -r gs://$GOOGLE_CLOUD_PROJECT-artifacts

Yolculuğunuz Devam Ediyor

Basit bir soruyla başlayıp eksiksiz bir yanıt oluşturdunuz. Güvenilir yapay zeka temsilcileri için temel kalıplarda uzmanlaştınız. Bu kalıplar, yapay zeka temsilcilerinin hassas işlemleri (finansal işlemler, sağlık hizmetleriyle ilgili kararlar, yasal belgeler, tedarik zinciri işlemleri) gerçekleştirdiği tüm alanlara aktarılır.

İlkeler aktarılır. Güven modeli çalışır.

Şimdi güvenilir bir şeyler oluşturun! ❤️

banner