1. 📖 Pengantar

Protokol Agent2Agent (A2A) dirancang untuk menstandardisasi komunikasi antar-agen AI, terutama untuk agen yang di-deploy dalam sistem eksternal. Sebelumnya, protokol tersebut ditetapkan untuk Alat yang disebut Model Context Protocol (MCP) yang merupakan standar baru untuk menghubungkan LLM dengan data dan resource. A2A mencoba melengkapi MCP yang berfokus pada masalah yang berbeda. Jika MCP berfokus pada penurunan kompleksitas untuk menghubungkan agen dengan alat dan data, A2A berfokus pada cara memungkinkan agen berkolaborasi dalam modalitas alami mereka. Hal ini memungkinkan agen berkomunikasi sebagai agen (atau sebagai pengguna), bukan sebagai alat; misalnya, memungkinkan komunikasi dua arah saat Anda ingin memesan sesuatu.
A2A diposisikan untuk melengkapi MCP, dalam dokumentasi resminya, aplikasi direkomendasikan untuk menggunakan MCP untuk alat dan A2A untuk agen - yang diwakili oleh AgentCard ( Kita akan membahasnya nanti). Framework kemudian dapat menggunakan A2A untuk berkomunikasi dengan penggunanya, agen jarak jauh, dan agen lainnya.

Dalam demo ini, kita akan memulai dengan penerapan A2A menggunakan Python SDK. Kita akan mempelajari kasus penggunaan saat kita memiliki petugas pembelian pribadi yang dapat membantu kita berkomunikasi dengan agen penjual burger dan pizza untuk menangani pesanan kita.
A2A menggunakan prinsip klien-server. Berikut adalah alur A2A umum yang akan Anda temui dalam tutorial ini

- Klien A2A akan terlebih dahulu melakukan penemuan pada semua kartu agen Server A2A yang dapat diakses dan menggunakan informasinya untuk membangun klien koneksi
- Jika diperlukan, Klien A2A akan mengirim pesan ke Server A2A, dan server akan mengevaluasi pesan ini sebagai Tugas yang harus diselesaikan. Jika URL penerima notifikasi push dikonfigurasi di klien A2A dan didukung oleh Server A2A, server juga akan dapat memublikasikan status progres tugas ke endpoint penerima di klien
- Setelah tugas selesai, server A2A akan mengirimkan artefak respons ke Klien A2A
Selama mengikuti codelab, Anda akan menggunakan pendekatan langkah demi langkah sebagai berikut:
- Siapkan project Google Cloud
- Menyiapkan direktori kerja untuk lingkungan coding
- Men-deploy agen burger ke Cloud Run
- Men-deploy agen pizza ke Cloud Run
- Men-deploy concierge pembelian ke Agent Engine
- Berinteraksi dengan concierge pembelian melalui antarmuka lokal
Ringkasan Arsitektur
Anda akan men-deploy arsitektur layanan berikut

Anda akan men-deploy 2 layanan yang akan bertindak sebagai server A2A, agen Burger ( didukung oleh framework agen CrewAI) dan agen Pizza ( didukung oleh framework agen Langgraph). Pengguna hanya akan berinteraksi langsung dengan Purchasing concierge yang akan dijalankan menggunakan framework Agent Development Kit (ADK) yang akan bertindak sebagai klien A2A.
Setiap agen ini akan memiliki lingkungan dan deploymentnya sendiri.
Prasyarat
- Nyaman bekerja dengan Python
- Pemahaman tentang arsitektur full-stack dasar menggunakan layanan HTTP
Yang akan Anda pelajari
- Struktur inti Server A2A
- Struktur inti Klien A2A
- Men-deploy layanan agen ke Cloud Run
- Men-deploy layanan agen ke Agent Engine
- Cara Klien A2A terhubung ke Server A2A
- Struktur Permintaan dan Respons pada koneksi non-streaming
Yang Anda butuhkan
- Browser web Chrome
- Akun Gmail
- Project Cloud dengan akun penagihan diaktifkan
Codelab ini, yang dirancang untuk developer dari semua level (termasuk pemula), menggunakan Python dalam aplikasi contohnya. Namun, pengetahuan Python tidak diperlukan untuk memahami konsep yang disajikan.
2. 🚀 Menyiapkan Penyiapan Pengembangan Workshop
Langkah 1: Pilih Project Aktif di Konsol Cloud
Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud (lihat bagian kiri atas konsol Anda)

Klik, dan Anda akan melihat daftar semua project Anda seperti contoh ini,

Nilai yang ditunjukkan oleh kotak merah adalah PROJECT ID dan nilai ini akan digunakan di seluruh tutorial.
Pastikan penagihan diaktifkan untuk project Cloud Anda. Untuk memeriksanya, klik ikon burger ☰ di panel kiri atas yang menampilkan Menu Navigasi, lalu temukan menu Penagihan

Jika Anda melihat "Akun Penagihan Uji Coba Google Cloud Platform" ditautkan, project Anda siap digunakan untuk tutorial ini. Jika tidak, kembali ke awal tutorial ini dan tukarkan akun penagihan

Langkah 2: Pelajari Cloud Shell
Anda akan menggunakan Cloud Shell untuk sebagian besar tutorial. Klik Activate Cloud Shell di bagian atas konsol Google Cloud. Jika Anda diminta untuk memberikan otorisasi, klik Authorize.


Setelah terhubung ke Cloud Shell, kita perlu memeriksa apakah shell ( atau terminal) sudah diautentikasi dengan akun kita
gcloud auth list
Jika Anda melihat Gmail pribadi Anda seperti contoh output di bawah, semuanya baik-baik saja
Credentialed Accounts
ACTIVE: *
ACCOUNT: alvinprayuda@gmail.com
To set the active account, run:
$ gcloud config set account `ACCOUNT`
Jika tidak, coba muat ulang browser Anda dan pastikan Anda mengklik Izinkan saat diminta ( mungkin terganggu karena masalah koneksi)
Selanjutnya, kita juga perlu memeriksa apakah shell sudah dikonfigurasi ke PROJECT ID yang benar yang Anda miliki. Jika Anda melihat ada nilai di dalam ( ) sebelum ikon $ di terminal ( pada screenshot di bawah, nilainya adalah "a2a-agent-engine"), nilai ini menunjukkan project yang dikonfigurasi untuk sesi shell aktif Anda.

Jika nilai yang ditampilkan sudah benar, Anda dapat melewati perintah berikutnya. Namun, jika tidak benar atau tidak ada, jalankan perintah berikut
gcloud config set project <YOUR_PROJECT_ID>
Kemudian, clone direktori kerja template untuk codelab ini dari GitHub dengan menjalankan perintah berikut. Perintah ini akan membuat direktori kerja di direktori purchasing-concierge-a2a
git clone https://github.com/alphinside/purchasing-concierge-intro-a2a-codelab-starter.git purchasing-concierge-a2a
Langkah 3: Pahami Editor Cloud Shell dan Siapkan Direktori Kerja Aplikasi
Sekarang, kita dapat menyiapkan editor kode untuk melakukan beberapa hal terkait coding. Kita akan menggunakan Cloud Shell Editor untuk melakukannya
Klik tombol Open Editor, dan Cloud Shell Editor akan terbuka 
Setelah itu, buka bagian atas Editor Cloud Shell, klik File->Open Folder, temukan direktori username Anda, lalu temukan direktori purchasing-concierge-a2a, lalu klik tombol OK. Tindakan ini akan menjadikan direktori yang dipilih sebagai direktori kerja utama. Dalam contoh ini, nama penggunanya adalah alvinprayuda, sehingga jalur direktori ditampilkan di bawah


Sekarang, Cloud Shell Editor Anda akan terlihat seperti ini

Sekarang, buka terminal untuk editor. Anda dapat melakukannya dengan mengklik Terminal -> New Terminal di panel menu, atau menggunakan Ctrl + Shift + C , yang akan membuka jendela terminal di bagian bawah browser

Terminal aktif Anda saat ini harus berada di dalam direktori kerja purchasing-concierge-a2a. Kita akan menggunakan Python 3.12 dalam codelab ini dan kita akan menggunakan pengelola project python uv untuk menyederhanakan kebutuhan pembuatan dan pengelolaan versi python serta lingkungan virtual. Paket uv ini sudah diinstal sebelumnya di Cloud Shell.
Jalankan perintah ini untuk menginstal dependensi yang diperlukan ke lingkungan virtual di direktori .venv
uv sync --frozen
Periksa pyproject.toml untuk melihat dependensi yang dideklarasikan untuk tutorial ini, yaitu a2a-sdk, google-adk, and gradio.
Sekarang, kita perlu mengaktifkan API yang diperlukan melalui perintah yang ditunjukkan di bawah. Proses ini memerlukan waktu beberapa saat.
gcloud services enable aiplatform.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
cloudresourcemanager.googleapis.com
Jika perintah berhasil dieksekusi, Anda akan melihat pesan yang mirip dengan yang ditampilkan di bawah:
Operation "operations/..." finished successfully.
3. 🚀 Men-deploy Agen Penjual Jarak Jauh Server A2A ke Cloud Run
Pada langkah ini, kita akan men-deploy dua agen penjual jarak jauh yang ditandai dengan kotak merah. Agen burger akan didukung oleh framework agen CrewAI dan agen pizza akan didukung oleh agen Langgraph

4. 🚀 Men-deploy Agen Penjual Burger - Server A2A
Kode sumber agen burger ada di direktori remote_seller_agents/burger_agent.
Semua file yang ada di direktori remote_seller_agents/burger_agent sudah cukup untuk men-deploy agen kita ke Cloud Run sehingga dapat diakses sebagai layanan. Jalankan perintah berikut untuk men-deploy-nya
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}
Jika Anda diminta untuk membuat repositori penampung untuk men-deploy dari sumber, jawab Y. Setelah deployment berhasil, log seperti ini akan ditampilkan.
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
Bagian xxxx di sini akan menjadi ID unik saat kita men-deploy layanan.
Buka tab browser baru dan buka rute https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json dari layanan agen burger yang di-deploy tersebut melalui browser. Ini adalah URL untuk mengakses kartu agen server A2A yang di-deploy.
Jika berhasil di-deploy, Anda akan melihat respons seperti yang ditunjukkan di bawah ini di browser saat mengakses kartu agen

Ini adalah informasi kartu agen burger yang harus dapat diakses untuk tujuan penemuan.
Perhatikan bahwa nilai url masih ditetapkan pada http://0.0.0.0:8080/ di sini. Nilai url ini harus berupa informasi utama bagi Klien A2A untuk mengirim pesan dari dunia luar dan tidak dikonfigurasi dengan benar.
Kita perlu memperbarui nilai ini ke URL layanan agen burger dengan menambahkan variabel lingkungan tambahan HOST_OVERRIDE.
Memperbarui Nilai URL Agen Burger di Kartu Agen melalui Variabel Lingkungan
Untuk menambahkan HOST_OVERRIDE ke layanan agen burger, lakukan langkah-langkah berikut
- Telusuri Cloud Run di kotak penelusuran di bagian atas konsol cloud Anda

- Klik layanan Cloud Run burger-agent yang di-deploy sebelumnya

- Salin URL burger-service, lalu klik Edit dan deploy revisi baru

- Kemudian, klik bagian Variable & Secrets

- Setelah itu, klik Tambahkan variabel dan tetapkan nilai
HOST_OVERRIDEke URL layanan ( yang memiliki polahttps://burger-agent-xxxxxxxxx.us-central1.run.app)

- Terakhir, klik tombol deploy untuk men-deploy ulang layanan Anda

Saat Anda mengakses kartu agen burger-agent lagi di browser https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json , nilai url akan dikonfigurasi dengan benar

5. 🚀 Men-deploy Agen Penjual Pizza - Server A2A
Demikian pula, kode sumber agen pizza berada di direktori remote_seller_agents/pizza_agent.
Mirip dengan langkah deployment burger-agent sebelumnya, semua file yang ada di direktori remote_seller_agents/pizza_agent sudah cukup untuk men-deploy agen kita ke Cloud Run sehingga dapat diakses sebagai layanan. Jalankan perintah berikut untuk men-deploy-nya
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}
Setelah deployment berhasil, log seperti ini akan ditampilkan.
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
Bagian xxxx di sini akan menjadi ID unik saat kita men-deploy layanan.
Hal yang sama terjadi pada agen burger, saat Anda mencoba membuka rute https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json dari layanan agen pizza yang di-deploy tersebut melalui browser untuk mengakses kartu agen server A2A, nilai url agen pizza pada kartu agennya belum dikonfigurasi dengan benar. Kita juga perlu menambahkan HOST_OVERRIDE ke variabel lingkungannya
Memperbarui Nilai URL Agen Pizza di Kartu Agen melalui Variabel Lingkungan
Untuk menambahkan HOST_OVERRIDE ke layanan agen pizza, lakukan langkah-langkah berikut
- Telusuri Cloud Run di kotak penelusuran di bagian atas konsol cloud Anda

- Klik layanan Cloud Run pizza-agent yang di-deploy sebelumnya

- Klik Edit dan deploy revisi baru.

- Salin URL pizza-service, lalu klik bagian Variable & Secrets

- Setelah itu, klik Tambahkan variabel dan tetapkan nilai
HOST_OVERRIDEke URL layanan ( yang memiliki polahttps://pizza-agent-xxxxxxxxx.us-central1.run.app)

- Terakhir, klik tombol deploy untuk men-deploy ulang layanan Anda

Sekarang, saat Anda mengakses kartu agen pizza-agent lagi di browser https://pizza-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json, nilai url akan dikonfigurasi dengan benar

Pada tahap ini, kita telah berhasil men-deploy layanan burger dan pizza ke Cloud Run.
6. 🚀 Men-deploy Purchasing Concierge - A2A Client ke Agent Engine
Pada langkah ini, kita akan men-deploy agen concierge pembelian. Agen inilah yang akan kita ajak berinteraksi.

Kode sumber agen pemandu pembelian kami berada di direktori purchasing_concierge. Inisialisasi agen dapat diperiksa pada skrip purchasing_concierge/purchasing_agent.py.
Ikuti langkah-langkah berikut untuk men-deploy-nya :
- Pertama, kita perlu membuat penyimpanan staging di Cloud Storage
gcloud storage buckets create gs://purchasing-concierge-{your-project-id} --location=us-central1
- Sekarang, kita perlu menyiapkan variabel .env terlebih dahulu. Mari salin .env.example ke file .env
cp .env.example .env
- Sekarang, buka file .env dan Anda akan melihat konten berikut
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}
Agen ini akan berkomunikasi dengan agen burger dan pizza, sehingga kita perlu memberikan kredensial yang tepat untuk keduanya. Kita perlu memperbarui PIZZA_SELLER_AGENT_URL dan BURGER_SELLER_AGENT_URL dengan URL Cloud Run dari langkah-langkah sebelumnya.
Jika Anda lupa tentang hal ini, buka konsol Cloud Run. Ketik "Cloud Run" di kotak penelusuran di bagian atas konsol Anda, lalu klik kanan ikon Cloud Run untuk membukanya di tab baru

Anda akan melihat layanan agen penjual jarak jauh yang sebelumnya di-deploy seperti yang ditunjukkan di bawah

Sekarang, untuk melihat URL publik layanan tersebut, klik salah satu layanan dan Anda akan dialihkan ke halaman Detail layanan. Anda dapat melihat URL di area atas tepat di samping informasi Wilayah

Variabel lingkungan akhir akan terlihat seperti ini
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}
- Sekarang, kita siap men-deploy agen concierge pembelian. Kita akan men-deploy-nya ke mesin agen dan kode deployment ada di dalam skrip
deploy_to_agent_engine.py.
Kita dapat men-deploy-nya dengan menjalankan skrip:
uv run deploy_to_agent_engine.py
Setelah deployment berhasil, log seperti ini akan ditampilkan. Output akan menampilkan nama resource Agent Engine sebagai "projects/xxxx/locations/us-central1/reasoningEngines/yyyy"
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
Saat kita memeriksanya di dasbor agent engine (telusuri "agent engine" di kotak penelusuran), deployment sebelumnya akan ditampilkan

Anda juga dapat memeriksa apakah nama resource Agent Engine ditampilkan di sana.Kemudian, kita dapat menggunakan nama resource ini untuk mengujinya
Setelah itu, perbarui AGENT_ENGINE_RESOURCE_NAME di file .env dengan nilai ini. Pastikan Anda memberikan nama resource mesin agen yang benar. File .env Anda akan terlihat seperti ini:
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
Menguji Agen yang Di-deploy di Agent Engine
Interaksi dengan mesin agen dapat dilakukan melalui perintah curl dan SDK. Misalnya, jalankan perintah berikut untuk mencoba berinteraksi dengan agen yang di-deploy.
Anda dapat mencoba mengirim kueri ini untuk memeriksa apakah agen berhasil di-deploy. Jalankan skrip test_agent_engine.sh berikut
bash test_agent_engine.sh
Anda dapat memeriksa skrip, dan melihat bahwa kita mencoba bertanya "List available burger menu please" kepada agen
Jika berhasil, beberapa peristiwa respons yang di-streaming di konsol Anda akan ditampilkan seperti ini
{
"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
}
Kita akan mencoba menggunakan UI pada langkah berikutnya, tetapi mari kita bahas terlebih dahulu komponen inti dan alur umum klien A2A
7. 🚀 Pengujian Integrasi dan Pemeriksaan Payload
Sekarang, mari kita periksa concierge pembelian dengan interaksi agen jarak jauh menggunakan UI web. Jalankan perintah berikut untuk men-deploy aplikasi Gradio. Untuk menjalankan aplikasi ini, Anda harus mengisi file .env dengan benar
uv run purchasing_concierge_ui.py
Output berikut akan ditampilkan jika berhasil
* Running on local URL: http://0.0.0.0:8080 * To create a public link, set `share=True` in `launch()`.
Kemudian, Ctrl + klik URL http://0.0.0.0:8080 di terminal atau klik tombol pratinjau web untuk membuka UI web

Coba lakukan percakapan seperti ini :
- Tampilkan menu burger dan pizza
- Saya ingin memesan 1 pizza ayam BBQ dan 1 burger cajun pedas
Lanjutkan percakapan hingga Anda menyelesaikan pesanan. Periksa bagaimana interaksi berlangsung dan apa panggilan serta respons alatnya? Gambar berikut adalah contoh hasil interaksi.




Kita dapat melihat bahwa berkomunikasi dengan 2 agen yang berbeda menghasilkan 2 perilaku yang berbeda dan A2A dapat menanganinya dengan baik. Agen penjual pizza langsung menerima permintaan agen pembelian kami, sedangkan agen burger memerlukan konfirmasi kami sebelum melanjutkan permintaan kami dan setelah kami mengonfirmasi, agen dapat mengandalkan konfirmasi tersebut untuk agen burger
Sekarang, kita telah menyelesaikan konsep dasar A2A dan melihat cara penerapannya sebagai arsitektur klien dan server
8. 💡 [Penjelasan Kode] Konsep dan Penerapan Server A2A
Inisialisasi agen penjual jarak jauh dapat diperiksa pada skrip remote_seller_agents/*/agent.py. Berikut adalah cuplikan kode agen penjual.
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,
)
...
Seperti yang dapat Anda lihat, kedua agen ini dibuat dengan framework yang sama sekali berbeda ( CrewAI dan Langgraph) dibandingkan dengan agen klien ( ADK). Dengan A2A, hal ini tidak menjadi masalah. Kita tidak perlu membuat mereka berbagi kode internal untuk saling berkomunikasi. Framework apa pun yang digunakan, bahasa apa pun yang digunakan, atau tempat mereka di-deploy tidak menjadi masalah.
Komponen Inti Server A2A
Sekarang mari kita bahas konsep dan komponen inti server A2A
Kartu Agen
Setiap Server A2A harus memiliki kartu agen yang dapat diakses di resource /.well-known/agent.json. Hal ini untuk mendukung fase penemuan di Klien A2A, yang akan memberikan informasi dan konteks lengkap tentang cara mengakses agen dan mengetahui semua kemampuannya. Hal ini agak mirip dengan dokumentasi API yang terdokumentasi dengan baik menggunakan Swagger atau Postman.
Ini adalah konten kartu agen burger yang di-deploy
{
"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"
}
Kartu agen ini menyoroti banyak komponen penting, seperti keterampilan agen, kemampuan streaming, modalitas yang didukung, versi protokol, dan hal lainnya.
Semua informasi ini dapat digunakan untuk mengembangkan mekanisme komunikasi yang tepat sehingga klien A2A dapat berkomunikasi dengan benar. Mekanisme autentikasi dan modalitas yang didukung memastikan komunikasi dapat dilakukan dengan benar, dan informasi agen skills dapat disematkan ke dalam perintah sistem klien A2A untuk memberikan konteks agen klien tentang kemampuan dan keterampilan agen jarak jauh yang akan dipanggil. Kolom yang lebih mendetail untuk kartu agen ini dapat ditemukan di dokumentasi ini.
Dalam kode kami, penerapan kartu agen ditetapkan menggunakan A2A python SDK. Lihat cuplikan remote_seller_agents/burger_agent/main.py di bawah untuk mengetahui penerapannya
...
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],
)
...
Kita dapat melihat beberapa kolom di sana seperti:
AgentCapabilities: Deklarasi fungsi opsional tambahan yang didukung oleh layanan agen,seperti kemampuan untuk streaming dan/atau dukungan notifikasi pushAgentSkill: Alat atau fungsi yang didukung oleh agenInput/OutputModes: Modalitas jenis Input/Output yang didukungUrl: Alamat untuk berkomunikasi dengan agen
Dalam konfigurasi ini, kami menyediakan pembuatan URL host agen dinamis, sehingga memudahkan peralihan antara pengujian lokal dan deployment cloud. Oleh karena itu, kami perlu menambahkan variabel HOST_OVERRIDE pada langkah sebelumnya.
Task Queue dan Agent Executor
Server A2A dapat menangani permintaan dari berbagai agen atau pengguna dan dapat mengisolasi setiap tugas dengan sempurna. Untuk memvisualisasikan konteks ini dengan lebih baik, Anda dapat memeriksa gambar di bawah

Oleh karena itu, setiap server A2A harus dapat melacak tugas masuk dan menyimpan informasi yang tepat tentang tugas tersebut. SDK A2A menyediakan modul untuk mengatasi tantangan ini di server A2A. Pertama, kita dapat membuat instance logika tentang cara menangani permintaan masuk. Dengan mewarisi class abstrak AgentExecutor, kita dapat mengontrol cara kita ingin mengelola eksekusi dan pembatalan tugas. Penerapan contoh ini dapat diperiksa di modul remote_seller_agents/burger_agent/agent_executor.py ( jalur serupa untuk kasus penjual pizza)
...
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())
...
Dalam kode di atas, kita mengimplementasikan skema pemrosesan dasar yang mana agen akan dipanggil secara langsung saat permintaan masuk dan mengirimkan peristiwa tugas selesai setelah menyelesaikan pemanggilan. Namun, kita tidak menerapkan metode pembatalan di sini karena dianggap sebagai operasi yang berjalan singkat.
Setelah membuat executor, kita dapat langsung menggunakan DefaultRequestHandler, InMemoryTaskStore, dan A2AStarletteApplication bawaan untuk menjalankan Server HTTP. Penerapan ini dapat diperiksa di remote_seller_agents/burger_agent/__main__.py
...
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)
...
Modul ini akan memberi Anda implementasi rute /.well-known/agent.json untuk mengakses kartu agen dan juga endpoint POST untuk mendukung protokol A2A
Ringkasan
Singkatnya, sejauh ini Server A2A yang di-deploy menggunakan Python SDK dapat mendukung 2 fungsi di bawah ini:
- Memublikasikan kartu agen di rute
/.well-known/agent.json - Menangani permintaan JSON-RPC dengan antrean tugas dalam memori
Titik entri saat memulai fungsi ini dapat diperiksa pada skrip __main__.py ( di remote_seller_agents/burger_agent atau remote_seller_agents/pizza_agent) .
9. 💡 [Penjelasan Kode] Penerapan Agent Engine
Berikut cuplikan kode agen concierge pembelian di purchasing_concierge/purchasing_agent.py:
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,
],
)
...
Agen ini dibangun menggunakan ADK dan di-deploy di Agent Engine.
Vertex AI Agent Engine adalah serangkaian layanan yang memungkinkan developer men-deploy, mengelola, dan menskalakan agen AI dalam produksi. Vertex AI Agent Engine menangani infrastruktur untuk menskalakan agen dalam produksi sehingga kita dapat berfokus pada pembuatan aplikasi. Anda dapat membaca selengkapnya tentang hal ini di dokumen ini . Jika sebelumnya kita perlu menyiapkan file yang diperlukan untuk men-deploy layanan agen (seperti skrip server main dan Dockerfile), dalam hal ini kita dapat men-deploy agen langsung dari skrip python tanpa perlu mengembangkan layanan backend sendiri dengan menggunakan kombinasi ADK dan Agent Engine.
Dalam tutorial ini, kita akan men-deploy menggunakan skrip deploy_to_agent_engine.py yang kontennya ditampilkan di bawah
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}")
Berikut adalah langkah-langkah yang diperlukan untuk men-deploy agen ADK ke agent engine. Pertama, kita perlu membuat objek AdkApp dari root_agent ADK kita. Kemudian, kita dapat menjalankan metode agent_engines.create dengan memberikan objek adk_app, menentukan persyaratan di kolom requirements, menentukan jalur direktori agen di extra_packages ( Anda juga dapat memberikan direktori dan file lain jika diperlukan di sini), dan memberikan variabel lingkungan yang diperlukan.
10. 💡 [Penjelasan Kode] Konsep dan Penerapan Klien A2A

Gambar di atas menunjukkan alur umum interaksi A2A:
- Klien akan mencoba menemukan kartu agen yang dipublikasikan di URL agen jarak jauh yang diberikan di rute
/.well-known/agent.json - Kemudian, jika perlu, server akan mengirimkan Pesan ke agen tersebut dengan parameter pesan dan metadata yang diperlukan ( misalnya, ID sesi, konteks historis, dll.). Server akan menganggap Pesan ini sebagai Tugas yang harus diselesaikan
- Server A2A memproses permintaan, jika server mendukung notifikasi push, server juga akan dapat memublikasikan beberapa notifikasi selama pemrosesan tugas ( Fungsi ini berada di luar cakupan codelab ini)
- Setelah selesai, server A2A akan mengirimkan artefak respons kembali ke klien
Beberapa objek inti untuk interaksi di atas adalah item ini (detail selengkapnya dapat dibaca di sini) :
- Pesan: Giliran komunikasi antara klien dan agen jarak jauh
- Tugas: Unit kerja dasar yang dikelola oleh A2A, diidentifikasi oleh ID unik
- Artefak: Output (misalnya, dokumen, gambar, data terstruktur) yang dihasilkan oleh agen sebagai hasil dari tugas, yang terdiri dari Bagian
- Bagian: Unit konten terkecil dalam Pesan atau Artefak. Bagian dapat berupa teks, gambar, video, file, dll.
Penemuan Kartu
Saat layanan Klien A2A diluncurkan, proses biasanya adalah mencoba mendapatkan informasi kartu agen dan menyimpannya agar mudah diakses saat diperlukan. Dalam codelab ini, kita akan menerapkannya di before_agent_callback. Anda dapat melihat penerapannya di purchasing_concierge/purchasing_agent.py. Lihat cuplikan kode di bawah
...
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)
...
Di sini, kita mencoba mengakses semua kartu agen yang tersedia menggunakan modul klien A2A A2ACardResolver bawaan, lalu kita mengumpulkan koneksi yang diperlukan untuk mengirim pesan ke agen, setelah itu kita juga perlu mencantumkan semua agen yang tersedia dan spesifikasinya ke dalam perintah sehingga agen kita mengetahui bahwa ia dapat berkomunikasi dengan agen-agen ini
Alat Prompt dan Kirim Tugas
Ini adalah perintah dan alat yang kami berikan kepada agen ADK kami di sini
...
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
...
Dalam perintah, kita memberikan semua nama dan deskripsi agen jarak jauh yang tersedia kepada agen concierge pembelian, dan di alat self.send_task kita menyediakan mekanisme untuk mengambil klien yang sesuai untuk terhubung ke agen dan mengirim metadata yang diperlukan menggunakan objek SendMessageRequest.
Protokol Komunikasi
Definisi Task adalah domain yang dimiliki oleh server A2A. Namun, dari perspektif klien A2A, klien melihatnya sebagai Pesan yang dikirim ke server. Serverlah yang menentukan cara mendefinisikan pesan masuk dari klien sebagai tugas yang mana dan apakah penyelesaian tugas memerlukan interaksi dari klien. Anda dapat membaca detail selengkapnya tentang siklus proses tugas di dokumentasi ini. Konsep tingkat yang lebih tinggi dari hal ini dapat divisualisasikan di bawah:


Pertukaran pesan -> tugas ini diimplementasikan menggunakan format payload di atas standar JSON-RPC seperti yang ditunjukkan dalam contoh protokol message/send di bawah :
{
# 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?"
}
}
Ada berbagai metode yang tersedia, misalnya untuk mendukung berbagai jenis komunikasi (misalnya sinkronisasi, streaming, asinkron) atau untuk mengonfigurasi notifikasi untuk status tugas. Server A2A dapat dikonfigurasi secara fleksibel untuk menangani standar definisi tugas ini. Detail metode ini dapat dibaca di dokumen ini.
11. 🎯 Tantangan
Sekarang, dapatkah Anda menyiapkan file yang diperlukan dan men-deploy aplikasi Gradio ke Cloud Run sendiri? Saatnya menerima tantangan!
12. 🧹 Membersihkan
Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam codelab ini, ikuti langkah-langkah berikut:
- Di konsol Google Cloud, buka halaman Manage resources.
- Dalam daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
- Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.
- Atau, Anda dapat membuka Cloud Run dan Agent Engine di konsol, memilih layanan yang baru saja Anda deploy, lalu menghapusnya.