Agent2Agent (A2A) Protokolü ile Çalışmaya Başlama: Cloud Run ve Agent Engine'de Satın Alma Asistanı ve Uzaktan Satıcı Temsilcisi Etkileşimleri

1. 📖 Giriş

b013ad6b246401eb.png

Agent2Agent (A2A) protokolü, özellikle harici sistemlerde dağıtılanlar olmak üzere yapay zeka aracıları arasındaki iletişimi standartlaştırmak için tasarlanmıştır. Daha önce, bu tür protokoller Model Context Protocol (MCP) adı verilen Araçlar için oluşturulmuştu. MCP, LLM'leri veriler ve kaynaklarla bağlamak için geliştirilen bir standarttır. A2A, farklı bir soruna odaklanırken MCP'yi tamamlamaya çalışır. MCP, aracıları araçlara ve verilere bağlamak için karmaşıklığı azaltmaya odaklanırken A2A, aracıların doğal yöntemleriyle işbirliği yapmasını nasıl sağlayacağına odaklanır. Bu sayede temsilciler, araç olarak değil temsilci (veya kullanıcı) olarak iletişim kurabilir. Örneğin, bir şey sipariş etmek istediğinizde karşılıklı iletişimi etkinleştirebilirsiniz.

A2A, MCP'yi tamamlayacak şekilde konumlandırılmıştır. Resmi belgelerde, uygulamaların araçlar için MCP'yi, AgentCard ile temsil edilen aracılar için ise A2A'yı kullanması önerilir ( Bunu daha sonra ele alacağız). Ardından, çerçeveler kullanıcıları, uzak aracıları ve diğer aracılarla iletişim kurmak için A2A'yı kullanabilir.

83b1a03588b90b68.png

Bu demoda, Python SDK'sını kullanarak A2A'nın uygulanmasıyla başlayacağız. Siparişimizle ilgilenmek için hamburger ve pizza satıcısı temsilcileriyle iletişim kurmamıza yardımcı olabilecek kişisel bir satın alma danışmanımız olduğunda nasıl bir kullanım durumuyla karşılaşacağımızı inceleyeceğiz.

A2A, istemci-sunucu ilkesini kullanır. Bu eğitimde beklenen tipik A2A akışı aşağıda verilmiştir.

aa6c8bc5b5df73f1.jpeg

  1. A2A istemcisi, önce erişilebilen tüm A2A sunucu aracı kartlarında keşif yapar ve istemci bağlantısı oluşturmak için bu kartlardaki bilgileri kullanır.
  2. Gerektiğinde A2A İstemcisi, A2A Sunucusu'na bir mesaj gönderir. Sunucu bu mesajı tamamlanacak bir Görev olarak değerlendirir. A2A istemcisinde anlık bildirim alıcı URL'si yapılandırılmışsa ve A2A sunucusu tarafından destekleniyorsa sunucu, görev ilerleme durumunu istemcideki alıcı uç noktaya da yayınlayabilir.
  3. Görev tamamlandıktan sonra A2A sunucusu, yanıt yapısını A2A istemcisine gönderir.

Bu codelab'de aşağıdaki gibi adım adım bir yaklaşım kullanacaksınız:

  1. Google Cloud projesini hazırlama
  2. Kodlama ortamı için çalışma dizini ayarlama
  3. Burger aracısını Cloud Run'a dağıtma
  4. Pizza aracısını Cloud Run'a dağıtma
  5. Satın alma danışmanını Agent Engine'e dağıtma
  6. Yerel arayüz üzerinden satın alma danışmanıyla etkileşim kurma

Mimariye Genel Bakış

Aşağıdaki hizmet mimarisini dağıtacaksınız

9cfc4582f2d8b6f3.jpeg

A2A sunucusu olarak işlev görecek 2 hizmet dağıtacaksınız: Burger temsilcisi ( CrewAI temsilci çerçevesi tarafından desteklenir) ve Pizza temsilcisi ( Langgraph temsilci çerçevesi tarafından desteklenir). Kullanıcı yalnızca A2A istemcisi olarak işlev görecek Agent Development Kit (ADK) çerçevesi kullanılarak çalıştırılacak olan Satın Alma temsilcisiyle doğrudan etkileşim kuracak.

Bu aracıların her biri kendi ortamına ve kendi dağıtımına sahip olur.

Ön koşullar

  • Python ile rahatça çalışabilme
  • HTTP hizmetini kullanan temel tam yığın mimarisi hakkında bilgi sahibi olmak

Neler öğreneceksiniz?

  • A2A sunucusunun temel yapısı
  • A2A istemcisinin temel yapısı
  • Aracı hizmetini Cloud Run'a dağıtma
  • Aracı hizmetini Agent Engine'e dağıtma
  • A2A istemcisi, A2A sunucusuna nasıl bağlanır?
  • Akışkan olmayan bağlantıda istek ve yanıt yapısı

Gerekenler

  • Chrome web tarayıcısı
  • Gmail hesabı
  • Faturalandırma hesabı etkinleştirilmiş bir Cloud projesi

Her seviyeden geliştirici (yeni başlayanlar dahil) için tasarlanan bu codelab'de örnek uygulamada Python kullanılmaktadır. Ancak sunulan kavramları anlamak için Python bilgisi gerekmez.

2. 🚀 Atölye Geliştirme Kurulumuna Hazırlanma

1. adım: Cloud Console'da Etkin Proje'yi seçin

Google Cloud Console'daki proje seçici sayfasında bir Google Cloud projesi seçin veya oluşturun (konsolunuzun sol üst bölümüne bakın).

78c981437f90248.png

Bu seçeneği tıkladığınızda, örnekteki gibi tüm projelerinizin listesini görürsünüz.

2f5247dd825b808c.png

Kırmızı kutuyla belirtilen değer PROJE KİMLİĞİ'dir ve bu değer, eğitim boyunca kullanılacaktır.

Cloud projeniz için faturalandırmanın etkinleştirildiğinden emin olun. Bunu kontrol etmek için sol üst çubuğunuzdaki hamburger simgesini ☰ tıklayarak gezinme menüsünü gösterin ve Faturalandırma menüsünü bulun.

db49b5267c00cc33.png

"Google Cloud Platform deneme faturalandırma hesabı bağlı" mesajını görüyorsanız projeniz bu eğitim için kullanılmaya hazırdır. Aksi takdirde, bu eğitimin başına dönün ve faturalandırma hesabını kullanın.

e44b767990aa6aab.png

2. adım: Cloud Shell'i tanıyın

Eğitimlerin büyük bir bölümünde Cloud Shell'i kullanacaksınız. Google Cloud Console'un üst kısmındaki Cloud Shell'i Etkinleştir'i tıklayın. Yetkilendirmeniz istenirse Yetkilendir'i tıklayın.

1829c3759227c19b.png

b8fe7df5c3c2b919.png

Cloud Shell'e bağlandıktan sonra, kabuğun ( veya terminalin) hesabımızla kimliğinin doğrulanıp doğrulanmadığını kontrol etmemiz gerekir.

gcloud auth list

Aşağıdaki örnek çıktıda olduğu gibi kişisel Gmail'inizi görüyorsanız her şey yolundadır.

Credentialed Accounts

ACTIVE: *
ACCOUNT: alvinprayuda@gmail.com

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

Aksi takdirde tarayıcınızı yenilemeyi deneyin ve istendiğinde Yetkilendir'i tıkladığınızdan emin olun ( bağlantı sorunu nedeniyle kesintiye uğrayabilir).

Ardından, terminalde $simgesinden önce ( ) içinde değer olup olmadığını kontrol etmemiz gerekir. Bu değer, etkin kabuk oturumunuz için yapılandırılmış projeyi gösterir. Aşağıdaki ekran görüntüsünde bu değer "a2a-agent-engine"'dir.

fadd80f0da3b906.png

Gösterilen değer zaten doğruysa sonraki komutu atlayabilirsiniz. Ancak doğru değilse veya eksikse aşağıdaki komutu çalıştırın.

gcloud config set project <YOUR_PROJECT_ID>

Ardından, bu codelab için şablon çalışma dizinini GitHub'dan klonlayın ve aşağıdaki komutu çalıştırın. Çalışma dizini, purchasing-concierge-a2a dizininde oluşturulur.

git clone https://github.com/alphinside/purchasing-concierge-intro-a2a-codelab-starter.git purchasing-concierge-a2a

3. adım: Cloud Shell Editor'a alışın ve uygulama çalışma dizinini ayarlayın

Şimdi kod düzenleyicimizi bazı kodlama işlemleri yapacak şekilde ayarlayabiliriz. Bu işlem için Cloud Shell Düzenleyici'yi kullanacağız.

Open Editor (Düzenleyiciyi Aç) düğmesini tıklayın. Bu işlem, Cloud Shell Düzenleyici'yi açar. b16d56e4979ec951.png

Ardından Cloud Shell Düzenleyici'nin üst bölümüne gidip File->Open Folder'ı (Dosya->Klasör Aç) tıklayın, username (kullanıcı adı) dizininizi ve purchasing-concierge-a2a dizinini bulup Tamam düğmesini tıklayın. Bu işlem, seçilen dizini ana çalışma dizini yapar. Bu örnekte, kullanıcı adı alvinprayuda olduğundan dizin yolu aşağıda gösterilmiştir.

2c53696f81d805cc.png

253b472fa1bd752e.png

Cloud Shell Düzenleyiciniz artık aşağıdaki gibi görünmelidir.

aedd0725db87717e.png

Şimdi düzenleyicinin terminalini açın. Menü çubuğunda Terminal -> New Terminal'ı tıklayarak veya Ctrl + Üst Karakter + C kısayolunu kullanarak yapabilirsiniz. Bu kısayol, tarayıcının alt kısmında bir terminal penceresi açar.

f8457daf0bed059e.jpeg

Mevcut etkin terminaliniz purchasing-concierge-a2a çalışma dizininde olmalıdır. Bu codelab'de Python 3.12'yi kullanacağız. Python sürümü ve sanal ortam oluşturma ve yönetme ihtiyacını basitleştirmek için uv python proje yöneticisini kullanacağız. Bu uv paketi, Cloud Shell'e önceden yüklenmiştir.

.venv dizinindeki sanal ortama gerekli bağımlılıkları yüklemek için bu komutu çalıştırın.

uv sync --frozen

Bu eğitim için bildirilen bağımlılıkları (a2a-sdk, google-adk, and gradio) görmek üzere pyproject.toml dosyasını kontrol edin.

Şimdi de aşağıdaki komutu kullanarak gerekli API'leri etkinleştirmemiz gerekiyor. Bu işlem biraz zaman alabilir.

gcloud services enable aiplatform.googleapis.com \
                       run.googleapis.com \
                       cloudbuild.googleapis.com \
                       cloudresourcemanager.googleapis.com

Komut başarıyla yürütüldüğünde aşağıda gösterilene benzer bir mesaj görürsünüz:

Operation "operations/..." finished successfully.

3. 🚀 A2A Server Remote Seller Agents'ı Cloud Run'a dağıtma

Bu adımda, kırmızı kutuyla işaretlenmiş bu iki uzaktan satıcı aracısını dağıtacağız. Hamburger temsilcisi, CrewAI temsilci çerçevesi tarafından desteklenir. Pizza temsilcisi ise Langgraph temsilcisi tarafından desteklenir.

e91777eecfbae4f7.png

4. 🚀 Burger Satıcısı Aracısı'nı dağıtma - A2A Sunucusu

Burger aracısının kaynak kodu, remote_seller_agents/burger_agent dizinindedir.

remote_seller_agents/burger_agent dizininde bulunan tüm dosyalar, aracımızı Cloud Run'a dağıtmak için yeterlidir. Böylece aracımıza hizmet olarak erişilebilir. Dağıtmak için aşağıdaki komutu çalıştırın:

gcloud run deploy burger-agent \
    --source remote_seller_agents/burger_agent \
    --port=8080 \
    --allow-unauthenticated \
    --min 1 \
    --region us-central1 \
    --update-env-vars GOOGLE_CLOUD_LOCATION=us-central1 \
    --update-env-vars GOOGLE_CLOUD_PROJECT={your-project-id}

Kaynak koddan dağıtım için bir container deposu oluşturulacağı sorulursa Y yanıtını verin. Başarılı dağıtımın ardından aşağıdaki gibi bir günlük gösterilir.

Service [burger-agent] revision [burger-agent-xxxxx-xxx] has been deployed and is serving 100 percent of traffic.
Service URL: https://burger-agent-xxxxxxxxx.us-central1.run.app

Buradaki xxxx kısmı, hizmeti kullanıma sunduğumuzda benzersiz bir tanımlayıcı olacaktır.

Yeni bir tarayıcı sekmesi açın ve tarayıcı üzerinden dağıtılan bu burger aracısı hizmetlerinin https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json rotasına gidin. Bu, dağıtılan A2A sunucu aracısı kartına erişmek için kullanılan URL'dir.

Başarıyla dağıtıldıysa aracı kartına erişirken tarayıcınızda aşağıdaki gibi bir yanıt görürsünüz.

72fdf3f52b5e8313.png

Bu, keşif amacıyla erişilebilir olması gereken burger temsilcisi kartı bilgileridir.

url değerinin burada hâlâ http://0.0.0.0:8080/ olarak ayarlandığını unutmayın. Bu url değeri, A2A istemcisinin dış dünyadan mesaj göndermesi için gereken temel bilgidir ve düzgün şekilde yapılandırılmamıştır.

Ek bir ortam değişkeni HOST_OVERRIDE ekleyerek bu değeri burger aracısı hizmetimizin URL'siyle güncellememiz gerekiyor.

Ortam değişkeni aracılığıyla temsilci kartındaki Burger Agent URL değerini güncelleme

Burger aracısı hizmetine HOST_OVERRIDE eklemek için aşağıdaki adımları uygulayın.

  1. Cloud Console'unuzun üst kısmındaki arama çubuğunda Cloud Run'ı arayın.

1adde569bb345b48.png

  1. Daha önce dağıtılan burger-agent Cloud Run hizmetini tıklayın.

9091c12526fb7f41.png

  1. Burger hizmeti URL'sini kopyalayın, ardından Yeni düzeltmeyi düzenle ve dağıt'ı tıklayın.

2701da8b124793b9.png

  1. Ardından Değişkenler ve Gizli Anahtarlar bölümünü tıklayın.

31ea00e12134d74d.png

  1. Ardından Değişken ekle'yi tıklayın ve HOST_OVERRIDE değerini hizmet URL'si ( https://burger-agent-xxxxxxxxx.us-central1.run.app kalıbına sahip olan) olarak ayarlayın.

52b382da7cf33cd5.png

  1. Son olarak, hizmetinizi yeniden dağıtmak için dağıt düğmesini tıklayın.

11464f4a51ffe54.png

Tarayıcıda https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json burger-agent aracı kartına tekrar eriştiğinizde url değeri doğru şekilde yapılandırılmış olur.

2ed7ebcb530f070a.png

5. 🚀 Pizza Satıcısı Aracısı - A2A Sunucusu dağıtma

Benzer şekilde, pizza aracısı kaynak kodu remote_seller_agents/pizza_agent dizinindedir.

Önceki burger-agent dağıtım adımına benzer şekilde, remote_seller_agents/pizza_agent dizininde bulunan tüm dosyalar, aracımızı Cloud Run'a dağıtmak için yeterlidir. Böylece aracımıza hizmet olarak erişilebilir. Dağıtmak için aşağıdaki komutu çalıştırın:

gcloud run deploy pizza-agent \
    --source remote_seller_agents/pizza_agent \
    --port=8080 \
    --allow-unauthenticated \
    --min 1 \
    --region us-central1 \
    --update-env-vars GOOGLE_CLOUD_LOCATION=us-central1 \
    --update-env-vars GOOGLE_CLOUD_PROJECT={your-project-id}

Başarılı dağıtımın ardından aşağıdaki gibi bir günlük gösterilir.

Service [pizza-agent] revision [pizza-agent-xxxxx-xxx] has been deployed and is serving 100 percent of traffic.
Service URL: https://pizza-agent-xxxxxxxxx.us-central1.run.app

Buradaki xxxx kısmı, hizmeti kullanıma sunduğumuzda benzersiz bir tanımlayıcı olacaktır.

A2A sunucu aracısı kartına erişmek için tarayıcı üzerinden dağıtılan pizza aracısı hizmetlerinin https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json rotasına gitmeye çalıştığınızda burger aracısında da aynı durum söz konusudur. Pizza aracısının, aracısı kartındaki url değeri henüz düzgün şekilde yapılandırılmamıştır. Ayrıca, ortam değişkenine HOST_OVERRIDE eklememiz gerekiyor.

Ortam değişkeni aracılığıyla temsilci kartındaki Pizza Temsilcisi URL değerini güncelleme

Pizza aracısı hizmetine HOST_OVERRIDE eklemek için aşağıdaki adımları uygulayın.

  1. Cloud Console'unuzun üst kısmındaki arama çubuğunda Cloud Run'ı arayın.

1adde569bb345b48.png

  1. Daha önce dağıtılan pizza-agent Cloud Run hizmetini tıklayın.

5743b0aa0555741f.png

  1. Yeni düzeltmeyi düzenle ve dağıt'ı tıklayın.

d60ba267410183be.png

  1. Pizza servisi URL'sini kopyalayın, ardından Variable & Secrets (Değişken ve Gizli Dizeler) bölümünü tıklayın.

618e9da2f94ed415.png

  1. Ardından Değişken ekle'yi tıklayın ve HOST_OVERRIDE değerini hizmet URL'si ( https://pizza-agent-xxxxxxxxx.us-central1.run.app kalıbına sahip olan) olarak ayarlayın.

214a6eb98f877e65.png

  1. Son olarak, hizmetinizi yeniden dağıtmak için dağıt düğmesini tıklayın.

11464f4a51ffe54.png

Artık tarayıcıda pizza-agent aracı kartına tekrar eriştiğinizde https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json değeri doğru şekilde yapılandırılmış olacak.url

c37b26ec80c821b6.png

Bu noktada, hem hamburger hem de pizza hizmetlerini Cloud Run'a başarıyla dağıtmış oluyoruz.

6. 🚀 Satın Alma Asistanı - A2A İstemcisini Agent Engine'e dağıtma

Bu adımda, satın alma danışmanı aracısını dağıtacağız. Etkileşim kuracağımız temsilci budur.

c4a8e7a3d18b1ef.png

Satın alma concierge aracımızın kaynak kodu, purchasing_concierge dizinindedir. Aracı başlatma işlemi, purchasing_concierge/purchasing_agent.py komut dosyasında incelenebilir.

Dağıtmak için aşağıdaki adımları uygulayın :

  1. Öncelikle Cloud Storage'da hazırlama depolama alanımızı oluşturmamız gerekiyor.
gcloud storage buckets create gs://purchasing-concierge-{your-project-id} --location=us-central1
  1. Şimdi önce .env değişkenini hazırlamamız gerekiyor. .env.example dosyasını .env dosyasına kopyalayalım.
cp .env.example .env
  1. Şimdi .env dosyasını açın. Aşağıdaki içeriği görürsünüz.
GOOGLE_GENAI_USE_VERTEXAI=TRUE
GOOGLE_CLOUD_PROJECT={your-project-id}
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://purchasing-concierge-{your-project-id}
PIZZA_SELLER_AGENT_URL={your-pizza-agent-url}
BURGER_SELLER_AGENT_URL={your-burger-agent-url}
AGENT_ENGINE_RESOURCE_NAME={your-agent-engine-resource-name}

Bu temsilci, hamburger ve pizza temsilcisiyle iletişim kuracağından her ikisi için de uygun kimlik bilgilerini sağlamamız gerekir. PIZZA_SELLER_AGENT_URL ve BURGER_SELLER_AGENT_URL parametrelerini önceki adımlardaki Cloud Run URL'siyle güncellememiz gerekir.

Bunu unutursanız Cloud Run Console'u ziyaret edin. Konsolunuzun üst kısmındaki arama çubuğuna "Cloud Run" yazın ve Cloud Run simgesini sağ tıklayarak yeni bir sekmede açın.

1adde569bb345b48.png

Daha önce dağıtılan uzaktan satıcı aracısı hizmetlerimizi aşağıda gösterildiği gibi görmelisiniz.

179e55cc095723a8.png

Bu hizmetlerin herkese açık URL'sini görmek için hizmetlerden birini tıkladığınızda Hizmet ayrıntıları sayfasına yönlendirilirsiniz. URL'yi, bölge bilgilerinin hemen yanındaki üst alanda görebilirsiniz.

64c01403a92b1107.png

Son ortam değişkeni aşağıdaki gibi görünmelidir.

GOOGLE_GENAI_USE_VERTEXAI=TRUE
GOOGLE_CLOUD_PROJECT={your-project-id}
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://purchasing-concierge-{your-project-id}
PIZZA_SELLER_AGENT_URL=https://pizza-agent-xxxxx.us-central1.run.app
BURGER_SELLER_AGENT_URL=https://burger-agent-xxxxx.us-central1.run.app
AGENT_ENGINE_RESOURCE_NAME={your-agent-engine-resource-name}
  1. Artık satın alma danışmanı temsilcimizi dağıtmaya hazırız. Bu kodu aracı motoruna dağıtırız ve dağıtım kodu deploy_to_agent_engine.py komut dosyasının içindedir.

Komut dosyasını çalıştırarak dağıtabiliriz:

uv run deploy_to_agent_engine.py

Başarılı dağıtımın ardından aşağıdaki gibi bir günlük gösterilir. Bu işlem, Agent Engine kaynak adını "projects/xxxx/locations/us-central1/reasoningEngines/yyyy" olarak gösterir.

AgentEngine created. Resource name: projects/xxxx/locations/us-central1/reasoningEngines/yyyy
To use this AgentEngine in another session:
agent_engine = vertexai.agent_engines.get('projects/xxxx/locations/us-central1/reasoningEngines/yyyy)
Deployed remote app resource: projects/xxxx/locations/us-central1/reasoningEngines/xxxx

Ayrıca, arama motoru kontrol panelinde incelediğimizde (arama çubuğunda "arama motoru" ifadesini arayın) önceki dağıtımımız gösterilir.

e80f1c00ec9fbb38.png

Ayrıca, Agent Engine kaynak adının orada gösterildiğini de inceleyebilirsiniz. Ardından, bu kaynak adını kullanarak test edebiliriz.

Ardından, .env dosyasındaki AGENT_ENGINE_RESOURCE_NAME değerini bu değerle güncelleyin. Doğru aracı motoru kaynak adını sağladığınızdan emin olun. .env dosyanız şu şekilde görünmelidir:

GOOGLE_GENAI_USE_VERTEXAI=TRUE
GOOGLE_CLOUD_PROJECT={your-project-id}
GOOGLE_CLOUD_LOCATION=us-central1
STAGING_BUCKET=gs://purchasing-concierge-{your-project-id}
PIZZA_SELLER_AGENT_URL=https://pizza-agent-xxxxx.us-central1.run.app
BURGER_SELLER_AGENT_URL=https://burger-agent-xxxxx.us-central1.run.app
AGENT_ENGINE_RESOURCE_NAME=projects/xxxx/locations/us-central1/reasoningEngines/yyyy

Dağıtılan Aracıyı Agent Engine'de Test Etme

Aracı motoruyla etkileşim, curl komutu ve SDK aracılığıyla yapılabilir. Örneğin, dağıtılan temsilciyle etkileşim kurmayı denemek için aşağıdaki komutu çalıştırın.

Temsilcinin başarıyla dağıtılıp dağıtılmadığını kontrol etmek için bu sorguyu göndermeyi deneyebilirsiniz. Aşağıdaki test_agent_engine.sh komut dosyasını çalıştırın

bash test_agent_engine.sh

Komut dosyasını inceleyebilir ve "Lütfen mevcut hamburger menüsünü listele" istemini aracıya göndermeye çalıştığımızı görebilirsiniz.

Başarılı olursa konsolunuzda aşağıdaki gibi birkaç yanıt etkinliği yayınlanır.

{
  "content": {
    "parts": [
      {
        "text": "Here is our burger menu:\n- Classic Cheeseburger: IDR 85K\n- Double Cheeseburger: IDR 110K\n- Spicy Chicken Burger: IDR 80K\n- Spicy Cajun Burger: IDR 85K"
      }
    ],
    "role": "model"
  },
  "usage_metadata": {
    "candidates_token_count": 51,
    "candidates_tokens_details": [
      {
        "modality": "TEXT",
        "token_count": 51
      }
    ],
    "prompt_token_count": 907,
    "prompt_tokens_details": [
      {
        "modality": "TEXT",
        "token_count": 907
      }
    ],
    "total_token_count": 958,
    "traffic_type": "ON_DEMAND"
  },
  "invocation_id": "e-14679918-af68-45f1-b942-cf014368a733",
  "author": "purchasing_agent",
  "actions": {
    "state_delta": {},
    "artifact_delta": {},
    "requested_auth_configs": {}
  },
  "id": "dbe7fc43-b82a-4f3e-82aa-dd97afa8f15b",
  "timestamp": 1754287348.941454
}

Bir sonraki adımda kullanıcı arayüzünü kullanmayı deneyeceğiz ancak öncelikle A2A istemcilerinin temel bileşenleri ve tipik akışı hakkında konuşalım.

7. 🚀 Entegrasyon testi ve yük incelemesi

Şimdi de web kullanıcı arayüzünü kullanarak uzaktan temsilci etkileşimiyle satın alma asistanımızı inceleyelim. Gradio uygulamasını dağıtmak için aşağıdaki komutu çalıştırın. Bu uygulamayı çalıştırmak için .env dosyasını doğru şekilde doldurmuş olmanız gerekir.

uv run purchasing_concierge_ui.py

İşlem başarılı olursa aşağıdaki çıkış gösterilir.

* Running on local URL:  http://0.0.0.0:8080
* To create a public link, set `share=True` in `launch()`.

Ardından, terminalde http://0.0.0.0:8080 URL'sini Ctrl + tıklayın veya web kullanıcı arayüzünü açmak için web önizleme düğmesini tıklayın.

b38b428d9e4582bc.png

Şu şekilde bir görüşme yapmayı deneyin :

  • Bana burger ve pizza menüsünü göster
  • 1 adet barbekü soslu tavuklu pizza ve 1 adet acı baharatlı Cajun burger sipariş etmek istiyorum.

Siparişi tamamlayana kadar sohbete devam edin. Etkileşimin nasıl ilerlediğini, araç çağrısının ve yanıtının ne olduğunu inceleyin. Aşağıdaki resimde, etkileşim sonucuna dair bir örnek verilmiştir.

ff5f752965816b2b.png

6f65155c7a289964.png

b390f4b15f1c5a8c.png

ff44c54b50c36e1a.png

2 farklı temsilciyle iletişim kurmanın 2 farklı davranışa yol açtığını ve A2A'nın bunu iyi bir şekilde ele alabildiğini görüyoruz. Pizza satıcısı temsilcisi, satın alma temsilcisi isteğimizi doğrudan kabul ederken burger temsilcisinin isteğimizle devam etmeden önce onayımızı alması gerekir. Onayımızı aldıktan sonra temsilci, burger temsilcisine onayımızı iletebilir.

Şimdi A2A'nın temel kavramlarını tamamladık ve bunun istemci ve sunucu mimarisi olarak nasıl uygulandığını görelim.

8. 💡 [Kod Açıklaması] A2A Sunucu Kavramı ve Uygulaması

Uzaktan satıcı aracısı başlatma işlemi, remote_seller_agents/*/agent.py komut dosyasında incelenebilir. Satıcı temsilcilerinin kod snippet'i aşağıda verilmiştir.

Burger Agent

from crewai import Agent, Crew, LLM, Task, Process
from crewai.tools import tool

...

       model = LLM(
            model="vertex_ai/gemini-2.5-flash-lite",  # Use base model name without provider prefix
        )
        burger_agent = Agent(
            role="Burger Seller Agent",
            goal=(
                "Help user to understand what is available on burger menu and price also handle order creation."
            ),
            backstory=("You are an expert and helpful burger seller agent."),
            verbose=False,
            allow_delegation=False,
            tools=[create_burger_order],
            llm=model,
        )

        agent_task = Task(
            description=self.TaskInstruction,
            agent=burger_agent,
            expected_output="Response to the user in friendly and helpful manner",
        )

        crew = Crew(
            tasks=[agent_task],
            agents=[burger_agent],
            verbose=False,
            process=Process.sequential,
        )

        inputs = {"user_prompt": query, "session_id": sessionId}
        response = crew.kickoff(inputs)
        return response

...

Pizza Agent

from langchain_google_vertexai import ChatVertexAI
from langgraph.prebuilt import create_react_agent

...

self.model = ChatVertexAI(
    model="gemini-2.5-flash-lite",
    location=os.getenv("GOOGLE_CLOUD_LOCATION"),
    project=os.getenv("GOOGLE_CLOUD_PROJECT"),
)
self.tools = [create_pizza_order]
self.graph = create_react_agent(
    self.model,
    tools=self.tools,
    checkpointer=memory,
    prompt=self.SYSTEM_INSTRUCTION,
)

...

Gördüğünüz gibi bu 2 aracı, istemci aracına ( ADK) kıyasla tamamen farklı çerçevelerle ( CrewAI ve Langgraph) oluşturulmuştur. A2A ile bu bir sorun değildir. Birbirleriyle iletişim kurmaları için dahili kodlarını paylaşmaları gerekmez. Hangi çerçevelerin kullanıldığı, hangi dilin kullanıldığı veya nereye dağıtıldıkları önemli değildir.

A2A Sunucusunun Temel Bileşenleri

Şimdi de A2A sunucusunun temel kavramını ve bileşenlerini ele alalım.

Aracı kartı

Her A2A sunucusunda, /.well-known/agent.json kaynağında erişilebilen bir aracı kartı olmalıdır. Bu, A2A istemcisindeki keşif aşamasını desteklemek için yapılır. Bu aşamada, aracıya nasıl erişileceği ve tüm özelliklerinin nasıl kullanılacağı hakkında eksiksiz bilgi ve bağlamlar sağlanır. Swagger veya Postman kullanılarak iyi belgelenmiş API belgelerine benzer.

Bu, dağıtılan burger agent agent kartımızın içeriğidir.

{
  "capabilities": {
    "streaming": true
  },
  "defaultInputModes": [
    "text",
    "text/plain"
  ],
  "defaultOutputModes": [
    "text",
    "text/plain"
  ],
  "description": "Helps with creating burger orders",
  "name": "burger_seller_agent",
  "protocolVersion": "0.2.6",
  "skills": [
    {
      "description": "Helps with creating burger orders",
      "examples": [
        "I want to order 2 classic cheeseburgers"
      ],
      "id": "create_burger_order",
      "name": "Burger Order Creation Tool",
      "tags": [
        "burger order creation"
      ]
    }
  ],
  "url": "https://burger-agent-109790610330.us-central1.run.app",
  "version": "1.0.0"
}

Bu aracı kartlarında; aracı becerileri, yayın özellikleri, desteklenen yöntemler ve protokol sürümü gibi birçok önemli bileşen öne çıkarılır.

Tüm bu bilgiler, A2A istemcisinin düzgün iletişim kurabilmesi için uygun bir iletişim mekanizması geliştirmek amacıyla kullanılabilir. Desteklenen yöntem ve kimlik doğrulama mekanizması, iletişimin düzgün şekilde kurulabilmesini sağlar. Ayrıca, istemcinin temsilcisine çağrılacak uzak temsilci özellikleri ve becerileri hakkında bağlam bilgisi vermek için temsilci skills bilgileri A2A istemci sistemi istemine yerleştirilebilir. Bu temsilci kartıyla ilgili daha ayrıntılı alanları bu dokümanda bulabilirsiniz.

Kodumuzda, aracı kartının uygulanması A2A Python SDK'sı kullanılarak gerçekleştirilir. Uygulama için aşağıdaki remote_seller_agents/burger_agent/main.py snippet'ini inceleyin.

...

        capabilities = AgentCapabilities(streaming=True)
        skill = AgentSkill(
            id="create_burger_order",
            name="Burger Order Creation Tool",
            description="Helps with creating burger orders",
            tags=["burger order creation"],
            examples=["I want to order 2 classic cheeseburgers"],
        )
        agent_host_url = (
            os.getenv("HOST_OVERRIDE")
            if os.getenv("HOST_OVERRIDE")
            else f"http://{host}:{port}/"
        )
        agent_card = AgentCard(
            name="burger_seller_agent",
            description="Helps with creating burger orders",
            url=agent_host_url,
            version="1.0.0",
            defaultInputModes=BurgerSellerAgent.SUPPORTED_CONTENT_TYPES,
            defaultOutputModes=BurgerSellerAgent.SUPPORTED_CONTENT_TYPES,
            capabilities=capabilities,
            skills=[skill],
        )

...

Burada şu gibi çeşitli alanlar görebiliriz:

  1. AgentCapabilities : Temsilci hizmeti tarafından desteklenen,akış ve/veya push bildirimi desteği gibi ek isteğe bağlı işlevlerin beyanı
  2. AgentSkill : Temsilci tarafından desteklenen araçlar veya işlevler
  3. Input/OutputModes : Desteklenen giriş/çıkış türü modalitesi
  4. Url : Temsilciyle iletişim kurulacak adres

Bu yapılandırmada, yerel test ile bulut dağıtımı arasında geçişi kolaylaştırmak için dinamik aracı ana makine URL'si oluşturma özelliği sunuyoruz. Bu nedenle, önceki adımda HOST_OVERRIDE değişkenini eklememiz gerekiyor.

Görev sırası ve aracı yürütücü

A2A sunucusu, farklı aracıların veya kullanıcıların isteklerini işleyebilir ve her görevi mükemmel bir şekilde izole edebilir. Bunların bağlamlarını daha iyi görselleştirmek için aşağıdaki resmi inceleyebilirsiniz.

b9eb6b4025db4642.jpeg

Bu nedenle, her A2A sunucusu gelen görevleri izleyebilmeli ve görevle ilgili uygun bilgileri saklayabilmelidir. A2A SDK, A2A sunucusunda bu zorluğun üstesinden gelmek için modüller sağlar. İlk olarak, gelen isteği nasıl işlemek istediğimize dair mantık oluşturabiliriz. AgentExecutor soyut sınıfını devralarak görev yürütme ve iptal işlemlerini nasıl yönetmek istediğimizi kontrol edebiliriz. Bu örnek uygulama, remote_seller_agents/burger_agent/agent_executor.py modülünde ( pizza satıcısı örneğinde benzer bir yol) incelenebilir.

...

class BurgerSellerAgentExecutor(AgentExecutor):
    """Burger Seller AgentExecutor."""

    def __init__(self):
        self.agent = BurgerSellerAgent()

    async def execute(
        self,
        context: RequestContext,
        event_queue: EventQueue,
    ) -> None:
        query = context.get_user_input()
        try:
            result = self.agent.invoke(query, context.context_id)
            print(f"Final Result ===> {result}")

            parts = [Part(root=TextPart(text=str(result)))]
            await event_queue.enqueue_event(
                completed_task(
                    context.task_id,
                    context.context_id,
                    [new_artifact(parts, f"burger_{context.task_id}")],
                    [context.message],
                )
            )
        except Exception as e:
            print("Error invoking agent: %s", e)
            raise ServerError(error=ValueError(f"Error invoking agent: {e}")) from e

    async def cancel(
        self, request: RequestContext, event_queue: EventQueue
    ) -> Task | None:
        raise ServerError(error=UnsupportedOperationError())

...

Yukarıdaki kodda, istek geldiğinde aracının doğrudan çağrılacağı ve çağrıyı tamamladıktan sonra tamamlanan görev etkinliklerini göndereceği temel bir işleme şeması uyguluyoruz. Ancak kısa süreli bir işlem olarak değerlendirildiği için burada iptal yöntemi uygulanmadı.

Yürütücüyü oluşturduktan sonra, HTTP sunucusunu başlatmak için yerleşik DefaultRequestHandler, InMemoryTaskStore ve A2AStarletteApplication'ı doğrudan kullanabiliriz. Bu uygulama remote_seller_agents/burger_agent/__main__.py içinde incelenebilir.

...

        request_handler = DefaultRequestHandler(
            agent_executor=BurgerSellerAgentExecutor(),
            task_store=InMemoryTaskStore(),
        )
        server = A2AStarletteApplication(
            agent_card=agent_card, http_handler=request_handler
        )

        uvicorn.run(server.build(), host=host, port=port)

...

Bu modül, /.well-known/agent.json aracının kartına erişim rotasının ve A2A protokolünü destekleyen POST uç noktasının uygulanmasını sağlar.

Özet

Kısacası, şu ana kadar aşağıdaki 2 işlevi destekleyebilen Python SDK'sını kullanarak bir A2A sunucusu dağıttık:

  1. Temsilci kartını /.well-known/agent.json rotasında yayınlama
  2. JSON-RPC isteğini bellek içi görev sırasına alma ile işleme

Bu işlevlerin başlatılmasındaki giriş noktası, __main__.py komut dosyasında ( remote_seller_agents/burger_agent veya remote_seller_agents/pizza_agent üzerinde) incelenebilir.

9. 💡 [Kod Açıklaması] Agent Engine Dağıtımı

purchasing_concierge/purchasing_agent.py: dosyasındaki satın alma yardımcısı aracısının kod snippet'i aşağıda verilmiştir:

from google.adk import Agent

...

def create_agent(self) -> Agent:
        return Agent(
            model="gemini-2.5-flash-lite",
            name="purchasing_agent",
            instruction=self.root_instruction,
            before_model_callback=self.before_model_callback,
            before_agent_callback=self.before_agent_callback,
            description=(
                "This purchasing agent orchestrates the decomposition of the user purchase request into"
                " tasks that can be performed by the seller agents."
            ),
            tools=[
                self.send_task,
            ],
        )

...

Bu aracı, ADK kullanılarak oluşturulur ve Agent Engine'e dağıtılır.

Vertex AI Agent Engine, geliştiricilerin üretimde yapay zeka aracılarını dağıtmasına, yönetmesine ve ölçeklendirmesine olanak tanıyan bir hizmetler kümesidir. Üretimde aracıları ölçeklendirmek için altyapıyı yönetir. Böylece biz de uygulama oluşturmaya odaklanabiliriz. Bu konu hakkında daha fazla bilgiyi bu belgede bulabilirsiniz. Daha önce aracı hizmetimizi dağıtmak için gereken dosyaları (ör. ana sunucu komut dosyası ve Dockerfile) hazırlamamız gerekiyordu. Bu durumda, ADK ve Agent Engine'i birlikte kullanarak kendi arka uç hizmetimizi geliştirmemize gerek kalmadan aracımızı doğrudan Python komut dosyasından dağıtabiliriz.

Bu eğitimde, içeriği aşağıda gösterilen deploy_to_agent_engine.py komut dosyasını kullanarak dağıtım yapacağız.

import vertexai
from vertexai.preview import reasoning_engines
from vertexai import agent_engines
from dotenv import load_dotenv
import os
from purchasing_concierge.agent import root_agent

load_dotenv()

PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
LOCATION = os.getenv("GOOGLE_CLOUD_LOCATION")
STAGING_BUCKET = os.getenv("STAGING_BUCKET")

vertexai.init(
    project=PROJECT_ID,
    location=LOCATION,
    staging_bucket=STAGING_BUCKET,
)

adk_app = reasoning_engines.AdkApp(
    agent=root_agent,
)

remote_app = agent_engines.create(
    agent_engine=adk_app,
    display_name="purchasing-concierge",
    requirements=[
        "google-cloud-aiplatform[adk,agent_engines]",
        "a2a-sdk==0.2.16",
    ],
    extra_packages=[
        "./purchasing_concierge",
    ],
    env_vars={
        "GOOGLE_GENAI_USE_VERTEXAI": os.environ["GOOGLE_GENAI_USE_VERTEXAI"],
        "PIZZA_SELLER_AGENT_URL": os.environ["PIZZA_SELLER_AGENT_URL"],
        "BURGER_SELLER_AGENT_URL": os.environ["BURGER_SELLER_AGENT_URL"],
    },
)

print(f"Deployed remote app resource: {remote_app.resource_name}")

Bu, ADK aracımızı aracı motoruna dağıtmak için gereken adımlardır. Öncelikle ADK'mızdan AdkApp nesnesi oluşturmamız gerekir root_agent. Ardından, agent_engines.create yöntemini adk_app nesnesini sağlayarak, requirements alanında gereksinimleri belirterek, extra_packages alanında aracı dizini yolunu belirterek ( gerekirse burada başka dizinler ve dosyalar da sağlayabilirsiniz) ve gerekli ortam değişkenlerini sağlayarak çalıştırabiliriz.

10. 💡 [Kod Açıklaması] A2A Client Concept and Implementation

aa6c8bc5b5df73f1.jpeg

Yukarıda gösterilen resimde, A2A etkileşimlerinin tipik akışı gösterilmektedir:

  1. İstemci, rotadaki sağlanan uzak aracı URL'sinde yayınlanmış bir aracı kartı bulmaya çalışır /.well-known/agent.json
  2. Ardından, gerektiğinde bu aracıya ileti ve gerekli meta veri parametreleriyle ( ör. oturum kimliği, geçmiş bağlam vb.) bir mesaj gönderir. Sunucu bu mesajı tamamlanması gereken bir görev olarak algılar.
  3. A2A sunucusu isteği işler. Sunucu push bildirimlerini destekliyorsa görev işleme sırasında bazı bildirimleri de yayınlayabilir ( Bu işlev, bu codelab'in kapsamı dışındadır).
  4. İşlem tamamlandıktan sonra A2A sunucusu yanıt yapısını istemciye geri gönderir.

Yukarıdaki etkileşimlerle ilgili temel nesnelerden bazıları şunlardır (daha fazla bilgiyi burada bulabilirsiniz) :

  • Mesaj: İstemci ile uzak aracı arasındaki iletişim dönüşü
  • Görev: A2A tarafından yönetilen ve benzersiz bir kimlikle tanımlanan temel iş birimi
  • Öğe: Temsilci tarafından bir görev sonucunda oluşturulan ve Bölümlerden oluşan bir çıktı (ör. belge, resim, yapılandırılmış veri)
  • Bölüm: İleti veya Yapılandırma Öğesi içindeki en küçük içerik birimi. Bölüm; metin, resim, video, dosya vb. olabilir.

Kart Keşfi

A2A Client hizmeti başlatıldığında, genellikle aracı kartı bilgilerini almaya ve gerektiğinde kolayca erişmek için depolamaya çalışılır. Bu codelab'de before_agent_callback üzerinde uyguluyoruz. Uygulamayı purchasing_concierge/purchasing_agent.py adresinde görebilirsiniz. Aşağıdaki kod snippet'ine bakın.

...

async def before_agent_callback(self, callback_context: CallbackContext):
        if not self.a2a_client_init_status:
            httpx_client = httpx.AsyncClient(timeout=httpx.Timeout(timeout=30))
            for address in self.remote_agent_addresses:
                card_resolver = A2ACardResolver(
                    base_url=address, httpx_client=httpx_client
                )
                try:
                    card = await card_resolver.get_agent_card()
                    remote_connection = RemoteAgentConnections(
                        agent_card=card, agent_url=card.url
                    )
                    self.remote_agent_connections[card.name] = remote_connection
                    self.cards[card.name] = card
                except httpx.ConnectError:
                    print(f"ERROR: Failed to get agent card from : {address}")
            agent_info = []
            for ra in self.list_remote_agents():
                agent_info.append(json.dumps(ra))
            self.agents = "\n".join(agent_info)

...

Burada, yerleşik A2A istemci A2ACardResolver modülünü kullanarak mevcut tüm temsilci kartlarına erişmeye çalışırız. Ardından, temsilciye mesaj göndermek için gereken bağlantıyı toplarız. Bundan sonra, mevcut tüm temsilcileri ve özelliklerini isteme listelememiz gerekir. Böylece temsilcimiz, bu temsilcilerle iletişim kurabileceğini bilir.

İstem ve Görev Gönderme Aracı

Bu, ADK temsilcimize sağladığımız istem ve araçtır.

...

def root_instruction(self, context: ReadonlyContext) -> str:
    current_agent = self.check_active_agent(context)
    return f"""You are an expert purchasing delegator that can delegate the user product inquiry and purchase request to the
appropriate seller remote agents.

Execution:
- For actionable tasks, you can use `send_task` to assign tasks to remote agents to perform.
- When the remote agent is repeatedly asking for user confirmation, assume that the remote agent doesn't have access to user's conversation context. 
So improve the task description to include all the necessary information related to that agent
- Never ask user permission when you want to connect with remote agents. If you need to make connection with multiple remote agents, directly
connect with them without asking user permission or asking user preference
- Always show the detailed response information from the seller agent and propagate it properly to the user. 
- If the remote seller is asking for confirmation, rely the confirmation question to the user if the user haven't do so. 
- If the user already confirmed the related order in the past conversation history, you can confirm on behalf of the user
- Do not give irrelevant context to remote seller agent. For example, ordered pizza item is not relevant for the burger seller agent
- Never ask order confirmation to the remote seller agent 

Please rely on tools to address the request, and don't make up the response. If you are not sure, please ask the user for more details.
Focus on the most recent parts of the conversation primarily.

If there is an active agent, send the request to that agent with the update task tool.

Agents:
{self.agents}

Current active seller agent: {current_agent["active_agent"]}
"""

...

async def send_task(self, agent_name: str, task: str, tool_context: ToolContext):
        """Sends a task to remote seller agent

        This will send a message to the remote agent named agent_name.

        Args:
            agent_name: The name of the agent to send the task to.
            task: The comprehensive conversation context summary
                and goal to be achieved regarding user inquiry and purchase request.
            tool_context: The tool context this method runs in.

        Yields:
            A dictionary of JSON data.
        """
        if agent_name not in self.remote_agent_connections:
            raise ValueError(f"Agent {agent_name} not found")
        state = tool_context.state
        state["active_agent"] = agent_name
        client = self.remote_agent_connections[agent_name]
        if not client:
            raise ValueError(f"Client not available for {agent_name}")
        session_id = state["session_id"]
        task: Task
        message_id = ""
        metadata = {}
        if "input_message_metadata" in state:
            metadata.update(**state["input_message_metadata"])
            if "message_id" in state["input_message_metadata"]:
                message_id = state["input_message_metadata"]["message_id"]
        if not message_id:
            message_id = str(uuid.uuid4())

        payload = {
            "message": {
                "role": "user",
                "parts": [
                    {"type": "text", "text": task}
                ],  # Use the 'task' argument here
                "messageId": message_id,
                "contextId": session_id,
            },
        }

        message_request = SendMessageRequest(
            id=message_id, params=MessageSendParams.model_validate(payload)
        )
        send_response: SendMessageResponse = await client.send_message(
            message_request=message_request
        )
        print(
            "send_response",
            send_response.model_dump_json(exclude_none=True, indent=2),
        )

        if not isinstance(send_response.root, SendMessageSuccessResponse):
            print("received non-success response. Aborting get task ")
            return None

        if not isinstance(send_response.root.result, Task):
            print("received non-task response. Aborting get task ")
            return None

        return send_response.root.result

...

İstemde, satın alma danışmanı aracımıza mevcut tüm uzak aracıların adını ve açıklamasını veriyoruz. Araçta self.send_task ise aracıya bağlanılacak uygun istemciyi almak ve SendMessageRequest nesnesini kullanarak gerekli meta verileri göndermek için bir mekanizma sağlıyoruz.

İletişim Protokolleri

Görev tanımı, A2A sunucusuna ait bir alandır. Ancak A2A istemcisi açısından bu, sunucuya gönderilen bir Mesaj olarak görülür. İstemciden gelen mesajların hangi görev olarak tanımlanacağı ve görevin tamamlanması için istemciyle etkileşim gerekip gerekmediği sunucuya bağlıdır. Görev yaşam döngüsü hakkında daha fazla bilgiyi bu dokümanda bulabilirsiniz. Bu kavramın daha üst düzey bir görünümü aşağıda gösterilmiştir:

65b8878a4854fd93.jpeg

9ddfae690d40cbbf.jpeg

Bu mesaj -> görev değişimi, message/send protokolünün aşağıdaki örneğinde gösterildiği gibi JSON-RPC standardının üzerinde yük biçimi kullanılarak uygulanır :

{
  # identifier for this request
  "id": "abc123",
  # version of JSON-RPC protocol
  "jsonrpc": "2.0",
  # method name
  "method": "message/send",
  # parameters/arguments of the method
  "params": {
    "message": "hi, what can you help me with?"
  }  
}

Örneğin, farklı iletişim türlerini (ör. senkronizasyon, yayın, asenkron) desteklemek veya görev durumuyla ilgili bildirimleri yapılandırmak için çeşitli yöntemler kullanılabilir. A2A sunucusu, bu görev tanımı standartlarını işleyecek şekilde esnek bir şekilde yapılandırılabilir. Bu yöntemlerin ayrıntılarını bu belgede bulabilirsiniz.

11. 🎯 Hedef

Şimdi gerekli dosyayı hazırlayıp Gradio uygulamasını kendiniz Cloud Run'a dağıtabilir misiniz? Meydan okumaya katılma zamanı!

12. 🧹 Temizleme

Bu codelab'de kullanılan kaynaklar için Google Cloud hesabınızın ücretlendirilmesini istemiyorsanız şu adımları uygulayın:

  1. Google Cloud Console'da Kaynakları yönetin sayfasına gidin.
  2. Proje listesinde silmek istediğiniz projeyi seçin ve Sil'i tıklayın.
  3. İletişim kutusunda proje kimliğini yazın ve projeyi silmek için Kapat'ı tıklayın.
  4. Alternatif olarak, konsolda Cloud Run ve Agent Engine'a gidip yeni dağıttığınız hizmeti seçip silebilirsiniz.