1. Ringkasan
Dalam codelab ini, Anda akan membangun AI Creative Studio - sistem multi-agen terdistribusi yang mengubah satu perintah menjadi kampanye Instagram yang lengkap.
Ketik satu kalimat. Dapatkan kembali riset audiens, teks, konsep visual, teks yang telah ditinjau kualitasnya, dan linimasa project lengkap - semuanya dihasilkan oleh tim agen AI yang berkolaborasi.
Agen yang akan Anda buat
Agen | Peran |
Brand Strategist | Menelusuri web untuk mendapatkan analisis audiens, analisis kompetitor, dan tren 2025 |
Copywriter | Menulis teks Instagram dengan hashtag dan CTA - didukung oleh Skill ADK yang memuat pedoman platform dan formula teks sesuai permintaan |
Desainer | Membuat konsep visual dan menghasilkan gambar asli melalui Gemini, yang disimpan di GCS |
Kritik | Salinan dan visual ulasan - menampilkan |
Project Manager | Membuat linimasa project dan perincian tugas, yang secara opsional disinkronkan ke Notion melalui MCP |
Creative Director | Mengatur semua lima spesialis secara berurutan - Anda memberikan satu perintah, lalu model akan mengoordinasikan sisanya |
Kelima agen di-deploy sebagai microservice Cloud Run yang independen. Agen berkomunikasi melalui protokol A2A - standar terbuka yang tidak bergantung pada bahasa sehingga agen mana pun dapat memanggil agen lain terlepas dari framework-nya. Creative Director berjalan di Agent Runtime dan terhubung ke setiap spesialis dari jarak jauh.
Arsitektur

Yang akan Anda pelajari
- Bangun agen LLM dengan Google ADK -
Agent, petunjuk sistem, dan alat bawaan. - Paketkan pengetahuan agen yang dapat digunakan kembali ke dalam file modular dengan Keterampilan ADK (
SkillToolset). - Membuat gambar nyata dengan menghubungkan agen teks ke model gambar melalui
FunctionTool. - Mengintegrasikan API eksternal tanpa kode lem kustom menggunakan Model Context Protocol (MCP).
- Ubah agen apa pun menjadi layanan yang dapat dipanggil melalui jaringan menggunakan Protokol Agent to Agent (A2A) melalui HTTPS.
- Mengatur agen terdistribusi dengan
RemoteA2aAgentdanAgentTool. - Kemasan dan deploy agen independen sebagai microservice Cloud Run.
- Menampung orkestrator stateful di Agent Runtime.
- Menjaga alur kerja multi-agen yang panjang dalam batas konteks menggunakan pemadatan konteks.
- Membangun loop kontrol kualitas: Output ulasan kritikus → revisi otomatis jika diperlukan.
Yang Anda butuhkan
- Project Google Cloud dengan penagihan diaktifkan
- Peran IAM Pemilik atau Editor
- Pengetahuan Python dasar
2. Menyiapkan Lingkungan Anda
Untuk codelab ini, kita akan menggunakan Cloud Shell.
Apa itu Cloud Shell?
Cloud Shell adalah lingkungan Linux berbasis browser gratis dengan semuanya telah diinstal sebelumnya: gcloud, git, Python, Docker, dan lainnya. Anda tidak perlu menginstal apa pun secara lokal.
Untuk membuka Cloud Shell, klik ikon terminal di toolbar kanan atas Konsol GCP:

Saat membuka Cloud Shell untuk pertama kalinya, Anda akan diminta untuk memverifikasi akun Anda - klik Verify:

Kemudian, klik Authorize untuk mengizinkan Cloud Shell melakukan panggilan Google Cloud API:

Cloud Shell kini sudah siap. Anda akan melihat pesan selamat datang di terminal: 
Lakukan autentikasi dan konfigurasi project Anda
Cloud Shell sudah diautentikasi dengan Akun Google Anda. Konfirmasi akun aktif Anda dan temukan Project ID Anda:
gcloud config list
Anda juga dapat melihat Project ID di dasbor Konsol GCP di panel sisi kiri. Salin - Anda akan membutuhkannya di perintah berikutnya:

Sekarang tetapkan project Anda:
export PROJECT_ID=$(gcloud config get-value project)
export REGION="us-central1" # Cloud Run deployment region
echo "Project: $PROJECT_ID"
Output yang diharapkan:
Project: my-project-123
Aktifkan API yang diperlukan
gcloud services enable \
aiplatform.googleapis.com \
apphub.googleapis.com \
run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
generativelanguage.googleapis.com \
iam.googleapis.com \
cloudresourcemanager.googleapis.com \
storage.googleapis.com \
secretmanager.googleapis.com
Proses ini memerlukan waktu sekitar 2 menit. Anda akan melihat Operation finished successfully setelah selesai.
Menyiapkan Kredensial Default Aplikasi (ADC)
Agen akan memanggil Gemini Enterprise Agent Platform menggunakan Google Auth library, yang memerlukan Kredensial Default Aplikasi - terpisah dari autentikasi CLI gcloud.
Jalankan ini sekali:
gcloud auth application-default login
Tab browser akan terbuka dan meminta Anda untuk mengonfirmasi. Klik Izinkan. Anda akan melihat:
Credentials saved to file: ~/.config/gcloud/application_default_credentials.json
Meng-clone repositori starter
Codelab ini menggunakan repositori awal - project kerangka dengan semua infrastruktur yang sudah ada (Dockerfiles, pyproject.toml, skrip deployment), tetapi dengan logika agen yang harus Anda tulis.
git clone https://github.com/Saoussen-CH/mas-a2a-gcp.git ~/ai-creative-studio
cd ~/ai-creative-studio/workshop/starter
Setiap agent.py berisi placeholder # TODO tempat Anda akan menulis logika agen. Skrip Dockerfile, pyproject.toml, dan deployment sudah selesai.
Mengonfigurasi variabel lingkungan
Salin contoh yang diberikan dan masukkan project ID Anda dalam satu langkah:
cp .env.example .env
sed -i "s|GOOGLE_CLOUD_PROJECT=your-project-id|GOOGLE_CLOUD_PROJECT=$(gcloud config get-value project)|" .env
Kemudian, buat bucket GCS tempat Designer akan menyimpan gambar yang dihasilkan dan perbarui .env dengan namanya:
export PROJECT_ID=$(gcloud config get-value project)
export BUCKET_NAME="${PROJECT_ID}-campaign-images"
gcloud storage buckets create gs://${BUCKET_NAME} \
--location=us-central1 \
--project=${PROJECT_ID}
sed -i "s|GCS_IMAGES_BUCKET=your-project-id-campaign-images|GCS_IMAGES_BUCKET=${BUCKET_NAME}|" .env
Kemudian, siapkan dukungan URL gambar bertanda tangan. Direktur Kreatif membuat link HTTPS yang dapat diklik untuk setiap gambar dalam ringkasan akhir kampanye. Hal ini memerlukan akun layanan untuk menandatangani URL. Jalankan perintah berikut untuk mengonfigurasinya:
export PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value project) --format="value(projectNumber)")
export SA_EMAIL="${PROJECT_NUMBER}-compute@developer.gserviceaccount.com"
export AGENT_RUNTIME_SA="service-${PROJECT_NUMBER}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
# Allow your user account to sign URLs locally (adk web)
gcloud iam service-accounts add-iam-policy-binding ${SA_EMAIL} \
--member="user:$(gcloud config get-value account)" \
--role="roles/iam.serviceAccountTokenCreator"
# Allow Agent Runtime to sign URLs when deployed
gcloud projects add-iam-policy-binding $(gcloud config get-value project) \
--member="serviceAccount:${AGENT_RUNTIME_SA}" \
--role="roles/iam.serviceAccountTokenCreator"
# Save SA email and project number to .env
grep -q "^SIGNING_SERVICE_ACCOUNT" .env \
&& sed -i "s|^SIGNING_SERVICE_ACCOUNT=.*|SIGNING_SERVICE_ACCOUNT=${SA_EMAIL}|" .env \
|| echo "SIGNING_SERVICE_ACCOUNT=${SA_EMAIL}" >> .env
grep -q "^GOOGLE_CLOUD_PROJECT_NUMBER" .env \
&& sed -i "s|^GOOGLE_CLOUD_PROJECT_NUMBER=.*|GOOGLE_CLOUD_PROJECT_NUMBER=${PROJECT_NUMBER}|" .env \
|| echo "GOOGLE_CLOUD_PROJECT_NUMBER=${PROJECT_NUMBER}" >> .env
Buka .env di editor untuk meninjau semua setelan:
cloudshell edit .env
Tindakan ini akan membuka .env sebagai tab di Cloud Shell Editor - klik tombol Open Editor di toolbar jika panel editor tidak terlihat:


Pastikan project telah disetel dengan benar:
grep GOOGLE_CLOUD_PROJECT .env
Menginstal dependensi
Kita menggunakan uv - pengelola paket Python modern yang cepat yang menangani lingkungan virtual dan menginstal dalam satu alat. Cara ini ~10-100x lebih cepat daripada pip dan merupakan cara yang direkomendasikan untuk mengelola project Python.
uv sudah diinstal di Cloud Shell. Semua agen memiliki dependensi inti yang sama, jadi instal sekali dan akan berfungsi untuk setiap agen dalam codelab ini:
uv sync
Perintah uv sync membaca pyproject.toml dan membuat direktori .venv/ dengan semua dependensi. Setiap spesialis juga memiliki pyproject.toml sendiri yang digunakan secara eksklusif oleh build Docker - penginstalan bersama di atas mencakup semua yang Anda butuhkan untuk pengujian lokal.
3. Memahami Google ADK
Sebelum menulis kode, mari kita pahami Agent Development Kit (ADK) - framework yang akan Anda gunakan untuk membangun setiap agen dalam codelab ini.
Apa itu ADK?
Agent Development Kit (ADK) adalah framework fleksibel dan modular untuk mengembangkan serta men-deploy agen AI. Meskipun dioptimalkan untuk Gemini dan ekosistem Google, ADK tidak bergantung pada model, tidak bergantung pada deployment, dan dibuat agar kompatibel dengan framework lain. ADK dirancang agar pengembangan agen terasa lebih seperti pengembangan software, sehingga memudahkan developer membuat, men-deploy, dan mengorkestrasi arsitektur agentic yang berkisar dari tugas sederhana hingga alur kerja yang kompleks.
ADK menangani bagian yang kompleks - panggilan alat, percakapan multi-giliran, pengelolaan konteks, streaming - sehingga Anda dapat berfokus pada logika agen.
Elemen penyusun agen ADK
Setiap agen terdiri dari empat elemen penyusun:
Blokir | Peran |
Model | LLM yang menalar sasaran, menentukan rencana, dan menghasilkan respons |
Alat | Fungsi yang mengambil data atau melakukan tindakan dengan memanggil API atau layanan |
Orkestrasi | Mempertahankan memori dan status di seluruh giliran, merutekan panggilan alat, meneruskan hasil kembali ke model |
Runtime | Mengeksekusi sistem saat dipanggil - secara lokal melalui |
Definisi agen
Setiap dari 5 agen dalam codelab ini ditentukan dengan cara yang sama:
from google.adk.agents import Agent
from google.adk.tools.google_search_tool import google_search
root_agent = Agent(
name="brand_strategist", # unique identifier
model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"), # the LLM powering this agent
instruction=SYSTEM_INSTRUCTION, # the agent's persona, constraints, and output format
description="Brand strategist for market research, trend analysis, and competitive insights",
tools=[google_search], # functions the LLM can call
)
Kolom | Tujuan |
| ID unik - digunakan oleh orkestrator untuk merutekan panggilan |
| Model Gemini yang mendukung agen ini |
| Perintah sistem - menentukan peran, batasan, dan format output agen |
| Ringkasan satu baris - orchestrator membaca ini untuk memutuskan spesialis mana yang akan dipanggil |
| Fungsi yang dapat dipanggil LLM (bawaan seperti |
Cara ADK menjalankan agen
User message
│
▼
Agent (LLM) ← reads instruction + conversation history
│
├─► needs more info? → calls a tool → gets result → continues reasoning
│
└─► done reasoning → returns final text response
LLM secara mandiri memutuskan apakah akan memanggil alat, alat mana yang akan dipanggil, dan dengan argumen apa. Anda menulis petunjuk - ADK akan menangani sisanya.
4. Membangun dan Menguji agen Brand Strategist
Mari kita mulai dengan agen pertama: Ahli Strategi Merek. Agen ini hanya untuk riset guna menelusuri insight audiens target, analisis kompetitor, dan topik trending menggunakan Google Penelusuran.
Buka file agen kerangka di Cloud Shell Editor:
cloudshell edit agents/brand_strategist/agent.py
Anda akan melihat dua bagian # TODO yang harus Anda isi.
TODO 1 - Tulis petunjuk sistem
Pertama, Anda akan menulis petunjuk sistem untuk agen. Petunjuk sistem adalah string yang menentukan peran, batasan, dan format output agen.
SYSTEM_INSTRUCTION = f"""You are a Brand Strategist specializing in market research and trend analysis.
IMPORTANT: Today's date is {datetime.date.today().strftime("%B %d, %Y")}.
When conducting research, focus on current trends from {datetime.date.today().year}.
Use search queries like "[topic] trends {datetime.date.today().year}" for recent insights.
IMPORTANT: Your role is RESEARCH ONLY. You do NOT create campaign content, captions, or designs.
After providing research insights, your work is complete.
Your expertise:
- Identifying target audience insights and behaviors
- Analyzing competitor strategies
- Researching current social media trends
- Understanding platform algorithms and best practices
You have access to:
- google_search: Search the web for competitors, trends, and market insights
When given a campaign brief:
1. Use google_search to research the target audience's current interests
2. Search for and analyze 2-3 competitor brands
3. Identify 3-5 trending topics related to the product category
4. Provide high-level strategic insights - NOT specific campaign content
DO NOT create captions, copy, designs, or any campaign content.
Format your output as:
**Audience Insights:**
[Key behaviors and preferences based on research]
**Competitive Analysis:**
[What 2-3 competitors are doing - strengths and weaknesses]
**Trending Topics:**
[3-5 relevant trends to consider]
**Key Strategic Insights:**
[High-level themes and positioning opportunities]
"""
TODO 2 - Buat root_agent
Selanjutnya, ganti root_agent yang belum selesai dengan:
root_agent = Agent(
name="brand_strategist",
model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"),
instruction=SYSTEM_INSTRUCTION,
description="Brand strategist for market research, trend analysis, and competitive insights",
tools=[google_search],
)
Menguji secara lokal dengan UI web ADK
Sekarang mari kita uji agen menggunakan UI web ADK - antarmuka chat bawaan untuk menguji agen sebelum men-deploy ke cloud.
uv run adk web agents --allow_origins='*'
Anda akan melihat:
INFO: Started server process
INFO: Uvicorn running on http://localhost:8000
Server kini berjalan di dalam Cloud Shell:
Untuk membukanya di browser, gunakan Pratinjau Web:
- Lihat toolbar Cloud Shell di bagian atas halaman
- Klik ikon Web Preview (terlihat seperti kotak dengan panah ke atas, di kanan atas toolbar Cloud Shell)
- Klik "Ubah port" dan masukkan
8000, lalu klik "Ubah dan Pratinjau"
Tab browser baru akan terbuka dengan UI web ADK. Klik dropdown "Select an agent" di kiri atas - Anda akan melihat semua agen Anda tercantum:
Pilih brand_strategist untuk mulai menguji:
Coba perintah pengujian berikut
Di kotak chat UI web ADK, coba:
Research the eco-friendly water bottle market for health-conscious millennialsWhat are the top Instagram trends in the wellness space in 2025?
Anda akan melihat agen memanggil Google Penelusuran dan menampilkan riset terstruktur dengan bagian Audience Insights, Competitive Analysis, dan Trending Topics.
5. Membangun Keterampilan Copywriter - ADK
Peran: Mengubah riset merek menjadi teks Instagram. Copywriter membuat 3 variasi teks yang mencakup berbagai gaya bahasa (inspiratif, edukatif, komunitas), masing-masing dengan hashtag dan CTA.
Konsep: Keterampilan ADK
Pendekatan sederhana akan menyematkan semua pengetahuan platform - batas karakter, tingkat hashtag, formula teks, contoh gaya bahasa merek - langsung dalam perintah sistem. Cara ini memang berfungsi, tetapi membuat setiap permintaan menjadi besar dengan konten yang hanya dibutuhkan agen sesekali.
Keterampilan ADK (SkillToolset, diperkenalkan di ADK 1.25.0) memungkinkan Anda mengemas pengetahuan tersebut ke dalam file modular dengan tiga tingkat pemuatan:
- L1 - frontmatter (
name+descriptiondiSKILL.md): selalu tersedia, digunakan untuk penemuan skill - L2 - instructions (isi
SKILL.md): dimuat saat agen memicu skill - L3 - resource (file
references/danassets/): dimuat hanya saat agen membacanya secara eksplisit
Petunjuk sistem menyusut menjadi pernyataan peran singkat ditambah "muat skill sebelum menulis". Detail platform hanya masuk ke periode konteks saat agen benar-benar membutuhkannya.
Keahlian Copywriter ada di agents/copywriter/skills/instagram-copywriting/:
skills/
instagram-copywriting/
SKILL.md ← L1 frontmatter (discovery) + L2 instructions (loaded on trigger)
references/
platform-guide.md ← L3: character limits, hashtag tiers, algorithm signals
caption-formulas.md ← L3: hook formulas, CTA patterns, full caption structures
assets/
brand-voice-examples.md ← L3: annotated real-world caption examples
Buka file langsung di editor Cloud Shell:
cloudshell edit agents/copywriter/agent.py
TODO 1 - Impor load_skill_from_dir dan skill_toolset
Cari komentar # TODO 1: Import load_skill_from_dir and skill_toolset dan tambahkan dua impor:
from google.adk.skills import load_skill_from_dir
from google.adk.tools import skill_toolset
TODO 2 - Muat keahlian dan buat SkillToolset
Temukan dua komentar di bawah impor:
# TODO 2: Load the instagram-copywriting skill from the skills/ directory
# TODO 2: Create a SkillToolset with the loaded skill
Ganti dengan:
_instagram_skill = load_skill_from_dir(
pathlib.Path(__file__).parent / "skills" / "instagram-copywriting"
)
_copywriting_skills = skill_toolset.SkillToolset(skills=[_instagram_skill])
load_skill_from_dir membaca SKILL.md serta file apa pun di references/ dan assets/. SkillToolset membungkusnya ke dalam format yang diterima agen ADK - toolset, bukan kemampuan mentah.
TODO 3 - Mendaftarkan toolset ke agen
Temukan tools=[], # TODO 3: Add the SkillToolset here dan ganti dengan:
tools=[_copywriting_skills],
Buka file skill untuk melihat strukturnya:
cloudshell edit agents/copywriter/skills/instagram-copywriting/SKILL.md
Biarkan UI web ADK tetap berjalan. Gunakan dropdown agen untuk beralih ke copywriter tanpa memulai ulang server.
Jika tidak berjalan, mulai lagi:
uv run adk web agents --allow_origins='*'
Coba: Alihkan dropdown ke copywriter dan kirim:
You are writing captions for EcoFlow Smart Water Bottle targeting health-conscious millennials aged 25-35.
Audience insight: they prioritize sustainability, track health metrics, and share lifestyle content.
Competitor insight: Hydro Flask dominates with lifestyle branding; S'well leads on premium aesthetics.
Write 3 Instagram captions - one inspirational, one educational, one community-focused. Include 5 hashtags each and a CTA.
6. Membangun Designer - Pembuatan Gambar Multimodal
Biarkan UI web ADK tetap berjalan. Gunakan dropdown agen untuk mengganti agen tanpa memulai ulang server.
Peran: Membuat konsep visual untuk setiap teks dan membuat gambar sebenarnya menggunakan pembuatan gambar native Gemini. Designer menghasilkan tepat 1 konsep visual per teks - dengan perintah, gaya, palet warna, suasana, dan format Instagram yang mendetail - lalu segera memanggil alat generate_image untuk menghasilkan gambar sebenarnya dan menguploadnya ke GCS.
Konsep: Menghubungkan agen teks dengan model gambar melalui alat
Desainer berjalan di gemini-3-flash-preview (model teks yang ditetapkan melalui GEMINI_MODEL di .env), tetapi pembuatan gambar memerlukan model khusus (gemini-3.1-flash-image-preview). Model gambar tersebut tidak mendukung panggilan fungsi, sehingga tidak dapat digunakan secara langsung sebagai agen ADK. Sebagai gantinya, fungsi ini di-wrap dalam fungsi Python biasa dan didaftarkan sebagai FunctionTool.
Pola ini berlaku untuk model atau API apa pun yang tidak dapat dipanggil LLM secara langsung: bungkus dalam alat, biarkan agen mengatur kapan harus memanggilnya, dan dapatkan hasil terstruktur.
Designer agent (text model)
│
│ decides visual concept, writes image prompt
▼
generate_image tool
│
│ calls gemini-3.1-flash-image-preview
│ uploads result to GCS
▼
{"status": "success", "gcs_uri": "gs://..."}
│
│ returned to agent, included in response
▼
Critic (receives gcs_uri, passes to Vertex AI for multimodal review)
Buka file langsung di editor Cloud Shell:
cloudshell edit agents/designer/image_gen_tool.py
Tanda tangan fungsi, penyiapan lingkungan, dan penyisipan rasio aspek disediakan. Selesaikan ketiga TODO secara berurutan:
TODO 1 - Panggil model gambar Gemini
Temukan komentar # TODO 1 dan ganti dengan:
client = genai.Client(vertexai=True, project=project_id, location=location)
response = client.models.generate_content(
model=image_model,
contents=prompt_with_aspect,
config=types.GenerateContentConfig(
response_modalities=["IMAGE", "TEXT"],
http_options=types.HttpOptions(
retry_options=types.HttpRetryOptions(
attempts=5, exp_base=2, initial_delay=30,
http_status_codes=[429, 500, 503, 504],
),
timeout=180_000,
),
),
)
TODO 2 - Ekstrak byte gambar dari respons
Temukan komentar # TODO 2 dan ganti dengan:
image_bytes = None
mime_type = "image/png"
for part in response.candidates[0].content.parts:
if part.inline_data is not None:
image_bytes = part.inline_data.data
mime_type = part.inline_data.mime_type or "image/png"
break
if not image_bytes:
return {"status": "error", "error": "Gemini returned no image data"}
TODO 3 - Upload ke GCS dan menampilkan URI
Temukan komentar # TODO 3 dan ganti dengan:
ext = "jpg" if "jpeg" in mime_type else "png"
from google.cloud import storage
gcs_client = storage.Client(project=project_id)
bucket = gcs_client.bucket(bucket_name)
blob_name = f"campaign-images/{concept_name}-{uuid.uuid4().hex[:8]}.{ext}"
blob = bucket.blob(blob_name)
blob.upload_from_file(io.BytesIO(image_bytes), content_type=mime_type)
gcs_uri = f"gs://{bucket_name}/{blob_name}"
Coba: Alihkan dropdown ke designer dan kirim:
Create a visual concept and generate the image for an EcoFlow Smart Water Bottle Instagram post targeting health-conscious millennials.
Style: clean, modern, lifestyle-focused. Include a detailed prompt with color palette, mood, and format (1080x1080 or 1080x1350).
7. Membangun Kritikus - Output Terstruktur
Peran: Memastikan kualitas teks dan visual sebelum diserahkan kepada Project Manager. Kritikus menilai kedua hasil kerja dan menampilkan APPROVED atau NEEDS_REVISION dengan saran spesifik. Jika nilai gcs_uri ada dalam input, alat review_image akan dipanggil untuk memeriksa setiap gambar yang dihasilkan secara visual sebelum diberi skor.
Konsep: Kapan menggunakan model Pydantic untuk output Gemini
Aturan ini terkait siapa yang menggunakan output:
- Kode Python menggunakannya → gunakan
response_schema+ Pydantic. Kode tidak dapat menangani ambiguitas, jadi Anda memerlukan struktur yang terjamin untuk mengekstrak kolom secara andal. - LLM menggunakannya → format teks + petunjuk sistem sudah cukup. LLM memahami aturan pemformatan dan mentoleransi variasi.
Di review_image, kode Python memerlukan score, approval_status, what_works, issues, dan suggestions sebagai nilai yang diketik. Penerusan response_schema=_GeminiReview membatasi Gemini di tingkat API untuk menampilkan JSON yang valid; model_validate_json() menguraikannya menjadi objek yang diketik yang dapat digunakan kode Anda dengan andal.
class _GeminiReview(BaseModel):
score: int = Field(ge=1, le=10)
approval_status: Literal["APPROVED", "NEEDS_REVISION"]
what_works: str
issues: str
suggestions: str
Buka file langsung di editor Cloud Shell:
cloudshell edit agents/critic/image_review_tool.py
Model Pydantic dan perintah disediakan. Selesaikan ketiga TODO secara berurutan:
TODO 1 - Buat bagian gambar dari URI GCS
Temukan komentar # TODO 1 dan ganti dengan:
image_part = types.Part.from_uri(file_uri=gcs_uri, mime_type=mime_type)
TODO 2 - Panggil Gemini dengan skema respons terstruktur
Temukan komentar # TODO 2 dan ganti dengan:
response = client.models.generate_content(
model=model,
contents=[image_part, prompt],
config=types.GenerateContentConfig(
response_schema=_GeminiReview,
response_mime_type="application/json",
),
)
TODO 3 - Parse respons dan tampilkan hasilnya
Temukan komentar # TODO 3 dan ganti dengan:
review = _GeminiReview.model_validate_json(response.text)
return ImageReviewResult(status="success", concept_name=concept_name, **review.model_dump())
Coba: Alihkan dropdown ke critic dan kirim:
Review this Instagram caption for an eco-friendly water bottle brand targeting millennials:
"Hydrate smarter, live greener. 💧 Our EcoFlow bottle tracks your intake, keeps your drink cold for 24h, and never touches single-use plastic. Because what you drink from matters as much as what you drink. #EcoFlow #HydrationGoals #SustainableLiving #ZeroWaste #HealthyHabits - Shop link in bio."
Score it and indicate APPROVED or NEEDS_REVISION with specific feedback.
Verifikasi bahwa respons berisi **POSTS REVIEW:**, Status: APPROVED (atau NEEDS_REVISION), dan **OVERALL ASSESSMENT:**. Jika bagian tersebut ada, Critic siap dihubungkan ke orkestrator.
Setelah Anda selesai menguji ketiga agen, tekan Ctrl+C untuk menghentikan server.
8. Membangun Agen Project Manager dengan MCP
Project Manager memperkenalkan konsep baru: MCP (Model Context Protocol).
Buka file:
cloudshell edit agents/project_manager/agent.py
File ini lebih kompleks - memiliki fungsi create_project_manager_agent() dengan dua cabang: satu tanpa Notion (linimasa hanya teks) dan satu dengan toolset MCP Notion. Anda akan mengisi keduanya.
Masalah yang diatasi MCP
Agen Anda perlu memanggil layanan eksternal - misalnya, membuat halaman di Notion. Anda dapat menulis kode Python yang memanggil Notion REST API secara langsung. Namun, kemudian:
- Setiap developer menulis wrapper yang berbeda
- Anda perlu mempertahankan kode integrasi kustom
- LLM tidak mengetahui keberadaan API kecuali jika Anda menjelaskan setiap endpoint secara manual
MCP memecahkan masalah ini dengan menentukan cara standar bagi layanan eksternal untuk mengekspos kemampuannya sebagai alat yang dapat ditemukan dan dipanggil secara otomatis oleh LLM.
Apa itu MCP?
MCP (Model Context Protocol) adalah standar terbuka (dipublikasikan oleh Anthropic) untuk menghubungkan agen AI ke alat dan sumber data eksternal. Cara kerjanya seperti adaptor universal.
Server MCP adalah program kecil yang:
- Membungkus API eksternal (Notion, GitHub, database, filesystem...)
- Mengekspos API tersebut sebagai daftar alat yang diketik dan didokumentasikan
- Berkomunikasi dengan agen melalui protokol sederhana (stdio atau HTTP)
Agen terhubung ke server MCP, otomatis menemukan alat yang tersedia, dan dapat memanggilnya seperti alat lainnya - LLM melihat API-post-page(...) sebagai fungsi yang dapat dipanggil.
A2A vs MCP - apa perbedaannya?
Hal ini sering kali membingungkan. Berikut perbedaan utamanya:
A2A | MCP | |
Yang terhubung | Agen ↔ Agen | Agen ↔ Alat/layanan eksternal |
Sisi lainnya adalah | Agen LLM lainnya | Wrapper API (tanpa LLM) |
Contoh | Direktur Kreatif menelepon Pakar Strategi Merek | Project Manager memanggil Notion API |
Protokol | JSON-RPC melalui HTTPS | Aliran stdio atau HTTP |
Ditentukan oleh | Anthropic |
Pikirkan seperti ini:
- A2A = cara agen berkomunikasi dengan agen lain
- MCP = cara agen berkomunikasi dengan alat dan layanan
Dalam project ini, keduanya digunakan bersama:
Creative Director
│
│ (A2A) Brand Strategist ─── (google_search tool built into ADK)
│ (A2A) Copywriter
│ (A2A) Designer
│ (A2A) Critic
│ (A2A) Project Manager
│
│ (MCP) notion-mcp-server ──► Notion REST API
Cara kerja MCP dalam project ini
Saat agen berjalan, ADK meluncurkan notion-mcp-server sebagai proses turunan. Proses tersebut mengekspos alat ini langsung ke LLM:
Alat | Fungsinya |
| Mengambil skema (nama properti, jenis, nilai yang valid) |
| Mengkueri halaman yang ada |
| Membuat halaman baru |
| Memperbarui halaman yang ada |
LLM memanggilnya seperti fungsi lainnya - LLM tidak tahu bahwa fungsi tersebut melewati MCP ke Notion REST API di balik layar.
Mengapa stdio? Mengapa tidak menggunakan HTTP saja?
Server MCP berjalan sebagai proses turunan agen, yang berkomunikasi melalui stdin/stdout. Artinya:
- Tidak memerlukan port jaringan tambahan
- Siklus proses dikelola oleh agen (dimulai sesuai permintaan, dihentikan saat keluar)
- Semuanya dikirim dalam satu image Docker - tidak ada layanan terpisah untuk di-deploy
(Opsional) Mengaktifkan Integrasi Notion
Anda dapat melewati seluruh bagian ini. Agen Project Manager selalu menghasilkan linimasa kampanye berbasis teks yang lengkap, dengan atau tanpa Notion. Jika Anda melewati penyiapan ini, agen akan kembali ke mode dalam memori dan menampilkan linimasa sebagai teks biasa dalam chat. Tidak ada yang rusak - Anda hanya tidak akan melihat tugas muncul di database Notion. Langsung buka TODO 1 jika Anda ingin melewati.
Jika Anda memiliki akun Notion dan ingin melihat cara kerja integrasi MCP, selesaikan penyiapan di bawah sekarang. TODO yang mengikuti merujuk pada ID database Notion - di sinilah Anda mendapatkannya.
Langkah 1 - Buat database Notion dari template
Kami menggunakan template Notion Projects & Tasks resmi sebagai database kami. Kami sengaja memilih template ini untuk mendemonstrasikan setelan dunia nyata yang kompleks - template ini memiliki beberapa jenis properti (status, rentang tanggal, relasi, pilihan) dengan nama yang tidak jelas. Ini adalah pengujian yang bagus untuk penemuan skema dinamis MCP: agen harus mengetahui nama properti yang tepat saat runtime, bukan memiliki nama properti yang di-hardcode.
Klik link di bawah untuk menambahkan template ke ruang kerja Notion Anda:
→ Menambahkan template "Projects & Tasks" ke Notion

Setelah ditambahkan, Anda akan memiliki dua database tertaut: Projects dan Tasks. Template dilengkapi dengan contoh entri - hapus semuanya sebelum melanjutkan agar agen memulai dengan ruang kerja yang bersih (pilih semua → Hapus).
Langkah 2 - Buat integrasi Notion
Buat integrasi:
- Buka notion.so/my-integrations
- Klik New Integration → beri nama
AI Creative Studio - Mengaitkannya dengan ruang kerja Anda
- Klik Konfigurasi setelan → pastikan kemampuan Baca konten, Perbarui konten, dan Sisipkan konten semuanya dicentang

- Salin Internal Integration Token (
ntn_...) dan tempelkan ke file.envAnda:
NOTION_TOKEN=ntn_your-token-here
Hubungkan integrasi ke database Anda:
- Buka halaman template yang baru saja Anda duplikasikan, lalu klik database Projects
- Klik menu
...(kanan atas) → Koneksi → Tambahkan koneksi → pilihAI Creative Studio


- Lakukan hal yang sama untuk database Tasks
Mendapatkan ID database:
- Klik link database Projects untuk membukanya - link ini akan terbuka di halamannya sendiri dengan URL seperti:
https://www.notion.so/9887b6a94f7f83f68f8581e038d1aaa4?v=2c37b6a94f7f838685f1086e312c7278

ID database adalah UUID pertama dalam URL - semua yang ada sebelum ?v=:
https://www.notion.so/{DATABASE_ID}?v=...
^^^^^^^^^^^^^^^^
9887b6a94f7f83f68f8581e038d1aaa4 ← this is your DATABASE_ID
- Lakukan hal yang sama untuk link database Tasks guna mendapatkan ID databasenya
- Tambahkan ketiga nilai ke
.envAnda:
NOTION_TOKEN=ntn_your-token-here
NOTION_PROJECT_DATABASE_ID=9887b6a94f7f83f68f8581e038d1aaa4 # <-- your Projects DB ID
NOTION_TASKS_DATABASE_ID=your-tasks-db-id # <-- your Tasks DB ID
Langkah 3 - Instal server MCP Notion
Project Manager terhubung ke Notion melalui paket Node.js @notionhq/notion-mcp-server resmi. Instal secara global:
npm install -g @notionhq/notion-mcp-server@1.9.1
Verifikasi penginstalan:
npm list -g @notionhq/notion-mcp-server
Output yang diharapkan:
└── @notionhq/notion-mcp-server@1.9.1
notion-mcp-server: command not found
? Pastikan Node.js telah diinstal (node --version) dan bin global npm Anda ada di PATH Anda (export PATH=$PATH:$(npm bin -g)).
Langkah 4 - Verifikasi .env Anda
Buka .env dan konfirmasi bahwa ketiga nilai Notion telah ditetapkan (Anda menambahkannya di Langkah 2):
cloudshell edit .env
NOTION_TOKEN=ntn_... # integration token
NOTION_PROJECT_DATABASE_ID=... # Projects database ID
NOTION_TASKS_DATABASE_ID=... # Tasks database ID
Agen Project Manager otomatis mendeteksi variabel ini saat startup dan mengaktifkan set alat MCP Notion.
Cara kerja penemuan skema
Project Manager menggunakan penemuan skema dinamis - tidak pernah meng-hardcode nama properti Notion:
Step 1: Call API-retrieve-a-database to discover exact property names
Step 2: Read the "properties" object in the response
Step 3: Use ONLY discovered property names (case-sensitive) in API calls
Step 4: For select/status fields, use only values from the options array
Artinya, agen akan otomatis menyesuaikan diri dengan struktur database Notion apa pun - ganti nama properti Anda ke bahasa Prancis, Arab, atau bahasa lainnya, dan agen akan tetap berfungsi.
TODO 1 - Tulis petunjuk sistem
Starter sudah menghitung notion_section - string kosong saat Notion tidak dikonfigurasi, atau blok yang berisi ID database ditambah panduan alat lengkap saat dikonfigurasi. Hal ini membuat petunjuk Notion sepenuhnya tidak ada dalam perintah agen tanpa Notion; LLM tidak pernah melihat aturan untuk alat yang tidak dimilikinya.
Tugas Anda adalah mengganti placeholder return dengan petunjuk sistem sebenarnya yang menggunakan {notion_section}:
return f"""You are a Project Manager specializing in creative campaign execution.
Today's date is {datetime.date.today().strftime("%B %d, %Y")}.
Use this as the starting point for all timelines.
Your goal: create a complete project plan for the campaign.
{notion_section}
**Project Timeline:**
Phase 1: Strategy & Research | [date] → [date] | [key activities]
Phase 2: Content Creation | [date] → [date] | [key activities]
Phase 3: Review & Revision | [date] → [date] | [key activities]
Phase 4: Launch & Monitoring | [date] → [date] | [key activities]
**Task List:**
| Task | Owner | Deadline | Status |
[list each task with realistic deadlines from today; set Owner to TBD]
**Budget Breakdown:**
[by category with approximate allocations]
**Milestones:**
[3-5 key checkpoints with dates]
**Notion Status:**
[What happened - e.g. "Project created (ID: xxx), 8 tasks linked" or "Notion not configured - text timeline only"]
"""
TODO 2 - Agen tanpa Notion
Di dalam create_project_manager_agent(), di cabang if not notion_token, ganti agen yang belum lengkap dengan:
return Agent(
name="project_manager",
model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"),
generate_content_config=GENERATE_CONTENT_CONFIG,
instruction=get_system_instruction(),
description="Project manager that creates campaign timelines and task breakdowns",
)
TODO 3 - Agen dengan Notion MCP
Catatan: File awal sudah berisi callback handle_notion_error yang telah ditulis sebelumnya di atas create_project_manager_agent(). Alat ini mencegat error Notion API (400/404) dan mengganti payload error mentah dengan pesan yang jelas dan dapat ditindaklanjuti sehingga LLM dapat mengoreksi diri sendiri. Anda hanya perlu menghubungkannya melalui after_tool_callback.
Pertama, baca kedua ID database di bagian atas create_project_manager_agent():
notion_token = os.getenv("NOTION_TOKEN")
notion_project_db_id = os.getenv("NOTION_PROJECT_DATABASE_ID")
notion_tasks_db_id = os.getenv("NOTION_TASKS_DATABASE_ID")
Kemudian di cabang else, buat toolset MCP dan agen:
from google.adk.tools.mcp_tool import McpToolset, StdioConnectionParams
from mcp import StdioServerParameters
server_params = StdioServerParameters(
command="notion-mcp-server",
env={
"NOTION_TOKEN": notion_token,
"PATH": os.environ.get("PATH", ""),
}
)
notion_toolset = McpToolset(
connection_params=StdioConnectionParams(
server_params=server_params,
timeout=30.0
)
)
return Agent(
name="project_manager",
model=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"),
generate_content_config=GENERATE_CONTENT_CONFIG,
after_tool_callback=handle_notion_error,
instruction=get_system_instruction(
project_database_id=notion_project_db_id,
tasks_database_id=notion_tasks_db_id,
),
description="Project manager with Notion integration for task tracking",
tools=[notion_toolset],
)
Praktik terbaik: Jangan pernah gagal total pada integrasi opsional. Linimasa teks selalu menjadi hasil utama; Notion bersifat tambahan.
Menguji Project Manager Secara Lokal dengan ADK Web
uv run adk web agents --allow_origins='*'
Buka Pratinjau Web di port 8000. Gunakan dropdown agen untuk memilih project_manager, lalu coba:
Create a project plan for a GreenBrew organic coffee brand Instagram campaign.
Budget: $2,500. Launch in 3 weeks. Target audience: eco-conscious millennials aged 22-30.
Include phases, tasks with deadlines from today, and milestones.
Anda akan melihat linimasa teks terstruktur dengan fase, daftar tugas, dan tonggak pencapaian. Jika kredensial Notion ditetapkan di .env, agen juga akan membuat entri di ruang kerja Notion Anda.
9. Memahami A2A Protocol
Kita akan menggunakan Protokol Agent-to-Agent (A2A) untuk menghubungkan berbagai agen dalam sistem kita. Mari kita pahami cara kerjanya.
Masalah yang dipecahkan A2A
Bayangkan Anda memiliki agen Brand Strategist yang dibangun dengan ADK dan agen Copywriter yang dibangun dengan LangGraph. Bagaimana cara memanggil orang lain? Mereka menggunakan bahasa internal yang berbeda. Anda harus menulis kode penggabungan kustom setiap saat.
A2A mengatasi hal ini dengan menentukan bahasa universal yang dapat digunakan oleh agen mana pun, terlepas dari framework-nya. Ini adalah HTTP dunia agen: standar yang disepakati semua orang sehingga siapa pun dapat berbicara dengan siapa pun.
Apa itu A2A?
Agent-to-Agent (A2A) adalah standar terbuka untuk komunikasi agen yang dipublikasikan oleh Google. Parameter ini menentukan:
- Cara agen mendeskripsikan dirinya sendiri - kartu agen di
/.well-known/agent.json - Cara agen lain memanggilnya - JSON-RPC melalui HTTPS
- Cara hasil ditampilkan - streaming atau respons tunggal
Yang membuat A2A fleksibel:
- Agnostik bahasa - Agen Python dapat berkomunikasi dengan agen TypeScript
- Agnostik framework - Agen ADK dapat berkomunikasi dengan agen LangGraph atau CrewAI
- Agnostik terhadap infrastruktur - agen lokal dapat berkomunikasi dengan agen cloud
Cara kerjanya - langkah demi langkah
Creative Director Brand Strategist
│ │
│ 1. GET /.well-known/agent.json │
│ ────────────────────────────────►│
│ ◄──── agent card (name, url, │
│ skills, capabilities) ───│
│ │
│ 2. POST / │
│ {"method": "tasks/send", │
│ "params": {"message": ...}} │
│ ────────────────────────────────►│
│ │ LLM does
│ │ the work...
│ 3. streaming response chunks │
│ ◄───────────────────────────────│
│ ◄───────────────────────────────│
│ ◄───────────────────────────────│
Langkah 1 - Penemuan: Pengelola mengambil kartu agen satu kali untuk mempelajari nama, URL, dan kemampuan agen.
Langkah 2 - Pemanggilan: Pengelola mengirimkan tugas melalui JSON-RPC POST. Isi berisi pesan (perintah untuk spesialis).
Langkah 3 - Respons: Pakar akan mengalirkan kembali responsnya dalam bagian-bagian, seperti panggilan LLM biasa.
Kartu agen
Setiap agen memublikasikan deskripsi dirinya di /.well-known/agent.json. Ini seperti kartu nama - memberi tahu dunia tentang kemampuan agen dan tempat untuk menghubunginya:
{
"name": "brand_strategist",
"description": "Market research and competitive analysis",
"url": "https://brand-strategist-xyz.run.app",
"capabilities": { "streaming": true },
"skills": [
{
"id": "market_research",
"description": "Research target audiences, competitors, and trends"
}
]
}
Orchestrator membaca kartu ini untuk membuat objek RemoteA2aAgent-nya - tidak diperlukan pengetahuan hardcode tentang internal spesialis.
Mengekspos agen melalui A2A di ADK
to_a2a() membungkus agen ADK apa pun dalam aplikasi FastAPI yang kompatibel dengan A2A. Satu baris:
from google.adk.a2a.utils.agent_to_a2a import to_a2a
# root_agent = your normal ADK Agent(...)
a2a_app = to_a2a(root_agent, host=PUBLIC_HOST, port=PUBLIC_PORT, protocol=PROTOCOL)
uvicorn.run(a2a_app, host=HOST, port=PORT)
Tindakan ini akan otomatis membuat:
/.well-known/agent.json- kartu agen/- endpoint JSON-RPC (semua permintaan tugas A2A masuk ke jalur root)
10. Mengekspos agen sebagai layanan A2A
Untuk mengekspos agen sebagai layanan A2A, Anda dapat menggunakan fungsi utilitas to_a2a() dari ADK.
Cara kerja to_a2a()
from google.adk.a2a.utils.agent_to_a2a import to_a2a
a2a_app = to_a2a(root_agent, host=PUBLIC_HOST, port=PUBLIC_PORT, protocol=PROTOCOL)
uvicorn.run(a2a_app, host=HOST, port=PORT)
to_a2a() membungkus agen ADK Anda dalam aplikasi FastAPI yang otomatis mengekspos:
/.well-known/agent.json- kartu agen (nama, deskripsi, kemampuan)/a2a/{agent_name}- endpoint JSON-RPC untuk menerima tugas
Kode kerangka setiap agen sudah menyertakan blok __main__ yang membungkus agen di server A2A menggunakan to_a2a(). Anda tidak perlu menulis kode ini - kode ini sudah disediakan.
Memahami konfigurasi URL ganda
Saat Anda menjalankan python agent.py, blok __main__ menggunakan dua konfigurasi URL terpisah:
# Where the server actually listens (network interface):
HOST = "0.0.0.0"
PORT = 8082 # Brand Strategist (others use 8083–8086 locally)
# What gets advertised in the agent card (the address other agents use to reach it):
PUBLIC_HOST = os.getenv("PUBLIC_HOST", "localhost")
PUBLIC_PORT = int(os.getenv("PUBLIC_PORT", str(PORT)))
PROTOCOL = os.getenv("PROTOCOL", "http")
a2a_app = to_a2a(root_agent, host=PUBLIC_HOST, port=PUBLIC_PORT, protocol=PROTOCOL)
uvicorn.run(a2a_app, host=HOST, port=PORT)
Lingkungan |
|
|
Lokal |
|
|
Cloud Run |
|
|
Secara lokal, keduanya mengarah ke mesin yang sama. Di Cloud Run, penampung memproses secara internal di 8080, tetapi kartu agen harus mengiklankan URL HTTPS publik. Jika tidak, Creative Director tidak dapat menghubungi spesialis dari luar penampung.
Mulai semua 5 server A2A spesialis
Mari jalankan kelima spesialis sebagai server A2A secara bersamaan, lalu uji Creative Director secara lokal yang mengarah ke mereka.
Buka 5 terminal Cloud Shell terpisah (klik ikon + di panel tab terminal) dan jalankan satu agen per terminal.
uv run mengaktifkan .venv secara otomatis - tidak perlu source manual di setiap terminal.
Terminal 1 - Brand Strategist (port 8082):
cd ~/ai-creative-studio/workshop/starter
PORT=8082 uv run agents/brand_strategist/agent.py
Terminal 2 - Copywriter (port 8083):
cd ~/ai-creative-studio/workshop/starter
PORT=8083 uv run agents/copywriter/agent.py
Terminal 3 - Desainer (port 8084):
cd ~/ai-creative-studio/workshop/starter
PORT=8084 uv run agents/designer/agent.py
Terminal 4 - Kritikus (port 8085):
cd ~/ai-creative-studio/workshop/starter
PORT=8085 uv run agents/critic/agent.py
Terminal 5 - Project Manager (port 8086):
cd ~/ai-creative-studio/workshop/starter
PORT=8086 uv run agents/project_manager/agent.py
Menetapkan URL localhost di .env
Di Terminal 6, perbarui .env dengan URL agen lokal agar Creative Director dapat menemukannya:
cd ~/ai-creative-studio/workshop/starter
sed -i \
-e 's|STRATEGIST_AGENT_URL=.*|STRATEGIST_AGENT_URL=http://localhost:8082|' \
-e 's|COPYWRITER_AGENT_URL=.*|COPYWRITER_AGENT_URL=http://localhost:8083|' \
-e 's|DESIGNER_AGENT_URL=.*|DESIGNER_AGENT_URL=http://localhost:8084|' \
-e 's|CRITIC_AGENT_URL=.*|CRITIC_AGENT_URL=http://localhost:8085|' \
-e 's|PM_AGENT_URL=.*|PM_AGENT_URL=http://localhost:8086|' \
.env
Memeriksa agen dengan A2A Inspector
A2A Inspector adalah alat developer open source yang menggunakan protokol A2A secara native. Dengan alat ini, Anda dapat terhubung langsung ke agen A2A yang sedang berjalan, membaca kartu agennya, dan mengirim tugas - semuanya tanpa menulis kode klien apa pun.
Informasi yang ditampilkan:
- Kartu agen - metadata terstruktur yang diiklankan agen Anda: nama, deskripsi, mode input/output yang didukung, dan URL endpoint-nya. Inilah yang dibaca Direktur Kreatif saat menemukan spesialis.
- Antarmuka chat - kirim pesan apa pun ke agen melalui A2A dan lihat respons mentahnya. Anda dapat menguji perintah secara terpisah sebelum menghubungkan agen.
- Validasi protokol - pemeriksa memastikan bahwa kartu agen sesuai dengan spesifikasi A2A, menampilkan kolom yang tidak ada atau respons yang salah format lebih awal.
Mengapa hal ini penting: Saat Anda men-deploy ke Cloud Run nanti, Creative Director akan menemukan setiap spesialis dengan mengambil kartu agennya dari /.well-known/agent.json. Jika kartu tersebut salah - URL buruk, kemampuan tidak ada - orkestrator akan gagal secara diam-diam. Pemeriksa memungkinkan Anda mendeteksi masalah ini secara lokal sebelum deployment cloud.

Kartu agen menampilkan identitas dan kemampuan spesialis persis seperti yang dilihat agen lain.

Menginstal dan memulai pemeriksa
cd ~/ai-creative-studio/workshop
./setup_inspector.sh
Update .env adalah perintah satu kali. Gunakan Terminal 6 untuk memulai pemeriksa berikutnya:
cd ~/a2a-inspector
bash scripts/run.sh
Untuk membuka UI pemeriksa, gunakan Web Preview → Change port → ketik 5001.
Terhubung dengan Brand Strategist
Masukkan http://localhost:8082 di kolom URL pemeriksa, lalu klik Hubungkan. Pemeriksa mengambil kartu agen dan menampilkan metadata spesialis.

Informasi yang ditampilkan kartu agen
Kartu agen lebih dari sekadar metadata - kartu ini adalah kontrak kapabilitas lengkap yang diiklankan agen ke jaringan. Hubungkan ke Project Manager (http://localhost:8086) untuk melihat contoh yang paling lengkap:
{
"name": "project_manager",
"description": "Project manager with Notion integration for task tracking",
"protocolVersion": "0.3.0",
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["text/plain"],
"skills": [
{
"id": "project_manager",
"name": "model",
"tags": ["llm"],
"description": "... full system instruction including today's date and Notion database IDs ..."
},
{
"id": "project_manager-API-post-page",
"name": "API-post-page",
"tags": ["llm", "tools"],
"description": "Notion | Create a page"
},
{
"id": "project_manager-API-retrieve-a-database",
"name": "API-retrieve-a-database",
"tags": ["llm", "tools"],
"description": "Notion | Retrieve a database"
}
]
}
Ada tiga hal yang terlihat jelas:
1. Alat MCP menjadi kemampuan A2A - Setiap alat Notion yang dapat diakses oleh Project Manager (API-post-page, API-retrieve-a-database, dll.) dicantumkan sebagai kemampuan terpisah di kartu agen. Agen lain di jaringan dapat menemukan secara persis alat apa yang dapat digunakan agen ini - tanpa membaca kode apa pun.
2. Petunjuk sistem disematkan - description keterampilan pertama berisi petunjuk sistem lengkap, termasuk tanggal hari ini dan ID database Notion. Dengan cara ini, Direktur Kreatif mengetahui apa yang harus diteruskan saat memanggil Manajer Proyek.
3. URL adalah endpoint aktif - Bidang url adalah apa yang digunakan RemoteA2aAgent saat Creative Director memanggil spesialis ini. Jika URL di kartu salah, orkestrator tidak dapat menjangkau agen.
Inilah alasan mengapa pemeriksa adalah alat pen-debug yang canggih: sekilas melihat kartu agen akan memberi tahu Anda apakah agen sedang berjalan, alat apa yang dimilikinya, dan apakah endpoint sudah benar.
Mengirim pesan uji coba
Setelah terhubung, ketik perintah di panel chat, lalu kirimkan. Pemeriksa mengirimkannya sebagai tugas A2A dan mengalirkan respons kembali - sama seperti cara Direktur Kreatif akan memanggil agen ini dalam produksi.

Arahkan pemeriksa ke port lokal (8082–8086) untuk menguji setiap spesialis satu per satu.
11. Membangun Pengelola Direktur Kreatif
Direktur Kreatif adalah pengatur utama. Plugin ini membaca URL spesialis dari variabel lingkungan, membungkus setiap URL sebagai RemoteA2aAgent, dan mengeksposnya sebagai AgentTool yang dapat dipanggil oleh LLM.
Pastikan 5 agen spesialis masih berjalan (Terminal 1–5 dari Langkah 10).
Di Terminal 6 (terminal A2A Inspector), hentikan pemeriksa dengan Ctrl+C.
Buka file:
cd ~/ai-creative-studio/workshop/starter
cloudshell edit agents/creative_director/agent.py
File ini memiliki tiga TODO. Selesaikan secara berurutan.
TODO 1 - Tinjau instruksi sistem yang sudah ditulis
Petunjuk sistem ada di prompt.py di direktori yang sama - petunjuk ini diimpor secara otomatis:
from .prompt import SYSTEM_INSTRUCTION_TEMPLATE
Buka prompt.py untuk membacanya sebelum melanjutkan:
cloudshell edit agents/creative_director/prompt.py
Memahaminya penting karena mengontrol seluruh perilaku orkestrasi.
Mengapa perintah orchestrator mengontrol segalanya
Buka prompt.py bersama bagian ini - contoh di bawah merujuk pada bagian tertentu di dalamnya.
Perintah di prompt.py bukan hanya dokumentasi, tetapi juga bidang kontrol seluruh sistem. Perintah orkestrator yang disusun dengan buruk akan menghasilkan: agen yang dipanggil secara tidak berurutan, konten yang dibuat oleh orkestrator, bukan spesialis, alur kerja yang berlanjut setelah terjadi kegagalan, dan konteks yang dihilangkan secara diam-diam di antara agen. Sembilan elemen ini mencegah kegagalan yang paling umum:
Elemen 0 - Rencanakan terlebih dahulu, lalu jalankan
Ini adalah elemen yang paling penting. Sebelum memanggil spesialis, orkestrator diinstruksikan untuk menampilkan rencana bernomor:
I'll create your campaign by coordinating the specialist agents in sequence:
1. Brand Strategist - develop positioning and audience insights
2. Copywriter - write captions using those insights
3. Visual Designer - create image prompts aligned with the copy
4. Critic - review and score the full package
5. Project Manager - build the timeline and task breakdown
Tanpa langkah ini, LLM langsung melakukan panggilan alat dan kehilangan jejak posisinya dalam alur kerja - terutama setelah menerima respons panjang dari spesialis. Menguraikan rencana terlebih dahulu akan memandu orkestrator: orkestrator mengetahui langkah yang sedang dilakukan, langkah selanjutnya, dan seperti apa proses yang lengkap. Melewati langkah ini akan menyebabkan orchestrator terhenti di tengah alur kerja atau mengulangi langkah-langkah.
Elemen 1 - Penentuan peran eksplisit
❌ "You are a helpful creative assistant."
✅ "You orchestrate specialists. You do NOT write captions, designs, or timelines yourself."
Tanpa larangan eksplisit, LLM terkadang akan melewati panggilan ke spesialis dan membuat konten secara langsung - hal ini lebih cepat dan LLM "tahu" cara melakukannya. Petunjuknya pasti salah.
Elemen 2 - Sintaksis panggilan alat dengan pola yang salah tercantum
Hanya menampilkan sintaksis yang benar saja tidak cukup. LLM dapat menghasilkan panggilan yang terlihat masuk akal, tetapi gagal tanpa pemberitahuan. Perintah secara eksplisit mencantumkan pola yang benar dan pola yang tidak boleh digunakan:
✅ copywriter(request="...") ← correct
❌ print(copywriter(...)) ← breaks silently
❌ default_api.copywriter(...) ← breaks silently
❌ copywriter.run(...) ← breaks silently
❌ agents.copywriter(...) ← breaks silently
Mencantumkan pola yang salah secara eksplisit mengurangi panggilan alat yang salah bentuk hingga ~95% dalam produksi.
Elemen 3 - Eksekusi berurutan yang dijelaskan langkah demi langkah
a) Call the tool
b) Wait for tool_output
c) Verify the output is not an error
d) Confirm to the user: "✓ Brand Strategist complete"
e) Then move to the next agent
Tanpa langkah (b) dan (c), LLM terkadang akan memanggil dua agen secara bersamaan, atau menganggap berhasil dan melanjutkan sebelum menerima respons.
Elemen 4 - Petunjuk error: STOP, report, do not proceed
Pada versi awal, orkestrator akan menerima error dari salah satu spesialis, membuat output yang masuk akal untuk error tersebut, dan melanjutkan ke agen berikutnya. Pengguna mendapatkan kampanye yang tampak lengkap yang dibangun di atas fondasi halusinasi. Perbaikannya jelas: STOP segera. Laporkan error yang muncul. Jangan pernah melanjutkan.
Elemen 5 - Aturan penerusan konteks
Agen jarak jauh tidak memiliki histori percakapan. Saat orkestrator memanggil Copywriter melalui A2A, Copywriter hanya melihat pesan dalam satu permintaan tersebut - dia tidak tahu apa yang dikatakan Brand Strategist. Orchestrator harus secara eksplisit menggabungkan output sebelumnya ke dalam setiap panggilan berikutnya:
copywriter(request="Create 3 posts for EcoFlow water bottle targeting millennials.
Use these insights from the Brand Strategist: [paste full strategist output here].
Create engaging captions with hashtags.")
Petunjuk ini menyatakan secara eksplisit: "Agen jarak jauh TIDAK memiliki memori bersama - Anda harus meneruskan output sebelumnya secara eksplisit." Tanpa hal ini, setiap agen bekerja tanpa mengetahui konteks.
Elemen 6 - Klasifikasi permintaan: sederhana vs. kompleks
Tidak setiap permintaan memerlukan kelima agen. Perintah menginstruksikan orkestrator untuk mengklasifikasikan permintaan sebelum membuat rencana:
SIMPLE → one agent needed
"Research the eco-friendly water bottle market" → brand_strategist only
"Write 3 Instagram captions" → copywriter only
COMPLEX → all agents sequentially
"Create a complete campaign with timeline" → all 5 agents
Tanpa klasifikasi ini, orkestrator akan menjalankan kelima agen untuk setiap permintaan - termasuk "beri saya 3 ide postingan" - sehingga menambah latensi dan biaya yang tidak perlu.
Elemen 7 - Aturan komunikasi: tampilkan output lengkap, tanpa pemfilteran
Perintah secara eksplisit menyatakan bahwa orkestrator tidak boleh meringkas atau mengedit apa yang ditampilkan oleh spesialis:
- DO NOT summarize unless the output exceeds 2000 words
- DO NOT filter or edit agent responses
- Show the user exactly what each specialist produced
- NEVER say results are ready unless you received them in tool_output
Tanpa ini, orkestrator akan menulis ulang output spesialis dengan kata-katanya sendiri, sehingga kehilangan detail, menimbulkan error, dan menggagalkan tujuan memiliki spesialis.
Elemen 8 - Penyelesaian alur kerja: jangan pernah berhenti lebih awal
Mode kegagalan yang halus tetapi penting: orchestrator mengumumkan rencana 5 langkah, menyelesaikan 3 langkah, lalu menyajikan hasil seolah-olah sudah selesai. Perintah mencegah hal ini dengan checklist eksplisit yang harus lulus sebelum orkestrator dapat menyelesaikan:
✓ Did I announce a plan with N agents?
✓ Have I called ALL N agents from my plan?
✓ Did each agent respond successfully?
✓ Am I presenting complete results from ALL agents?
If any answer is NO → continue executing the remaining agents.
Tindakan ini akan menghentikan orkestrator memperlakukan eksekusi sebagian sebagai selesai.
Loop Kontrol Kualitas
Alur kerja revisi adalah bagian paling rumit dari prompt.py. Buka bagian ## REVISION WORKFLOW dan ikuti.
Cara kerjanya
Setelah Kritikus merespons, Direktur Kreatif tidak melanjutkan begitu saja kepada Manajer Proyek. Node ini membaca output Kritikus dan membuat cabang:
Critic output
│
├── "All Approved: YES"
│ └──► proceed to Project Manager
│
└── "Status: NEEDS_REVISION"
│
├── posts fail → call copywriter again with feedback
├── visuals fail → call designer again with feedback
└── both fail → call copywriter, then designer
│
└──► revised output → Project Manager
(1 revision max per deliverable)
Ini didukung LLM, bukan kode
Codelab sebelumnya menyebutkan bahwa orkestrator "mengurai" respons Kritikus. Tidak ada kode Python yang melakukan parsing ini - tidak ada ekspresi reguler, tidak ada pencocokan string. Creative Director adalah LLM yang membaca instruksinya sendiri. Petunjuk tersebut menyatakan:
Look for "Status: NEEDS_REVISION" in the critic's response.
Posts need revision → call copywriter
Visuals need revision → call designer
LLM membaca string persis tersebut dalam output Critic dan mengikuti cabang. Itulah sebabnya format Kritikus tidak dapat dinegosiasikan: jika Kritikus menulis "perlu sedikit perbaikan" alih-alih NEEDS_REVISION, LLM tidak akan menemukan kecocokan dalam instruksinya dan akan melewati langkah revisi secara diam-diam.
Cara konteks diteruskan dalam panggilan revisi
Panggilan revisi mengikuti aturan penerusan konteks yang sama dari Elemen 5 - orkestrator harus menyertakan semuanya secara eksplisit karena Copywriter tidak memiliki memori versi pertamanya:
"I need you to revise the Instagram posts based on critic feedback.
ORIGINAL BRIEF:
[the original user request]
YOUR FIRST VERSION:
[the posts the copywriter created]
CRITIC FEEDBACK (Score: 6/10 - NEEDS_REVISION):
[the critic's specific suggestions]
Please revise the posts addressing this feedback while maintaining
the strengths the critic identified."
Tanpa bagian "VERSI PERTAMA ANDA", Copywriter akan menulis dari awal, bukan meningkatkan kualitas hasil yang sudah dibuatnya.
Batas 1 revisi dan alasannya
Setelah satu putaran revisi, orchestrator akan melanjutkan ke Project Manager, terlepas dari skornya. Instruksi melacak hal ini secara mental:
After calling copywriter for revision once:
→ mark "copywriter_revised = true" in context
→ even if the critic still suggests changes, proceed to PM
Tanpa batas ini, loop dapat berjalan tanpa batas: Kritikus menandai masalah → Copywriter merevisi → Kritikus menandai lagi → Copywriter merevisi lagi. Setiap putaran membutuhkan token dan waktu. Satu revisi sudah cukup untuk meningkatkan kualitas tanpa risiko siklus yang tidak terkendali.
Informasi yang diteruskan ke Manajer Proyek
Project Manager selalu menerima versi akhir yang disetujui, bukan versi aslinya. Jika revisi terjadi, pengelola akan meneruskan salinan dan visual yang direvisi. Jika semuanya disetujui pada tahap pertama, maka semuanya akan langsung disetujui. PM tidak pernah melihat draf yang ditolak.
TODO 2 - Register each specialist as a RemoteA2aAgent + AgentTool
Temukan komentar # TODO 2: For each specialist URL... dan ganti dengan:
if strategist_url:
available_agents_list.append(
"- **brand_strategist**: Market research, competitor analysis, trend identification"
)
strategist_agent = RemoteA2aAgent(
name="brand_strategist",
description="Researches markets, competitors, and trends using Google Search",
agent_card=f"{strategist_url}/.well-known/agent.json",
)
agent_tools.append(AgentTool(agent=strategist_agent))
if copywriter_url:
available_agents_list.append(
"- **copywriter**: Instagram captions, hashtags, and CTAs"
)
copywriter_agent = RemoteA2aAgent(
name="copywriter",
description="Creates Instagram captions with hashtags and CTAs",
agent_card=f"{copywriter_url}/.well-known/agent.json",
)
agent_tools.append(AgentTool(agent=copywriter_agent))
if designer_url:
available_agents_list.append(
"- **designer**: Visual concepts and real images generated via Gemini (GCS URIs returned)"
)
designer_agent = RemoteA2aAgent(
name="designer",
description="Creates visual concepts and generates real images via Gemini, stored in GCS",
agent_card=f"{designer_url}/.well-known/agent.json",
)
agent_tools.append(AgentTool(agent=designer_agent))
if critic_url:
available_agents_list.append(
"- **critic**: Quality review with APPROVED/NEEDS_REVISION scoring"
)
critic_agent = RemoteA2aAgent(
name="critic",
description="Reviews campaign materials and returns structured quality feedback",
agent_card=f"{critic_url}/.well-known/agent.json",
)
agent_tools.append(AgentTool(agent=critic_agent))
if pm_url:
available_agents_list.append(
"- **project_manager**: Project timelines, task breakdowns, Notion integration"
)
pm_agent = RemoteA2aAgent(
name="project_manager",
description="Creates project timelines and task breakdowns, optionally in Notion",
agent_card=f"{pm_url}/.well-known/agent.json",
)
agent_tools.append(AgentTool(agent=pm_agent))
TODO 3 - Bungkus dalam Aplikasi dengan pemadatan konteks
Alasan pemadatan diperlukan
Setiap pesan dalam percakapan - perintah pengguna, setiap panggilan alat, setiap respons alat - ditambahkan ke jendela konteks yang dibaca LLM pada giliran berikutnya. Dalam alur kerja 5 agen, hal ini akan terakumulasi dengan cepat:
Turn 1: user prompt ~200 tokens
Turn 2: orchestrator plan ~300 tokens
Turn 3: brand_strategist tool_call ~150 tokens
Turn 4: brand_strategist tool_output ~1,500 tokens ← full research report
Turn 5: copywriter tool_call ~300 tokens ← must include strategist output
Turn 6: copywriter tool_output ~2,000 tokens ← 3 captions
Turn 7: designer tool_call ~500 tokens
Turn 8: designer tool_output ~1,500 tokens
...
Pada Agen 4 (Kritikus), jendela konteks berisi output lengkap dari ketiga agen sebelumnya - sering kali 8.000–12.000 token hanya dalam respons alat. Meskipun dengan jendela konteks besar Gemini 2.5 Pro, kualitas penalaran pengelola menurun karena harus memperhatikan histori yang terus bertambah. Tanpa pemadatan, alur kerja yang panjang akan mencapai batas praktis di sekitar Agent 4.
Fungsi pemadatan
Daripada menyimpan setiap peristiwa secara penuh, ADK secara berkala memanggil LLM untuk meringkas peristiwa lama menjadi representasi yang ringkas. Hanya ringkasan peristiwa sebelumnya + output lengkap agen terbaru yang disimpan dalam konteks.
Without compaction:
[full strategist output] + [full copywriter output] + [full designer output] + → Critic
With compaction (interval=3, overlap=1):
[summary of strategist + copywriter] + [full designer output] + → Critic
Ringkasan ini mempertahankan fakta penting (insight utama, teks yang disetujui, konsep visual) sekaligus menghapus format yang bertele-tele, konteks berulang yang diteruskan ke setiap agen, dan penalaran perantara. Pengkritik masih memiliki semua yang diperlukan untuk melakukan evaluasi - hanya saja ia membaca ringkasan, bukan tiga laporan lengkap.
Kode
Temukan komentar # TODO 3: Wrap the agent in an App... dan ganti placeholder App(...) dengan:
from google.adk.apps import App
from google.adk.apps.app import EventsCompactionConfig
from google.adk.apps.llm_event_summarizer import LlmEventSummarizer
from google.adk.models import Gemini
compaction_config = EventsCompactionConfig(
summarizer=LlmEventSummarizer(llm=Gemini(model_id=os.getenv("GEMINI_MODEL", "gemini-2.5-flash"))),
compaction_interval=3, # Summarize after every 3 agent completions
overlap_size=1, # Keep the most recent agent's output in full
)
app = App(
name="creative_director",
root_agent=agent,
events_compaction_config=compaction_config,
plugins=[LoggingPlugin()],
)
return agent, app
compaction_interval=3 - pemadatan diaktifkan setelah setiap 3 penyelesaian agen. Untuk pipeline 5 agen, ini berarti pipeline dijalankan sekali (setelah agen 1–3), lalu Critic dan PM melihat ringkasan 1–3 ditambah output agen sebelumnya secara lengkap.
overlap_size=1 - output lengkap agen terbaru selalu dipertahankan kata demi kata, tidak pernah diringkas. Hal ini penting karena Kritikus memerlukan output lengkap Desainer - termasuk nilai gcs_uri - untuk memuat dan meninjau gambar sebenarnya. Ringkasan akan kehilangan URI tersebut.
Cara penerapannya dalam menjalankan kampanye lengkap:
Agent 1 (Strategist) → full context
Agent 2 (Copywriter) → full context
Agent 3 (Designer) → full context
↓ compaction fires: summarizes agents 1-2, keeps 3 in full
Agent 4 (Critic) → sees [summary of 1-2] + [full output of 3]
Agent 5 (PM) → sees [summary of 1-3] + [full output of 4]
Memahami RemoteA2aAgent dan AgentTool
RemoteA2aAgent("brand_strategist", agent_card=url)
│
│ wraps the remote service so ADK can call it
▼
AgentTool(agent=strategist_agent)
│
│ exposes it as a callable tool to the LLM
▼
Agent(tools=[...])
│
│ LLM calls tool("brand_strategist", message=...) when needed
▼
brand-strategist-xxxx.run.app ← actual HTTP A2A call happens here
LLM memutuskan kapan harus memanggil setiap alat berdasarkan petunjuk sistem dan permintaan pengguna. Orchestrator tidak pernah memanggil agen secara langsung dalam kode - semuanya didorong oleh penalaran LLM.
Menguji Creative Director secara lokal
uv run adk web agents --allow_origins='*'
Buka Pratinjau Web di port 8000. Gunakan dropdown agen untuk memilih creative_director, lalu coba:
Research the eco-friendly water bottle market for health-conscious millennials
Anda akan melihat bahwa Creative Director akan mengarahkan permintaan ini hanya kepada Brand Strategist dan Anda akan mendapatkan respons dari Brand Strategist.
Untuk kampanye lengkap, coba hal berikut:
Create a complete Instagram campaign for SolarPack portable solar charger targeting
outdoor enthusiasts and digital nomads aged 22-35.
Budget $2,000, launch in 2 weeks.
Anda akan melihat Creative Director mengoordinasikan kelima spesialis secara berurutan, dengan output setiap agen mengalir ke agen berikutnya.

Hentikan Creative Director (Ctrl+C) sebelum melanjutkan - pemeriksa A2A juga menggunakan port 8000.
Hentikan 5 server spesialis (Ctrl+C di setiap terminal) setelah pengujian lokal selesai.
12. Men-deploy dan Menguji Agen Spesialis
Sekarang kita siap men-deploy agen ke Google Cloud. Cloud Run adalah layanan yang tepat untuk men-deploy agen. Layanan ini serverless, skalabel, dan mudah digunakan. Setiap agen spesialis di-deploy sebagai layanan Cloud Run independen.
Konfigurasi deployment
Dockerfile untuk setiap spesialis mengikuti pola ini:
FROM python:3.12-slim
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends gcc curl
# Fast dependency install with uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
COPY pyproject.toml .
RUN uv sync --no-install-project --no-dev
COPY . .
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
USER appuser
ENV PYTHONUNBUFFERED=1 PORT=8080 HOST=0.0.0.0
EXPOSE 8080
CMD ["uv", "run", "python", "agent.py"]
Men-deploy semua 5 spesialis secara berurutan
cd ~/ai-creative-studio/workshop/starter
source .env
uv run deploy/deploy_all_specialists.py
Skrip ini men-deploy semua 5 agen satu per satu (total ~10-12 menit). Deployment berurutan menghindari kuota polling Cloud Build (60 permintaan/menit). Setelah selesai, skrip ini akan menulis kembali URL Cloud Run setiap agen ke .env.
Setelah Designer di-deploy, skrip akan otomatis memberikan izin roles/storage.objectCreator pada akun layanan Cloud Run-nya di bucket GCS Anda sehingga dapat mengupload gambar yang dihasilkan.
Jika Anda mengonfigurasi kredensial Notion di .env, skrip juga akan menyimpannya dengan aman di Secret Manager (sebagai notion-token, notion-project-db-id, notion-tasks-db-id) dan menyuntikkannya ke layanan Project Manager melalui --set-secrets, bukan variabel lingkungan biasa. Artinya, token tidak pernah muncul di tab lingkungan Cloud Run atau di histori perintah gcloud.
Memverifikasi deployment
Setelah deployment selesai, skrip akan otomatis menulis kembali URL Cloud Run ke .env, menggantikan URL localhost dari langkah sebelumnya:
source .env
echo "Deployed URLs:"
echo " Brand Strategist: $STRATEGIST_AGENT_URL"
echo " Copywriter: $COPYWRITER_AGENT_URL"
echo " Designer: $DESIGNER_AGENT_URL"
echo " Critic: $CRITIC_AGENT_URL"
echo " Project Manager: $PM_AGENT_URL"
Creative Director akan otomatis menggunakan URL Cloud Run ini saat di-deploy ke Agent Runtime pada langkah berikutnya.
Memverifikasi kartu agen
Setiap agen yang di-deploy menampilkan kartu agen di /.well-known/agent.json. Ambil untuk mengonfirmasi bahwa semuanya sudah aktif:
source .env
for agent_url in $STRATEGIST_AGENT_URL $COPYWRITER_AGENT_URL $DESIGNER_AGENT_URL $CRITIC_AGENT_URL $PM_AGENT_URL; do
echo "=== Agent Card: $agent_url ==="
curl -s "${agent_url}/.well-known/agent.json" | python3 -m json.tool | grep -E '"name"|"url"|"description"'
echo ""
done
Output yang diharapkan untuk setiap agen:
"name": "brand_strategist",
"url": "https://brand-strategist-xxxx.run.app",
"description": "Brand strategist for market research and competitive insights"
Menguji dengan A2A Inspector (Cloud Run)
A2A Inspector sudah diinstal dari Langkah 10. Mulai:
cd ~/a2a-inspector
bash scripts/run.sh
Buka Pratinjau Web → Ubah port → 5001. Masukkan URL Cloud Run Anda di kolom koneksi:
https://brand-strategist-xxxx.us-central1.run.app
Klik Connect - tidak memerlukan token autentikasi karena layanan di-deploy dengan --allow-unauthenticated.
Pemeriksa terhubung, memvalidasi kartu agen, dan memungkinkan Anda melakukan chat secara interaktif melalui A2A.
Memeriksa agen yang di-deploy ke Cloud Run
Setelah men-deploy ke Cloud Run, arahkan pemeriksa ke URL HTTPS publik untuk memverifikasi bahwa deployment cloud berfungsi:

Alur kerjanya sama - tempelkan URL Cloud Run, hubungkan, dan kirim pesan pengujian. Jika kartu agen dimuat dan chat merespons, spesialis telah di-deploy dan dapat dihubungi dengan benar.
13. Men-deploy Creative Director ke Agent Runtime
Orchestrator di-deploy ke Agent Runtime, yang menyediakan status sesi terkelola, penskalaan otomatis, dan pelacakan bawaan.
Mengapa Agent Runtime untuk orkestrator?
Lima spesialis di-deploy ke Cloud Run - ringan, stateless, masing-masing menangani satu tugas. Direktur Kreatif memiliki persyaratan yang berbeda:
Persyaratan | Mengapa hal ini penting |
Status sesi | Alur kerja multi-langkah membutuhkan waktu 45+ detik. Runtime Agen mempertahankan status percakapan di antara panggilan alat orkestrator sehingga tidak ada yang hilang di tengah pipeline. |
Beban variabel | Terkadang satu kampanye per jam, terkadang banyak secara paralel. Agent Runtime diskalakan hingga nol saat tidak ada aktivitas dan diskalakan secara otomatis - Anda tidak membayar kapasitas yang tidak digunakan. |
Kemampuan observasi | Cloud Logging, Cloud Monitoring, dan Cloud Trace sudah tersedia secara bawaan. Anda dapat melihat setiap panggilan A2A, setiap token yang digunakan, setiap lonjakan latensi - tanpa menambahkan instrumentasi apa pun. |
Alur kerja yang berjalan lama | Cloud Run memiliki waktu tunggu permintaan 3.600 detik. Agent Runtime dirancang untuk alur kerja yang dapat memakan waktu beberapa menit, dengan percobaan ulang terkelola dan persistensi status. |
Cloud Run adalah platform yang tepat untuk spesialis stateless. Agent Runtime adalah platform yang tepat untuk orkestrator stateful.
Men-deploy orchestrator
cd ~/ai-creative-studio/workshop/starter
source .env
uv run deploy/deploy_orchestrator.py --action deploy
Proses ini memerlukan waktu sekitar 5–10 menit. Setelah selesai, AGENT_ENGINE_ID dan AGENT_ENGINE_RESOURCE_NAME akan disimpan ke .env.
source .env
echo "Agent Engine ID: $AGENT_ENGINE_ID"
echo "Resource: $AGENT_ENGINE_RESOURCE_NAME"
Cara kerja deployment
client.agent_engines.create() mengemas objek App Anda, menguploadnya dengan dependensinya, dan men-deploy-nya ke infrastruktur terkelola. Berikut fungsi setiap parameter:
import vertexai
from vertexai import Client, agent_engines
vertexai.init(project=PROJECT_ID, location=LOCATION, staging_bucket=STAGING_BUCKET)
# Wrap the App in an AdkApp adapter - enables tracing in Cloud Trace
adk_app = agent_engines.AdkApp(app=root_app, enable_tracing=True)
# Initialize client and deploy
client = Client(project=PROJECT_ID, location=LOCATION)
agent_engine_resource = client.agent_engines.create(
agent=adk_app,
config={
"staging_bucket": STAGING_BUCKET, # GCS bucket for packaging artifacts
"display_name": "Creative Director",
# Python packages installed in the managed runtime - pin for reproducibility
"requirements": [
"google-cloud-aiplatform[agent_engines]>=1.132.0,<2.0.0",
"google-adk[a2a]==1.31.1",
"google-genai>=1.70.0",
"google-cloud-storage>=2.10.0",
"python-dotenv>=1.0.0",
"pydantic>=2.0.0",
"cloudpickle>=3.0.0",
],
# Specialist URLs passed as env vars - the orchestrator reads these at runtime
"env_vars": {
"COPYWRITER_AGENT_URL": COPYWRITER_URL,
"DESIGNER_AGENT_URL": DESIGNER_URL,
"STRATEGIST_AGENT_URL": STRATEGIST_URL,
"CRITIC_AGENT_URL": CRITIC_URL,
"PM_AGENT_URL": PM_URL,
},
},
)
resource_name = agent_engine_resource.api_resource.name
agent_engine_id = resource_name.split("/")[-1]
Yang terjadi di balik layar:
1. Agent Engine packages your App + requirements into a container
2. Uploads it to the staging bucket in your project
3. Deploys to managed compute (you never see or manage the VM)
4. Returns a resource name: projects/.../locations/.../reasoningEngines/<id>
5. That ID is saved to .env as AGENT_ENGINE_ID
Setelah deployment, orkestrator terhubung ke lima spesialis Cloud Run melalui URL di variabel lingkungannya
- Variabel ini diteruskan melalui
.envsebelum skrip deployment dijalankan.
14. Menjalankan kampanye secara menyeluruh
Seluruh sistem di-deploy. Jalankan kampanye lengkap dari playground Agent Runtime.
Buka playground Agent Runtime
- Buka https://console.cloud.google.com/agent-platform/runtimes. Anda juga dapat membuka Agent Runtime dari Agent Platform > Agents > Deployments.
- Pilih Agent Runtime yang di-deploy (
creative-director) - Klik Playground di sidebar kiri
- Klik Sesi baru untuk membuka percakapan baru
Menjalankan kampanye lengkap
Tempelkan ringkasan ini ke dalam chat dan kirim:
Create a complete Instagram campaign for:
- Product: EcoFlow Smart Water Bottle (tracks hydration, keeps drinks cold 24h)
- Target Audience: Health-conscious millennials, 25-35 years old
- Platform: Instagram
- Goal: Brand awareness + drive website traffic
- Brand Voice: Motivational, clean, science-backed
- Budget: $3,000
- Timeline: Launch in 2 weeks
Direktur Kreatif akan menjalankan semua 5 agen secara berurutan:
- Ahli Strategi Merek → riset pasar, analisis pesaing, insight audiens
- Copywriter → 3 postingan Instagram dengan teks, hashtag, CTA
- Desainer → konsep visual + gambar asli yang dibuat melalui Gemini (URI GCS) untuk setiap postingan
- Kritik → ulasan kualitas dengan skor DISETUJUI / PERLU_REVISI
- (Revisi jika diperlukan) → Copywriter atau Desainer dipanggil lagi untuk mendapatkan masukan
- Project Manager → Rentang waktu 2 minggu, perincian tugas, alokasi anggaran

Menguji pemilihan rute agen tunggal
Kirim permintaan yang lebih singkat ini dalam sesi baru:
Research the luxury skincare market - top brands and trends in 2025
Perhatikan bahwa Creative Director merutekan ini hanya ke Brand Strategist - tidak ada agen lain yang dipanggil. Ini adalah logika klasifikasi permintaan dari petunjuk sistem yang berfungsi dengan benar.
Memeriksa rekaman aktivitas eksekusi
Saat masih berada di konsol:
- Klik Traces di sidebar kiri (di samping Playground)
- Di bagian Trace View, pilih rekaman aktivitas untuk sesi yang baru saja Anda jalankan
- Luaskan pohon rekaman aktivitas untuk melihat setiap panggilan agen, input/output, latensi, dan penggunaan tokennya
Setiap panggilan A2A ke spesialis muncul sebagai rentang terpisah. Anda dapat melihat dengan tepat konteks yang diteruskan Direktur Kreatif ke setiap agen dan apa yang diterima kembali.
Opsional: Menjalankan dari terminal
Anda juga dapat menjalankan kampanye secara terprogram menggunakan skrip run_campaign.py yang sudah disertakan dalam starter.
cd ~/ai-creative-studio/workshop/starter
uv run run_campaign.py
15. Pembersihan
Bersihkan resource Google Cloud untuk menghindari biaya berkelanjutan.
Jalankan skrip pembongkaran - skrip ini akan membaca .env Anda dan menghapus semua yang dibuat selama codelab ini:
bash deploy/teardown_gcp.sh
Skrip akan menunjukkan dengan tepat apa yang akan dihapus dan meminta konfirmasi sebelum melakukan apa pun:
Resource | Data yang dihapus |
Layanan Cloud Run | brand-strategist, copywriter, designer, kritikus, project-manager |
Runtime Agen | Mesin penalaran Creative Director + semua sesi |
Artifact Registry | Repositori |
Bucket GCS |
|
Secret Manager |
|
Pastikan semuanya telah dihapus
gcloud run services list --region=us-central1
gcloud storage buckets list --project=$GCP_PROJECT_ID
Output yang diharapkan: daftar kosong atau hanya resource Anda sendiri yang sudah ada.
16. Ringkasan
Selamat! Anda telah membangun dan men-deploy sistem AI multi-agen tingkat produksi di Google Cloud.
Yang Anda bangun
Agen | Kemampuan | Deployment |
Brand Strategist | Riset pasar melalui Google Penelusuran | Cloud Run |
{i>Copywriter<i} | Pembuatan teks Instagram | Cloud Run |
Desainer | Pembuatan gambar melalui Gemini + upload GCS | Cloud Run |
Kritik | Ulasan berkualitas dengan pemberian skor | Cloud Run |
Manajer Project | Linimasa + MCP Notion | Cloud Run |
Creative Director | Orkestrasi penuh melalui A2A | Runtime Agen |
Pola utama yang Anda pelajari
- ADK
Agent- menentukan agen LLM dengan petunjuk + alat opsional adk web- menjalankan dan menguji agen ADK apa pun secara lokal dengan UI chat bawaanSkillToolset- mengemas pengetahuan yang dapat digunakan kembali ke dalam file modular yang dimuat sesuai permintaanFunctionTool- gabungkan fungsi Python (atau model eksternal) sebagai alat agen yang dapat dipanggilto_a2a()- mengekspos agen ADK sebagai layanan HTTPS yang kompatibel dengan A2ARemoteA2aAgent+AgentTool- mengatur agen jarak jauh sebagai alat yang dapat dipanggilMcpToolset- terhubung ke layanan eksternal melalui server stdio MCPEventsCompactionConfig- menangani batas token dalam alur kerja multi-agen yang panjang- Output kritikus terstruktur - kontrol kualitas yang dapat dibaca mesin dengan revisi otomatis
- Cloud Run - men-deploy agen dalam container dengan skala besar
- Agent Runtime - meng-hosting orkestrator dengan sesi dan pelacakan terkelola
Langkah berikutnya
- Menambahkan pengeditan gambar multi-turn ke Desainer menggunakan kemampuan pengeditan
gemini-3.1-flash-image-preview - Menambahkan autentikasi IAM ke layanan Cloud Run (menghapus
--allow-unauthenticated) - Mengganti satu pakar dengan agen LangGraph atau CrewAI - A2A tidak bergantung pada framework
- Menambahkan masukan pengguna sebagai alat agar peserta dapat memberi rating dan melakukan iterasi pada output
- Menjelajahi pelacakan Runtime Agen di Konsol Cloud