1. Pengantar
Dalam sesi praktik ini, Anda akan melampaui chatbot dasar tanpa status untuk membuat Smart Cafe Concierge–agen AI yang didukung oleh Gemini yang bertindak sebagai barista yang ramah. Aplikasi ini mengambil pesanan kopi yang dilacak dalam status sesi, mengingat preferensi diet jangka panjang dalam status cakupan pengguna, dan mempertahankan semuanya ke database Cloud SQL PostgreSQL. Pada akhirnya, agen Anda akan mengingat bahwa Anda intoleran terhadap laktosa meskipun Anda memulai ulang aplikasi dan memulai percakapan baru.
Berikut adalah arsitektur sistem yang akan kita bangun

Prasyarat
- Akun Google Cloud dengan akun penagihan uji coba
- Pemahaman dasar tentang Python
- Tidak diperlukan pengalaman sebelumnya dengan ADK, agen AI, atau Cloud SQL
Yang akan Anda pelajari
- Membuat agen AI menggunakan Agent Development Kit (ADK) Google dengan alat kustom
- Menentukan alat yang membaca dan menulis status sesi melalui
ToolContext - Membedakan antara status cakupan sesi dan status cakupan pengguna (awalan
user:) - Menyediakan instance Cloud SQL PostgreSQL dan menghubungkannya dari Cloud Shell
- Migrasikan dari penyimpanan lokal (yang merupakan default saat Anda menggunakan perintah
adk web) keDatabaseSessionServiceuntuk penyimpanan persisten dengan database khusus - Memastikan memori agen tetap ada di seluruh proses mulai ulang aplikasi dan di seluruh sesi percakapan terpisah
Yang Anda butuhkan
- Komputer yang berfungsi dan koneksi internet yang andal.
- Browser, seperti Chrome, untuk mengakses Konsol Google Cloud
- Pikiran yang ingin tahu dan semangat untuk belajar.
2. Menyiapkan Lingkungan Anda
Langkah ini akan menyiapkan lingkungan Cloud Shell dan mengonfigurasi project Google Cloud Anda
Buka Cloud Shell
Buka Cloud Shell di browser Anda. Cloud Shell menyediakan lingkungan yang telah dikonfigurasi sebelumnya dengan semua alat yang Anda perlukan untuk codelab ini. Klik Authorize saat diminta untuk
Antarmuka Anda akan terlihat seperti ini

Ini akan menjadi antarmuka utama kita, IDE di atas, terminal di bawah
Menyiapkan direktori kerja Anda
Buat direktori kerja Anda. Semua kode yang Anda tulis dalam codelab ini ada di sini — terpisah dari repo referensi:
# Create your working directory
mkdir -p ~/build-agent-adk-cloudsql
# Change cloudshell workspace and working directory into previously created dir
cloudshell workspace ~/build-agent-adk-cloudsql && cd ~/build-agent-adk-cloudsql
Untuk memunculkan terminal, cari View -> Terminal

Menyiapkan project Google Cloud dan variabel lingkungan awal
Download skrip penyiapan project ke direktori kerja Anda:
curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh
Jalankan skrip. Skrip ini memverifikasi akun penagihan uji coba Anda, membuat project baru (atau memvalidasi project yang ada), menyimpan ID project Anda ke file .env di direktori saat ini, dan menetapkan project aktif di terminal
bash setup_verify_trial_project.sh && source .env
Saat menjalankan perintah ini, Anda akan diminta untuk memasukkan nama project ID yang disarankan. Anda dapat menekan Enter untuk melanjutkan

Setelah menunggu beberapa saat, jika Anda melihat output ini di konsol, Anda siap melanjutkan ke langkah berikutnya 
Skrip yang dijalankan akan melakukan langkah-langkah berikut:
- Pastikan Anda memiliki akun penagihan uji coba yang aktif
- Periksa project yang ada di
.env(jika ada) - Buat project baru atau gunakan kembali project yang sudah ada
- Menautkan akun penagihan uji coba ke project Anda
- Simpan project ID ke .env
- Tetapkan project sebagai project gcloud aktif
Pastikan project disetel dengan benar dengan memeriksa teks berwarna kuning di samping direktori kerja Anda di perintah terminal Cloud Shell. Project ID Anda akan ditampilkan.

Aktifkan API yang diperlukan
Aktifkan Google Cloud API yang diperlukan untuk codelab ini:
gcloud services enable \
aiplatform.googleapis.com \
sqladmin.googleapis.com \
compute.googleapis.com
- Vertex AI API (
aiplatform.googleapis.com) — agen Anda menggunakan model Gemini melalui Vertex AI. - Cloud SQL Admin API (
sqladmin.googleapis.com) — Anda menyediakan dan mengelola instance PostgreSQL untuk penyimpanan persisten. - Compute Engine API (
compute.googleapis.com) — diperlukan untuk membuat instance Cloud SQL.
Mengonfigurasi wilayah produk Gemini dan Cloud
Sebelum melanjutkan, mari kita siapkan juga konfigurasi lokasi/wilayah yang diperlukan untuk produk yang berinteraksi dengan kita. Tambahkan konfigurasi berikut ke file .env kita
# This is for our Gemini endpoint
echo "GOOGLE_CLOUD_LOCATION=global" >> .env
# This is for our other Cloud products
echo "REGION=us-central1" >> .env
source .env
Lanjutkan ke langkah berikutnya
3. Menyiapkan Cloud SQL
Langkah ini menyediakan instance Cloud SQL PostgreSQL dan mengalihkan agen Anda dari penyimpanan dalam memori ke penyimpanan yang didukung database. Pembuatan instance memerlukan waktu beberapa menit, jadi Anda akan memulainya terlebih dahulu dan kita dapat melanjutkan diskusi ke topik berikutnya sambil menunggu prosesnya selesai
Mulai pembuatan instance
Tambahkan sandi database ke file .env Anda dan muat ulang, kita akan menggunakan cafe-agent-pwd-2025 sebagai sandi.
echo "DB_PASSWORD=cafe-agent-pwd-2025" >> .env
source .env
Jalankan perintah ini untuk membuat instance Cloud SQL PostgreSQL. Proses ini memerlukan waktu beberapa menit untuk diselesaikan — biarkan proses ini berjalan dan lanjutkan ke bagian berikutnya.
gcloud sql instances create cafe-concierge-db \
--database-version=POSTGRES_17 \
--edition=ENTERPRISE \
--region=${REGION} \
--availability-type=ZONAL \
--project=${GOOGLE_CLOUD_PROJECT} \
--tier=db-f1-micro \
--root-password=${DB_PASSWORD} \
--quiet &
Beberapa catatan tentang perintah di atas:
db-f1-microadalah tingkat Cloud SQL terkecil (dan termurah) — cukup untuk codelab ini.--root-passwordmenyetel sandi untuk pengguna postgres default.- Sufiks
&dalam perintah menjalankan perintah di latar belakang sehingga Anda dapat terus bekerja.
Proses akan dijalankan di latar belakang, tetapi output konsol akan sesekali ditampilkan di terminal saat ini. Mari buka tab terminal baru di Cloud Shell (klik ikon +) agar kita bisa lebih fokus.

Buka direktori kerja Anda lagi dan aktifkan project menggunakan skrip penyiapan sebelumnya.
cd ~/build-agent-adk-cloudsql
bash setup_verify_trial_project.sh && source .env
Kemudian, lanjutkan ke bagian berikutnya
4. Membangun Agen Cafe Concierge
Langkah ini membuat struktur project untuk agen ADK Anda dan menentukan Concierge Kafe dasar dengan alat menu.
Lakukan inisialisasi project Python
Codelab ini menggunakan uv, pengelola paket Python cepat yang menangani lingkungan virtual dan dependensi dalam satu alat. Alat ini sudah terinstal di Cloud Shell.
Lakukan inisialisasi project Python dan tambahkan ADK sebagai dependensi:
uv init
uv add google-adk==1.25.0 asyncpg
uv init membuat pyproject.toml dan lingkungan virtual. uv add menginstal dependensi dan mencatatnya di pyproject.toml.
Menginisialisasi struktur project agen
ADK mengharapkan tata letak folder tertentu: direktori yang dinamai sesuai agen Anda yang berisi __init__.py, agent.py, dan juga .env di dalam direktori agen
ADK memiliki perintah bawaan untuk membantu Anda melakukannya dengan cepat. Jalankan perintah berikut
uv run adk create cafe_concierge \
--model gemini-2.5-flash \
--project ${GOOGLE_CLOUD_PROJECT} \
--region ${GOOGLE_CLOUD_LOCATION}
Perintah ini akan membuat struktur agen dengan gemini-2.5-flash sebagai otak. Direktori Anda sekarang akan terlihat seperti ini:
build-agent-adk-cloudsql/ ├── cafe_concierge/ │ ├── __init__.py │ ├── agent.py │ └── .env ├── pyproject.toml ├── .env ├── .venv/ └── ...
Menulis agen
Buka cafe_concierge/agent.py di Cloud Shell Editor
cloudshell edit cafe_concierge/agent.py
dan menimpa file dengan kode berikut
# cafe_concierge/agent.py
from google.adk.agents import LlmAgent
from google.adk.tools import ToolContext
CAFE_MENU = {
"espresso": {
"price": 3.50,
"description": "Rich and bold single shot",
"tags": ["vegan", "dairy-free", "gluten-free"],
},
"latte": {
"price": 5.00,
"description": "Espresso with steamed milk",
"tags": ["gluten-free"],
},
"oat milk latte": {
"price": 5.50,
"description": "Espresso with steamed oat milk",
"tags": ["vegan", "dairy-free", "gluten-free"],
},
"cappuccino": {
"price": 4.50,
"description": "Espresso with equal parts steamed milk and foam",
"tags": ["gluten-free"],
},
"cold brew": {
"price": 4.00,
"description": "Slow-steeped for 12 hours, served over ice",
"tags": ["vegan", "dairy-free", "gluten-free"],
},
"matcha latte": {
"price": 5.50,
"description": "Ceremonial grade matcha with steamed milk",
"tags": ["gluten-free"],
},
"croissant": {
"price": 3.00,
"description": "Buttery, flaky French pastry",
"tags": [],
},
"banana bread": {
"price": 3.50,
"description": "Homemade with walnuts",
"tags": ["vegan"],
},
}
def get_menu() -> dict:
"""Returns the full cafe menu with prices, descriptions, and dietary tags.
Use this tool when the customer asks what's available, wants to see
the menu, or asks about specific items.
"""
return CAFE_MENU
root_agent = LlmAgent(
name="cafe_concierge",
model="gemini-2.5-flash",
instruction="""You are a friendly and knowledgeable barista at "The Cloud Cafe".
Your job:
- Help customers browse the menu and answer questions about items.
- Take coffee and food orders.
- Remember and respect dietary preferences.
Be conversational, warm, and concise. If a customer mentions a dietary
restriction, acknowledge it and suggest suitable options from the menu.
""",
tools=[get_menu],
)
Ini menentukan agen dasar dengan satu alat: get_menu(). Agen dapat menjawab pertanyaan tentang menu, tetapi belum dapat melacak pesanan atau mengingat preferensi.
Memverifikasi agen berjalan
Mulai UI dev ADK dari direktori kerja Anda:
cd ~/build-agent-adk-cloudsql
uv run adk web
Buka URL yang ditampilkan di terminal (biasanya http://localhost:8000) menggunakan fitur Pratinjau Web Cloud Shell. Pilih cafe_concierge dari dropdown agen di sudut kiri atas.
Ketik teks berikut di kolom chat dan verifikasi bahwa agen merespons dengan item menu dan harga.
What's on the menu?

Hentikan UI dev dengan Ctrl+C sebelum melanjutkan.
5. Menambahkan Pengelolaan Pesanan Stateful
Agen dapat menampilkan menu, tetapi tidak dapat menerima pesanan atau mengingat preferensi. Langkah ini menambahkan empat alat yang menggunakan sistem status ADK untuk melacak pesanan dalam percakapan dan menyimpan preferensi diet di seluruh percakapan.
Memahami peristiwa dan status sesi
Setiap percakapan ADK berada di dalam objek Session. Sesi melacak dua hal yang berbeda: peristiwa dan status. Memahami perbedaan ini adalah kunci untuk membangun agen yang mengingat hal yang tepat dengan cara yang tepat.
Peristiwa adalah log kronologis dari semua yang terjadi dalam percakapan. Setiap pesan pengguna, setiap respons agen, setiap panggilan alat dan nilai kembaliannya — masing-masing dicatat sebagai Event dan ditambahkan ke daftar events sesi. Peristiwa tidak dapat diubah: setelah dicatat, peristiwa tidak akan pernah berubah. Anggap peristiwa sebagai transkrip lengkap percakapan.
Status adalah area kerja nilai kunci yang dibaca dan ditulis agen selama percakapan. Tidak seperti peristiwa, status dapat berubah — nilai berubah seiring berkembangnya percakapan. Status adalah tempat agen menyimpan data terstruktur yang perlu ditindaklanjuti: pesanan saat ini, preferensi pelanggan, total yang sedang berjalan. Anggap status sebagai catatan tempel yang disimpan agen di samping transkrip.
Berikut cara kerjanya:

Alat membaca dan menulis status melalui ToolContext — objek yang otomatis disuntikkan ADK ke dalam fungsi alat yang mendeklarasikannya sebagai parameter. Anda tidak membuatnya sendiri. Melalui tool_context.state, alat dapat membaca dan menulis scratchpad status sesi. ADK memeriksa tanda tangan fungsi: parameter dengan jenis ToolContext disisipkan, semua parameter lainnya diisi oleh LLM berdasarkan percakapan.
Saat alat menulis ke tool_context.state, ADK mencatat perubahan tersebut sebagai state_delta di dalam peristiwa. Kemudian, SessionService menerapkan delta ke status sesi saat ini. Artinya, perubahan status selalu dapat dilacak kembali ke peristiwa yang menyebabkannya. Hal ini juga berlaku untuk bentuk konteks lain seperti callback_context
Memahami awalan status
Kunci status menggunakan awalan untuk mengontrol cakupannya:
Awalan | Cakupan | Tetap ada setelah dimulai ulang? (dengan DB) |
(tidak ada) | Khusus sesi saat ini | Ya |
| Semua sesi untuk pengguna ini | Ya |
| Semua sesi, semua pengguna | Ya |
| Hanya pemanggilan saat ini | Tidak |
Dalam codelab ini, Anda menggunakan dua awalan tersebut: kunci tanpa awalan untuk data cakupan sesi (pesanan saat ini — hanya relevan dengan percakapan ini) dan kunci user: untuk data cakupan pengguna (preferensi diet — relevan di semua percakapan untuk pengguna ini).
Menambahkan alat stateful
Buka cafe_concierge/agent.py di Cloud Shell Editor.
cloudshell edit cafe_concierge/agent.py
Kemudian, tambahkan empat fungsi berikut di atas definisi root_agent:
# cafe_concierge/agent.py (add below get_menu, above root_agent)
def place_order(tool_context: ToolContext, items: list[str]) -> dict:
"""Places an order for the specified menu items.
Use this tool when the customer confirms they want to order something.
Args:
tool_context: Provided automatically by ADK.
items: A list of menu item names the customer wants to order.
"""
valid_items = []
invalid_items = []
total = 0.0
for item in items:
item_lower = item.lower()
if item_lower in CAFE_MENU:
valid_items.append(item_lower)
total += CAFE_MENU[item_lower]["price"]
else:
invalid_items.append(item)
if not valid_items:
return {"error": f"None of these items are on our menu: {invalid_items}"}
order = {"items": valid_items, "total": round(total, 2)}
tool_context.state["current_order"] = order
result = {"order": order}
if invalid_items:
result["warning"] = f"These items are not on our menu: {invalid_items}"
return result
def get_order_summary(tool_context: ToolContext) -> dict:
"""Returns the current order summary for this session.
Use this tool when the customer asks about their current order,
wants to review what they ordered, or asks for the total.
Args:
tool_context: Provided automatically by ADK.
"""
order = tool_context.state.get("current_order")
if order:
return {"order": order}
return {"message": "No order has been placed yet in this session."}
def set_dietary_preference(tool_context: ToolContext, preference: str) -> dict:
"""Saves a dietary preference that persists across all conversations.
Use this tool when the customer mentions a dietary restriction or
preference (e.g., "I'm vegan", "I'm lactose intolerant",
"I have a nut allergy").
Args:
tool_context: Provided automatically by ADK.
preference: The dietary preference to save (e.g., "vegan",
"lactose intolerant", "nut allergy").
"""
existing = tool_context.state.get("user:dietary_preferences", [])
if not isinstance(existing, list):
existing = []
preference_lower = preference.lower().strip()
if preference_lower not in existing:
existing.append(preference_lower)
tool_context.state["user:dietary_preferences"] = existing
return {
"saved": preference_lower,
"all_preferences": existing,
}
def get_dietary_preferences(tool_context: ToolContext) -> dict:
"""Retrieves the customer's saved dietary preferences.
Use this tool when you need to check the customer's dietary
restrictions before making recommendations.
Args:
tool_context: Provided automatically by ADK.
"""
preferences = tool_context.state.get("user:dietary_preferences", [])
if preferences:
return {"preferences": preferences}
return {"message": "No dietary preferences saved yet."}
Dua hal yang perlu diperhatikan:
place_orderdanget_order_summarymenggunakan kunci tanpa awalan (current_order). Status ini terkait dengan sesi saat ini — percakapan baru dimulai dengan pesanan kosong.set_dietary_preferencedanget_dietary_preferencesmenggunakan awalanuser:(user:dietary_preferences). Status ini dibagikan di semua sesi untuk pengguna yang sama.
Memperbarui agen dengan alat dan petunjuk baru
Ganti definisi root_agent yang ada di bagian bawah file dengan:
# cafe_concierge/agent.py (replace the existing root_agent)
root_agent = LlmAgent(
name="cafe_concierge",
model="gemini-2.5-flash",
instruction="""You are a friendly and knowledgeable barista at "The Cloud Cafe".
Your job:
- Help customers browse the menu and answer questions about items.
- Take coffee and food orders.
- Remember and respect dietary preferences.
The customer's saved dietary preferences are: {user:dietary_preferences?}
IMPORTANT RULES:
- When a customer mentions a dietary restriction, ALWAYS save it using the
set_dietary_preference tool before doing anything else.
- Before recommending items, check the customer's dietary preferences. If they
have preferences saved, only recommend items compatible with those
restrictions. Check the menu item tags to determine compatibility.
- When placing an order, confirm the items and total with the customer.
Be conversational, warm, and concise.
""",
tools=[
get_menu,
place_order,
get_order_summary,
set_dietary_preference,
get_dietary_preferences,
],
)
Petunjuk ini menggunakan template injeksi status {user:dietary_preferences?} untuk menyuntikkan preferensi tersimpan pelanggan ini langsung ke dalam perintah.
Memverifikasi file yang lengkap
cafe_concierge/agent.py Anda sekarang harus berisi:
- Kamus
CAFE_MENU - Lima fungsi alat:
get_menu,place_order,get_order_summary,set_dietary_preference,get_dietary_preferences - Definisi
root_agentdengan kelima alat
6. Menguji Agen dengan UI Dev ADK
Langkah ini menjalankan agen dan melatih semua fitur stateful: pemesanan, pelacakan preferensi, dan memori lintas sesi (dalam proses yang sama). Anda juga akan memeriksa panel Peristiwa dan Status untuk melihat cara ADK melacak percakapan secara internal.
Mulai UI dev
cd ~/build-agent-adk-cloudsql
uv run adk web
Buka Pratinjau Web di port 8000 dan pilih cafe_concierge dari dropdown.
Percakapan 1: Melakukan pemesanan dan menyetel preferensi
Coba perintah ini secara berurutan:
What's on the menu?
I'm lactose intolerant
What would you recommend?
I'll have an oat milk latte and a banana bread
What's my order?
Memeriksa peristiwa sesi
Semua Peristiwa akan direkam dan ditampilkan di UI web. Anda akan melihat bahwa di kotak chat, tidak hanya ada perintah dan respons Anda, tetapi juga tool_call dan tool_response

Anda akan melihat daftar acara secara berurutan. Setiap peristiwa memiliki penulis (yang membuatnya) dan jenis (jenis interaksi yang diwakilinya):
Author | Jenis | Yang diwakilinya |
|
| Pesan yang Anda ketik dalam chat |
|
| Respons teks agen |
|
| Agen memutuskan untuk memanggil alat (menampilkan nama fungsi + argumen) |
|
| Nilai yang ditampilkan dari panggilan alat |
Klik salah satu peristiwa tool_call, misalnya, panggilan set_dietary_preference. Anda akan melihat:
- Nama fungsi:
set_dietary_preference - Argumen:
{"preference": "lactose intolerant"}
Sekarang klik acara tool_response yang sesuai tepat di bawahnya. Anda akan melihat nilai yang ditampilkan:
- Respons:
{"saved": "lactose intolerant", "all_preferences": ["lactose intolerant"]}

Cari kolom state_delta di dalam peristiwa tool_response. Bagian ini menunjukkan secara persis status apa yang berubah sebagai hasil dari panggilan alat ini:
state_delta: {"user:dietary_preferences": ["lactose intolerant"]}
Setiap perubahan status dapat dilacak ke peristiwa tertentu. Dengan demikian, ADK memastikan bahwa scratchpad status tetap sinkron dengan histori percakapan.
Memeriksa status sesi
Klik tab State. Tidak seperti log peristiwa (yang menampilkan histori lengkap), tab status menampilkan ringkasan tentang apa yang diketahui agen saat ini — nilai saat ini dari setiap kunci status.

Anda akan melihat dua entri:
current_order—{"items": ["oat milk latte", "banana bread"], "total": 9.0}user:dietary_preferences—["lactose intolerant"]
Perhatikan perbedaan nama kunci:
current_ordertidak memiliki awalan — cakupannya adalah sesi. Pesan ini hanya ada dalam percakapan ini dan akan hilang saat sesi berakhir.user:dietary_preferencesmemiliki awalanuser:— cakupannya adalah pengguna. Nilai ini dibagikan di setiap sesi untuk pengguna ini.
Perbedaan ini tidak terlihat dalam kode (keduanya menggunakan tool_context.state), tetapi mengontrol seberapa jauh data dijangkau. Anda akan melihatnya di pengujian berikutnya.
Percakapan 2: Memverifikasi status pengguna lintas sesi
Klik tombol New Session di UI developer untuk memulai percakapan baru. Tindakan ini akan membuat sesi baru untuk pengguna yang sama.

Coba perintah ini:
What do you recommend for me?
Periksa tab State di sesi baru. Kunci user:dietary_preferences tetap ada, tetapi current_order sudah tidak ada — status tersebut terikat dengan sesi sebelumnya.

7. Mematuhi Batasan Penyimpanan Lokal
Agen mengingat preferensi di seluruh sesi, tetapi hanya selama penyimpanan lokal ada. Langkah ini menunjukkan batasan mendasar penyimpanan lokal.
Mulai agen lagi
Anda menghentikan UI dev di akhir langkah sebelumnya. Sekarang, hapus penyimpanan lokal dan mulai lagi, untuk menyimulasikan lingkungan serverless yang stateless:
cd ~/build-agent-adk-cloudsql
rm -f cafe_concierge/.adk/session.db
uv run adk web
Sekarang, buka Pratinjau Web di port 8000 dan pilih cafe_concierge.
Menguji ingatan preferensi
Jenis:
Do you remember my dietary preferences?
Agen tidak ingat. Preferensi diet, histori pesanan — semuanya hilang.

Semua data dihapus saat kita menghapus penyimpanan lokal, yang biasanya terjadi saat kita menggunakan lingkungan serverless. session.db menyimpan semua status dalam memori proses. Menghapusnya akan menghapus semuanya.
Solusinya: tentukan DatabaseSessionService, yang dalam tutorial ini akan menyimpan semua data sesi dalam database PostgreSQL di Cloud SQL. Kode dan alat agen tetap sama persis — hanya backend penyimpanan yang berubah.
Hentikan UI dev dengan Ctrl+C sebelum melanjutkan.
8. Membuka Kembali Penyiapan Database
Pada tahap ini, pembuatan instance database kita seharusnya sudah selesai. Mari kita verifikasi, jalankan perintah berikut
gcloud sql instances describe cafe-concierge-db --format="value(state)"
Anda akan melihat output berikut, tandai sebagai selesai
RUNNABLE
Membuat database
Buat database khusus untuk data sesi agen:
gcloud sql databases create agent_db --instance=cafe-concierge-db
Mulai Proxy Auth Cloud SQL.
Proxy Auth Cloud SQL menyediakan koneksi yang aman dan diautentikasi dari Cloud Shell ke instance Cloud SQL Anda tanpa perlu memasukkan alamat IP ke daftar yang diizinkan. Alat ini sudah diinstal sebelumnya di Cloud Shell.
cloud-sql-proxy ${GOOGLE_CLOUD_PROJECT}:${REGION}:cafe-concierge-db --port 5432 &
Sufiks & dalam perintah membuat proxy berjalan di latar belakang. Anda akan melihat output yang mengonfirmasi bahwa proxy sudah siap seperti yang ditunjukkan di bawah
[your-project-id:your-region:cafe-concierge-db] Listening on 127.0.0.1:5432 The proxy has started successfully and is ready for new connections!
Memverifikasi koneksi
Uji bahwa Anda dapat terhubung ke database melalui proxy:
psql "host=127.0.0.1 port=5432 dbname=agent_db user=postgres password=$DB_PASSWORD" -c "SELECT 'Connection ok' AS status;"
Anda akan melihat:
status --------------------- Connection ok (1 row)
9. Memverifikasi Memori Persisten di Seluruh Sesi
Langkah ini membuktikan bahwa memori agen Anda tetap ada setelah direset saat kita memastikan bahwa cafe_concierge/.adk/session_db (database lokal) dihapus dan mencakup sesi percakapan.
Mulai agen
Pastikan Proxy Auth Cloud SQL masih berjalan (periksa dengan tugas). Jika tidak, mulai ulang:
if ss -tlnp | grep -q ':5432 '; then
echo "Cloud SQL Auth Proxy is already running."
else
cloud-sql-proxy ${GOOGLE_CLOUD_PROJECT}:${REGION}:cafe-concierge-db --port 5432 &
fi
Kemudian, mulai UI dev ADK dengan menentukan database sebagai layanan sesi
uv run adk web --session_service_uri postgresql+asyncpg://postgres:${DB_PASSWORD}@127.0.0.1:5432/agent_db
Buka Pratinjau Web di port 8000 dan pilih cafe_concierge.
Pengujian 1: Lakukan pemesanan dan tetapkan preferensi
Di sesi pertama, jalankan perintah berikut:
Show me the menu
I'm vegan
What can I eat?
I'll have a cold brew and banana bread
Pengujian 2: Bertahan saat dimulai ulang
Hentikan UI dev dengan Ctrl+C dan pastikan session.db lokal dihapus
rm -f cafe_concierge/.adk/session.db
Kemudian, jalankan kembali server UI dev
uv run adk web --session_service_uri postgresql+asyncpg://postgres:${DB_PASSWORD}@127.0.0.1:5432/agent_db
Buka Pratinjau Web di port 8000, pilih cafe_concierge, dan mulai sesi baru. Kemudian tanyakan
What are my dietary preferences?
Agen akan merespons dengan preferensi tersimpan Anda — vegan. Data tetap ada setelah dimulai ulang karena kini disimpan di PostgreSQL, bukan di penyimpanan lokal. Hal yang sama akan terjadi jika kita membuat sesi baru karena status user: akan diteruskan ke setiap sesi baru untuk pengguna ini.

Memeriksa database secara langsung
Buka tab terminal baru di Cloud Shell dan kueri database untuk melihat data yang disimpan:
psql "host=127.0.0.1 port=5432 dbname=agent_db user=postgres password=$DB_PASSWORD" -c "\dt"
Anda akan melihat tabel yang dibuat ADK secara otomatis untuk menyimpan sesi, peristiwa, dan status seperti contoh ini
List of relations Schema | Name | Type | Owner --------+-----------------------+-------+---------- public | adk_internal_metadata | table | postgres public | app_states | table | postgres public | events | table | postgres public | sessions | table | postgres public | user_states | table | postgres (5 rows)
Ringkasan perilaku status
Kunci status | Awalan | Cakupan | Dibagikan di seluruh sesi? |
| (tidak ada) | Sesi | Tidak |
|
| Pengguna | Ya |
10. Selamat / Pembersihan
Selamat! Anda telah berhasil membangun agen AI persisten dan stateful menggunakan ADK dan Cloud SQL.
Yang telah Anda pelajari
- Cara membuat agen ADK dengan alat kustom yang membaca dan menulis status sesi
- Perbedaan antara status cakupan sesi (tanpa awalan) dan status cakupan pengguna (awalan
user:) - Mengapa adk lokal
session.dbdefault hanya cocok untuk pengembangan — semua data akan hilang saat dihapus (dan mudah dihapus, tidak ada cadangan), tidak cocok untuk deployment serverless yang stateless - Cara menyediakan instance Cloud SQL PostgreSQL dan terhubung ke instance tersebut dengan Proxy Auth Cloud SQL
- Cara terhubung ke DatabaseSessionService dengan PostgreSQL di CloudSQL dengan perubahan kode minimal — alat yang sama, agen yang sama, backend yang berbeda
- Cara status cakupan pengguna dipertahankan di seluruh sesi percakapan terpisah
Pembersihan
Agar tidak menimbulkan biaya pada akun Google Cloud Anda, bersihkan resource yang dibuat dalam codelab ini.
Opsi 1: Menghapus project (direkomendasikan)
Cara termudah untuk membersihkan adalah dengan menghapus project. Tindakan ini akan menghapus semua resource yang terkait dengan project.
gcloud projects delete ${GOOGLE_CLOUD_PROJECT}
Opsi 2: Menghapus resource satu per satu
Jika Anda ingin mempertahankan project, tetapi hanya menghapus resource yang dibuat di codelab ini:
gcloud sql instances delete cafe-concierge-db --quiet