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 duyuyorsunuz. 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. Mali 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 mi? Emin değilsiniz.

Başka bir kuruluş deneyebilirsiniz. Bu kişiyi 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 zaman yerine ulaşmadı" 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.

Yarım saat 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, sonunda kapatana kadar birkaç gün açık kalır. Bu süre zarfında, iyi niyetinizi hatırlatır.

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 doludur:

  • Araştırma Sürtünmesi: Her hayır kurumu için ayrı 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.
  • Analiz felci: Çok fazla seçenek, 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 var. ABD'de bireysel bağışlar çok büyük bir yer tutuyor. 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, bağış yapmanın önündeki engellerin (ör. arama maliyetleri, psikolojik sürtünme ve zaman kısıtlamaları) 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, amaçlanan bağışların milyarlarca dolarının, ihtiyaç sahiplerine ulaşmadığını gösteriyor.

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ğış Temsilcisi'nin 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 konusunda güven duyması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) [Aracı Ödemeleri Protokolü (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:

Uzmanlaşmış rollere sahip çoklu aracı 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 eğitim amaçlı bir yardım kuruluşu 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 alınması

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ı kurup ilk yapay zeka temsilcinizi oluşturacağı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 kredisine mi ihtiyacınız var?

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

Aracılarınızın ç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: Aracı Geliştirme Kiti ç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

Yapılandırmanızı şablondan 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üklendi
  • ✅ Ş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 Acenteniz 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, "önceki" resminizdir. Güvenilir temsilciler oluşturmak için bir 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 dolduracağımız yer tutucular içeren temel bir yapıya sahiptir.

👉 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. Ajanımızı 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, aracının "iş tanımıdır ". LLM'ye araçlarını ne zaman ve nasıl kullanacağını söyler. Temsilcimizi hayır kurumu bilgileri 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çları olmayan bir temsilci yalnızca sohbet edebilir. Ajanımıza ilk yeteneğini, yani web'de arama yapma yeteneğ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 temsilcilerin finansal kararlar söz konusu olduğunda neden güvenilir olmadığını bu noktada anlıyoruz.

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 (yükü geri atıyor).

2. Test: Uygulama Sorunu

Şimdi de önemli 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 olan "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. Bunu yaparak güvenilir bir sistem oluşturmanın iki temel zorluğunu ortaya çıkardınız.

Uzmanlaşılan Temel Kavramlar

The Agent Class:

  • ADK'nın temel yapı taşı
  • LLM akıl yürütme (beyin) ile araçları (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
  • Uygulama 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ın nasıl çalıştığını görelim.

4. Alışveriş aracı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 Yapabilen" Temsilcilerle İlgili Sorun

Finans danışmanınız, muhasebeciniz ve yatırım aracınız olarak bir kişiyi işe aldığınızı düşünün. Kolay mı? Evet. Güvenli mi? Kesinlikle hayır. Bu durumda:

  • 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 hata yaparsa her şey risk altında olur.

AP2'nin Çözümü: Tek Temsilci, Tek İş

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. Bu özelliği, 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 Temsilcimiz: Alışveriş Temsilcisi

Alışveriş Agent'ı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. save_user_choice aracını kullanarak bir IntentMandate oluşturun ve durumu kaydedin.
  4. 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şlevini (zaten tamamlanmış) 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 aşağı kaydırarak

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ş aracısı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: Aracıya 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ğıdaki özelliklere sahip, AP2 uyumlu ve üretim kalitesinde bir temsilci 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ş aracısı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 gidiyor
📋 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 gidiyor
📋 Misyon: Bilgisayar bilimi 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 oluşturduğumuz IntentMandate sayesinde daha yapılandırılmış bir yanıt göreceksiniz:

Mükemmel! Bağışınız için bir IntentMandate 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 kaydeder 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şlemcimize iletiyorum.

Arka planda 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.

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

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

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'nin 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 görevi vardır.
  • Aracılar, 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.

Paylaşılan Anı Olarak Durum:

  • tool_context.state, tüm temsilcilerin erişebileceği "not defteri"dir.
  • Durum 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ı:

  • İş akışıyla ilgili adım adım açıklamalı kılavuz
  • 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 olan CartMandate'i oluşturmak için Merchant Agent'ı oluşturacağız.

Alışveriş aracısı, kullanıcının amacını son kullanma tarihiyle birlikte yakalayan bir IntentMandate oluşturdu. Şimdi bu kimlik bilgisini 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 bir uzman olan Alışveriş Aracısı'nı 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şlenebilmesi için ş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:

  • Dünya genelindeki ödeme işleyiciler bu biçimi tanır.
  • Tüm işlem ayrıntılarını standart bir şekilde içerir.
  • Özgünlüğünü 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: Ayrıntılı maliyetler, toplam, imza, tarih

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

sepete ekleme niyeti

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 sertifika şunları kanıtlar:

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

Ü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ölyemizde 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. Durumdan IntentMandate'i okuma (Alışveriş Aracısı'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ı ayıklama
  4. AP2 Pydantic modellerini kullanarak W3C uyumlu bir PaymentRequest yapısı oluşturma
  5. AP2'nin CartMandate with expiry (Son kullanma tarihi olan CartMandate) ile sarmalayın.
  6. Simüle edilmiş satıcı imzası ekleme
  7. Kimlik bilgisi sağlayıcı için CartMandate'i eyalete göre 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ı oluşturalım ve IntentMandate'in geçerlilik süresinin dolduğunu 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ç İmzası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 saralı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şaretçiler 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 CartMandates'i 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 Uyumluluğ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 süresinin dolması (amaçlanan süreden 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ı:

  • Eyaletten gelen 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ğrulanır) 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ı iznini 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 işlemine

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 Merchant Agent'ı 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 İşlemi

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 yürütme yetkisi veren bir kimlik bilgisi
  • Gerçek ödeme işleme (veya atölye çalışmamız için simülasyon)

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

Ödeme yetkisi 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: Sürecin parçası olan insan akışı olup olmadığı

3. timestamp: Yetkilendirmenin oluşturulduğu zaman

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

Kimlik bilgisi sağlayıcı:

  1. Eyalet tarafından verilen CartMandate'i okuyun (Satıcı temsilcisinin 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ç İmzası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 talimatı 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şaretçiler 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: Tam kimlik bilgisi sağlayıcıyı 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 modelleri kullanılarak uygun CartMandate okuma ve PaymentMandate oluşturma işlemlerinin yapıldığı 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ıştığı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ı + geçerlilik kontrolü) kullanarak doğrular.
  3. AP2 modellerini kullanarak sonraki kimlik bilgisini oluşturur.
  4. Bir sonraki temsilci için durumu yazar.

Az Önce Oluşturduğunuz

Pydantic modellerini ve ödeme simülasyonunu kullanarak AP2 üç aracılı kimlik bilgisi zincirini uygun yapı doğrulama ile 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 eklenir.
  • 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 modeli kabul eder.
  • cart.contents.cart_expiry (özellik erişimi) öğesinden okuma
  • Eski alışveriş sepeti işlemlerini önleyen güvenlik özelliği
  • Sürenin (15 dakika) amaca (1 saat) göre daha kısa olması

Ödeme Simülasyonu:

  • Gerçek ödeme işleyicinin eğitici amaçlı taklidi
  • İşlem kimliği oluşturur.
  • Durumda payment_result kaydeder
  • Açıkça simülasyon olarak işaretlenmiş (simülasyon: 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, denetim izi için önceki kimlik bilgisine bağlanır.
  • Duruma dayalı devirler, rol ayrımını korur
  • Zincir boyunca tür 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 desenler

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ı 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ş Temsilcisi: 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 gerekiyor.

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 orkestrasyon neden önemlidir?

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üzenin garantileri:

  • ✅ 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 Bir Sistem Oluşturmak

İki katman oluşturacağız:

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

  • Merchant → Credentials (Satıcı → 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 verilir.
  • 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 görüşme (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 orkestrasyon 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 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 yöneten, kullanıcıya yönelik temsilciyi oluşturalım. Bu bölümü üç kısımda 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 bağış 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, alışveriş aracısına ve işleme hattına erişim izni verip 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ş aracısı sessizce başarısız oluyor (IntentMandate hiçbir zaman oluşturulmuyor)
  • Alışveriş ile Merchant 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: 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 en üstünde, 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 Merchant Agent çalışmadan önce IntentMandate'i doğrulayan bir geri çağırma işlevi oluşturalım.

👉 In

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.

👉 In

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ına doğrulama ekleyelim.

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

👉

charity_advisor/credentials_provider/agent.py

Dosyanın en üstünde, 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

👉 In

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

👉 In

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ğundaki (genellikle sağ üstte) 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:

  • Sohbet paneli: Sol tarafta, sohbet için
  • İzleme paneli: Gözlemlenebilirlik için sağ tarafta (9. modülde bu paneli 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 amaçlı yardım kuruluşları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 araması, 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 (✓ başarılı) ← YENİ!
  • Kimlik bilgisi sağlayıcı ödemeyi hazırlar

6. Ödeme işlemleri:

  • Kimlik bilgisi sağlayıcı, PaymentMandate oluşturur
  • Ödeme işlemini simüle eder.
  • İade işlemi 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ı yakalarken nasıl çalıştığı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ş Temsilcisi aracı 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şlevleri engelliyor: "Hata: Alışveriş sepetinin süresi doldu (15 dakika sınırı)..."

Bu uç durumlar artık doğrulama geri aramaları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 etkinleştirilmiş ş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 izini mümkün kı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ı

Cold Start

Yok

100-500ms

100-2000ms

Ölçeklendirme

Tek örnek

Otomatik

Otomatik (sıfıra)

Maliyet modeli

Ücretsiz (yerel bilgi 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ım temsilcileri

Yapım temsilcileri

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

  • 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 projesi 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: Gözlemlenebilirlik 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) bulunuyor.

👉 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 Wrapper'ı 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, temsilcinin AdkApp nesnesiyle 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, tamamen 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.

Temsilci 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ığı (Amaç → Sepet → Ödeme yetkileri)
✅ Onay iş akışıyla kullanıcı izni 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ı bulunuyor.

👉 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 yapılacaklar listesi

Testten sonra şunları doğrulayın:

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

Hatalarla karşılaşı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üne şu adresten erişebilirsiniz: 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 aracısı para işlediğ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ü okuma
  • Sertifika zincirini bulun (Amaç → Sepet → Ödeme yetkileri)
  • Zaman damgası kanıtıyla izin anlarını bulma
  • İtiraz çözümünde izleri kullanma
  • Uygunluk ve denetim için izlemeleri dışa aktarma

Güvenilir sistemleri yetenekli ancak şeffaf olmayan sistemlerden ayıran şey budur: Adli kesinlikle ne olduğunu kanıtlama yeteneği.

İzler ve Kapsamlar Hakkında

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 son 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ı.

Span nedir?

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

Bağış sisteminizdeki yaygın kapsam 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çimi isteği

execute_tool

Araç işlevi yürütme

find_charities, create_payment_mandate

state_read

Oturum belleğinden okuma

Durumdan intent_mandate alma

state_write

Oturum belleğine yazma

Durumda cart_mandate depolama

Her kapsamda şunlar bulunur:

  • Ad: Bu işlemin neyi 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?

Nedenselliği göstermek için aralıklar 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 yetkisinin, kullanıcının bir hayır kurumu seçmesinden sonra oluşturulan alışveriş sepeti yetkisinden 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ıştıysanız önceden seçilmiş olmalıdır).
  3. Cloud Trace Gezgini'ne gidin:

Ne Görüntülüyorsunuz?

İz 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 aracınıza 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 (ö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: Normalde 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ı beklenmesi nedeniyle)
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 Span'i 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)

İzdeki her bir zorunluluğu bulalım.

Finding the IntentMandate

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 (üretimde 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 yayı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" kimlikli sepet oluşturuldu
  • ✅ Alışveriş sepeti 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 zinciri oluşturarak IntentMandate'i referans alıyor.

PaymentMandate'i 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ı
  • Sistem, kullanıcı kararını 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 yetki belgesi, 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östererek optimizasyon yapmanıza olanak tanır.

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 kapsamı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, düşünülerek verilmiş iznin 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 (jeton sayısı × model fiyatlandırması) izleme
  • 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 izi 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.

Herhangi bir ödeme onay olmadan işlenirse uyarı oluşturun:

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 izin mekanizmanızda bir sorun var demektir.

Öğrendikleriniz

Cloud Trace ile artık şunları yapmayı biliyorsunuz:

✅ Üretim izlerini bulmak için Cloud Trace Explorer'da gezinin
✅ Tam yürütme akışını görmek için şelale görünümlerini okuyun
Kimlik bilgisi zincirini izleyin (IntentMandate → CartMandate → PaymentMandate) ✅ İzleri anlaşmazlık çözümü için kanıt olarak kullanın
Performansı analiz ederek darboğazları belirleyin
LLM maliyetlerini ayrıntılı düzeyde takip edin

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.

Sorumluluk izlerinin gücü budur. "Bize güvenin"den "Size tam olarak ne olduğunu gösterelim"e geçiş yaparsınız.

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, izin mekanizmaları, tam gözlemlenebilirlik) doğrudan gerçek para, gerçek veriler ve gerçek sonuçlar işleyen üretim sistemlerine aktarılır.

10. Yolculuğunuzun Aşamaları

Oluşturduklarınız

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

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 anda 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 hesap verebilirlik izini tamamlama
  • ✅ 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 nelerin gerekli olduğu 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

Google Secret Manager veya şifrelemeli 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 şüphelenmeyin.

Rol Ayrımı (AP2 1. İlkesi)

Her temsilcinin NET bir işi 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 geçerlilik süresi vardır, önceki kimlik bilgisine referans verir ve bir sonraki adımdan önce doğrulama gerektirir. Bu, kurcalamaya karşı korumalı bir denetim zinciri oluşturur.

Üretim değeri: Ne olduğu, ne zaman olduğu ve hangi sırayla olduğuyla ilgili eksiksiz kanıt. Anlaşmazlıkların çözümü ve yasalara 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 takipleri. Üretim sorunlarında hassas bir şekilde hata ayıklama

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 (dağıtılmışsa):

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ıpları öğrendiniz. 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