1. Öğrenecekleriniz
Hoş geldiniz! Bugün oldukça keyifli bir yolculuğa çıkacağız. Popüler bir sosyal etkinlik platformu olan InstaVibe'ı düşünerek başlayalım. Bu özellik başarılı olsa da bazı kullanıcılar için grup etkinliklerinin planlanması sıkıcı bir iş olabilir. Tüm arkadaşlarınızın ilgi alanlarını öğrenmeye çalıştığınızı, ardından etkinlikler veya mekanlarla ilgili sonsuz seçenek arasından eleme yaptığınızı ve son olarak her şeyi koordine ettiğinizi hayal edin. Çok fazla! İşte tam da bu noktada yapay zekayı ve daha spesifik olarak akıllı aracıları devreye sokarak gerçek bir fark yaratabiliriz.
Bu fikrin amacı, kullanıcı ve arkadaş tercihlerini anlamak için akıllıca "dinlemek" gibi zorlu görevleri yerine getirebilecek ve ardından proaktif olarak harika ve kişiye özel etkinlikler önerebilecek bir sistem oluşturmaktır. Amacımız, InstaVibe'daki sosyal planlamayı sorunsuz ve keyifli bir deneyime dönüştürmektir. Bu akıllı asistanları oluşturmaya başlamak için doğru araçlarla güçlü bir temel oluşturmamız gerekiyor.
Göreceğiniz konsept:
Google'ın ADK'sı ile temeller: Google'ın Agent Development Kit'ini (ADK) kullanarak ilk akıllı aracınızı oluşturmanın temellerinde uzmanlaşın. Temel bileşenleri, aracı yaşam döngüsünü ve çerçevenin yerleşik araçlarından nasıl etkili bir şekilde yararlanacağınızı öğrenin.
Model Context Protocol (MCP) ile Asistan Özelliklerini Genişletme: Asistanlarınıza özel araçlar ve bağlam ekleyerek uzmanlık gerektiren görevleri yerine getirmelerini ve belirli bilgilere erişmelerini sağlayın. Model Context Protocol (MCP) kavramını tanıtın. Bu bağlamı sağlamak için MCP sunucusu ayarlamayı öğreneceksiniz.
Aracı Etkileşimlerini ve Düzenlemeyi Tasarlama: Aracı düzenlemesini anlamak için tek bir aracının ötesine geçin. Basit sıralı iş akışlarından döngüler, koşullu mantık ve paralel işlemeyi içeren karmaşık senaryolara kadar çeşitli etkileşim kalıpları tasarlayın. Modüler görevleri yönetmek için ADK çerçevesinde alt aracı kavramını kullanıma sunma.
İşbirlikçi Çoklu Aracı Sistemleri Oluşturma: Birden fazla aracının karmaşık hedeflere ulaşmak için işbirliği yaptığı sistemleri nasıl tasarlayacağınızı keşfedin. Dağıtılmış aracıların (farklı makinelerde veya hizmetlerde çalışıyor olabilir) güvenilir bir şekilde etkileşim kurması için standartlaştırılmış bir yol oluşturan Aracıdan Aracıya (A2A) iletişim protokolünü öğrenin ve uygulayın.
Google Cloud'da aracıları üretime alma: Aracı uygulamalarınızı geliştirme ortamlarından buluta taşıyın. Google Cloud Platform'da (GCP) ölçeklenebilir ve sağlam çok aracı sistemler tasarlayıp dağıtmaya yönelik en iyi uygulamaları öğrenin. Cloud Run gibi GCP hizmetlerinden yararlanma hakkında bilgi edinin ve aracılarınızı barındırmak ve yönetmek için en yeni Google Agent Engine'in özelliklerini keşfedin.
2. Mimari
InstaVibe ile yapay zeka destekli sosyal medya planlaması
Sosyal dinleme nedir?
Sosyal medya dinleme, bir konu, marka veya sektör hakkında insanların ne söylediğini anlamak için sosyal medya, forumlar ve haber siteleri gibi platformlardaki dijital sohbetleri izleme sürecidir. Kamuoyu duyguları, trendler ve kullanıcı ihtiyaçları hakkında değerli bilgiler sağlar. Bu atölye çalışmasında, bu kavramı aracı tabanlı bir sistemde kullanacağız.
You're on the Team at InstaVibe
Genç yetişkinlere yönelik popüler bir sosyal etkinlik platformu olan başarılı bir startup şirketi "InstaVibe"da çalıştığınızı hayal edin. İşler iyi gidiyor ancak ekibiniz, birçok teknoloji şirketi gibi yatırımcıların yapay zekayı kullanarak yenilik yapma baskısıyla karşı karşıya. Ayrıca, diğer kullanıcılar kadar etkileşimde bulunmayan bir kullanıcı segmenti olduğunu da fark ettiniz. Bu kullanıcılar, grup etkinlikleri başlatmaya daha az istekli olabilir veya planlama sürecini zor bulabilir. Bu durum, şirketiniz için bu önemli kullanıcı grubu arasında platforma bağlılığın azalması anlamına gelir.
Ekibinizin araştırması, yapay zeka destekli yardımın bu kullanıcıların deneyimini önemli ölçüde iyileştirebileceğini gösteriyor. Bu uygulamanın amacı, kullanıcının ve arkadaşlarının ilgi alanlarına göre alakalı etkinlikleri proaktif olarak önererek sosyal gezileri planlama sürecini kolaylaştırmaktır. Sizin ve iş arkadaşlarınızın karşılaştığı soru şudur: Yapay zeka temsilcileri, ilgi alanlarını keşfetme, etkinlik araştırması yapma ve potansiyel olarak ilk koordinasyonu sağlama gibi genellikle zaman alan görevleri nasıl otomatikleştirebilir?
Aracı Tabanlı Çözüm (Prototip Kavramı)
Çoklu temsilci sistemiyle desteklenen bir prototip özellik geliştirmenizi öneriyoruz. Kavramsal bir döküm:
- Sosyal profilleme aracısı: Bu aracı, kullanıcı bağlantılarını, etkileşimlerini ve kullanıcının tercihleriyle ilgili olabilecek daha geniş kamu trendlerini analiz etmek için sosyal dinleme tekniklerini kullanır. Bu özelliğin amacı, ortak ilgi alanlarını ve uygun etkinlik özelliklerini (ör. daha sakin toplantılarla ilgili tercihler, belirli hobiler) belirlemektir.
- Etkinlik Planlama Aracısı: Bu aracı, Sosyal Profil Oluşturma Aracısı'nın sunduğu analizlerden yararlanarak belirlenen ölçütlere (ör. konum, ilgi alanları) uygun belirli etkinlikler, mekanlar veya fikirler için online kaynaklarda arama yapar.
- Platform Etkileşimi Temsilcisi (MCP kullanılarak): Bu temsilci, Etkinlik Planlama Temsilcisi'nden son planı alır. Temel işlevi, önceden tanımlanmış bir MCP (Model Context Protocol) aracı kullanarak doğrudan InstaVibe platformuyla etkileşim kurmaktır. Bu araç, temsilciye etkinlik önerisi taslağı oluşturma ve planı özetleyen bir gönderi oluşturma gibi belirli özellikler sunar.
- Orchestrator Agent: Bu aracı, merkezi koordinatör olarak işlev görür. InstaVibe platformundan ilk kullanıcı isteğini alır, genel hedefi anlar (ör. "plan a event for me and my friends" [Ben ve arkadaşlarım için bir etkinlik planla]) ve ardından belirli görevleri mantıksal bir sırayla uygun uzmanlaşmış aracılara devreder. Aracılar arasındaki bilgi akışını yönetir ve nihai sonucun kullanıcıya geri iletilmesini sağlar.
Temel Mimari Öğeler ve Teknolojiler
Google Cloud Platform (GCP):
- Vertex AI:
- Gemini Modelleri: Google'ın en gelişmiş Büyük Dil Modelleri'ne (LLM) erişim sağlar. Bu modeller, temsilcilerimizin akıl yürütme ve karar verme özelliklerini destekler.
- Vertex AI Agent Engine: Orkestratör aracımızı dağıtmak, barındırmak ve ölçeklendirmek için kullanılan yönetilen bir hizmettir. Üretime geçişi basitleştirir ve altyapı karmaşıklıklarını soyutlar.
- Cloud Run: Container mimarisine alınmış uygulamaları dağıtmak için kullanılan sunucusuz platform. Bu bilgileri şu amaçlarla kullanırız:
- Ana InstaVibe web uygulamasını barındırır.
- A2A özellikli bağımsız aracıları (Planlayıcı, Sosyal Profil Oluşturma, Platform Etkileşimi) bağımsız mikro hizmetler olarak dağıtın.
- MCP Tool Server'ı çalıştırarak InstaVibe'ın dahili API'lerini temsilcilerin kullanımına sunun.
- Spanner: Tümden yönetilen, küresel olarak dağıtılmış ve son derece tutarlı bir ilişkisel veritabanı. Bu atölyede, GRAPH DDL ve sorgu özelliklerini kullanarak aşağıdaki işlemleri yapmak için bu hizmetin Grafik Veritabanı olarak sunduğu özelliklerden yararlanacağız:
- Karmaşık sosyal ilişkileri (kullanıcılar, arkadaşlıklar, etkinlik katılımı, gönderiler) modelleme ve depolama.
- Sosyal Profil Oluşturma temsilcileri için bu ilişkilerin verimli bir şekilde sorgulanmasını sağlar.
- Artifact Registry: Container görüntülerini depolamak, yönetmek ve güvenliğini sağlamak için tümüyle yönetilen bir hizmettir.
- Cloud Build: Derlemelerinizi Google Cloud'da yürüten bir hizmettir. Bu hizmeti, aracımızın ve uygulamamızın kaynak kodundan Docker container görüntülerini otomatik olarak oluşturmak için kullanıyoruz.
- Cloud Storage: Cloud Build gibi hizmetler tarafından derleme yapılarını depolamak ve Agent Engine tarafından operasyonel ihtiyaçları için kullanılır.
- Temel Aracı Çerçeveleri ve Protokolleri:
- Google'ın Agent Development Kit'i (ADK): Aşağıdakiler için birincil çerçeve:
- Her bir akıllı aracının temel mantığını, davranışını ve talimat kümelerini tanımlama.
- Aracıların yaşam döngülerini, durumunu ve belleğini (kısa süreli oturum durumu ve potansiyel olarak uzun süreli bilgi) yönetme.
- Temsilcilerin dünyayla etkileşim kurmak için kullanabileceği araçları (ör. Google Arama veya özel olarak geliştirilmiş araçlar) entegre etme
- Alt aracıların sıralı, döngü ve paralel yürütülmesi de dahil olmak üzere çoklu aracı iş akışlarını düzenleme
- Temsilciden Temsilciye (A2A) İletişim Protokolü: Aşağıdakileri sağlayan açık bir standarttır:
- Farklı yapay zeka temsilcileri arasında, ayrı hizmetler olarak veya farklı makinelerde çalışıyor olsalar bile doğrudan ve standartlaştırılmış iletişim ve ortak çalışma.
- Aracıların birbirlerinin özelliklerini (Aracı Kartları aracılığıyla) keşfetmesi ve görevleri devretmesi. Bu, Orchestrator temsilcimizin uzmanlaşmış Planner, Social ve Platform temsilcileriyle etkileşim kurması için çok önemlidir.
- A2A Python Kitaplığı (a2a-python): ADK aracılarımızın A2A protokolünü konuşmasını sağlamak için kullanılan somut kitaplık. Aşağıdakiler için gereken sunucu tarafı bileşenlerini sağlar:
- Aracıları A2A uyumlu sunucular olarak kullanıma sunma.
- Keşif için "Aracı Kartı"nın yayınlanmasını otomatik olarak yönetir.
- Diğer aracılardan (ör. Orchestrator) gelen görev isteklerini alıp yönetme
- Model Context Protocol (MCP): Temsilcilerin şunları yapmasına olanak tanıyan açık bir standarttır:
- Harici araçlar, veri kaynakları ve sistemlerle standart bir şekilde bağlantı kurup bunları kullanın.
- Platform Etkileşimi Aracımız, bir MCP sunucusuyla iletişim kurmak için bir MCP istemcisi kullanır. Bu istemci de InstaVibe platformunun mevcut API'leriyle etkileşim kurmak için araçlar sunar.
- Google'ın Agent Development Kit'i (ADK): Aşağıdakiler için birincil çerçeve:
- Hata Ayıklama Araçları:
- A2A Inspector: A2A Inspector, A2A özellikli aracılarımıza bağlanmak, onları incelemek ve onlarla etkileşim kurmak için bu atölye çalışması boyunca kullanılan web tabanlı bir hata ayıklama aracıdır. Nihai üretim mimarisinin bir parçası olmasa da geliştirme iş akışımızın önemli bir parçasıdır. Bu hizmet şunları sağlar:
- Agent Card Viewer: Bir aracının herkese açık özelliklerini getirmek ve doğrulamak için kullanılır.
- Canlı Sohbet Arayüzü: Dağıtılan bir temsilciye doğrudan mesaj göndererek anında test yapabilirsiniz.
- Hata Ayıklama Konsolu: İnceleyici ile aracı arasında değiştirilen ham JSON-RPC mesajlarını görüntülemek için kullanılır.
- A2A Inspector: A2A Inspector, A2A özellikli aracılarımıza bağlanmak, onları incelemek ve onlarla etkileşim kurmak için bu atölye çalışması boyunca kullanılan web tabanlı bir hata ayıklama aracıdır. Nihai üretim mimarisinin bir parçası olmasa da geliştirme iş akışımızın önemli bir parçasıdır. Bu hizmet şunları sağlar:
- Dil modelleri (LLM'ler): Sistemin "beyinleri":
- Google'ın Gemini Modelleri: Özellikle gemini-2.0-flash gibi sürümleri kullanırız. Bu modeller şu amaçlarla seçilir:
- Gelişmiş Akıl Yürütme ve Talimatları Uygulama: Karmaşık istemleri anlama, ayrıntılı talimatları uygulama ve görevler hakkında akıl yürütme becerileri sayesinde bu modeller, aracıların karar verme sürecini desteklemek için uygundur.
- Araç Kullanımı (İşlev Çağırma): Gemini modelleri, ADK aracılığıyla sağlanan araçların ne zaman ve nasıl kullanılacağını belirlemede mükemmeldir. Bu sayede temsilciler bilgi toplayabilir veya işlem gerçekleştirebilir.
- Verimlilik (Flash Modelleri): "Flash" varyantları, performans ve maliyet açısından iyi bir denge sunar. Hızlı yanıt gerektiren birçok etkileşimli aracı görevinde kullanılabilir.
- Google'ın Gemini Modelleri: Özellikle gemini-2.0-flash gibi sürümleri kullanırız. Bu modeller şu amaçlarla seçilir:
Google Cloud kredisine mi ihtiyacınız var?
3. Başlamadan önce
👉Google Cloud Console'un üst kısmındaki Cloud Shell'i etkinleştir'i tıklayın (Cloud Shell bölmesinin üst kısmındaki terminal şeklindeki simge).
👉 "Open Editor" (Düzenleyiciyi Aç) düğmesini tıklayın (kalemli açık bir klasöre benzer). Bu işlemle pencerede Cloud Shell kod düzenleyici açılır. Sol tarafta bir dosya gezgini görürsünüz.
👉Gösterildiği gibi, alt durum çubuğundaki Cloud Code ile oturum açma düğmesini tıklayın. Eklentiyi talimatlara göre yetkilendirin. Durum çubuğunda Cloud Code - no project (Cloud Code - proje yok) ifadesini görüyorsanız bunu seçin, ardından açılır listede "Select a Google Cloud Project" (Bir Google Cloud projesi seçin) seçeneğini ve oluşturduğunuz projeler listesinden belirli bir Google Cloud projesini seçin.
👉 Google Cloud proje kimliğinizi bulun:
- 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.
👉Bulut IDE'sinde terminali açın.
👉💻 Terminalde, aşağıdaki komutu kullanarak kimliğinizin zaten doğrulandığını ve projenin proje kimliğinize ayarlandığını doğrulayın:
gcloud auth list
👉💻 instavibe-bootstrap
projesini GitHub'dan kopyalayın:
git clone -b adk-1.2.1-a2a-0.2.7 https://github.com/weimeilin79/instavibe-bootstrap.git
chmod +x ~/instavibe-bootstrap/init.sh
chmod +x ~/instavibe-bootstrap/set_env.sh
Proje Yapısını Anlama
İnşa etmeye başlamadan önce, az önce klonladığınız instavibe-bootstrap
projenin düzenini anlamak için biraz zaman ayıralım. Bu sayede, atölye boyunca dosyaları nerede bulacağınızı ve nasıl düzenleyeceğinizi öğrenebilirsiniz.
instavibe-bootstrap/
├── agents/
│ ├── orchestrate/
│ ├── planner/
│ ├── platform_mcp_client/
│ └── social/
├── instavibe/
│ ├── static/
│ └── templates/
├── tools/
│ └── instavibe/
├── utils/
├── init.sh
└── set_env.sh
Önemli dizinlerin dökümü:
agents/
: Bu, yapay zeka sistemimizin kalbidir. Her alt dizin (planner/, social/ vb.), belirli bir akıllı aracının kaynak kodunu içerir.agent.py
: Her aracının klasöründe, aracının mantığının bulunduğu ana dosyadır.a2a_server.py
: Bu dosya, ADK aracısını bir Aracıdan Aracıya (A2A) sunucusuyla sarmalar.Dockerfile
: Aracıyı Cloud Run veya Agent Engine'e dağıtmak için container görüntüsünün nasıl oluşturulacağını tanımlar.
instavibe/
: Bu dizin, InstaVibe web uygulamasının kaynak kodunun tamamını içerir.tools/
: Bu dizin, temsilcilerimizin kullanabileceği harici araçlar oluşturmak için kullanılır.instavibe/
, Model Context Protocol (MCP) sunucusunu içerir.
Bu modüler yapı, web uygulamasını çeşitli yapay zeka bileşenlerinden ayırarak tüm sistemin yönetilmesini, test edilmesini ve dağıtılmasını kolaylaştırır.
👉💻 İlk kullanıma hazırlama komut dosyasını çalıştırın:
Bu komut dosyası, Google Cloud proje kimliğinizi girmenizi ister.
init.sh
komut dosyası tarafından istendiğinde son adımda bulduğunuz Google Cloud proje kimliğini girin:
cd ~/instavibe-bootstrap
./init.sh
👉💻 Gerekli proje kimliğini ayarlayın:
gcloud config set project $(cat ~/project_id.txt) --quiet
👉💻 Gerekli Google Cloud API'lerini etkinleştirmek için aşağıdaki komutu çalıştırın:
gcloud services enable run.googleapis.com \
cloudfunctions.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
spanner.googleapis.com \
apikeys.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
aiplatform.googleapis.com \
cloudresourcemanager.googleapis.com \
maps-backend.googleapis.com
👉💻 Gerekli tüm ortam değişkenlerini ayarlayın:
export PROJECT_ID=$(gcloud config get project)
export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")
export SERVICE_ACCOUNT_NAME=$(gcloud compute project-info describe --format="value(defaultServiceAccount)")
export SPANNER_INSTANCE_ID="instavibe-graph-instance"
export SPANNER_DATABASE_ID="graphdb"
export GOOGLE_CLOUD_PROJECT=$(gcloud config get project)
export GOOGLE_GENAI_USE_VERTEXAI=TRUE
export GOOGLE_CLOUD_LOCATION="us-central1"
İzinleri ayarlama
👉💻 İzin verin. Terminalde şunu çalıştırın :
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/spanner.admin"
# Spanner Database User
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/spanner.databaseUser"
# Artifact Registry Admin
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/artifactregistry.admin"
# Cloud Build Editor
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/cloudbuild.builds.editor"
# Cloud Run Admin
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/run.admin"
# IAM Service Account User
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/iam.serviceAccountUser"
# Vertex AI User
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/aiplatform.user"
# Logging Writer (to allow writing logs)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.viewer"
👉 Sonucu IAM konsolunuzda doğrulayın.
👉💻 Artifact Registry deposu oluşturmak için terminalde aşağıdaki komutları çalıştırın. Aracılarımız, MCP sunucusu ve InstaVibe uygulaması için tüm Docker görüntüleri, Cloud Run veya Agent Engine'e dağıtılmadan önce burada depolanır.
export REPO_NAME="introveally-repo"
gcloud artifacts repositories create $REPO_NAME \
--repository-format=docker \
--location=us-central1 \
--description="Docker repository for InstaVibe workshop"
API anahtarları için Harita Platformu'nu ayarlama
InstaVibe uygulamanızda Google Haritalar hizmetlerini kullanmak için bir API anahtarı oluşturmanız ve bu anahtarı uygun şekilde kısıtlamanız gerekir.
👉 Yeni bir sekmede API'ler ve Hizmetler > Kimlik Bilgileri'ne gidin. "Kimlik bilgileri" sayfasında üstteki + KİMLİK BİLGİLERİ OLUŞTUR düğmesini tıklayın. Açılır menüden API anahtarı'nı seçin.
👉 Yeni oluşturduğunuz API anahtarını gösteren bir iletişim kutusu açılır. Uygulama yapılandırmanız için daha sonra bu değere ihtiyacınız olacak.
👉 "API anahtarı oluşturuldu" iletişim kutusunda KAPAT'ı tıklayın.
👉 Yeni API anahtarınızın listelendiğini görürsünüz (ör. "API anahtarı 1"). Sağdaki üç noktayı tıklayın ve "API anahtarını kısıtla ve yeniden adlandır" sayfasını açmak için API anahtarını düzenle'yi seçin.
👉 En üstteki Ad alanında varsayılan adı şu şekilde değiştirin: Maps Platform API Key (🚨🚨ÖNEMLİ🚨🚨 Lütfen bu adı kullanın.)
Maps Platform API Key
👉 "Uygulama kısıtlamaları" bölümünde Yok'un seçili olduğundan emin olun.
👉 "API kısıtlamaları" bölümünde Anahtarı kısıtla radyo düğmesini seçin.
👉 API'leri seç açılır menüsünü tıklayın. Görüntülenen arama kutusuna Maps JavaScript API
yazın ve listeden seçin.
👉 Tamam'ı tıklayın.
👉 Sayfanın alt kısmındaki KAYDET düğmesini tıklayın.
Artık "Maps Platform API Key" adlı bir API anahtarını başarıyla oluşturdunuz, yalnızca "Maps JavaScript API" kullanımına izin verecek şekilde kısıtladınız ve API'nin projeniz için etkinleştirildiğinden emin oldunuz.
4. Grafik veritabanı oluşturma
Akıllı aracılarımızı oluşturmadan önce InstaVibe sosyal ağımızdaki zengin bağlantıları depolayabileceğimiz ve anlayabileceğimiz bir yöntem bulmamız gerekiyor. Bu noktada bir grafik veritabanı devreye girer. Verileri satır ve sütun tablolarında depolayan geleneksel ilişkisel veritabanlarının aksine, grafik veritabanı özellikle verileri düğümler (ör. kişiler, etkinlikler veya yayınlar) ve bunları birbirine bağlayan ilişkiler (kenarlar) (ör. arkadaşlıklar, etkinlik katılımı veya bahsetmeler) açısından temsil etmek ve sorgulamak için tasarlanmıştır. Bu yapı, gerçek dünyadaki sosyal ağların yapısını yansıttığı için sosyal medya uygulamaları açısından son derece güçlüdür. Böylece, farklı öğelerin nasıl birbirine bağlı olduğunu keşfetmek kolaylaşır.
Bu grafik veritabanını Google Cloud Spanner kullanarak uyguluyoruz. Spanner, öncelikle küresel olarak dağıtılmış, güçlü tutarlılığa sahip bir ilişkisel veritabanı olarak bilinse de grafik yapılarını doğrudan ilişkisel tablolarımızın üzerinde tanımlamamıza ve sorgulamamıza da olanak tanır.
Bu sayede, Spanner'ın ölçeklenebilirliği, işlemsel tutarlılığı ve tanıdık SQL arayüzünün yanı sıra yapay zeka destekli özelliklerimiz için çok önemli olan karmaşık sosyal dinamikleri analiz etmeye yönelik grafik sorgularının etkileyici gücünden yararlanabiliyoruz.
👉💻 Cloud Shell IDE terminalinde. Google Cloud'da gerekli altyapıyı sağlayın. Öncelikle, veritabanlarımız için özel bir kapsayıcı görevi gören bir Spanner örneği oluşturacağız. Örnek hazır olduğunda, içinde tüm tablolarımızı ve InstaVibe'ın grafik verilerini barındıracak olan gerçek Spanner veritabanını oluşturacağız:
. ~/instavibe-bootstrap/set_env.sh
gcloud spanner instances create $SPANNER_INSTANCE_ID \
--config=regional-us-central1 \
--description="GraphDB Instance InstaVibe" \
--processing-units=100 \
--edition=ENTERPRISE
gcloud spanner databases create $SPANNER_DATABASE_ID \
--instance=$SPANNER_INSTANCE_ID \
--database-dialect=GOOGLE_STANDARD_SQL
👉💻 Spanner'a varsayılan hizmet hesabına okuma/yazma erişimi verme
echo "Granting Spanner read/write access to ${SERVICE_ACCOUNT_NAME} for database ${SPANNER_DATABASE_ID}..."
gcloud spanner databases add-iam-policy-binding ${SPANNER_DATABASE_ID} \
--instance=${SPANNER_INSTANCE_ID} \
--member="serviceAccount:${SERVICE_ACCOUNT_NAME}" \
--role="roles/spanner.databaseUser" \
--project=${PROJECT_ID}
👉💻 Hemen. Python sanal ortamı oluşturacak, gerekli Python paketlerini yükleyecek, ardından Spanner'da grafik veritabanı şemasını oluşturup ilk verilerle yükleyecek ve setup.py
komut dosyasını çalıştıracağız.
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap
python -m venv env
source env/bin/activate
pip install -r requirements.txt
cd instavibe
python setup.py
👉 Yeni bir tarayıcı sekmesinde Google Cloud Console'a gidin ve Spanner'a gidin. Spanner örneklerinizin listesini görürsünüz. instavibe-graph-instance
simgesini tıklayın. 👉 Örnek genel bakış sayfasında, söz konusu örnekteki veritabanlarının listesini görürsünüz.
graphdb
simgesini tıklayın.
👉 Veritabanınızın sol gezinme bölmesinde Spanner Studio'yu tıklayın.
👉 Sorgu düzenleyicide (Untitled query sekmesi) aşağıdaki Graph SQL sorgusunu yapıştırın. Bu sorgu, tüm Kişi düğümlerini ve diğer Kişi düğümleriyle olan doğrudan Arkadaşlık ilişkilerini bulur. Sonucu görmek için ÇALIŞTIR'ı tıklayın.
Graph SocialGraph
MATCH result_paths = ((p:Person)-[f:Friendship]-(friend:Person))
RETURN SAFE_TO_JSON(result_paths) AS result_paths
👉 Aynı sorgu düzenleyicide, aynı etkinliğe katılan kullanıcıları bulmak için önceki DDL'yi değiştirin. Bu, paylaşılan bir etkinlik aracılığıyla dolaylı bir bağlantı olduğunu gösterir.
Graph SocialGraph
MATCH result_paths = (p1:Person)-[:Attended]->(e:Event)<-[:Attended]-(p2:Person)
WHERE p1.person_id < p2.person_id
RETURN SAFE_TO_JSON(result_paths) AS result_paths
👉 Bu sorgu, farklı bir bağlantı türünü inceler. Belirli bir kişinin arkadaşları tarafından yazılan gönderilerde bahsedilen kişiler, sorgu düzenleyicide aşağıdaki sorguyu çalıştırır.
Graph SocialGraph
MATCH result_paths = (user:Person {name: "Alice"})-[:Friendship]-(friend:Person)-[:Wrote]->(post:Post)-[:Mentioned]->(mentioned_person:Person)
WHERE user <> mentioned_person AND friend <> mentioned_person -- Avoid self-mentions or friend mentioning themselves in their own post if not intended
RETURN SAFE_TO_JSON(result_paths) AS result_paths
Bu sorgular, InstaVibe uygulamamız için Spanner'ı grafik veritabanı olarak kullanmanın gücüne dair sadece bir bakış sunmaktadır. Sosyal verilerimizi birbirine bağlı bir grafik olarak modelleyerek ilişkilerin ve etkinliklerin ayrıntılı analizini mümkün kılıyoruz. Bu analiz, yapay zeka aracılarımızın kullanıcı bağlamını anlaması, ilgi alanlarını keşfetmesi ve sonuç olarak akıllı sosyal planlama yardımı sunması için temel olacaktır.
Temel veri yapımız artık hazır ve test edildi. Şimdi de temsilcilerimizin etkileşimde bulunacağı mevcut InstaVibe uygulamasına odaklanalım.
5. InstaVibe'ın mevcut durumu
Yapay zeka temsilcilerimizin nerede yer alacağını anlamak için öncelikle mevcut InstaVibe web uygulamasını dağıtıp çalıştırmamız gerekir. Bu uygulama, kullanıcı arayüzünü ve daha önce oluşturduğumuz Spanner grafik veritabanına bağlanan temel işlevleri sağlar.
InstaVibe uygulaması, etkinlik ayrıntıları sayfalarında etkinlik konumlarını görsel olarak göstermek için Google Haritalar'ı kullanır. Bu işlevin etkinleştirilmesi için uygulamanın, daha önce oluşturduğumuz API anahtarına ihtiyacı vardır. Aşağıdaki komut dosyası, atadığımız görünen adı ("Haritalar Platformu API Anahtarı") kullanarak gerçek anahtar dizesini alır.
👉💻 Cloud Shell IDE'ye geri dönün. Aşağıdaki komut dosyasını çalıştırın. Ardından, gösterilen GOOGLE_MAPS_API_KEY'nin, daha önce Google Cloud Console'da oluşturup kopyaladığınız anahtarla eşleştiğinden emin olmak için çıkışı dikkatlice kontrol edin.
. ~/instavibe-bootstrap/set_env.sh
export KEY_DISPLAY_NAME="Maps Platform API Key"
GOOGLE_MAPS_KEY_ID=$(gcloud services api-keys list \
--project="${PROJECT_ID}" \
--filter="displayName='${KEY_DISPLAY_NAME}'" \
--format="value(uid)" \
--limit=1)
GOOGLE_MAPS_API_KEY=$(gcloud services api-keys get-key-string "${GOOGLE_MAPS_KEY_ID}" \
--project="${PROJECT_ID}" \
--format="value(keyString)")
echo "${GOOGLE_MAPS_API_KEY}" > ~/mapkey.txt
echo "Retrieved GOOGLE_MAPS_API_KEY: ${GOOGLE_MAPS_API_KEY}"
👉💻 Şimdi InstaVibe web uygulaması için container görüntüsünü oluşturup Artifact Registry depomuza aktaralım.
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/instavibe/
export IMAGE_TAG="latest"
export APP_FOLDER_NAME="instavibe"
export IMAGE_NAME="instavibe-webapp"
export IMAGE_PATH="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${IMAGE_NAME}:${IMAGE_TAG}"
export SERVICE_NAME="instavibe"
gcloud builds submit . \
--tag=${IMAGE_PATH} \
--project=${PROJECT_ID}
👉💻 Yeni derleme InstaVibe web uygulaması resmini Cloud Run'a dağıtın.
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/instavibe/
export IMAGE_TAG="latest"
export APP_FOLDER_NAME="instavibe"
export IMAGE_NAME="instavibe-webapp"
export IMAGE_PATH="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${IMAGE_NAME}:${IMAGE_TAG}"
export SERVICE_NAME="instavibe"
gcloud run deploy ${SERVICE_NAME} \
--image=${IMAGE_PATH} \
--platform=managed \
--region=${REGION} \
--allow-unauthenticated \
--set-env-vars="SPANNER_INSTANCE_ID=${SPANNER_INSTANCE_ID}" \
--set-env-vars="SPANNER_DATABASE_ID=${SPANNER_DATABASE_ID}" \
--set-env-vars="APP_HOST=0.0.0.0" \
--set-env-vars="APP_PORT=8080" \
--set-env-vars="GOOGLE_CLOUD_LOCATION=${REGION}" \
--set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
--set-env-vars="GOOGLE_MAPS_API_KEY=${GOOGLE_MAPS_API_KEY}" \
--project=${PROJECT_ID} \
--min-instances=1
Dağıtım başarıyla tamamlandıktan sonra Cloud Run günlüklerinde, çalışan InstaVibe uygulamanızın herkese açık URL'si gösterilir.
Bu URL'yi Google Cloud Console'da Cloud Run bölümüne gidip instavibe hizmetini seçerek de bulabilirsiniz.
Temel InstaVibe platformunu keşfetmek için bu URL'yi web tarayıcınızda açın. Oluşturduğumuz grafik veritabanı tarafından desteklenen gönderileri, etkinlikleri ve kullanıcı bağlantılarını görün.
Hedef uygulamamız çalıştığına göre, özelliklerini geliştirmek için ilk akıllı temsilciyi oluşturmaya başlayalım.
6. Basic Agent,Event Planner with ADK
ADK Çerçevesi
Google'ın ADK çerçevesine giriş Temelimiz (InstaVibe uygulaması ve veritabanı) hazır olduğuna göre Google'ın Agent Development Kit'ini (ADK) kullanarak ilk akıllı aracımızı oluşturmaya başlayabiliriz.
Agent Development Kit (ADK), yapay zeka aracı geliştirme ve dağıtma için özel olarak tasarlanmış esnek ve modüler bir çerçevedir. Tasarım ilkesi, geleneksel yazılım geliştirmeye daha çok benzeyen bir aracı geliştirme deneyimi sunmaktır. Bu sayede geliştiricilerin, basit ve tek amaçlı görevlerden karmaşık ve çok aracılı iş akışlarına kadar her şeyi yönetebilen aracı mimarileri oluşturması, dağıtması ve düzenlemesi önemli ölçüde kolaylaşır.
ADK, temel olarak Agent
kavramı etrafında döner. Bu kavram, talimatları, yapılandırmayı (ör. seçilen dil modeli, istemler, yanıtlar) ve değerlendirme ölçütlerini kapsar. Gemini) ve işlem yapmak ya da bilgi toplamak için kullanabileceği bir dizi Tools
.
İlk temsilcimiz "Etkinlik Planlayıcı" olacak. Temel amacı, sosyal etkinlikler için kullanıcı isteklerini (konum, tarihler ve ilgi alanlarını belirterek) almak ve yaratıcı, kişiye özel öneriler oluşturmaktır. Önerilerin alakalı ve güncel bilgilere (ör. o hafta sonu gerçekleşen belirli etkinlikler) dayalı olmasını sağlamak için ADK'nın yerleşik araçlarından biri olan Google Arama'yı kullanacağız. Bu sayede, kullanıcıların ölçütleriyle eşleşen mekanlar, etkinlikler ve aktivitelerle ilgili en son ayrıntıları alarak yanıtlarını gerçek zamanlı web sonuçlarına dayandırabilir.
👉📝 Cloud Shell IDE'ye geri dönün. ~/instavibe-bootstrap/agents/planner/agent.py
bölümünde, aracı oluşturmak için aşağıdaki istemi ve talimatı ekleyin.
from google.adk.agents import Agent
from google.adk.tools import google_search
root_agent = Agent(
name="planner_agent",
model="gemini-2.0-flash",
description="Agent tasked with generating creative and fun dating plan suggestions",
instruction="""
You are a specialized AI assistant tasked with generating creative and fun plan suggestions.
Request:
For the upcoming weekend, specifically from **[START_DATE_YYYY-MM-DD]** to **[END_DATE_YYYY-MM-DD]**, in the location specified as **[TARGET_LOCATION_NAME_OR_CITY_STATE]** (if latitude/longitude are provided, use these: Lat: **[TARGET_LATITUDE]**, Lon: **[TARGET_LONGITUDE]**), please generate a distinct dating plan suggestions.
Constraints and Guidelines for Suggestions:
1. Creativity & Fun: Plans should be engaging, memorable, and offer a good experience for a date.
2. Budget: All generated plans should aim for a moderate budget (conceptually "$$"), meaning they should be affordable yet offer good value, without being overly cheap or extravagant. This budget level should be *reflected in the choice of activities and venues*, but **do not** explicitly state "Budget: $$" in the `plan_description`.
3. Interest Alignment:
Consider the following user interests: **[COMMA_SEPARATED_LIST_OF_INTERESTS, e.g., outdoors, arts & culture, foodie, nightlife, unique local events, live music, active/sports]**. Tailor suggestions specifically to these where possible. The plan should *embody* these interests.
Fallback: If specific events or venues perfectly matching all listed user interests cannot be found for the specified weekend, you should create a creative and fun generic dating plan that is still appealing, suitable for the location, and adheres to the moderate budget. This plan should still sound exciting and fun, even if it's more general.
4. Current & Specific: Prioritize finding specific, current events, festivals, pop-ups, or unique local venues operating or happening during the specified weekend dates. If exact current events cannot be found, suggest appealing evergreen options or implement the fallback generic plan.
5. Location Details: For each place or event mentioned within a plan, you MUST provide its name, precise latitude, precise longitude, and a brief, helpful description.
6. Maximum Activities: The plan must contain a maximum of 3 distinct activities.
RETURN PLAN in MARKDOWN FORMAT
""",
tools=[google_search]
)
İlk aracımızı tanımladık. ADK'nın en iyi özelliklerinden biri, sezgisel yapısı ve sunduğu kullanışlı araçlardır. Özellikle yararlı olanlardan biri, aracınızı etkileşimli olarak test etmenize ve yanıtlarını anlık olarak görmenize olanak tanıyan ADK Dev UI'dir.
👉💻 Başlayalım. Aşağıdaki komutlar ADK DEV kullanıcı arayüzünü başlatır:
. ~/instavibe-bootstrap/set_env.sh
source ~/instavibe-bootstrap/env/bin/activate
cd ~/instavibe-bootstrap/agents
sed -i "s|^\(O\?GOOGLE_CLOUD_PROJECT\)=.*|GOOGLE_CLOUD_PROJECT=${PROJECT_ID}|" ~/instavibe-bootstrap/agents/planner/.env
adk web
Komutları çalıştırdıktan sonra terminalinizde ADK Web Sunucusu'nun başlatıldığını belirten bir çıkış görmelisiniz. Bu çıkış şuna benzer:
+-----------------------------------------------------------------------------+
| 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 Dev kullanıcı arayüzüne erişmek için:
Cloud Shell araç çubuğundaki (genellikle sağ üstte) Web önizleme simgesinden (genellikle bir göz veya ok içeren bir kare gibi görünür) 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 Dev kullanıcı arayüzünü gösteren yeni bir tarayıcı sekmesi veya penceresi açar.
ADK Dev UI tarayıcınızda açıldıktan sonra: Kullanıcı arayüzünün sağ üst kısmındaki açılır menüden etkileşim kurmak istediğiniz aracı olarak planner'ı seçin. Şimdi sağdaki sohbet iletişim kutusunda temsilcinize bir görev vermeyi deneyin. Örneğin, temsilciyle sohbet etme:
Search and plan something in Seattle for me this weekend
This weekend and I enjoy food and anime
Tarih öner (Tercihiniz)
July 12 2025
Temsilcinin isteğinizi işlediğini ve Google Arama sonuçlarına dayalı bir plan sunduğunu görürsünüz.
Bir temsilciyle etkileşim kurmak bir şeydir, ancak özellikle değişiklik yaparken temsilcinin her zaman beklendiği gibi davrandığını nasıl bilebiliriz?
Geleneksel yazılım testi yöntemleri, üretken ve deterministik olmayan doğaları nedeniyle yapay zeka aracıları için genellikle yetersiz kalır. Harika bir demodan güvenilir bir üretim aracına geçiş yapmak için sağlam bir değerlendirme stratejisi şarttır. Bir üretken modelin nihai çıktısını kontrol etmekten farklı olarak, bir aracıyı değerlendirmek genellikle karar verme sürecini ve çeşitli senaryolarda araçları doğru kullanma veya talimatları uygulama becerisini değerlendirmeyi içerir. ADK, bu konuda yardımcı olacak özellikler sunar.
👉 ADK Dev UI'de soldaki gezinme panelinde "Eval" (Değerlendirme) sekmesini tıklayın. plan_eval
adlı önceden yüklenmiş bir test dosyası görürsünüz. Bu dosya, planlayıcı aracımızı test etmek için önceden tanımlanmış girişler ve ölçütler içerir.
👉 "boston" gibi bir senaryo seçin ve Değerlendirmeyi Çalıştır düğmesini tıklayın. Açılan pop-up pencerede eşleşme puanını 0, 3'e düşürün ve Başlat'ı tıklayın.
Bu işlem, test girişiyle birlikte aracıyı çalıştırır ve çıktısının tanımlanan beklentileri karşılayıp karşılamadığını kontrol eder. Bu sayede, temsilcinizin performansını sistematik olarak test edebilirsiniz.
👉 Şimdi daha katı bir eşik kullanıldığında ne olacağına bakalım. "nyc" senaryosunu seçin ve Değerlendirmeyi Çalıştır'ı tekrar tıklayın. Bu kez eşleşme puanını varsayılan değerinde (Yanıta eşleşme puanı: 0, 7) bırakın ve Başlat'ı tıklayın. Sonucun "Başarısız" olduğunu görürsünüz. Bu durum, aracının yaratıcı çıktısı önceden tanımlanmış "altın" yanıtla tam olarak eşleşmediği için beklenir.
👉 Neden başarısız olduğunu anlamak için "nyc" satırındaki başarısız simgesini tıklayın. Kullanıcı arayüzünde artık aracının Gerçek yanıtı ile test senaryosunun Beklenen yanıtı yan yana karşılaştırılıyor. Bu görünüm, hata ayıklama için çok önemlidir. Temsilcinin çıktısının tam olarak nerede farklılaştığını görmenize ve talimatlarını buna göre iyileştirmenize olanak tanır.
Kullanıcı arayüzünü ve değerlendirmeyi incelemeyi tamamladığınızda Cloud Shell Editor terminalinize dönün ve ADK Dev UI'yi durdurmak için Ctrl+C
tuşuna basın.
Serbest biçimli metin çıkışı iyi bir başlangıç olsa da InstaVibe gibi uygulamaların bir aracının önerilerini kolayca kullanabilmesi için yapılandırılmış veriler (ör. JSON) çok daha pratiktir. Planını tutarlı bir JSON biçiminde döndürmek için aracımızı değiştirelim.
👉📝 ~/instavibe-bootstrap/agents/planner/agent.py
içinde, aracının talimat dizesinde şu anda RETURN PLAN in MARKDOWN FORMAT
yazan satırı bulun. Bu satırı aşağıdaki ayrıntılı JSON yapısıyla değiştirin:
Return your response *exclusively* as a single JSON object. This object should contain a top-level key, "fun_plans", which holds a plan objects. Each plan object in the list must strictly adhere to the following structure:
--json--
{
"plan_description": "A summary of the overall plan, consisting of **exactly three sentences**. Craft these sentences in a friendly, enthusiastic, and conversational tone, as if you're suggesting this awesome idea to a close friend. Make it sound exciting and personal, highlighting the positive aspects and appeal of the plan without explicitly mentioning budget or listing interest categories.",
"locations_and_activities": [
{
"name": "Name of the specific place or event",
"latitude": 0.000000, // Replace with actual latitude
"longitude": 0.000000, // Replace with actual longitude
"description": "A brief description of this place/event, why it's suitable for the date, and any specific details for the weekend (e.g., opening hours, event time)."
}
// Add more location/activity objects here if the plan involves multiple stops/parts
]
}
Aracının talimatlarını JSON çıkışı isteyecek şekilde güncellediğinize göre şimdi değişikliği doğrulayalım.
👉💻 ADK Geliştirici Kullanıcı Arayüzü'nü yeniden başlatmak için önceki komutu kullanın:
. ~/instavibe-bootstrap/set_env.sh
source ~/instavibe-bootstrap/env/bin/activate
cd ~/instavibe-bootstrap/agents
adk web
Sekme zaten açıksa yenileyin. Alternatif olarak, ADK Dev UI'yi tarayıcınızda açmak için (Cloud Shell'in 8000 bağlantı noktasındaki Web Önizlemesi aracılığıyla) daha önce yaptığınız gibi aynı adımları uygulayın. Kullanıcı arayüzü yüklendikten sonra planlayıcı aracısının seçildiğinden emin olun.
👉 Bu kez farklı bir istekte bulunalım. Sohbet iletişim kutusuna şunu girin:
Plan an event Boston this weekend with art and coffee
Aracının yanıtını dikkatlice inceleyin. Artık tamamen sohbet odaklı bir metin yanıtı yerine, talimatlarda tanımladığımız yapıya (fun_plans, plan_description, locations_and_activities vb. içeren) uygun şekilde kesinlikle JSON nesnesi olarak biçimlendirilmiş bir yanıt göreceksiniz. Bu, aracının artık InstaVibe uygulamamız tarafından programatik kullanıma uygun yapılandırılmış çıkış üretebileceğini onaylar.
JSON çıkışını onayladıktan sonra Cloud Shell terminalinize dönün ve ADK Dev UI'yi durdurmak için Ctrl+C
tuşuna basın.
ADK Bileşenleri
ADK Geliştirici Kullanıcı Arayüzü, etkileşimli test için harika olsa da genellikle aracıları programatik olarak çalıştırmamız gerekir. Bu, daha büyük bir uygulamanın veya arka uç hizmetinin parçası olarak yapılabilir. Bunun nasıl çalıştığını anlamak için çalışma zamanı ve bağlam yönetimiyle ilgili bazı temel ADK kavramlarına bakalım.
Anlamlı ve çok turlu sohbetler için aracıların bağlamı anlaması, yani sürekliliği korumak için söylenenleri ve yapılanları hatırlaması gerekir. ADK, Oturum, Durum ve Bellek aracılığıyla bu bağlamı yönetmek için yapılandırılmış yöntemler sunar:
- Oturum: Kullanıcı bir temsilciyle etkileşim kurmaya başladığında oturum oluşturulur. Bunu tek ve belirli bir sohbet dizisinin kapsayıcısı olarak düşünebilirsiniz. Benzersiz bir kimlik, etkileşim geçmişi (Etkinlikler), mevcut çalışma verileri (Durum) ve son güncelleme zamanı gibi meta veriler içerir.
- Durum: Bu, tek bir oturumdaki aracının kısa süreli çalışma belleğidir. Aracının, mevcut görevi tamamlamak için gereken geçici bilgileri (ör. şimdiye kadar toplanan kullanıcı tercihleri, araç çağrılarından elde edilen ara sonuçlar) depolayabileceği değiştirilebilir bir sözlüktür.
- Bellek: Bu, aracının farklı oturumlarda uzun süreli hatırlama veya harici bilgi tabanlarına erişme potansiyelini gösterir. Oturum ve Durum, anlık görüşmeyi yönetirken Bellek (genellikle MemoryService tarafından yönetilir), bir aracının geçmiş etkileşimlerden veya yapılandırılmış veri kaynaklarından bilgi almasına olanak tanıyarak daha geniş bir bilgi bağlamı sunar. (Not: Basit istemcimiz, basitlik için bellek içi hizmetleri kullanır. Bu nedenle, bellek/durum yalnızca komut dosyası çalışırken kalıcı olur.)
- Etkinlik: Bir oturumdaki her etkileşim (kullanıcı mesajı, aracı yanıtı, araç kullanım isteği, araç sonucu, durum değişikliği, hata) değiştirilemez bir etkinlik olarak kaydedilir. Bu işlem, kronolojik bir günlük oluşturur. Bu günlük, sohbetin transkripti ve işlem geçmişidir.
Peki, bir aracı çalıştırıldığında bunlar nasıl yönetilir? Bu, Runner'ın sorumluluğundadır.
- Runner: Runner, ADK tarafından sağlanan temel yürütme motorudur. Aracınızı ve kullandığı araçları siz tanımlarsınız. Runner ise kullanıcının isteğini yerine getirme sürecini düzenler. Oturumu yönetir, etkinlik akışını işler, durumu günceller, temel dil modelini çağırır, araç çağrılarını koordine eder ve MemoryService ile etkileşime girebilir. Bunu, tüm farklı parçaların doğru şekilde birlikte çalıştığından emin olan orkestra şefi olarak düşünebilirsiniz.
Aracı, geliştirme kullanıcı arayüzünden tamamen bağımsız olarak, aracımızı bağımsız bir Python uygulaması şeklinde çalıştırmak için kullanabiliriz.
Planlayıcı aracımızı programatik olarak çağırmak için basit bir istemci komut dosyası oluşturalım.
👉📝 ~/instavibe-bootstrap/agents/planner/planner_client.py
dosyasında, mevcut içe aktarma işlemlerinin altına aşağıdaki Python kodunu ekleyin. planner_client.py
içinde, içe aktarmaların altına aşağıdakileri ekleyin:
async def async_main():
session_service = InMemorySessionService()
session = await session_service.create_session(
state={}, app_name='planner_app', user_id='user_dc'
)
query = "Plan Something for me in San Francisco this weekend on wine and fashion "
print(f"User Query: '{query}'")
content = types.Content(role='user', parts=[types.Part(text=query)])
root_agent = agent.root_agent
runner = Runner(
app_name='planner_app',
agent=root_agent,
session_service=session_service,
)
print("Running agent...")
events_async = runner.run_async(
session_id=session.id, user_id=session.user_id, new_message=content
)
async for event in events_async:
print(f"Event received: {event}")
if __name__ == '__main__':
try:
asyncio.run(async_main())
except Exception as e:
print(f"An error occurred: {e}")
Bu kod, oturum ve yapay nesne yönetimi için bellek içi hizmetler oluşturur (bu örnekte basit tutulur), bir oturum oluşturur, kullanıcı sorgusunu tanımlar, Runner'ı aracımızla yapılandırır ve ardından aracıyı eşzamansız olarak çalıştırarak yürütme sırasında oluşturulan her etkinliği yazdırır.
👉💻 Şimdi bu istemci komut dosyasını terminalinizden çalıştırın:
. ~/instavibe-bootstrap/set_env.sh
source ~/instavibe-bootstrap/env/bin/activate
cd ~/instavibe-bootstrap/agents
python -m planner.planner_client
👀 Çıkışı inceleyin. Yalnızca son JSON planı yerine, aracının yürütme akışı sırasında oluşturulan her Event nesnesinin ayrıntılı yapısını görürsünüz. Bu kapsamda, ilk kullanıcı mesajı etkinliği, araç çağrılarıyla (ör. Google Arama) ilgili olası etkinlikler ve son olarak JSON planını içeren modelin yanıt etkinliği yer alır. Bu ayrıntılı etkinlik akışı, hata ayıklama ve ADK çalışma zamanında gerçekleşen adım adım işlemeyi anlamak için çok yararlıdır.
Running agent...
Event received: content=Content(parts=[Part(video_metadata=None, thought=None, code_execution_result=None, executable_code=None, file_data=None, function_call=None, function_response=None, inline_data=None, text='```json\n{\n "fun_plans": [\n {\n "plan_description": "Embark on a stylish adventure through Hayes Valley,
...(turncated)
, offering a variety of fashion styles to browse and enjoy."\n }\n ]\n }\n ]\n}\n```')], role='model') grounding_metadata=GroundingMetadata(grounding_chunks=[GroundingChunk(retrieved_context=None, web=GroundingChunkWeb(domain='islands.com', title='islands.com', uri='http
...(turncated)
QyTpPV7jS6wUt-Ix7GuP2mC9J4eY_8Km6Vv44liF9cb2VSs='))], grounding_supports=[GroundingSupport(confide
...(turncated)
>\n', sdk_blob=None), web_search_queries=['..e']) partial=None turn_complete=None error_code=None error_message=None interrupted=None custom_metadata=None invocation_id='e-04d97b8b-9021-47a5-ab41-17b5cbb4bf03' author='location_search_agent' actions=EventActions(skip_summarization=None, state_delta={}, artifact_delta={}, transfer_to_agent=None, escalate=None, requested_auth_configs={}) long_running_tool_ids=None branch=None id='CInHdkKw' timestamp=1746978846.232674
Komut dosyası sürekli çalışıyorsa veya askıda kalıyorsa Ctrl+C
tuşuna basarak komut dosyasını manuel olarak durdurmanız gerekebilir.
7. Platform Interaction Agent - MCP sunucusuyla etkileşim kurar
ADK, aracıların yapısını oluşturmaya yardımcı olsa da gerçek dünyadaki işlemleri gerçekleştirmek için genellikle harici sistemlerle veya API'lerle etkileşim kurmaları gerekir.
Model Context Protocol (MCP)
Model Bağlam Protokolü (MCP), aracı gibi yapay zeka uygulamalarının harici veri kaynakları, araçlar ve sistemlerle nasıl bağlantı kurduğunu standartlaştırmak için tasarlanmış açık bir standarttır. Evrensel bir arayüz sağlayarak her yapay zeka uygulaması ve veri kaynağı kombinasyonu için özel entegrasyonlara ihtiyaç duyma sorununu çözmeyi amaçlar. MCP, AI uygulamalarında (ana makineler) bulunan MCP istemcilerinin MCP sunucularına bağlantıları yönettiği bir istemci-sunucu mimarisini kullanır. Bu sunucular, yerel verilere erişme, API'ler aracılığıyla uzak hizmetlerle etkileşim kurma veya önceden tanımlanmış istemler sağlama gibi belirli işlevleri kullanıma sunan harici programlardır. Bu sayede yapay zeka modelleri güncel bilgilere erişebilir ve ilk eğitimlerinin ötesinde görevler gerçekleştirebilir. Bu yapı, yapay zeka modellerinin harici özellikleri standartlaştırılmış bir şekilde keşfetmesini ve bunlarla etkileşim kurmasını sağlayarak entegrasyonları daha basit ve ölçeklenebilir hale getirir.
InstaVibe MCP sunucusunu oluşturma ve dağıtma
Temsilcilerimizin sonunda InstaVibe platformuyla etkileşime geçmesi gerekecek.Özellikle, platformun mevcut API'lerini kullanarak gönderi oluşturmak ve etkinlik kaydetmek için. InstaVibe uygulaması, bu işlevleri standart HTTP uç noktaları üzerinden kullanıma sunar:
Enpoint | URL | HTTP yöntemi | Açıklama |
Gönderi oluştur | api/posts | POST | Yeni bir gönderi eklemek için kullanılan API uç noktası. JSON gövdesi bekleniyor: |
Etkinlik Oluştur | api/events | POST | Yeni bir etkinlik ve katılımcılarını eklemek için kullanılan API uç noktası (basitleştirilmiş şema). |
Bu özellikleri MCP aracılığıyla temsilcilerimizin kullanımına sunmak için öncelikle bu API çağrıları etrafında sarmalayıcı görevi gören basit Python işlevleri oluşturmamız gerekir. Bu işlevler, HTTP isteği mantığını işler.
👉 Öncelikle, gönderi oluşturmak için sarmalayıcı işlevi uygulayalım. ~/instavibe-bootstrap/tools/instavibe/instavibe.py
dosyasını açın ve #REPLACE ME CREATE POST
yorumunu aşağıdaki Python koduyla değiştirin:
def create_post(author_name: str, text: str, sentiment: str, base_url: str = BASE_URL):
"""
Sends a POST request to the /posts endpoint to create a new post.
Args:
author_name (str): The name of the post's author.
text (str): The content of the post.
sentiment (str): The sentiment associated with the post (e.g., 'positive', 'negative', 'neutral').
base_url (str, optional): The base URL of the API. Defaults to BASE_URL.
Returns:
dict: The JSON response from the API if the request is successful.
Returns None if an error occurs.
Raises:
requests.exceptions.RequestException: If there's an issue with the network request (e.g., connection error, timeout).
"""
url = f"{base_url}/posts"
headers = {"Content-Type": "application/json"}
payload = {
"author_name": author_name,
"text": text,
"sentiment": sentiment
}
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
print(f"Successfully created post. Status Code: {response.status_code}")
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error creating post: {e}")
# Optionally re-raise the exception if the caller needs to handle it
# raise e
return None
except json.JSONDecodeError:
print(f"Error decoding JSON response from {url}. Response text: {response.text}")
return None
👉📝 Ardından, etkinlik oluşturma API'si için sarmalayıcı işlevi oluşturacağız. Aynı ~/instavibe-bootstrap/tools/instavibe/instavibe.py
dosyasında, #REPLACE ME CREATE EVENTS
yorumunu aşağıdaki kodla değiştirin:
def create_event(event_name: str, description: str, event_date: str, locations: list, attendee_names: list[str], base_url: str = BASE_URL):
"""
Sends a POST request to the /events endpoint to create a new event registration.
Args:
event_name (str): The name of the event.
description (str): The detailed description of the event.
event_date (str): The date and time of the event (ISO 8601 format recommended, e.g., "2025-06-10T09:00:00Z").
locations (list): A list of location dictionaries. Each dictionary should contain:
'name' (str), 'description' (str, optional),
'latitude' (float), 'longitude' (float),
'address' (str, optional).
attendee_names (list[str]): A list of names of the people attending the event.
base_url (str, optional): The base URL of the API. Defaults to BASE_URL.
Returns:
dict: The JSON response from the API if the request is successful.
Returns None if an error occurs.
Raises:
requests.exceptions.RequestException: If there's an issue with the network request (e.g., connection error, timeout).
"""
url = f"{base_url}/events"
headers = {"Content-Type": "application/json"}
payload = {
"event_name": event_name,
"description": description,
"event_date": event_date,
"locations": locations,
"attendee_names": attendee_names,
}
try:
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
print(f"Successfully created event registration. Status Code: {response.status_code}")
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error creating event registration: {e}")
# Optionally re-raise the exception if the caller needs to handle it
# raise e
return None
except json.JSONDecodeError:
print(f"Error decoding JSON response from {url}. Response text: {response.text}")
return None
Gördüğünüz gibi bu işlevler, mevcut InstaVibe API'lerinin basit sarmalayıcılarıdır. Bu kalıp, hizmetleriniz için API'leriniz varsa kullanışlıdır. Bu tür sarmalayıcılar oluşturarak işlevlerini kolayca aracıların araçları olarak kullanıma sunabilirsiniz.
MCP Sunucusu Uygulaması
İşlemleri gerçekleştiren (InstaVibe API'lerini çağıran) Python işlevlerimiz olduğuna göre artık MCP Sunucusu bileşenini oluşturmamız gerekiyor. Bu sunucu, bu işlevleri MCP standardına göre "araçlar" olarak kullanıma sunar. Böylece MCP istemcileri (ör. temsilcilerimiz) bunları keşfedip çağırabilir.
Bir MCP sunucusu genellikle iki temel işlevi uygular:
- list_tools: İstemcinin sunucudaki mevcut araçları keşfetmesine olanak tanımaktan, adları, açıklamaları ve gerekli parametreleri gibi meta verileri sağlamaktan sorumludur. Bu meta veriler genellikle JSON şeması kullanılarak tanımlanır.
- call_tool: İstemci tarafından istenen belirli bir aracın yürütülmesini işler, aracın adını ve bağımsız değişkenlerini alır ve karşılık gelen işlemi (ör. bizim durumumuzda bir API ile etkileşim kurma) gerçekleştirir.
MCP sunucuları, yapay zeka modellerine gerçek dünya verilerine ve işlemlerine erişim sağlamak için kullanılır. Bu sayede e-posta gönderme, proje yönetimi sistemlerinde görev oluşturma, veritabanlarında arama yapma veya çeşitli yazılımlar ve web hizmetleriyle etkileşim kurma gibi görevler gerçekleştirilebilir. İlk uygulamalar genellikle basitlik için, özellikle geliştirme veya "stüdyo" ortamlarında standart giriş/çıkış (stdio) üzerinden iletişim kuran yerel sunuculara odaklanmış olsa da, HTTP gibi protokolleri kullanan uzak sunuculara geçiş, daha geniş bir benimseme ve kurumsal kullanım alanları için daha mantıklıdır.
Uzak mimari, eklenen ağ iletişimi katmanına rağmen önemli avantajlar sunar: Birden fazla yapay zeka istemcisinin tek bir sunucuya erişimi paylaşmasına olanak tanır, araçların yönetimini ve güncellemelerini merkezileştirir, hassas verileri ve API anahtarlarını olası birçok istemci makinesine dağıtmak yerine sunucu tarafında tutarak güvenliği artırır ve yapay zeka modelini harici sistem entegrasyonunun özelliklerinden ayırarak tüm ekosistemi daha ölçeklenebilir, güvenli ve sürdürülebilir hale getirir. Bu sayede, her yapay zeka örneğinin kendi doğrudan entegrasyonlarını yönetmesi gerekmez.
İletişim için HTTP ve sunucu tarafından gönderilen etkinlikleri (SSE) kullanarak MCP sunucumuzu uygulayacağız. Bu yöntem, uzun sürebilecek araç yürütmeleri ve kurumsal senaryolar için uygundur.
👉📝 Öncelikle list_tools uç noktasını uygulayalım. ~/instavibe-bootstrap/tools/instavibe/mcp_server.py
dosyasını açın ve #REPLACE ME - LIST TOOLS
yorumunu aşağıdaki kodla değiştirin. :
@app.list_tools()
async def list_tools() -> list[mcp_types.Tool]:
"""MCP handler to list available tools."""
# Convert the ADK tool's definition to MCP format
mcp_tool_schema_event = adk_to_mcp_tool_type(event_tool)
mcp_tool_schema_post = adk_to_mcp_tool_type(post_tool)
print(f"MCP Server: Received list_tools request. \n MCP Server: Advertising tool: {mcp_tool_schema_event.name} and {mcp_tool_schema_post}")
return [mcp_tool_schema_event,mcp_tool_schema_post]
Bu işlev, araçları (create_event, create_post) tanımlar ve bağlanan istemcilere bu araçlar hakkında bilgi verir.
👉📝 Ardından, istemcilerden gelen gerçek yürütme isteklerini işleyen call_tool
uç noktasını uygulayın. Aynı ~/instavibe-bootstrap/tools/instavibe/mcp_server.py
dosyasında, #REPLACE ME - CALL TOOLS
yorumunu bu kodla değiştirin.
@app.call_tool()
async def call_tool(
name: str, arguments: dict
) -> list[mcp_types.TextContent | mcp_types.ImageContent | mcp_types.EmbeddedResource]:
"""MCP handler to execute a tool call."""
print(f"MCP Server: Received call_tool request for '{name}' with args: {arguments}")
# Look up the tool by name in our dictionary
tool_to_call = available_tools.get(name)
if tool_to_call:
try:
adk_response = await tool_to_call.run_async(
args=arguments,
tool_context=None, # No ADK context available here
)
print(f"MCP Server: ADK tool '{name}' executed successfully.")
response_text = json.dumps(adk_response, indent=2)
return [mcp_types.TextContent(type="text", text=response_text)]
except Exception as e:
print(f"MCP Server: Error executing ADK tool '{name}': {e}")
# Creating a proper MCP error response might be more robust
error_text = json.dumps({"error": f"Failed to execute tool '{name}': {str(e)}"})
return [mcp_types.TextContent(type="text", text=error_text)]
else:
# Handle calls to unknown tools
print(f"MCP Server: Tool '{name}' not found.")
error_text = json.dumps({"error": f"Tool '{name}' not implemented."})
return [mcp_types.TextContent(type="text", text=error_text)]
Bu işlev, araç adını ve bağımsız değişkenleri alır, daha önce tanımladığımız ilgili Python sarmalayıcı işlevini bulur, yürütür ve sonucu döndürür.
👉💻 MCP sunucu mantığı tanımlandığına göre artık bunu bir kapsayıcı olarak paketlememiz gerekiyor. Terminalde, Cloud Build'i kullanarak Docker görüntüsünü oluşturmak için aşağıdaki komut dosyasını çalıştırın:
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/tools/instavibe
export IMAGE_TAG="latest"
export MCP_IMAGE_NAME="mcp-tool-server"
export IMAGE_PATH="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${MCP_IMAGE_NAME}:${IMAGE_TAG}"
export SERVICE_NAME="mcp-tool-server"
export INSTAVIBE_BASE_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep instavibe)/api
gcloud builds submit . \
--tag=${IMAGE_PATH} \
--project=${PROJECT_ID}
👉💻 Ardından, görüntüyü Google Cloud Run'da hizmet olarak dağıtın.
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/tools/instavibe
export IMAGE_TAG="latest"
export MCP_IMAGE_NAME="mcp-tool-server"
export IMAGE_PATH="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${MCP_IMAGE_NAME}:${IMAGE_TAG}"
export SERVICE_NAME="mcp-tool-server"
export INSTAVIBE_BASE_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep instavibe)/api
gcloud run deploy ${SERVICE_NAME} \
--image=${IMAGE_PATH} \
--platform=managed \
--region=${REGION} \
--allow-unauthenticated \
--set-env-vars="INSTAVIBE_BASE_URL=${INSTAVIBE_BASE_URL}" \
--set-env-vars="APP_HOST=0.0.0.0" \
--set-env-vars="APP_PORT=8080" \
--set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=TRUE" \
--set-env-vars="GOOGLE_CLOUD_LOCATION=${REGION}" \
--set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
--project=${PROJECT_ID} \
--min-instances=1
👉💻 Dağıtım başarıyla tamamlandıktan sonra MCP sunucusu çalışır ve herkese açık bir URL üzerinden erişilebilir. Temsilcimizin (MCP istemcisi olarak hareket eder) nereye bağlanacağını bilmesi için bu URL'yi yakalamamız gerekir.
export MCP_SERVER_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep mcp-tool-server)/sse
Ayrıca, mcp-tool-server hizmetinin Google Cloud Console'unuzun Cloud Run bölümünde "Çalışıyor" olarak listelendiğini de görebilirsiniz.
MCP sunucusu dağıtılıp URL'si yakalandıktan sonra artık MCP istemcisi olarak hareket edecek ve bu sunucu tarafından kullanıma sunulan araçları kullanacak aracıyı uygulayabiliriz.
8. Platform Etkileşimi Aracısı (MCP kullanılarak)
MCP İstemcisi: MCP istemcisi, bir yapay zeka uygulaması veya aracısında bulunan, yapay zeka modeli ile bir veya daha fazla MCP sunucusu arasında arayüz görevi gören bir bileşendir. Uygulamamızda bu istemci doğrudan aracımıza entegre edilecektir. Bu istemcinin temel işlevi, list_tools
işlevi aracılığıyla kullanılabilir araçları keşfetmek ve ardından call_tool
işlevini kullanarak belirli araçların yürütülmesini istemektir. Bu sırada, yapay zeka modeli veya aramayı düzenleyen aracı tarafından sağlanan gerekli bağımsız değişkenler iletilir.
Şimdi MCP istemcisi gibi davranan temsilciyi oluşturacağız. ADK çerçevesinde çalışan bu aracı, yeni dağıttığımız mcp-tool-server
ile iletişim kurmaktan sorumlu olacaktır.
👉 Öncelikle, çalışan MCP sunucumuzdaki araçları dinamik olarak getirmek için aracı tanımını değiştirmemiz gerekir. agents/platform_mcp_client/agent.py
içinde #REPLACE ME - FETCH TOOLS
yerine aşağıdakileri girin:
"""Gets tools from the File System MCP Server."""
tools = MCPToolset(
connection_params=SseServerParams(url=MCP_SERVER_URL, headers={})
)
Bu kod, MCP_SERVER_URL'ye (daha önce ortam değişkeni olarak ayarladığımız) bağlanmak ve kullanılabilir araçların listesini almak için MCPToolset.from_server yöntemini kullanır.
Ardından, ADK aracı tanımına bu dinamik olarak getirilen araçları gerçekten kullanmasını söylememiz gerekir.
👉 agents/platform_mcp_client/agent.py
içinde #REPLACE ME - SET TOOLs
ifadesini aşağıdakilerle değiştirin:
tools=[tools],
👉💻 Şimdi, bu aracının MCP sunucusuna doğru şekilde bağlanıp bağlanamadığını ve çalışan InstaVibe uygulamamızla etkileşim kurmak için araçları kullanıp kullanamadığını görmek üzere ADK Geliştirici Kullanıcı Arayüzü'nü kullanarak yerel olarak test edelim.
. ~/instavibe-bootstrap/set_env.sh
source ~/instavibe-bootstrap/env/bin/activate
export MCP_SERVER_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep mcp-tool-server)/sse
cd ~/instavibe-bootstrap/agents
sed -i "s|^\(O\?GOOGLE_CLOUD_PROJECT\)=.*|GOOGLE_CLOUD_PROJECT=${PROJECT_ID}|" ~/instavibe-bootstrap/agents/platform_mcp_client/.env
sed -i "s|^\(O\?MCP_SERVER_URL\)=.*|MCP_SERVER_URL=${MCP_SERVER_URL}|" ~/instavibe-bootstrap/agents/platform_mcp_client/.env
adk web
Tarayıcınızda ADK Dev UI'yi tekrar açın (Cloud Shell'in 8000 bağlantı noktasındaki web önizlemesini kullanarak). Bu kez sağ üstteki açılır listeden platform_mcp_client
aracısını seçin.
create_post aracını test edelim. Sohbet iletişim kutusuna aşağıdaki isteği girin:
Create a post saying "Y'all I just got the cutest lil void baby 😭✨ Naming him Abyss bc he's deep, mysterious, and lowkey chaotic 🔥🖤 #VoidCat #NewRoomie" I'm Julia
Temsilci bunu işlemeli, create_post aracının kullanılması gerektiğini belirlemeli, MCP sunucusuyla iletişim kurmalı ve bu sunucu da InstaVibe API'yi çağırmalıdır.
👉 Doğrulama adımı: Temsilci işlemi onayladıktan sonra InstaVibe uygulamanızın çalıştığı sekmeyi açın (veya sekmeyi yenileyin). "Julia" adlı kullanıcının yeni gönderisini ana özet akışında görürsünüz.
👉💻 Gerekirse Instavibe bağlantısını almak için bu komut dosyasını ayrı bir terminalde çalıştırın:
gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep instavibe
👉📝 Şimdi create_event aracını test edelim. Sohbet iletişim kutusuna aşağıdaki çok satırlı isteği girin:
Hey, can you set up an event for Hannah and George and me, and I'm Julia? Let's call it 'Mexico City Culinary & Art Day'.
here are more info
{"event_name": "Mexico City Culinary & Art Day",
"description": "A vibrant day in Mexico City for Hannah and George, starting with lunch at one of the city's best taco spots in the hip Condesa neighborhood, followed by an inspiring afternoon exploring the Museo Soumaya's stunning art collection.",
"event_date": "2025-10-17T12:00:00-06:00",
"locations": [
{
"name": "El Tizoncito",
"description": "Considered one of the original creators of tacos al pastor, El Tizoncito offers a legendary taco experience in the heart of Condesa. Their flavorful meats, house salsas, and casual vibe make it a must-visit for foodies.",
"latitude": 19.412179,
"longitude": -99.171308,
"address": "Av. Tamaulipas 122, Hipódromo, Cuauhtémoc, 06100 Ciudad de México, CDMX, Mexico"
},
{
"name": "Museo Soumaya",
"description": "An architectural icon in Mexico City, Museo Soumaya houses over 66,000 works of art, including pieces by Rodin, Dalí, and Rivera. The striking silver structure is a cultural landmark and a visual feast inside and out.",
"latitude": 19.440056,
"longitude": -99.204281,
"address": "Plaza Carso, Blvd. Miguel de Cervantes Saavedra 303, Granada, Miguel Hidalgo, 11529 Ciudad de México, CDMX, Mexico"
}
],
"attendee_names": ["Hannah", "George", Julia],
}
Yine, temsilci MCP sunucusu üzerinden uygun aracı kullanmalıdır. Etkinlikler sekmesinde, tek tek etkinlikleri tıklayarak yürütmenin ayrıntılı ve adım adım izini görebilirsiniz.
👉 Doğrulama Adımı: Çalışan InstaVibe uygulamanıza geri dönün ve "Etkinlikler" bölümüne (veya eşdeğer bir bölüme) gidin. Yeni oluşturulan "Mexico City Culinary & Art Day" etkinliğini artık listede görebilirsiniz.
Bu, MCP'nin temsilcimizin harici araçlardan (bu örnekte InstaVibe'ın API'leri) standart bir şekilde yararlanmasına nasıl olanak tanıdığını başarıyla gösteriyor.
Her iki işlemi de doğruladıktan sonra Cloud Shell terminalinize dönün ve ADK Dev UI'yı durdurmak için Ctrl+C
tuşuna basın.
9. ADK'daki İş Akışı Aracısı ve Çoklu Aracı
Şu ana kadar olan deneyimlerimize göre, temsilcilerimiz gezileri planlayabiliyor ve platformla etkileşim kurabiliyor. Ancak gerçekten kişiselleştirilmiş planlama için kullanıcının sosyal çevresinin anlaşılması gerekir. Arkadaşlarının etkinliklerini yakından takip etmeyen yoğun kullanıcılar için bu bağlamı manuel olarak toplamak zordur. Bu sorunu çözmek için arkadaş etkinliklerini ve ilgi alanlarını analiz ederek daha kişiye özel öneriler sunmamızı sağlayacak, Spanner Graph Veritabanımızdan yararlanan bir Sosyal Profil Oluşturma aracısı oluşturacağız.
Öncelikle bu aracının grafik verilerine erişebilmesi için araçlara ihtiyacımız var.
👉📝 Aşağıdaki Python işlevlerini ~/instavibe-bootstrap/agents/social/instavibe.py
dosyasının sonuna ekleyin:
def get_person_attended_events(person_id: str)-> list[dict]:
"""
Fetches events attended by a specific person using Graph Query.
Args:
person_id (str): The ID of the person whose posts to fetch.
Returns: list[dict] or None.
"""
if not db_instance: return None
graph_sql = """
Graph SocialGraph
MATCH (p:Person)-[att:Attended]->(e:Event)
WHERE p.person_id = @person_id
RETURN e.event_id, e.name, e.event_date, att.attendance_time
ORDER BY e.event_date DESC
"""
params = {"person_id": person_id}
param_types_map = {"person_id": param_types.STRING}
fields = ["event_id", "name", "event_date", "attendance_time"]
results = run_graph_query( graph_sql, params=params, param_types=param_types_map, expected_fields=fields)
if results is None: return None
for event in results:
if isinstance(event.get('event_date'), datetime):
event['event_date'] = event['event_date'].isoformat()
if isinstance(event.get('attendance_time'), datetime):
event['attendance_time'] = event['attendance_time'].isoformat()
return results
def get_person_id_by_name( name: str) -> str:
"""
Fetches the person_id for a given name using SQL.
Args:
name (str): The name of the person to search for.
Returns:
str or None: The person_id if found, otherwise None.
Returns the ID of the *first* match if names are duplicated.
"""
if not db_instance: return None
sql = """
SELECT person_id
FROM Person
WHERE name = @name
LIMIT 1 -- Return only the first match in case of duplicate names
"""
params = {"name": name}
param_types_map = {"name": param_types.STRING}
fields = ["person_id"]
# Use the standard SQL query helper
results = run_sql_query( sql, params=params, param_types=param_types_map, expected_fields=fields)
if results: # Check if the list is not empty
return results[0].get('person_id') # Return the ID from the first dictionary
else:
return None # Name not found
def get_person_posts( person_id: str)-> list[dict]:
"""
Fetches posts written by a specific person using Graph Query.
Args:
person_id (str): The ID of the person whose posts to fetch.
Returns:
list[dict] or None: List of post dictionaries with ISO date strings,
or None if an error occurs.
"""
if not db_instance: return None
# Graph Query: Find the specific Person node, follow 'Wrote' edge to Post nodes
graph_sql = """
Graph SocialGraph
MATCH (author:Person)-[w:Wrote]->(post:Post)
WHERE author.person_id = @person_id
RETURN post.post_id, post.author_id, post.text, post.sentiment, post.post_timestamp, author.name AS author_name
ORDER BY post.post_timestamp DESC
"""
# Parameters now include person_id and limit
params = {
"person_id": person_id
}
param_types_map = {
"person_id": param_types.STRING
}
# Fields returned remain the same
fields = ["post_id", "author_id", "text", "sentiment", "post_timestamp", "author_name"]
results = run_graph_query(graph_sql, params=params, param_types=param_types_map, expected_fields=fields)
if results is None:
return None
# Convert datetime objects to ISO format strings
for post in results:
if isinstance(post.get('post_timestamp'), datetime):
post['post_timestamp'] = post['post_timestamp'].isoformat()
return results
def get_person_friends( person_id: str)-> list[dict]:
"""
Fetches friends for a specific person using Graph Query.
Args:
person_id (str): The ID of the person whose posts to fetch.
Returns: list[dict] or None.
"""
if not db_instance: return None
graph_sql = """
Graph SocialGraph
MATCH (p:Person {person_id: @person_id})-[f:Friendship]-(friend:Person)
RETURN DISTINCT friend.person_id, friend.name
ORDER BY friend.name
"""
params = {"person_id": person_id}
param_types_map = {"person_id": param_types.STRING}
fields = ["person_id", "name"]
results = run_graph_query( graph_sql, params=params, param_types=param_types_map, expected_fields=fields)
return results
Şimdi de temsilcimizi nasıl yapılandıracağımızı ele alalım. Birden fazla arkadaşınızın profilini analiz edip bulguları özetlemek için birkaç adım uygulamanız gerekir. Bu, ADK'nın çoklu aracı özelliklerini, özellikle de iş akışı aracılarını kullanmak için mükemmel bir senaryodur.
Google'ın ADK'sında bir İş Akışı Aracısı, görevleri kendisi yapmaz ancak alt aracılar adı verilen diğer aracıları yönetir. Bu sayede, karmaşık sorunları uzmanlaşmış bileşenlere ayırarak modüler bir tasarım oluşturabilirsiniz. ADK, aşağıdakiler gibi yerleşik iş akışı türleri sağlar:
- Sıralı (adım adım)
- Paralel (eşzamanlı yürütme)
- ve Loop (tekrarlanan yürütme)
Sosyal profilleme görevimizde, tasarımımız yinelemeli bir iş akışı oluşturmak için Döngü Aracısı'nı kullanır. Amaç, her seferinde bir kişiyi işlemektir: profile_agent
verileri toplar, summary_agent
analizi günceller ve check_agent
tekrar döngüye girmemiz gerekip gerekmediğini belirler.
Bu iş akışı için gereken alt aracıları tanımlayalım.
👉📝 ~/instavibe-bootstrap/agents/social/agent.py
içinde #REPLACE FOR profile_agent
yerine aşağıdakileri girin:
profile_agent = LlmAgent(
name="profile_agent",
model="gemini-2.5-flash",
description=(
"Agent to answer questions about the this person social profile. Provide the person's profile using their name, make sure to fetch the id before getting other data."
),
instruction=(
"You are a helpful agent to answer questions about the this person social profile. You'll be given a list of names, provide the person's profile using their name, make sure to fetch the id before getting other data. Get one person at a time, start with the first one on the list, and skip if already provided. return this person's result"
),
tools=[get_person_posts,get_person_friends,get_person_id_by_name,get_person_attended_events],
)
Ardından, toplanan profil bilgilerini (döngü yinelemeleri boyunca biriktirilen) alan ve birden fazla kişi analiz edildiyse ortak noktaları belirleyerek nihai özeti oluşturan aracı.
👉📝 Aynı ~/instavibe-bootstrap/agents/social/agent.py
içinde #REPLACE FOR summary_agent
yerine aşağıdakileri girin:
summary_agent = LlmAgent(
name="summary_agent",
model="gemini-2.5-flash",
description=(
"Generate a comprehensive social summary as a single, cohesive paragraph. This summary should cover the activities, posts, friend networks, and event participation of one or more individuals. If multiple profiles are analyzed, the paragraph must also identify and integrate any common ground found between them."
),
instruction=(
"""
Your primary task is to synthesize social profile information into a single, comprehensive paragraph.
**Input Scope & Default Behavior:**
* If specific individuals are named by the user, focus your analysis on them.
* **If no individuals are specified, or if the request is general, assume the user wants an analysis of *all relevant profiles available in the current dataset/context*.**
**For each profile (whether specified or determined by default), you must analyze:**
1. **Post Analysis:**
* Systematically review their posts (e.g., content, topics, frequency, engagement).
* Identify recurring themes, primary interests, and expressed sentiments.
2. **Friendship Relationship Analysis:**
* Examine their connections/friends list.
* Identify key relationships, mutual friends (especially if comparing multiple profiles), and the general structure of their social network.
3. **Event Participation Analysis:**
* Investigate their past (and if available, upcoming) event participation.
* Note the types of events, frequency of attendance, and any notable roles (e.g., organizer, speaker).
**Output Generation (Single Paragraph):**
* **Your entire output must be a single, cohesive summary paragraph.**
* **If analyzing a single profile:** This paragraph will detail their activities, interests, and social connections based on the post, friend, and event analysis.
* **If analyzing multiple profiles:** This paragraph will synthesize the key findings regarding posts, friends, and events for each individual. Crucially, it must then seamlessly integrate or conclude with an identification and description of the common ground found between them (e.g., shared interests from posts, overlapping event attendance, mutual friends). The aim is a unified narrative within this single paragraph.
**Key Considerations:**
* Base your summary strictly on the available data.
* If data for a specific category (posts, friends, events) is missing or sparse for a profile, you may briefly acknowledge this within the narrative if relevant.
"""
),
output_key="summary"
)
Döngünün ne zaman durdurulması gerektiğini (ör.istenen tüm profiller özetlendiğinde) belirlememiz gerekiyor.
👉📝 Aynı ~/instavibe-bootstrap/agents/social/agent.py
içinde #REPLACE FOR check_agent
yerine aşağıdakileri girin:
check_agent = LlmAgent(
name="check_agent",
model="gemini-2.5-flash",
description=(
"Check if everyone's social profile are summarized and has been generated. Output 'completed' or 'pending'."
),
output_key="summary_status"
)
summary_status
değerini State içinde açıkça arayan, check_agent
tarafından döndürülen ve Loop Agent'a devam edip etmeyeceğini (escalate=False) veya durdurup durdurmayacağını (escalate=True) söyleyen basit bir programatik kontrol (CheckCondition) ekliyoruz.
👉📝 Aynı ~/instavibe-bootstrap/agents/social/agent.py
içinde, dosyanın üst kısmında bulunan #REPLACE FOR CheckCondition
öğesini aşağıdakilerle değiştirin:
class CheckCondition(BaseAgent):
async def _run_async_impl(self, ctx: InvocationContext) -> AsyncGenerator[Event, None]:
#log.info(f"Checking status: {ctx.session.state.get("summary_status", "fail")}")
log.info(f"Summary: {ctx.session.state.get("summary")}")
status = ctx.session.state.get("summary_status", "fail").strip()
is_done = (status == "completed")
yield Event(author=self.name, actions=EventActions(escalate=is_done))
Loop sonuçları için durum ve geri aramalar
Google'ın ADK'sında Durum, bir aracının yürütülmesi sırasında belleğini veya çalışma verilerini temsil eden önemli bir kavramdır. Bu, bir temsilcinin farklı adımlar, araç çağrıları veya etkileşimler boyunca koruması gereken bilgileri içeren kalıcı bir bağlamdır. Bu durum, ara sonuçları, kullanıcı bilgilerini, sonraki işlemler için parametreleri veya aracının bir görevde ilerlerken hatırlaması gereken diğer verileri depolayabilir.
Senaryomuzda, Loop Aracısı yineleme yaptığında summary_agent
ve check_agent
, çıkışlarını (özet ve summary_status) aracının durumunda saklar. Bu sayede bilgiler yinelemeler arasında korunur. Ancak Loop Agent, tamamlandığında durumdan otomatik olarak nihai özeti döndürmez.
ADK'daki geri çağırma işlevleri, bir aracının yaşam döngüsü sırasında belirli noktalarda veya belirli etkinliklere (ör. bir araç çağrısının tamamlanması ya da aracının yürütmeyi bitirmesinden önce) yanıt olarak yürütülecek özel mantık yerleştirmemize olanak tanır. Bu işlevler, aracının davranışını özelleştirmenin ve sonuçları dinamik olarak işlemenin bir yolunu sunar.
Döngü tamamlandığında (CheckCondition yükseltildiği için) çalışan bir after_agent_callback
kullanacağız. Bu geri çağırma işlevi modify_output_after_agent
, durumdan nihai özeti alır ve bunu temsilcinin nihai çıkış mesajı olarak biçimlendirir.
👉📝 Aynı ~/instavibe-bootstrap/agents/social/agent.py
içinde #REPLACE FOR modify_output_after_agent
ifadesini follow ile değiştirin:
def modify_output_after_agent(callback_context: CallbackContext) -> Optional[types.Content]:
agent_name = callback_context.agent_name
invocation_id = callback_context.invocation_id
current_state = callback_context.state.to_dict()
current_user_content = callback_context.user_content
print(f"[Callback] Exiting agent: {agent_name} (Inv: {invocation_id})")
print(f"[Callback] Current summary_status: {current_state.get("summary_status")}")
print(f"[Callback] Current Content: {current_user_content}")
status = current_state.get("summary_status").strip()
is_done = (status == "completed")
# Retrieve the final summary from the state
final_summary = current_state.get("summary")
print(f"[Callback] final_summary: {final_summary}")
if final_summary and is_done and isinstance(final_summary, str):
log.info(f"[Callback] Found final summary, constructing output Content.")
# Construct the final output Content object to be sent back
return types.Content(role="model", parts=[types.Part(text=final_summary.strip())])
else:
log.warning("[Callback] No final summary found in state or it's not a string.")
# Optionally return a default message or None if no summary was generated
return None
Kök Döngü Aracısını Tanımlama
Son olarak, ana LoopAgent'ı tanımlıyoruz. Her döngü yinelemesinde alt aracıları sırayla düzenler (profile_agent -> summary_agent -> check_agent -> CheckCondition). Bu sıra, CheckCondition tamamlanmayı işaret edene veya max_iterations kez tekrarlanana kadar devam eder. after_agent_callback, nihai özetin döndürülmesini sağlar.
👉📝 Aynı ~/instavibe-bootstrap/agents/social/agent.py
içinde #REPLACE FOR root_agent
ifadesini follow ile değiştirin:
root_agent = LoopAgent(
name="InteractivePipeline",
sub_agents=[
profile_agent,
summary_agent,
check_agent,
CheckCondition(name="Checker")
],
description="Find everyone's social profile on events, post and friends",
max_iterations=10,
after_agent_callback=modify_output_after_agent
)
ADK Dev UI'yi kullanarak bu çoklu aracı iş akışını test edelim.
👉💻 ADK web sunucusunu başlatın:
. ~/instavibe-bootstrap/set_env.sh
source ~/instavibe-bootstrap/env/bin/activate
cd ~/instavibe-bootstrap/agents
sed -i "s|^\(O\?GOOGLE_CLOUD_PROJECT\)=.*|GOOGLE_CLOUD_PROJECT=${PROJECT_ID}|" ~/instavibe-bootstrap/agents/social/.env
adk web
ADK Dev UI'yi (Web Önizlemesi üzerinden 8000 numaralı bağlantı noktası) açın. Aracı açılır menüsünde (sağ üst) Sosyal Aracı'yı seçin.
👉 Şimdi, birden fazla kişinin profilini oluşturma görevini verin. Sohbet iletişim kutusuna şunu girin:
Tell me about Mike and Bob
Aracı yanıt verdikten sonra (döngü ve birden fazla LLM çağrısı nedeniyle bu biraz daha uzun sürebilir) yalnızca son sohbet çıkışına bakmayın. ADK Dev UI'nin sol bölmesindeki Etkinlikler sekmesine gidin.
👉 Doğrulama Adımı: Etkinlikler sekmesinde, yürütmenin adım adım ayrıntılı izini görürsünüz.
Aracının her bir alt aracı nasıl çağırdığını gözlemledikten sonra, akışın her yinelemede profile_agent -> summary_agent -> check_agent -> Checker şeklinde ilerlemesini beklersiniz. Ancak uygulamada, aracının güçlü "kendi kendini optimize etme" özelliğinin çalıştığını görüyoruz.
Çünkü temel model, isteğin tamamını (ör. "Mike ve Bob'un profilini oluştur") gibi bir görev verildiğinde genellikle en verimli yolu seçer ve birden çok kez yineleme yapmak yerine gerekli tüm verileri tek bir birleştirilmiş adımda toplar. profile_agent tarafından yapılan araç çağrıları da dahil olmak üzere her adımın girişlerini, çıkışlarını ve durumlarını görebilirsiniz.
ve check_agent ile CheckCondition'dan gelen durum güncellemeleri.
Bu görsel iz, çoklu aracı iş akışının son özet oluşturulup geri çağırma tarafından döndürülene kadar nasıl çalıştığını anlamak ve hatalarını ayıklamak için çok değerlidir.
Sohbet yanıtını ve etkinlik izlemeyi inceledikten sonra Cloud Shell terminaline dönün ve ADK Dev UI'yi durdurmak için Ctrl+C
tuşuna basın.
10. Temsilciler Arası (A2A) İletişim
Şimdiye kadar uzmanlaşmış aracıları oluşturduk ancak bunlar yalıtılmış olarak veya aynı makinede önceden tanımlanmış bir iş akışı içinde çalışıyor. Gerçekten dağıtılmış ve ortak çalışmaya dayalı çoklu aracı sistemleri oluşturmak için, muhtemelen ayrı hizmetler olarak çalışan aracıların birbirini keşfedebileceği ve etkili bir şekilde iletişim kurabileceği bir yöntem gerekir. Bu noktada, temsilciden temsilciye (A2A) protokolü devreye girer.
A2A protokolü, yapay zeka aracıları arasında birlikte çalışabilir iletişimi için özel olarak tasarlanmış açık bir standarttır. MCP, temsilciden araca etkileşime odaklanırken A2A, temsilciden temsilciye etkileşime odaklanır. Bu özellik, temsilcilerin şunları yapmasına olanak tanır:
- Keşfetme: Diğer aracıları bulun ve standartlaştırılmış Aracı Kartları aracılığıyla özelliklerini öğrenin.
- İletişim kurma: Mesaj ve verileri güvenli bir şekilde paylaşın.
- İşbirliği yapma: Karmaşık hedeflere ulaşmak için görevleri devredin ve işlemleri koordine edin.
A2A protokolü, bu iletişimi "Aracı Kartları" gibi mekanizmalar aracılığıyla kolaylaştırır. Aracı Kartları, aracıların yeteneklerini ve bağlantı bilgilerini tanıtmak için kullanabileceği bir araçtır.
A2A, bilinen web standartlarından (HTTP, SSE, JSON-RPC) yararlanır ve genellikle bir aracının (istemci) görevleri diğerine (uzak aracı/sunucu) gönderdiği bir istemci-sunucu modeli kullanır. Bu standardizasyon, bağımsız olarak geliştirilen aracıların birlikte çalışabileceği modüler ve ölçeklenebilir sistemler oluşturmak için çok önemlidir.
InstaVibe temsilcileri için A2A'yı etkinleştirme
Mevcut Planner, Platform Interaction ve Social aracılarımızın A2A üzerinden diğer aracılara erişilebilir olması için her birini A2A sunucu bileşeniyle sarmamız gerekir. Bu sunucu:
- Aracı Kartı Gösterme: Aracı özelliklerinin standart bir açıklamasını HTTP uç noktası üzerinden sunun.
- Görevler için Dinleme(İstek Mesajları): A2A protokolüne göre diğer temsilcilerden (A2A istemcileri) gelen görev isteklerini kabul edin.
- Görev(İstek Mesajları) Yürütme İşlemini Yönetme: Alınan görevleri işlenmek üzere temel ADK aracısı mantığına aktarır.
Planner Agent (A2A Etkin)
Planlayıcı Temsilcimize A2A sunucu katmanını ekleyerek başlayalım.
A2A sunucusunun başlatma mantığını tanımlayın. Bu kod, AgentCard'ı (temsilcinin herkese açık açıklaması) tanımlar, A2AServer'ı yapılandırır ve başlatır. Böylece, A2AServer PlatformAgentExecutor'a bağlanır.
👉📝 Aşağıdaki kodu ~/instavibe-bootstrap/agents/planner/a2a_server.py
dosyasının sonuna ekleyin:
class PlannerAgent:
"""An agent to help user planning a event with its desire location."""
SUPPORTED_CONTENT_TYPES = ["text", "text/plain"]
def __init__(self):
self._agent = self._build_agent()
self.runner = Runner(
app_name=self._agent.name,
agent=self._agent,
artifact_service=InMemoryArtifactService(),
session_service=InMemorySessionService(),
memory_service=InMemoryMemoryService(),
)
capabilities = AgentCapabilities(streaming=True)
skill = AgentSkill(
id="event_planner",
name="Event planner",
description="""
This agent generates multiple fun plan suggestions tailored to your specified location, dates, and interests,
all designed for a moderate budget. It delivers detailed itineraries,
including precise venue information (name, latitude, longitude, and description), in a structured JSON format.
""",
tags=["instavibe"],
examples=["What about Bostona MA this weekend?"],
)
self.agent_card = AgentCard(
name="Event Planner Agent",
description="""
This agent generates multiple fun plan suggestions tailored to your specified location, dates, and interests,
all designed for a moderate budget. It delivers detailed itineraries,
including precise venue information (name, latitude, longitude, and description), in a structured JSON format.
""",
url=f"{PUBLIC_URL}",
version="1.0.0",
defaultInputModes=PlannerAgent.SUPPORTED_CONTENT_TYPES,
defaultOutputModes=PlannerAgent.SUPPORTED_CONTENT_TYPES,
capabilities=capabilities,
skills=[skill],
)
def get_processing_message(self) -> str:
return "Processing the planning request..."
def _build_agent(self) -> LlmAgent:
"""Builds the LLM agent for the night out planning agent."""
return agent.root_agent
if __name__ == '__main__':
try:
plannerAgent = PlannerAgent()
request_handler = DefaultRequestHandler(
agent_executor=PlannerAgentExecutor(plannerAgent.runner,plannerAgent.agent_card),
task_store=InMemoryTaskStore(),
)
server = A2AStarletteApplication(
agent_card=plannerAgent.agent_card,
http_handler=request_handler,
)
logger.info(f"Attempting to start server with Agent Card: {plannerAgent.agent_card.name}")
logger.info(f"Server object created: {server}")
uvicorn.run(server.build(), host='0.0.0.0', port=port)
except Exception as e:
logger.error(f"An error occurred during server startup: {e}")
exit(1)
👉💻 A2A sunucusunun yerel olarak doğru şekilde başlatılıp başlatılmadığını ve Agent Card'ını yayınlayıp yayınlamadığını hızlıca test edelim. İlk terminalinizde aşağıdaki komutu çalıştırın:
. ~/instavibe-bootstrap/set_env.sh
source ~/instavibe-bootstrap/env/bin/activate
cd ~/instavibe-bootstrap/agents/
python -m planner.a2a_server
👉 Şimdi başka bir terminal penceresi açın. (Terminal panelinde + işaretini tıklayın)
👉💻 Yerel olarak çalışan sunucudan Agent Card'ı istemek için curl'ü kullanın:
curl http://localhost:10003/.well-known/agent.json | jq
Sunucunun çalıştığını ve Planlayıcı aracısının reklamını yaptığını onaylayan, tanımladığımız AgentCard'ın JSON gösterimini görmeniz gerekir.
İlk terminale (sunucunun çalıştığı yer) geri dönün ve durdurmak için Ctrl+C
tuşuna basın.
👉💻 A2A sunucu mantığı eklendiğinden artık kapsayıcı görüntüsünü oluşturabiliriz.
Planlayıcı aracısını oluşturma ve dağıtma
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/agents
# Set variables specific to the PLANNER agent
export IMAGE_TAG="latest"
export AGENT_NAME="planner"
export IMAGE_NAME="planner-agent"
export IMAGE_PATH="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${IMAGE_NAME}:${IMAGE_TAG}"
export SERVICE_NAME="planner-agent"
export PUBLIC_URL="https://planner-agent-${PROJECT_NUMBER}.${REGION}.run.app"
echo "Building ${AGENT_NAME} agent..."
gcloud builds submit . \
--config=cloudbuild-build.yaml \
--project=${PROJECT_ID} \
--region=${REGION} \
--substitutions=_AGENT_NAME=${AGENT_NAME},_IMAGE_PATH=${IMAGE_PATH}
echo "Image built and pushed to: ${IMAGE_PATH}"
👉💻 Planlayıcı aracımızı Cloud Run'da dağıtın.
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/agents
# Set variables specific to the PLANNER agent
export IMAGE_TAG="latest"
export AGENT_NAME="planner"
export IMAGE_NAME="planner-agent"
export IMAGE_PATH="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${IMAGE_NAME}:${IMAGE_TAG}"
export SERVICE_NAME="planner-agent"
export PUBLIC_URL="https://planner-agent-${PROJECT_NUMBER}.${REGION}.run.app"
gcloud run deploy ${SERVICE_NAME} \
--image=${IMAGE_PATH} \
--platform=managed \
--region=${REGION} \
--set-env-vars="A2A_HOST=0.0.0.0" \
--set-env-vars="A2A_PORT=8080" \
--set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=TRUE" \
--set-env-vars="GOOGLE_CLOUD_LOCATION=${REGION}" \
--set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
--set-env-vars="PUBLIC_URL=${PUBLIC_URL}" \
--allow-unauthenticated \
--project=${PROJECT_ID} \
--min-instances=1
A2A Inspector'ı kullanarak dağıtılan hizmetin çalıştığını ve buluttan Agent Card'ını doğru şekilde sunduğunu doğrulayalım.
👉 Cloud Shell araç çubuğundaki Web önizlemesi simgesinden Bağlantı noktasını değiştir'i seçin. Bağlantı noktasını 8081 olarak ayarlayın ve "Değiştir ve Önizle"yi tıklayın. A2A Inspector arayüzünü içeren yeni bir tarayıcı sekmesi açılır.
👉💻 Terminalde, dağıtılan planlayıcı aracınızın URL'sini alın:
export PLANNER_AGENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep planner-agent)
echo ${PLANNER_AGENT_URL}
👉💻 Çıkış URL'sini kopyalayın.
👉 A2A Inspector kullanıcı arayüzünde URL'yi Agent URL (Aracı URL'si) alanına yapıştırıp Connect (Bağlan) seçeneğini tıklayın.
👀 Temsilcinin kart bilgileri ve JSON'u, başarılı bir bağlantıyı onaylayarak Temsilci Kartı sekmesinde görünmelidir.
👉 A2A Inspector'da Chat sekmesini tıklayın. Burada, dağıtılan temsilcinizle doğrudan etkileşim kurabilir ve planlama özelliğini test etmek için ona mesaj gönderebilirsiniz. Örneğin:
Plan something for me in Boston MA this weekend, and I enjoy classical music
👀 Ham iletişimi incelemek için mesaj balonunuzu, ardından sohbet penceresinde temsilcinin yanıt balonunu tıklayın. Her birini tıkladığınızda, gönderilen veya alınan tam JSON-RPC 2.0 mesajı gösterilir. Bu, hata ayıklama için çok değerlidir.
A2A Inspector sekmesini elinizin altında bulundurun. KAPATMAYIN. Diğer iki aracımızı test etmek için biraz sonra tekrar kullanacağız.
Platform Interaction Agent (A2A Etkin)
Ardından, Platform Interaction Agent (MCP'yi kullanan) için işlemi tekrarlayacağız.
👉📝 ~/instavibe-bootstrap/agents/platform_mcp_client/a2a_server.py
bölümünün sonunda, benzersiz AgentCard'ı da dahil olmak üzere A2A sunucu kurulumunu tanımlayın:
class PlatformAgent:
"""An agent that post event and post to instavibe."""
SUPPORTED_CONTENT_TYPES = ["text", "text/plain"]
def __init__(self):
self._agent = self._build_agent()
self.runner = Runner(
app_name=self._agent.name,
agent=self._agent,
artifact_service=InMemoryArtifactService(),
session_service=InMemorySessionService(),
memory_service=InMemoryMemoryService(),
)
capabilities = AgentCapabilities(streaming=True)
skill = AgentSkill(
id="instavibe_posting",
name="Post social post and events on instavibe",
description="""
This "Instavibe" agent helps you create posts (identifying author, text, and sentiment – inferred if unspecified) and register
for events (gathering name, date, attendee). It efficiently collects required information and utilizes dedicated tools
to perform these actions on your behalf, ensuring a smooth sharing experience.
""",
tags=["instavibe"],
examples=["Create a post for me, the post is about my cute cat and make it positive, and I'm Alice"],
)
self.agent_card = AgentCard(
name="Instavibe Posting Agent",
description="""
This "Instavibe" agent helps you create posts (identifying author, text, and sentiment – inferred if unspecified) and register
for events (gathering name, date, attendee). It efficiently collects required information and utilizes dedicated tools
to perform these actions on your behalf, ensuring a smooth sharing experience.
""",
url=f"{PUBLIC_URL}",
version="1.0.0",
defaultInputModes=PlatformAgent.SUPPORTED_CONTENT_TYPES,
defaultOutputModes=PlatformAgent.SUPPORTED_CONTENT_TYPES,
capabilities=capabilities,
skills=[skill],
)
def get_processing_message(self) -> str:
return "Processing the social post and event request..."
def _build_agent(self) -> LlmAgent:
"""Builds the LLM agent for the Processing the social post and event request."""
return agent.root_agent
if __name__ == '__main__':
try:
platformAgent = PlatformAgent()
request_handler = DefaultRequestHandler(
agent_executor=PlatformAgentExecutor(platformAgent.runner,platformAgent.agent_card),
task_store=InMemoryTaskStore(),
)
server = A2AStarletteApplication(
agent_card=platformAgent.agent_card,
http_handler=request_handler,
)
uvicorn.run(server.build(), host='0.0.0.0', port=port)
except Exception as e:
logger.error(f"An error occurred during server startup: {e}")
exit(1)
Sosyal Medya Temsilcisi (A2A Etkin)
Son olarak, sosyal profilleme aracımız için A2A'yı etkinleştirelim.
👉📝 ~/instavibe-bootstrap/agents/social/a2a_server.py
bölümünün sonunda A2A sunucu kurulumunu ve AgentCard'ı tanımlayın:
class SocialAgent:
"""An agent that handles social profile analysis."""
SUPPORTED_CONTENT_TYPES = ["text", "text/plain"]
def __init__(self):
self._agent = self._build_agent()
self.runner = Runner(
app_name=self._agent.name,
agent=self._agent,
artifact_service=InMemoryArtifactService(),
session_service=InMemorySessionService(),
memory_service=InMemoryMemoryService(),
)
capabilities = AgentCapabilities(streaming=True)
skill = AgentSkill(
id="social_profile_analysis",
name="Analyze Instavibe social profile",
description="""
Using a provided list of names, this agent synthesizes Instavibe social profile information by analyzing posts, friends, and events.
It delivers a comprehensive single-paragraph summary for individuals, and for groups, identifies commonalities in their social activities
and connections based on profile data.
""",
tags=["instavibe"],
examples=["Can you tell me about Bob and Alice?"],
)
self.agent_card = AgentCard(
name="Social Profile Agent",
description="""
Using a provided list of names, this agent synthesizes Instavibe social profile information by analyzing posts, friends, and events.
It delivers a comprehensive single-paragraph summary for individuals, and for groups, identifies commonalities in their social activities
and connections based on profile data.
""",
url=f"{PUBLIC_URL}",
version="1.0.0",
defaultInputModes=self.SUPPORTED_CONTENT_TYPES,
defaultOutputModes=self.SUPPORTED_CONTENT_TYPES,
capabilities=capabilities,
skills=[skill],
)
def get_processing_message(self) -> str:
return "Processing the social profile analysis request..."
def _build_agent(self) -> LoopAgent:
"""Builds the LLM agent for the social profile analysis agent."""
return agent.root_agent
if __name__ == '__main__':
try:
socialAgent = SocialAgent()
request_handler = DefaultRequestHandler(
agent_executor=SocialAgentExecutor(socialAgent.runner,socialAgent.agent_card),
task_store=InMemoryTaskStore(),
)
server = A2AStarletteApplication(
agent_card=socialAgent.agent_card,
http_handler=request_handler,
)
uvicorn.run(server.build(), host='0.0.0.0', port=port)
except Exception as e:
logger.error(f"An error occurred during server startup: {e}")
exit(1)
Platform Etkileşimi ve Sosyal medya aracılarını oluşturma ve dağıtma
Bu aracıların Spanner'a erişmesi gerekir. Bu nedenle, dağıtım sırasında SPANNER_INSTANCE_ID
, SPANNER_DATABASE_ID
ve MCP_SERVER_URL
ortam değişkenlerinin doğru şekilde iletildiğinden emin olun.
👉💻 Cloud Build ile Cloud Run'da derleme ve dağıtım yapma:
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/agents
export MCP_SERVER_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep mcp-tool-server)/sse
gcloud builds submit . \
--config=cloudbuild.yaml \
--project="${PROJECT_ID}" \
--region="${REGION}" \
--substitutions=\
_PROJECT_ID="${PROJECT_ID}",\
_PROJECT_NUMBER="${PROJECT_NUMBER}",\
_REGION="${REGION}",\
_REPO_NAME="${REPO_NAME}",\
_SPANNER_INSTANCE_ID="${SPANNER_INSTANCE_ID}",\
_SPANNER_DATABASE_ID="${SPANNER_DATABASE_ID}",\
_MCP_SERVER_URL="${MCP_SERVER_URL}"
👉💻 Terminalde, dağıtılan platform aracınızın URL'sini alın:
export PLATFORM_MPC_CLIENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep platform-mcp-client)
echo $PLATFORM_MPC_CLIENT_URL
👉💻 Çıkış URL'sini kopyalayın.
👉 A2A Inspector kullanıcı arayüzünde URL'yi Agent URL (Aracı URL'si) alanına yapıştırıp Connect (Bağlan) seçeneğini tıklayın.
👀 Temsilcinin kart bilgileri ve JSON'u, başarılı bir bağlantıyı onaylayarak Temsilci Kartı sekmesinde görünmelidir.
👉 A2A Inspector'da Chat sekmesini tıklayın. Burada, dağıtılan temsilcinizle doğrudan etkileşim kurabilir, ona mesaj göndererek temsilcinin gönderi oluşturma becerisini test edebilirsiniz:
Create a post for me, the post says 'Paws, purrs, and ocean views 🐾☕🌊. Spent my morning at the Morning Seaside Cat Café, where every sip comes with a side of snuggles and sea breeze.' and make it positive, and I'm Oscar.
👀 Ham iletişimi incelemek için mesaj balonunuzu, ardından sohbet penceresinde temsilcinin yanıt balonunu tıklayın. Her birini tıkladığınızda, gönderilen veya alınan tam JSON-RPC 2.0 mesajı gösterilir. Bu, hata ayıklama için çok değerlidir.
👉💻 Terminalde, dağıtılan Sosyal Aracınızın URL'sini alın:
export SOCIAL_AGENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep social-agent)
echo $SOCIAL_AGENT_URL
👉💻 Çıkış URL'sini kopyalayın.
👉 A2A Inspector kullanıcı arayüzünde URL'yi Agent URL (Aracı URL'si) alanına yapıştırıp Connect (Bağlan) seçeneğini tıklayın.
👀 Temsilcinin kart bilgileri ve JSON'u, başarılı bir bağlantıyı onaylayarak Temsilci Kartı sekmesinde görünmelidir.
👉 A2A Inspector'da Chat sekmesini tıklayın. Burada, dağıtılan aracınızla doğrudan etkileşim kurabilir ve veritabanınızdaki kullanıcı profillerini analiz etmesi için araca mesaj gönderebilirsiniz:
Can you tell me about both Ian and Kevin's profile, what are their common interests?
👀 Ham iletişimi incelemek için mesaj balonunuzu, ardından sohbet penceresinde temsilcinin yanıt balonunu tıklayın. Her birini tıkladığınızda, gönderilen veya alınan tam JSON-RPC 2.0 mesajı gösterilir. Bu, hata ayıklama için çok değerlidir.
👉 Tüm temsilcilerimizin denetimini tamamladık. Artık A2A Inspector sekmesini kapatabilirsiniz.
11. Orchestrator Aracısı (A2A İstemcisi)
Artık Cloud Run'da bağımsız, A2A özellikli hizmetler olarak çalışan üç uzman aracımız (Planlayıcı, Platform, Sosyal) var. Son parça, Orchestrator Agent'tır. Bu aracı, merkezi koordinatör veya A2A istemcisi olarak görev yapar. Kullanıcı isteklerini alır, isteği karşılamak için hangi uzak aracıların gerektiğini (potansiyel olarak sırayla) belirler ve ardından görevleri bu uzak aracılara devretmek için A2A protokolünü kullanır. Bu atölye çalışmasında, Orchestrator aracısını ADK Dev UI'yi kullanarak yerel olarak çalıştıracağız.
Öncelikle, Orchestrator'ın keşfettiği uzak aracıların kaydını işlemek için mantığını geliştirelim. Başlatma sırasında getirilen Temsilci Kartları'ndaki bağlantı ayrıntılarını depolar.
👉📝 ~/instavibe-bootstrap/agents/orchestrate/agent.py
içinde #REPLACE ME REG AGENT CARD
yerine şunu yazın:
async with httpx.AsyncClient(timeout=30) as client:
for i, address in enumerate(REMOTE_AGENT_ADDRESSES):
log.info(f"--- STEP 3.{i}: Attempting connection to: {address} ---")
try:
card_resolver = A2ACardResolver(client, address)
card = await card_resolver.get_agent_card()
remote_connection = RemoteAgentConnections(agent_card=card, agent_url=address)
self.remote_agent_connections[card.name] = remote_connection
self.cards[card.name] = card
log.info(f"--- STEP 5.{i}: Successfully stored connection for {card.name} ---")
except Exception as e:
log.error(f"--- CRITICAL FAILURE at STEP 4.{i} for address: {address} ---")
log.error(f"--- The hidden exception type is: {type(e).__name__} ---")
log.error(f"--- Full exception details and traceback: ---", exc_info=True)
Ardından, ADK'da Orchestrator aracısı için aracı tanımlayın.
send_message
(işi devretmek için kullanılan A2A işlevi).
👉📝 ~/instavibe-bootstrap/agents/orchestrate/agent.py
içindeki #REPLACE ME CREATE AGENT
yerine aşağıdakileri girin:
def create_agent(self) -> Agent:
"""Synchronously creates the ADK Agent object."""
return Agent(
model="gemini-2.5-flash",
name="orchestrate_agent",
instruction=self.root_instruction,
before_agent_callback=self.before_agent_callback,
description=("Orchestrates tasks for child agents."),
tools=[self.send_message],
)
Orchestrator'ın temel mantığı, A2A'yı nasıl kullanacağını belirten talimatlarında yatar.
👉📝 #REPLACE ME INSTRUCTIONS
içindeki ~/instavibe-bootstrap/agents/orchestrate/agent.py
kısmını talimat oluşturma yöntemiyle değiştirin:
def root_instruction(self, context: ReadonlyContext) -> str:
current_agent = self.check_active_agent(context)
return f"""
You are an expert AI Orchestrator. Your primary responsibility is to intelligently interpret user requests, break them down into a logical plan of discrete actions, and delegate each action to the most appropriate specialized remote agent using the send_message function. You do not perform the tasks yourself but manage their assignment, sequence, and critically, their outcomes.
**Core Directives & Decision Making:**
* **Understand User Intent & Complexity:**
* Carefully analyze the user's request to determine the core task(s) they want to achieve. Pay close attention to keywords and the overall goal.
* Identify if the request requires a single agent or a sequence of actions from multiple agents. For example, "Analyze John Doe's profile and then create a positive post about his recent event attendance" would require two agents in sequence.
* **Task Planning & Sequencing (for Multi-Step Requests):**
* Before delegating, outline the clear sequence of agent tasks.
* Identify dependencies. If Task B requires output from Task A, execute them sequentially. If tasks are independent (like creating a post and then creating an event), execute them one after the other as separate delegations.
* Agent Reusability: An agent's completion of one task does not make it unavailable. If a user's plan involves multiple, distinct actions that fall under the same agent's expertise (e.g., create a post, then create an event), you must call that same agent again for the subsequent task.
* **Task Delegation & Management (using `send_message`):**
* **Delegation:** Use `send_message` to assign actionable tasks to the selected remote agent. Your `send_message` call MUST include:
* The `remote_agent_name` you've selected.
* The `user_request` or all necessary parameters extracted from the user's input, formatted in a way the target agent will understand.
* **Contextual Awareness for Remote Agents:** If a remote agent repeatedly requests user confirmation or seems to lack context, assume it lacks access to the full conversation history. In such cases, enrich your `send_message` with all necessary contextual information relevant to that specific agent from the conversation history.
* **Sequential Task Execution:**
* After a preceding task completes (indicated by the agent's response or a success signal), gather any necessary output from it.
* Then, use `send_message` for the next agent in the sequence, providing it with the user's original relevant intent and any necessary data obtained from the previous agent's task.
* **Active Agent Prioritization:** If an active agent is already engaged and the user's request is related to its current task, route subsequent related requests directly to that agent by providing updated context via `send_message`.
**Critical Success Verification:**
* You **MUST** wait for the tool_output after every send_message call before taking any further action.
* Your decision to proceed to the next task in a sequence **MUST** be based entirely on a confirmation of success from the tool_output of the previous task.
* If a tool call fails, returns an error, or the tool_output is ambiguous, you MUST STOP the sequence. Your next action is to report the exact failure or ambiguity to the user.
* DO NOT assume a task was successful. Do not invent success messages like "The event has been created." Only state that a task is complete if the tool's response explicitly says so.
**Communication with User:**
* **Transparent Communication:** Always present the complete and detailed response from the remote agent to the user. Do not summarize or filter unless explicitly instructed.
* When you delegate a task (or the first task in a sequence), clearly inform the user which remote agent is handling it.
* For multi-step requests, you can optionally inform the user of the planned sequence (e.g., "Okay, first I'll ask the 'Social Profile Agent' to analyze the profile, and then I'll have the 'Instavibe Posting Agent' create the post.").
* If waiting for a task in a sequence to complete, you can inform the user (e.g., "The 'Social Profile Agent' is currently processing. I'll proceed with the post once that's done.").
* **User Confirmation Relay:** If a remote agent asks for confirmation, and the user has not already provided it, just make up something.
* If the user's request is ambiguous, if necessary information is missing for any agent in the sequence, or if you are unsure about the plan, just make up something.
**Important Reminders:**
* **Autonomous Agent Engagement:** Never seek user permission before engaging with remote agents. If multiple agents are required to fulfill a request, connect with them directly without requesting user preference or confirmation.
* **Focused Information Sharing:** Provide remote agents with only relevant contextual information. Avoid extraneous details that are not directly pertinent to their task.
* **No Redundant Confirmations:** Do not ask remote agents for confirmation of information or actions they have already processed or committed to.
* **Tool Reliance:** Strictly rely on your available tools, primarily `send_message`, to address user requests. Do not generate responses based on assumptions. If information is insufficient, request clarification from the user.
* **Prioritize Recent Interaction:** Focus primarily on the most recent parts of the conversation when processing requests, while maintaining awareness of the overall goal for multi-step tasks.
* Always prioritize selecting the correct agent(s) based on their documented purpose.
* Ensure all information required by the chosen remote agent is included in the `send_message` call, including outputs from previous agents if it's a sequential task.
Agents:
{self.agents}
Current agent: {current_agent['active_agent']}`
"""
Orchestrator ve tam A2A sistemini test etme
Şimdi tüm sistemi test edelim. Orchestrator'ı ADK Dev UI'yi kullanarak yerel olarak çalıştıracağız. Orchestrator, Cloud Run'da uzaktan çalışan Planner, Platform ve Social aracılarıyla iletişim kuracak.
👉💻 Öncelikle REMOTE_AGENT_ADDRESSES
ortam değişkeninin, dağıtılan A2A özellikli aracılarınızın virgülle ayrılmış URL'lerini içerdiğinden emin olun. Ardından, Orchestrator aracısı için gerekli ortam değişkenlerini ayarlayın ve ADK Dev UI'yi başlatın:
. ~/instavibe-bootstrap/set_env.sh
source ~/instavibe-bootstrap/env/bin/activate
export PLATFORM_MPC_CLIENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep platform-mcp-client)
export PLANNER_AGENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep planner-agent)
export SOCIAL_AGENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep social-agent)
export REMOTE_AGENT_ADDRESSES=${PLANNER_AGENT_URL},${PLATFORM_MPC_CLIENT_URL},${SOCIAL_AGENT_URL}
cd ~/instavibe-bootstrap/agents
sed -i "s|^\(O\?REMOTE_AGENT_ADDRESSES\)=.*|REMOTE_AGENT_ADDRESSES=${REMOTE_AGENT_ADDRESSES}|" ~/instavibe-bootstrap/agents/orchestrate/.env
adk web
👉 ADK Dev kullanıcı arayüzünü açın (Web önizlemesi aracılığıyla bağlantı noktasını tekrar 8000 olarak değiştirin).
👉 Aracı açılır listesinde orchestrate aracısını seçin.
👉 Şimdi, birden fazla uzak aracının koordine edilmesini gerektiren karmaşık bir görev verin. Önce Sosyal Ajan'ın, ardından Planlayıcı Ajan'ın dahil olması gereken şu ilk örneği deneyin:
You are an expert event planner for a user named Diana.
Your task is to design a fun and personalized event.
Here are the details for the plan:
- Friends to invite: Ian, Nora
- Desired date: "2025-10-15"
- Location idea or general preference: "Chicago"
Your process should be:
1. Analyze the provided friend names. If you have access to a tool to get their InstaVibe profiles or summarized interests, please use it.
2. Based on their potential interests (or general good taste if profiles are unavailable), create a tailored plan for the outing, check if you have access to any event planner tools.
3. Ensure the plan includes the original `planned_date`.
The user wants a comprehensive plan that includes:
- The list of invited friends.
- A catchy and descriptive name for the event.
- The exact planned date for the event.
- A summary of what the group will do.
- Specific recommended spots (e.g., restaurants, bars, activity venues) with their names, (if possible, approximate latitude/longitude for mapping, and address), and a brief description of why it fits the plan.
- A short, exciting message that {Diana} can send to {Ian, Nora} to get them excited about the event.
ADK Dev UI sohbet penceresindeki etkileşimi gözlemleyin. Orchestrator'ın yanıtlarına dikkat edin.Orchestrator, görevleri hangi uzak aracıya devrettiğini belirtmelidir (ör. "Tamam, önce Ian ve Nora hakkında Sosyal Profil Aracısı'na soracağım...").
Ayrıca, uzak aracıların URL'lerine yapılan temel araç çağrılarını (send_message) görmek için kullanıcı arayüzündeki Etkinlikler sekmesini kontrol edin.
👉 Şimdi, Platform Entegrasyon Aracısı'nın doğrudan dahil olması gereken ikinci bir örneği deneyin:
Hey, can you register an event on Instavibe for Laura and Charlie? Let's call it 'Vienna Concert & Castles Day'.
here are more info
"event_name": "Vienna Concert & Castles Day",
"description": "A refined and unforgettable day in Vienna with Laura and Charlie. The day begins with a guided tour of the magnificent Schönbrunn Palace, showcasing imperial architecture and history. In the evening, enjoy a classical music concert in one of Vienna's most iconic concert halls.",
"event_date": "2025-10-14T10:00:00+02:00",
"locations": [
{
"name": "Schönbrunn Palace",
"description": "A UNESCO World Heritage Site and former imperial summer residence, Schönbrunn Palace offers opulent rooms, beautiful baroque gardens, and a glimpse into the life of the Habsburg monarchy. Visitors can stroll the grounds or take a guided historical tour.",
"latitude": 48.184516,
"longitude": 16.312222,
"address": "Schönbrunner Schloßstraße 47, 1130 Wien, Austria"
},
{
"name": "Musikverein Vienna",
"description": "Home to the world-renowned Vienna Philharmonic, the Musikverein is one of the finest concert halls in the world. Its 'Golden Hall' is famous for its acoustics and ornate design. Attendees can enjoy a powerful classical concert in an unforgettable setting.",
"latitude": 48.200132,
"longitude": 16.373777,
"address": "Musikvereinsplatz 1, 1010 Wien, Austria"
}
],
"attendee_names": ["Laura", "Charlie", "Oscar"] And I am Oscar
Sohbeti ve Etkinlikler sekmesini tekrar izleyin. Orkestratör, etkinlik oluşturma ihtiyacını belirlemeli ve görevi (sağlanan tüm ayrıntılarla birlikte) "Platform Entegrasyon Aracısı"na devretmelidir. Sorgu yanıt sürelerini ve yürütülen işlemleri analiz etmek için izlemeleri görüntülemek üzere İzleme düğmesini de tıklayabilirsiniz.
Ardından, etkinliğin InstaVibe web uygulamasında göründüğünü doğrulayabilirsiniz.
Bu, ADK ve A2A protokolü kullanılarak çoklu aracı sisteminin başarılı bir şekilde uygulandığını gösterir. Merkezi bir düzenleyici, görevleri uzmanlaşmış uzak aracılara devreder.
Testi tamamladığınızda ADK Dev UI'yi (terminalde Ctrl+C
) durdurmayı unutmayın.
12. InstaVibe'dan Agent Engine ve Uzak Arama
Şimdiye kadar uzmanlaşmış temsilcilerimizi Cloud Run'da çalıştırdık ve ADK Geliştirici Kullanıcı Arayüzü'nü kullanarak Orchestrator'ı yerel olarak test ettik. Üretim senaryosunda, aracıları barındırmak için sağlam, ölçeklenebilir ve yönetilen bir ortama ihtiyacımız var. Google Vertex AI Agent Engine bu noktada devreye girer.
Agent Engine, Vertex AI'da özel olarak yapay zeka aracılarını dağıtmak ve ölçeklendirmek için tasarlanmış, tümüyle yönetilen bir hizmettir. Altyapı yönetimi, güvenlik ve operasyonel yükü soyutlayarak geliştiricilerin (özellikle karmaşık bulut ortamlarına daha az aşina olanlar) sunucuları yönetmek yerine aracının mantığına ve özelliklerine odaklanmasına olanak tanır. Bu hizmet, yapay zeka aracılı iş yükleri için optimize edilmiş özel bir çalışma zamanı sağlar.
Şimdi Orchestrator aracımızı Agent Engine'e dağıtacağız. (Not: Aşağıda gösterilen dağıtım mekanizmasında, atölye materyallerinde sağlanan özel bir komut dosyası (agent_engine_app.py) kullanılmaktadır. Bunun nedeni, resmi doğrudan ADK-to-Agent-Engine dağıtım araçlarının hâlâ geliştirilme aşamasında olabilmesidir. Bu komut dosyası, gerekli uzak aracı adresleriyle yapılandırılmış Orchestrator aracısının paketlenmesini ve dağıtılmasını sağlar.
Orchestrator aracısını Agent Engine'e dağıtmak için aşağıdaki komutu yürütün. Cloud Run'daki Planner, Platform ve Social aracılarının URL'lerini içeren REMOTE_AGENT_ADDRESSES ortam değişkeninin önceki bölümde doğru şekilde ayarlandığından emin olun.
👉💻 Orchestrate aracısını Agent Engine'e dağıtacağız (Not: Bu, dağıtımın kendi uygulamamdır. ADK'da dağıtıma yardımcı olacak bir CLI vardır. BYO-SA uygulandıktan sonra bunu güncelleyeceğim).
cd ~/instavibe-bootstrap/agents/
. ~/instavibe-bootstrap/set_env.sh
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:service-$PROJECT_NUMBER@gcp-sa-aiplatform-re.iam.gserviceaccount.com" \
--role="roles/viewer"
source ~/instavibe-bootstrap/env/bin/activate
export PLATFORM_MPC_CLIENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep platform-mcp-client)
export PLANNER_AGENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep planner-agent)
export SOCIAL_AGENT_URL=$(gcloud run services list --platform=managed --region=us-central1 --format='value(URL)' | grep social-agent)
export REMOTE_AGENT_ADDRESSES=${PLANNER_AGENT_URL},${PLATFORM_MPC_CLIENT_URL},${SOCIAL_AGENT_URL}
sed -i "s|^\(O\?REMOTE_AGENT_ADDRESSES\)=.*|REMOTE_AGENT_ADDRESSES=${REMOTE_AGENT_ADDRESSES}|" ~/instavibe-bootstrap/agents/orchestrate/.env
adk deploy agent_engine \
--display_name "orchestrate-agent" \
--project $GOOGLE_CLOUD_PROJECT \
--region $GOOGLE_CLOUD_LOCATION \
--staging_bucket gs://$GOOGLE_CLOUD_PROJECT-agent-engine \
--trace_to_cloud \
--requirements_file orchestrate/requirements.txt \
orchestrate
Orkestratör, yönetilen Agent Engine platformunda barındırıldığı için InstaVibe web uygulamamızın orkestratörle iletişim kurması gerekiyor. Web uygulaması, ADK Dev UI üzerinden etkileşim kurmak yerine Agent Engine uç noktasına uzaktan çağrı yapar.
Öncelikle, dağıtılan Orchestrator aracımızın benzersiz kimliğini kullanarak Agent Engine istemcisini başlatmak için InstaVibe uygulama kodunu değiştirmemiz gerekir. Bu kimlik, platformda doğru aracı örneğini hedeflemek için gereklidir.
👉📝 ~/instavibe-bootstrap/instavibe/introvertally.py
bağlantısını açın ve #REPLACE ME initiate agent_engine
yerine aşağıdaki kodu girin. Bu kod, bir ortam değişkeninden (kısa süre içinde ayarlayacağız) Agent Engine kimliğini alır ve bir istemci nesnesi edinir:
ORCHESTRATE_AGENT_ID = os.environ.get('ORCHESTRATE_AGENT_ID')
agent_engine = agent_engines.get(ORCHESTRATE_AGENT_ID)
InstaVibe'daki planlanan kullanıcı akışımız, temsilciyle iki etkileşim içerir: Birincisi, önerilen planı oluşturma; ikincisi ise temsilci etkinliği platformda yayınlamadan önce kullanıcıdan onay isteme.
InstaVibe web uygulaması (Cloud Run'da çalışır) ve Orchestrator aracısı (Agent Engine'de çalışır) artık ayrı hizmetler olduğundan web uygulamasının, aracıyla etkileşim kurmak için Agent Engine uç noktasına uzaktan çağrı yapması gerekir.
👉📝 Plan önerisi oluşturmak için ilk çağrıyı yapan kodu güncelleyelim. Aynı introvertally.py
dosyasında, #REPLACE ME Query remote agent get plan
öğesini, kullanıcının isteğini göndermek için agent_engine istemcisini kullanan aşağıdaki snippet ile değiştirin:
agent_engine.stream_query(
user_id=user_id,
message=prompt_message,
)
👉📝 Ardından, kullanıcının onayını işleyen kodu güncelleyin (ör. kullanıcı "Planı Onayla"yı tıkladığında). Bu işlem, Agent Engine'deki aynı görüşmeye bir takip mesajı göndererek Orchestrator'a etkinliği yayınlamaya devam etmesini (Platform Integration temsilcisine devredeceği) bildirir. introvertally.py
içindeki onay için #REPLACE ME Query remote agent for confirmation
yerine aşağıdakileri girin:
agent_engine.stream_query(
user_id=agent_session_user_id,
message=prompt_message,
)
Web uygulamasının rotalarının bu işlevlere erişmesi gerekir. introvertally.py dosyasındaki gerekli işlevlerin Flask rotaları dosyasına aktarıldığından emin olun.
👉📝 cd ~/instavibe-bootstrap/instavibe/ally_routes.py
bölümünde, önce # REPLACE ME TO ADD IMPORT
yerine aşağıdaki örnekleri kullanacağız:
from introvertally import call_agent_for_plan, post_plan_event
👉📝 InstaVibe'a prototip özelliğini ekleyin. ~/instavibe-bootstrap/instavibe/templates/base.html
bölümünde <!–REPLACE_ME_LINK_TO_INTROVERT_ALLY–> yerine aşağıdakileri ekleyin:
<li class="nav-item">
<a class="nav-link" href="{{ url_for('ally.introvert_ally_page') }}">Introvert Ally</a>
</li>
InstaVibe uygulamasını yeniden dağıtabilmemiz için Agent Engine'e dağıttığımız Orchestrator aracısının Resource ID
gerekir.
Şu anda bu bilgiyi gcloud
üzerinden programatik olarak almak sınırlı olabilir. Bu nedenle, kimliği getirmek ve bir ortam değişkeninde saklamak için yardımcı bir Python komut dosyası (temp-endpoint.py
atölye çalışmasında sağlanır) kullanacağız.
👉💻 Komut dosyasını yürütmek için aşağıdaki komutları çalıştırın. Komut dosyası, Agent Engine Endpoint ID'yi yakalar ve aracı motorunun varsayılan hizmet hesabına gerekli izinleri verir (Not: Komut dosyası, şu anda kullanıcı tarafından değiştirilemediği için varsayılan hizmet hesabını kullanacak şekilde yapılandırılmıştır).
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/instavibe/
source ~/instavibe-bootstrap/env/bin/activate
python temp-endpoint.py
export ORCHESTRATE_AGENT_ID=$(cat temp_endpoint.txt)
echo "ORCHESTRATE_AGENT_ID set to: ${ORCHESTRATE_AGENT_ID}"
Son olarak, InstaVibe web uygulamasını güncellenmiş kod ve yeni ORCHESTRATE_AGENT_ID
ortam değişkeniyle yeniden dağıtmamız gerekiyor. Böylece uygulama, Agent Engine'de çalışan aracımıza nasıl bağlanacağını bilecek.
👉💻 Aşağıdaki komutlar, InstaVibe uygulama görüntüsünü yeniden oluşturur ve yeni sürümü Cloud Run'a dağıtır:
. ~/instavibe-bootstrap/set_env.sh
cd ~/instavibe-bootstrap/instavibe/
export IMAGE_TAG="latest"
export APP_FOLDER_NAME="instavibe"
export IMAGE_NAME="instavibe-webapp"
export IMAGE_PATH="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/${IMAGE_NAME}:${IMAGE_TAG}"
export SERVICE_NAME="instavibe"
echo "Building ${APP_FOLDER_NAME} webapp image..."
gcloud builds submit . \
--tag=${IMAGE_PATH} \
--project=${PROJECT_ID}
echo "Deploying ${SERVICE_NAME} to Cloud Run..."
gcloud run deploy ${SERVICE_NAME} \
--image=${IMAGE_PATH} \
--platform=managed \
--region=${REGION} \
--allow-unauthenticated \
--set-env-vars="SPANNER_INSTANCE_ID=${SPANNER_INSTANCE_ID}" \
--set-env-vars="SPANNER_DATABASE_ID=${SPANNER_DATABASE_ID}" \
--set-env-vars="APP_HOST=0.0.0.0" \
--set-env-vars="APP_PORT=8080" \
--set-env-vars="GOOGLE_CLOUD_LOCATION=${REGION}" \
--set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
--set-env-vars="GOOGLE_MAPS_API_KEY=${GOOGLE_MAPS_API_KEY}" \
--set-env-vars="ORCHESTRATE_AGENT_ID=${ORCHESTRATE_AGENT_ID}" \
--project=${PROJECT_ID} \
--min-instances=1 \
--cpu=2 \
--memory=2Gi
Son dağıtım tamamlandıktan sonra farklı bir tarayıcı sekmesinde InstaVibe uygulama URL'nize gidin.
Tam Yapay Zeka Destekli InstaVibe Deneyimini Test Etme
Vertex AI Agent Engine aracılığıyla düzenlenmiş ve A2A üzerinden iletişim kuran çoklu aracı sistemimiz tarafından desteklenen "InstaVibe Ally" özelliği kullanıma sunuldu.
"InstaVibe Ally"yi tıklayın ve etkinlik planlamasını isteyin.
Temsilciler çalışırken sağdaki etkinlik günlüğünü inceleyin (90-120 saniye sürebilir). Plan göründüğünde inceleyin ve yayınlama işlemine devam etmek için "Bu Planı Onayla"yı tıklayın.
Düzenleyici artık Platform aracısına InstaVibe'da gönderi ve etkinlik oluşturmasını söyleyecek.
Yeni gönderi ve etkinlik için InstaVibe ana sayfasını kontrol edin.
Etkinlik sayfasında, temsilci tarafından oluşturulan ayrıntılar gösterilir.
Cloud Trace ile Performansı Analiz Etme
Bu işlemin biraz zaman aldığını fark edebilirsiniz. Vertex AI Agent Engine, Cloud Trace ile entegre olarak çoklu aracı sistemimizin gecikmesini analiz etmemize olanak tanır.
Google Cloud Console'da İzler'e gidin, Kapsam'da agent_run[orchestrate_agent]
simgesini seçin. Birkaç Kapsam görmeniz gerekir. Kapsam'ı tıklayın.
İzleme ayrıntılarında hangi bölümlerin daha uzun sürdüğünü belirleyebilirsiniz. Örneğin, Planlayıcı aracısına yapılan çağrılarda, arama temellendirmesi ve karmaşık oluşturma nedeniyle daha yüksek gecikme süresi görülebilir.
Benzer şekilde, gönderi ve etkinlik oluştururken Orchestrator'ın verileri işlemek ve Platform temsilcisi için araç çağrıları hazırlamak üzere harcadığı süreyi görebilirsiniz.
Bu izleri incelemek, aracı sisteminizin performansını anlamanıza ve optimize etmenize yardımcı olur.
Tebrikler! Google'ın ADK, A2A, MCP ve Google Cloud hizmetlerini kullanarak gelişmiş bir çoklu aracı yapay zeka sistemi oluşturmayı, dağıtmayı ve test etmeyi başardınız. Aracı düzenleme, araç kullanımı, durum yönetimi ve bulut dağıtımı konularında başarılı bir şekilde ilerleyerek InstaVibe için işlevsel bir yapay zeka destekli özellik oluşturdunuz. Atölyeyi tamamladığınız için tebrik ederiz.
13. Temizleme
Google Cloud hesabınızın sürekli olarak ücretlendirilmesini önlemek için bu atölye çalışması sırasında oluşturduğumuz kaynakları silmeniz önemlidir. Aşağıdaki komutlar, Spanner örneğini, Cloud Run hizmetlerini, Artifact Registry deposunu, API anahtarını, Vertex AI Agent Engine'i ve ilişkili IAM izinlerini kaldırmanıza yardımcı olur.
Önemli:
- Bu komutları, çalıştay için kullanılan Google Cloud projesinde çalıştırdığınızdan emin olun.
- Cloud Shell terminalinizi kapattıysanız $PROJECT_ID, $SPANNER_INSTANCE_ID gibi bazı ortam değişkenleri ayarlanmamış olabilir. Bu öğeleri, atölye kurulumu sırasında yaptığınız gibi yeniden dışa aktarmanız veya aşağıdaki komutlardaki değişkenleri gerçek değerleriyle değiştirmeniz gerekir.
- Bu komutlar, kaynaklarınızı kalıcı olarak siler. Bu projede başka önemli verileriniz varsa çalıştırmadan önce tekrar kontrol edin.
👉💻 Temizleme işlemi için aşağıdaki komut dosyalarını çalıştırın.
Ortam değişkenlerini sıfırlama
. ~/instavibe-bootstrap/set_env.sh
Temsilci Motorunu Silme:
cd ~/instavibe-bootstrap/utils
source ~/instavibe-bootstrap/env/bin/activate
export ORCHESTRATE_AGENT_ID=$(cat ~/instavibe-bootstrap/instavibe/temp_endpoint.txt)
echo "ORCHESTRATE_AGENT_ID set to: ${ORCHESTRATE_AGENT_ID}"
python remote_delete.py
deactivate
echo "Vertex AI Agent Engine deletion initiated."
Cloud Run hizmetlerini silme:
# InstaVibe Web Application
gcloud run services delete instavibe --platform=managed --region=${REGION} --project=${PROJECT_ID} --quiet
# MCP Tool Server
gcloud run services delete mcp-tool-server --platform=managed --region=${REGION} --project=${PROJECT_ID} --quiet
# Planner Agent (A2A Server)
gcloud run services delete planner-agent --platform=managed --region=${REGION} --project=${PROJECT_ID} --quiet
# Platform MCP Client Agent (A2A Server)
gcloud run services delete platform-mcp-client --platform=managed --region=${REGION} --project=${PROJECT_ID} --quiet
# Social Agent (A2A Server)
gcloud run services delete social-agent --platform=managed --region=${REGION} --project=${PROJECT_ID} --quiet
echo "Cloud Run services deletion initiated."
A2A Inspector Docker Kapsayıcısını Durdurma ve Kaldırma
docker rm --force a2a-inspector
Spanner örneğini silme:
echo "Deleting Spanner instance: ${SPANNER_INSTANCE_ID}..."
gcloud spanner instances delete ${SPANNER_INSTANCE_ID} --project=${PROJECT_ID} --quiet
echo "Spanner instance deletion initiated."
Artifact Registry deposunu silme:
echo "Deleting Artifact Registry repository: ${REPO_NAME}..."
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --project=${PROJECT_ID} --quiet
echo "Artifact Registry repository deletion initiated."
Hizmet hesabından rolleri kaldırma:
echo "Removing roles from service account: $SERVICE_ACCOUNT_NAME in project $PROJECT_ID"
# Remove Project-level roles for default service account
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/spanner.admin"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/spanner.databaseUser"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/artifactregistry.admin"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/cloudbuild.builds.editor"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/run.admin"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/iam.serviceAccountUser"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/aiplatform.user"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.logWriter"
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
--role="roles/logging.viewer"
echo "All specified roles have been removed."
Yerel Atölye Dosyalarını Silme:
echo "Removing local workshop directory ~/instavibe-bootstrap..."
rm -rf ~/instavibe-bootstrap
rm -rf ~/a2a-inspector
rm -f ~/mapkey.txt
rm -f ~/project_id.txt
echo "Local directory removed."