Memulai Protokol Agent2Agent (A2A): Interaksi Agen Penjual Jarak Jauh dan Agen Concierge Pembelian di Cloud Run dan Agent Engine

1. 📖 Pengantar

983be32cd5f6b65d.png

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 mengaktifkan agen untuk 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 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 penggunanya, agen jarak jauh, dan agen lainnya.

cb49a578e47636e1.png

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

e7e3224d05b725f0.jpeg

  1. Klien A2A akan terlebih dahulu melakukan penemuan pada semua kartu agen Server A2A yang dapat diakses dan menggunakan informasinya untuk membangun klien koneksi
  2. 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
  3. Setelah tugas selesai, server A2A akan mengirimkan artefak respons ke Klien A2A

Selama mengikuti codelab, Anda akan menggunakan pendekatan langkah demi langkah sebagai berikut:

  1. Siapkan project Google Cloud
  2. Menyiapkan direktori kerja untuk lingkungan coding
  3. Men-deploy agen burger ke Cloud Run
  4. Men-deploy agen pizza ke Cloud Run
  5. Men-deploy asisten pembelian ke Agent Engine
  6. Berinteraksi dengan concierge pembelian melalui antarmuka lokal

Ringkasan Arsitektur

Anda akan men-deploy arsitektur layanan berikut

a485135c8f7b97bd.jpeg

Anda akan men-deploy 2 layanan yang akan bertindak sebagai server A2A, yaitu 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 deployment-nya 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)

7758dd17c20c3094.png

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

8c93fa37e7a7b856.png

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

db07810b26fc61d6.png

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

4f592f31aef0c40.png

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.

26f20e837ff06119.png

79b06cc89a99f840.png

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.

8365518c832055f.png

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 168eacea651b086c.png

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

c87d2b76896d0c59.png

d5d829a1c43d7451.png

Sekarang, Editor Cloud Shell Anda akan terlihat seperti ini

9b4793fa38e35af2.png

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

8635b60ae2f45bbc.jpeg

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

Setelah 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

87dbae9eff7781f9.png

4. 🚀 Men-deploy Agen Penjual Burger - Server A2A

Kode sumber agen burger berada 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

3d353be0e82ff46c.png

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

  1. Telusuri Cloud Run di kotak penelusuran di bagian atas konsol cloud Anda

f56ec00607eafb6f.png

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

9bf379c89e7fe625.png

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

75a4a1a3b7fa3cd6.png

  1. Kemudian, klik bagian Variable & Secrets

4fcaa1176de7038d.png

  1. Setelah itu, klik Tambahkan variabel dan tetapkan nilai HOST_OVERRIDE ke URL layanan ( yang memiliki pola https://burger-agent-xxxxxxxxx.us-central1.run.app)

c160f7d90d219129.png

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

763bbc02ceac0e28.png

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

9acf6c51329d6e91.png

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

  1. Telusuri Cloud Run di kotak penelusuran di bagian atas konsol cloud Anda

f56ec00607eafb6f.png

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

d9840497ae8afa2c.png

  1. Klik Edit dan deploy revisi baru.

e45d52012bef34c6.png

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

19265c4edc2be7ae.png

  1. Setelah itu, klik Tambahkan variabel dan tetapkan nilai HOST_OVERRIDE ke URL layanan ( yang memiliki pola https://pizza-agent-xxxxxxxxx.us-central1.run.app)

7a6bd93cb6f11b64.png

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

763bbc02ceac0e28.png

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

f682caa1d89c6b5d.png

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.

d62d062dd6959e8.png

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 :

  1. Pertama, kita perlu membuat penyimpanan staging di Cloud Storage
gcloud storage buckets create gs://purchasing-concierge-{your-project-id} --location=us-central1
  1. Sekarang, kita perlu menyiapkan variabel .env terlebih dahulu. Mari salin .env.example ke file .env
cp .env.example .env
  1. 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, 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

f56ec00607eafb6f.png

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

561e3d125ae54e35.png

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

382c2094967718ae.png

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}
  1. Sekarang, kita siap men-deploy agen concierge pembelian. Kita akan men-deploy-nya ke agent engine 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. Anda akan melihat 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

765cdbdbbc3a94bc.png

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 sudah 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

bf615f875b1d870.png

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.

e3ada3143680efff.png

f661b0721ec6fbb0.png

789782458635578e.png

5d66b087aed1743e.png

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 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:

  1. AgentCapabilities : Deklarasi fungsi opsional tambahan yang didukung oleh layanan agen,seperti kemampuan untuk streaming dan/atau dukungan notifikasi push
  2. AgentSkill : Alat atau fungsi yang didukung oleh agen
  3. Input/OutputModes : Modalitas jenis Input/Output yang didukung
  4. Url : 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

10c75db36741da90.jpeg

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 menerapkan skema pemrosesan dasar yang mana agen akan dipanggil secara langsung saat permintaan masuk dan mengirim peristiwa tugas selesai setelah selesai melakukan pemanggilan. Namun, kami 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:

  1. Memublikasikan kartu agen di rute /.well-known/agent.json
  2. 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 env yang diperlukan.

10. 💡 [Penjelasan Kode] Konsep dan Penerapan Klien A2A

e7e3224d05b725f0.jpeg

Gambar yang ditampilkan di atas adalah alur umum interaksi A2A:

  1. Klien akan mencoba menemukan kartu agen yang dipublikasikan di URL agen jarak jauh yang diberikan di rute /.well-known/agent.json
  2. 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
  3. 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)
  4. 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 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

Berikut 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 Tugas adalah domain yang dimiliki oleh server A2A. Namun, dari perspektif klien A2A, klien melihatnya sebagai Message 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:

4f2a4c908e0fc75.jpeg

1810d38d264cb6a.jpeg

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.

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:

  1. Di konsol Google Cloud, buka halaman Manage resources.
  2. Dalam daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.
  4. Atau, Anda dapat membuka Cloud Run dan Agent Engine di konsol, memilih layanan yang baru saja Anda deploy, lalu menghapusnya.