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

İ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.

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:
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 | • Role dayalı güvenlik sınırları |
Daha fazla bilgi |
Ne Oluşturacaksınız?
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.

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.

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

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
Öğ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.pyiçin arama yapar adk run agent_folderile 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

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:
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:
- Güvenilir veritabanımızı sorgulamak için
find_charitiesaracını kullanın. - Kullanıcıya seçenekler sunma
save_user_choicearacını kullanarak bir IntentMandate oluşturun ve durumu kaydedin.- 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.
👉 Aç
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.
👉 Aç
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:
_validate_charity_data()girişleri doğruladı_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"
})
- Araç, yalnızca IntentMandate'i paylaşılan duruma yazdı:
state["intent_mandate"] = intent_mandate_dict
- LLM'ye amaç ayrıntılarını içeren bir başarı mesajı döndürüldü.
- 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

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.
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:
- Durumdan IntentMandate'i okuma (Alışveriş Aracısı'nın yazdığı)
- Intent'in süresinin dolmadığını doğrulayın.
- Bağış yapılan kuruluşun adını, tutarı ve diğer ayrıntıları ayıklama
- AP2 Pydantic modellerini kullanarak W3C uyumlu bir PaymentRequest yapısı oluşturma
- AP2'nin CartMandate with expiry (Son kullanma tarihi olan CartMandate) ile sarmalayın.
- Simüle edilmiş satıcı imzası ekleme
- 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.
👉 Aç
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.
👉 Aç
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

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.
Ö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ı:
- Eyalet tarafından verilen CartMandate'i okuyun (Satıcı temsilcisinin yazdığı)
- AP2 Pydantic modellerini kullanarak sepetin süresinin dolmadığını doğrulayın.
- İç içe yerleştirilmiş yapıdan ödeme ayrıntılarını ayıklama
- AP2 modellerini kullanarak kullanıcı izniyle PaymentMandate oluşturma
- Ödeme işlemini simüle etme (üretimde gerçek ödeme API'si çağrılır)
- 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.
👉 Aç
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.
👉 Aç
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:
- Durumdan bir kimlik bilgisi okur.
- Pydantic modellerini (yapı + geçerlilik kontrolü) kullanarak doğrular.
- AP2 modellerini kullanarak sonraki kimlik bilgisini oluşturur.
- 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ış
CartMandatePydantic 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
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.
👉 Aç
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)

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.
👉 Aç
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
👉 Aç
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.

👉 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.

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:


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

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 ( | 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 ( |
Gözlemlenebilirlik Kurulumu | Yerel iz görüntüleyici |
|
|
İ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:
- Proje oluşturma: Google Cloud Console
- Faturalandırmayı etkinleştirme: Faturalandırmayı Etkinleştir'i tıklayın.
- 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_IDyerine gerçek proje kimliğinizi yazın (veya yukarıdaki komutları kullanın).GOOGLE_CLOUD_LOCATIONiç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
AdkAppnesnesiyle sarmalanmasını gerektirir. enable_tracing=Trueparametresi, 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.
3. adım: Agent Engine'e dağıtın (ÖNERİ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.pydosyasınıncharity_advisorklasö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:
VertexAiSessionServiceyerineDatabaseSessionServicekullanılıyor..enviç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:
- Hizmet URL'nize gidin (Dağıtım çıktısında sağlanır)
- ADK web arayüzünü görürsünüz. Açılır listeden temsilcinizi seçin.
- Test bağışı yapma:
I want to donate $50 to a children's education charity
- 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.
- 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


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 |
| Temsilcinin yürütülmesi |
|
| Dil modeline istek gönderme |
|
| Araç işlevi yürütme |
|
| Oturum belleğinden okuma | Durumdan |
| Oturum belleğine yazma | Durumda |
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.
Cloud Trace'e gitme
- Google Cloud Console'u açın: console.cloud.google.com
- En üstteki açılır listeden projenizi seçin (üzerinde çalıştıysanız önceden seçilmiş olmalıdır).
- Cloud Trace Gezgini'ne gidin:
- Sol kenar çubuğunda Gözlemlenebilirlik bölümüne gidin.
- İzleme'yi tıklayın.
- Alternatif olarak doğrudan bağlantıyı kullanın: console.cloud.google.com/traces/list
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:
- Cloud Monitoring'e gidin.
- "Uyarılar" → "Politika Oluştur"'u tıklayın.
- 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.
İzin Eksikliğiyle İlgili Uyarı
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ı ( | PKI veya özel anahtarlarla JWT kullanılarak oluşturulan gerçek kriptografik imzalar |
Ödeme İşleme | Simülasyonu yapılan iadeler ( | 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 |
| 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.
Açık Rıza (AP2 İlkesi #3)
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! ❤️
