1. Pengantar
Protokol agent-to-agent (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. Jika MCP berfokus pada pengurangan kompleksitas untuk menghubungkan agen dengan alat dan data, A2A berfokus pada cara memungkinkan agen berkolaborasi dalam modalitas alami mereka. Fitur 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 resmi, aplikasi disarankan 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 pengguna, 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 kita harapkan dalam demo 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 Anda dan Aktifkan semua API yang diperlukan di project tersebut
- Menyiapkan ruang kerja untuk lingkungan coding Anda
- Siapkan variabel env untuk layanan agen burger dan pizza, lalu coba secara lokal
- Men-deploy agen burger dan pizza ke Cloud Run
- Periksa detail tentang cara server A2A dibuat
- Siapkan variabel env untuk concierge pembelian dan coba secara lokal
- Men-deploy concierge pembelian ke Agent Engine
- Menghubungkan ke mesin agen melalui antarmuka lokal
- Periksa detail tentang cara klien A2A dibuat dan pemodelan datanya
- Memeriksa payload dan interaksi antara klien dan server A2A
Ringkasan Arsitektur
Kita akan men-deploy arsitektur layanan berikut
Kita 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 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. Sebelum memulai
Pilih Project Aktif di Konsol Cloud
Codelab ini mengasumsikan bahwa Anda sudah memiliki project Google Cloud dengan penagihan yang diaktifkan. Jika belum memilikinya, Anda dapat mengikuti petunjuk di bawah untuk memulai.
- Di Konsol Google Cloud, di halaman pemilih project, pilih atau buat project Google Cloud.
- Pastikan penagihan diaktifkan untuk project Cloud Anda. Pelajari cara memeriksa apakah penagihan telah diaktifkan pada suatu project.
Menyiapkan Project Cloud di Terminal Cloud Shell
- Anda akan menggunakan Cloud Shell, lingkungan command line yang berjalan di Google Cloud yang telah dilengkapi dengan bq. Klik Activate Cloud Shell di bagian atas konsol Google Cloud. Jika Anda diminta untuk memberikan otorisasi, klik Authorize.
- Setelah terhubung ke Cloud Shell, Anda dapat memeriksa bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke project ID Anda menggunakan perintah berikut:
gcloud auth list
- Jalankan perintah berikut di Cloud Shell untuk mengonfirmasi bahwa perintah gcloud mengetahui project Anda.
gcloud config list project
- Jika project Anda belum ditetapkan, gunakan perintah berikut untuk menetapkannya:
gcloud config set project <YOUR_PROJECT_ID>
Atau, Anda juga dapat melihat ID PROJECT_ID
di konsol
Klik project tersebut dan Anda akan melihat semua project Anda dan project ID di sisi kanan
- Aktifkan API yang diperlukan melalui perintah yang ditampilkan di bawah. Proses ini mungkin memerlukan waktu beberapa menit, jadi harap bersabar.
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.
Alternatif untuk perintah gcloud adalah melalui konsol dengan menelusuri setiap produk atau menggunakan link ini.
Jika ada API yang terlewat, Anda dapat mengaktifkannya kapan saja selama pelaksanaan.
Baca dokumentasi untuk mempelajari perintah gcloud dan penggunaannya.
Buka Cloud Shell Editor 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, yang akan membuka Cloud Shell Editor, kita dapat menulis kode di sini
- Pastikan project Cloud Code ditetapkan di pojok kiri bawah (status bar) editor Cloud Shell, seperti yang ditandai dalam gambar di bawah dan ditetapkan ke project Google Cloud aktif tempat Anda mengaktifkan penagihan. Authorize jika diminta. Jika Anda sudah mengikuti perintah sebelumnya, tombol juga dapat mengarah langsung ke project yang diaktifkan, bukan tombol login
- Selanjutnya, 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
- 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, Editor Cloud Shell Anda akan terlihat seperti ini
Penyiapan Lingkungan
Langkah selanjutnya adalah menyiapkan lingkungan pengembangan. 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
- Jika Anda belum membuka terminal, buka dengan mengklik Terminal -> New Terminal , atau gunakan Ctrl + Shift + C , yang akan membuka jendela terminal di bagian bawah browser
- Sekarang, mari kita lakukan inisialisasi lingkungan virtual concierge pembelian menggunakan
uv
(sudah diinstal sebelumnya di terminal cloud). Jalankan perintah ini
uv sync --frozen
Tindakan ini akan membuat direktori .venv dan menginstal dependensi. Pratinjau cepat di pyproject.toml akan memberi Anda informasi tentang dependensi yang ditampilkan seperti ini
dependencies = [ "a2a-sdk>=0.2.16", "google-adk>=1.8.0", "gradio>=5.38.2", ]
- Untuk menguji lingkungan virtual, buat file main.py baru dan salin kode berikut
def main():
print("Hello from purchasing-concierge-a2a!")
if __name__ == "__main__":
main()
- Kemudian, jalankan perintah berikut
uv run main.py
Anda akan mendapatkan output seperti yang ditunjukkan di bawah
Using CPython 3.12 Creating virtual environment at: .venv Hello from purchasing-concierge-a2a!
Ini menunjukkan bahwa project python sedang disiapkan dengan benar.
Sekarang kita dapat melanjutkan ke langkah berikutnya, yaitu mengonfigurasi dan men-deploy agen penjual jarak jauh
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, keduanya didukung oleh model Gemini Flash 2.0
Men-deploy Agen Burger Jarak Jauh
Kode sumber agen burger ada di direktori remote_seller_agents/burger_agent. Inisialisasi agen dapat diperiksa pada skrip agent.py. Berikut adalah cuplikan kode agen yang diinisialisasi
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
...
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. Kita akan membahasnya nanti. 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. Hal ini hanya terjadi jika Anda belum pernah men-deploy ke Cloud Run dari sumber sebelumnya. 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. Sekarang, mari kita coba membuka rute https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json
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 https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json
:
Ini adalah informasi kartu agen burger yang harus dapat diakses untuk tujuan penemuan. Kita akan membahasnya nanti. 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 luar dan tidak dikonfigurasi dengan benar. Untuk demo ini, 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_OVERRIDE
ke URL layanan ( yang memiliki polahttps://burger-agent-xxxxxxxxx.us-central1.run.app
)
- Terakhir, klik tombol deploy untuk men-deploy ulang layanan Anda
Sekarang, saat Anda mengakses kartu agen burger-agent lagi di https://burger-agent-xxxxxxxxx.us-central1.run.app/.well-known/agent.json
browser , nilai url
akan dikonfigurasi dengan benar
Men-deploy Agen Pizza Jarak Jauh
Demikian pula, kode sumber agen pizza berada di direktori remote_seller_agents/pizza_agent. Inisialisasi agen dapat diperiksa pada skrip agent.py. Berikut adalah cuplikan kode agen yang diinisialisasi
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,
)
...
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 di 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_OVERRIDE
ke 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. Sekarang mari kita bahas komponen inti Server A2A
4. 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 dilakukan 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 lebih mudah untuk beralih 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 yang 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
) .
5. 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 ada di direktori purchasing_concierge. Inisialisasi agen dapat diperiksa pada skrip purchasing_agent.py. Berikut adalah cuplikan kode agen yang diinisialisasi.
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,
],
)
...
Kita akan men-deploy agen ini ke agent engine. Vertex AI Agent Engine adalah serangkaian layanan yang memungkinkan developer men-deploy, mengelola, dan menskalakan agen AI dalam produksi. Layanan ini 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. 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. Dalam demo ini, kita akan men-deploy menggunakan skrip
deploy_to_agent_engine.py
yang kontennya ditampilkan di bawah
"""
Copyright 2025 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
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
, dan memberikan variabel lingkungan yang diperlukan.
Kita dapat men-deploy-nya dengan menjalankan skrip:
uv run deploy_to_agent_engine.py
Setelah deployment berhasil, log seperti ini akan ditampilkan. Perhatikan bahwa xxxx adalah project ID Anda dan yyyy adalah ID resource mesin agen Anda
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
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
curl \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://us-central1-aiplatform.googleapis.com/v1/projects/{YOUR_PROJECT_ID}/locations/us-central1/reasoningEngines/{YOUR_AGENT_ENGINE_RESOURCE_ID}:streamQuery?alt=sse -d '{
"class_method": "stream_query",
"input": {
"user_id": "user_123",
"message": "List available burger menu please",
}
}'
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
6. Komponen Inti 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 pesan dan parameter 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 umumnya 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 bawaan A2ACardResolver
, 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, mereka 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 dalam 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 sinkron, 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.
7. Pengujian Integrasi dan Inspeksi Payload
Sekarang, mari kita periksa concierge pembelian dengan interaksi agen jarak jauh menggunakan UI web.
Pertama, kita perlu memperbarui AGENT_ENGINE_RESOURCE_NAME
di .File env
. Pastikan Anda memberikan nama resource mesin agen yang benar. File .env
Anda seharusnya 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
Setelah itu, jalankan perintah berikut untuk men-deploy aplikasi Gradio
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
Kemudian, 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. Tantangan
Sekarang, dapatkah Anda menyiapkan file yang diperlukan dan men-deploy aplikasi Gradio ke Cloud Run sendiri? Saatnya menerima tantangan!
9. Pembersihan
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 di konsol, memilih layanan yang baru saja Anda deploy, lalu menghapusnya.