Database sebagai Alat: RAG Agentic dengan ADK, MCP Toolbox, dan Cloud SQL

1. Pengantar

Kualitas agen AI bergantung pada kualitas data yang dapat diaksesnya. Sebagian besar data dunia nyata berada di database — dan menghubungkan agen ke database biasanya berarti menulis pengelolaan koneksi, logika kueri, dan menyematkan pipeline di dalam kode agen Anda. Setiap agen yang memerlukan akses database mengulangi pekerjaan ini, dan setiap perubahan kueri memerlukan deployment ulang agen.

Codelab ini menunjukkan pendekatan yang berbeda. Anda mendeklarasikan alat database dalam file YAML — kueri SQL standar, penelusuran kemiripan vektor, bahkan pembuatan embedding otomatis — dan MCP Toolbox for Databases menangani semua operasi database sebagai server MCP. Kode agen Anda tetap minimal: muat alat, biarkan Gemini memutuskan alat mana yang akan dipanggil.

Yang akan Anda bangun

Asisten Papan Lowongan Pintar untuk "TechJobs" — agen ADK yang didukung Gemini yang membantu developer menjelajahi daftar lowongan di bidang teknologi menggunakan filter standar (peran, stack teknologi) dan menemukan pekerjaan melalui deskripsi bahasa alami seperti "Saya ingin pekerjaan jarak jauh yang mengerjakan chatbot AI." Agen membaca dan menulis ke database Cloud SQL PostgreSQL sepenuhnya melalui MCP Toolbox for Databases, yang menangani semua akses database — termasuk pembuatan embedding otomatis untuk penelusuran vektor. Pada akhirnya, Toolbox dan agen akan berjalan di Cloud Run.

eb6de681c40990c1.jpeg

Yang akan Anda pelajari

  • Cara MCP (Model Context Protocol) menstandardisasi akses alat untuk agen AI, dan cara MCP Toolbox untuk Database menerapkan hal ini pada operasi database
  • Menyiapkan MCP Toolbox untuk Database sebagai middleware antara agen ADK dan Cloud SQL PostgreSQL
  • Tentukan alat database secara deklaratif di tools.yaml — tidak ada kode database di agen Anda
  • Membangun agen ADK yang memuat alat dari server Toolbox yang sedang berjalan menggunakan ToolboxToolset
  • Buat embedding vektor menggunakan fungsi embedding() bawaan Cloud SQL dan aktifkan penelusuran semantik dengan pgvector
  • Gunakan fitur valueFromParam untuk penyerapan vektor otomatis pada operasi tulis
  • Men-deploy server Toolbox dan agen ADK ke Cloud Run

Prasyarat

  • Akun Google Cloud dengan akun penagihan uji coba
  • Pemahaman dasar tentang Python dan SQL
  • Pengalaman sebelumnya dengan Cloud Database dan ADK akan sangat membantu

2. Menyiapkan Lingkungan Anda

Langkah ini menyiapkan lingkungan Cloud Shell, mengonfigurasi project Google Cloud, dan meng-clone repositori referensi.

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

Kemudian, klik "View" -> "Terminal" untuk membuka terminal.Antarmuka Anda akan terlihat mirip dengan ini

86307fac5da2f077.png

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:

mkdir -p ~/build-agent-adk-toolbox-cloudsql
cloudshell workspace ~/build-agent-adk-toolbox-cloudsql && cd ~/build-agent-adk-toolbox-cloudsql

Setelah itu, siapkan beberapa direktori untuk mengelola hal-hal seperti skrip dan log seeding

mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs

Menyiapkan project Google Cloud

Buat file .env dengan variabel lokasi:

# For Vertex AI / Gemini API calls
echo "GOOGLE_CLOUD_LOCATION=global" > .env
# For Cloud SQL, Cloud Run, Artifact Registry
echo "REGION=us-central1" >> .env

Untuk menyederhanakan penyiapan project di terminal, download skrip penyiapan project ini 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 project ID Anda ke file .env di direktori saat ini, dan menetapkan project aktif di gcloud.

bash setup_verify_trial_project.sh && source .env

Skrip akan:

  1. Pastikan Anda memiliki akun penagihan uji coba yang aktif
  2. Periksa project yang ada di .env (jika ada)
  3. Buat project baru atau gunakan kembali project yang sudah ada
  4. Menautkan akun penagihan uji coba ke project Anda
  5. Simpan project ID ke .env
  6. Menetapkan project sebagai project gcloud yang 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.

dcba35ce1389f313.png

Aktifkan API yang Diperlukan

Selanjutnya, kita perlu mengaktifkan beberapa API untuk produk yang akan kita gunakan:

gcloud services enable \
  aiplatform.googleapis.com \
  sqladmin.googleapis.com \
  compute.googleapis.com \
  run.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com
  • Vertex AI API (aiplatform.googleapis.com) — agen Anda menggunakan model Gemini, dan Toolbox menggunakan embedding API untuk penelusuran vektor.
  • Cloud SQL Admin API (sqladmin.googleapis.com) — Anda menyediakan dan mengelola instance PostgreSQL.
  • Compute Engine API (compute.googleapis.com) — diperlukan untuk membuat instance Cloud SQL.
  • Cloud Run, Cloud Build, Artifact Registry — digunakan dalam langkah deployment nanti di codelab ini

3. Menyiapkan Skrip untuk Inisialisasi Database

Langkah ini memulai pembuatan instance Cloud SQL dan menjalankan skrip penyiapan otomatis yang menunggu hingga instance siap, lalu membuat database, mengisinya dengan listingan pekerjaan, dan membuat penyematan — semuanya dalam satu operasi.

Pertama, tambahkan sandi database ke file .env dan muat ulang:

echo "DB_PASSWORD=techjobs-pwd" >> .env
echo "DB_INSTANCE=jobs-instance" >> .env
echo "DB_NAME=jobs_db" >> .env
source .env

Membuat skrip Bash untuk pembuatan instance dan database

Kemudian, buat skrip scripts/setup_database.sh dengan perintah berikut

mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
cloudshell edit scripts/setup_database.sh

Kemudian, salin kode berikut ke dalam file scripts/setup_database.sh

#!/bin/bash
set -e
source .env

echo "================================================"
echo "Database Setup"
echo "================================================"
echo ""

# Step 1: Create Cloud SQL instance
echo "[1/5] Creating Cloud SQL instance..."

# Check if instance already exists
if gcloud sql instances describe "$DB_INSTANCE" --quiet >/dev/null 2>&1; then
    echo "      Instance already exists"
else
    echo "      Creating instance (takes 5-10 minutes)..."
    gcloud sql instances create "$DB_INSTANCE" \
        --database-version=POSTGRES_17 \
        --tier=db-custom-1-3840 \
        --edition=ENTERPRISE \
        --region="$REGION" \
        --root-password="$DB_PASSWORD" \
        --enable-google-ml-integration \
        --database-flags cloudsql.enable_google_ml_integration=on \
        --quiet
fi
echo "      ✓ Instance ready"
echo ""

# Step 2: Verify instance is ready
echo "[2/5] Verifying instance state..."

STATE=$(gcloud sql instances describe "$DB_INSTANCE" --format='value(state)')

if [ "$STATE" != "RUNNABLE" ]; then
    echo "ERROR: Instance not ready (state: $STATE)"
    exit 1
fi
echo "      ✓ Instance is RUNNABLE"
echo ""

# Step 3: Grant IAM permissions
echo "[3/5] Granting Vertex AI permissions..."

SERVICE_ACCOUNT=$(gcloud sql instances describe "$DB_INSTANCE" \
    --format='value(serviceAccountEmailAddress)')

if [ -z "$SERVICE_ACCOUNT" ]; then
    echo "ERROR: Could not retrieve service account"
    exit 1
fi

gcloud projects add-iam-policy-binding "$GOOGLE_CLOUD_PROJECT" \
    --member="serviceAccount:$SERVICE_ACCOUNT" \
    --role="roles/aiplatform.user" \
    --quiet

echo "      ✓ Permissions granted"
echo ""

# Step 4: Create database
echo "[4/5] Creating database..."

# Check if database already exists
if gcloud sql databases describe "$DB_NAME" \
    --instance="$DB_INSTANCE" --quiet >/dev/null 2>&1; then
    echo "      Database already exists"
else
    gcloud sql databases create "$DB_NAME" \
        --instance="$DB_INSTANCE" \
        --quiet
fi

echo "      ✓ Database '$DB_NAME' ready"
echo ""

# Step 5: Seed database and generate embeddings
echo "[5/5] Seeding database and generating embeddings..."

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SETUP_SCRIPT="${SCRIPT_DIR}/setup_jobs_db.py"

if [ ! -f "$SETUP_SCRIPT" ]; then
    echo "ERROR: Setup script not found: $SETUP_SCRIPT"
    exit 1
fi

uv run "$SETUP_SCRIPT"

echo ""
echo "================================================"
echo "Setup complete!"
echo "================================================"
echo ""

Membuat skrip Python untuk pengisian data

Setelah itu, buat file python skrip seeding scripts/setup_jobs_db.py menggunakan perintah di bawah

cloudshell edit scripts/setup_jobs_db.py

Kemudian, salin kode berikut ke dalam file scripts/setup_jobs_db.py

import os
import sys
from pathlib import Path
from dotenv import load_dotenv
from google.cloud.sql.connector import Connector
import pg8000
import time

# Load environment variables from .env file
env_path = Path(__file__).parent.parent / '.env'
load_dotenv(env_path)
EMBEDDING_MODEL='gemini-embedding-001'

# Verify required environment variables
required_vars = ['GOOGLE_CLOUD_PROJECT', 'REGION', 'DB_PASSWORD']
missing_vars = [var for var in required_vars if not os.environ.get(var)]

if missing_vars:
    print(f"ERROR: Missing required environment variables: {', '.join(missing_vars)}", file=sys.stderr)
    print(f"", file=sys.stderr)
    print(f"Expected .env file location: {env_path}", file=sys.stderr)
    if not env_path.exists():
        print(f"✗ File not found at that location", file=sys.stderr)
    else:
        print(f"✓ File exists but is missing the variables above", file=sys.stderr)
    print(f"", file=sys.stderr)
    print(f"Make sure your .env file contains:", file=sys.stderr)
    for var in missing_vars:
        print(f"  {var}=<value>", file=sys.stderr)
    sys.exit(1)

# Job listings data (fictional, for tutorial purposes only)
JOBS = [
    ("Senior Backend Engineer", "Stripe", "Backend", "Go, PostgreSQL, gRPC, Kubernetes", "$180-250K/year", "San Francisco, Hybrid", 3,
     "Design and build high-throughput microservices powering payment infrastructure for millions of businesses. Optimize Go services for sub-100ms latency at scale, work with PostgreSQL and Redis for data persistence, and deploy on Kubernetes clusters handling billions of API calls."),
    ("Machine Learning Engineer", "Spotify", "Data/AI", "Python, TensorFlow, BigQuery, Vertex AI", "$170-230K/year", "Stockholm, Remote", 2,
     "Build and deploy ML models for music recommendation and personalization systems serving hundreds of millions of listeners. Design feature pipelines in BigQuery, train models using distributed computing, and serve predictions through real-time APIs processing thousands of requests per second."),
    ("Frontend Engineer", "Vercel", "Frontend", "React, TypeScript, Next.js", "$140-190K/year", "Remote", 4,
     "Build developer-facing dashboard interfaces and deployment tools used by millions of developers worldwide. Create responsive, accessible React components for project management, analytics, and real-time deployment monitoring with a focus on developer experience."),
    ("DevOps Engineer", "Datadog", "DevOps", "Terraform, GCP, Docker, Kubernetes, ArgoCD", "$160-220K/year", "New York, Hybrid", 2,
     "Manage cloud infrastructure powering an observability platform used by thousands of engineering teams. Automate deployment pipelines with ArgoCD, manage multi-cloud Kubernetes clusters, and implement infrastructure-as-code with Terraform across production environments."),
    ("Mobile Engineer (Android)", "Grab", "Mobile", "Kotlin, Jetpack Compose, GraphQL", "$120-170K/year", "Singapore, Hybrid", 3,
     "Develop features for a super-app serving millions of users across Southeast Asia. Build modern Android UIs with Jetpack Compose, integrate GraphQL APIs, and optimize app performance for diverse device capabilities and network conditions."),
    ("Data Engineer", "Airbnb", "Data", "Python, Apache Spark, Airflow, BigQuery", "$160-210K/year", "San Francisco, Hybrid", 2,
     "Build data pipelines that process booking, search, and pricing data for a global travel marketplace. Design ETL workflows with Apache Spark and Airflow, maintain data warehouses in BigQuery, and ensure data quality for analytics and machine learning teams."),
    ("Full Stack Engineer", "Revolut", "Full Stack", "TypeScript, Node.js, React, PostgreSQL", "$130-180K/year", "London, Remote", 5,
     "Build the next generation of financial products making banking accessible to millions of users across 35 countries. Develop real-time trading interfaces with React and WebSockets, build Node.js APIs handling market data streams, and design PostgreSQL schemas for financial transactions."),
    ("Site Reliability Engineer", "Cloudflare", "SRE", "Go, Prometheus, Grafana, GCP, Terraform", "$170-230K/year", "Austin, Hybrid", 2,
     "Ensure 99.99% uptime for a global network handling millions of requests per second. Define SLOs, build monitoring dashboards with Prometheus and Grafana, manage incident response, and automate infrastructure scaling across 300+ data centers worldwide."),
    ("Cloud Architect", "Google Cloud", "Cloud", "GCP, Terraform, Kubernetes, Python", "$200-280K/year", "Seattle, Hybrid", 1,
     "Help enterprises modernize their infrastructure on Google Cloud. Design multi-region architectures, lead migration projects from on-premises to GKE, and build reference implementations using Terraform and Cloud Foundation Toolkit."),
    ("Backend Engineer (Payments)", "Square", "Backend", "Java, Spring Boot, PostgreSQL, Kafka", "$160-220K/year", "San Francisco, Hybrid", 3,
     "Build payment processing systems handling millions of transactions for businesses of all sizes. Design event-driven architectures using Kafka, implement idempotent payment flows with Spring Boot, and ensure PCI-DSS compliance across all services."),
    ("AI Engineer", "Hugging Face", "Data/AI", "Python, LangChain, Vertex AI, FastAPI, PostgreSQL", "$150-210K/year", "Paris, Remote", 2,
     "Build AI-powered tools for the largest open-source ML community. Develop RAG pipelines that index and search model documentation, create conversational agents using LangChain, and deploy AI services with FastAPI on cloud infrastructure."),
    ("Platform Engineer", "Coinbase", "Platform", "Rust, Kubernetes, AWS, Terraform", "$180-250K/year", "Remote", 0,
     "Build the infrastructure platform for a leading cryptocurrency exchange. Develop high-performance matching engines in Rust, manage Kubernetes clusters for microservices, and design CI/CD pipelines that enable rapid feature deployment with zero downtime."),
    ("QA Automation Engineer", "Shopify", "QA", "Python, Selenium, Cypress, Jenkins", "$110-160K/year", "Toronto, Hybrid", 3,
     "Design and maintain automated test suites for a commerce platform powering millions of merchants. Build end-to-end test frameworks with Cypress and Selenium, integrate tests into Jenkins CI pipelines, and establish quality gates that prevent regressions in checkout and payment flows."),
    ("Security Engineer", "CrowdStrike", "Security", "Python, SIEM, Kubernetes, Penetration Testing", "$170-240K/year", "Austin, On-site", 1,
     "Protect enterprise customers from cyber threats on a leading endpoint security platform. Conduct penetration testing, design security monitoring with SIEM tools, implement zero-trust networking in Kubernetes environments, and lead incident response for security events."),
    ("Product Engineer", "GitLab", "Full Stack", "Go, React, PostgreSQL, Redis, GCP", "$140-200K/year", "Remote", 4,
     "Own features end-to-end for an all-in-one DevSecOps platform used by millions of developers. Build Go microservices for CI/CD pipelines, create React frontends for code review and project management, and collaborate with product managers to iterate on user-facing features using data-driven development."),
]


def get_connection():
    """Create a connection to Cloud SQL using the connector."""
    project = os.environ['GOOGLE_CLOUD_PROJECT']
    region = os.environ['REGION']
    password = os.environ['DB_PASSWORD']
    instance = os.environ['DB_INSTANCE']
    database = os.environ['DB_NAME']

    connector = Connector()
    conn = connector.connect(
        f"{project}:{region}:{instance}",
        "pg8000",
        user="postgres",
        password=password,
        db=database
    )
    return conn, connector


def create_schema(cursor):
    """Create extensions and jobs table."""
    cursor.execute("CREATE EXTENSION IF NOT EXISTS google_ml_integration")
    cursor.execute("CREATE EXTENSION IF NOT EXISTS vector")
    cursor.execute("""
        CREATE TABLE IF NOT EXISTS jobs (
            id SERIAL PRIMARY KEY,
            title VARCHAR NOT NULL,
            company VARCHAR NOT NULL,
            role VARCHAR NOT NULL,
            tech_stack VARCHAR NOT NULL,
            salary_range VARCHAR NOT NULL,
            location VARCHAR NOT NULL,
            openings INTEGER NOT NULL,
            description TEXT NOT NULL,
            description_embedding vector(3072)
        )
    """)


def seed_jobs(cursor, conn):
    """Insert job listings."""
    cursor.execute("SELECT COUNT(*) FROM jobs")
    existing_count = cursor.fetchone()[0]

    if existing_count > 0:
        print(f"      {existing_count} jobs already exist, skipping seed")
        return 0

    cursor.executemany("""
        INSERT INTO jobs (title, company, role, tech_stack, salary_range, location, openings, description)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
    """, JOBS)
    conn.commit()
    return len(JOBS)


def generate_embeddings(cursor, conn):
    """Generate embeddings using Cloud SQL's embedding() function."""
    cursor.execute("SELECT COUNT(*) FROM jobs WHERE description_embedding IS NULL")
    null_count = cursor.fetchone()[0]

    if null_count == 0:
        print("      All jobs already have embeddings")
        return 0

    cursor.execute(f"""
        UPDATE jobs
        SET description_embedding = embedding('{EMBEDDING_MODEL}', description)::vector
        WHERE description_embedding IS NULL
    """)
    rows_updated = cursor.rowcount
    conn.commit()
    return rows_updated


def main():
    conn, connector = get_connection()
    cursor = conn.cursor()

    try:
        create_schema(cursor)
        conn.commit()

        seeded = seed_jobs(cursor, conn)
        if seeded > 0:
            print(f"      ✓ Inserted {seeded} jobs")

        # Waiting for vertex role propagation
        time.sleep(60)
        embedded = generate_embeddings(cursor, conn)
        if embedded > 0:
            print(f"      ✓ Generated {embedded} embeddings")

    except Exception as e:
        print(f"ERROR: {e}", file=sys.stderr)
        sys.exit(1)
    finally:
        cursor.close()
        conn.close()
        connector.close()


if __name__ == "__main__":
    main()

Sekarang, mari kita lanjutkan ke langkah berikutnya

4. Membuat dan Menginisialisasi Database

Sekarang skrip kita siap dieksekusi. Kita akan memerlukan Python untuk mengeksekusi skrip yang sudah disiapkan, jadi mari kita siapkan terlebih dahulu

Menyiapkan project Python

uv adalah pengelola project dan paket Python cepat yang ditulis dalam Rust ( dokumentasi uv ). Codelab ini menggunakannya untuk kecepatan dan kesederhanaan dalam memelihara project Python

Inisialisasi project Python dan tambahkan dependensi yang diperlukan:

uv init
uv add cloud-sql-python-connector --extra pg8000
uv add python-dotenv

Perhatikan bahwa kita menggunakan cloud-sql-python-connector Python SDK di sini untuk menginisialisasi koneksi yang aman dengan instance database yang diautentikasi menggunakan Kredensial Default Aplikasi.

Jalankan skrip penyiapan

Sekarang, kita dapat menjalankan skrip penyiapan di latar belakang dan memeriksa output konsol yang akan ditulis ke file logs/atabase_setup.log menggunakan perintah berikut. Anda dapat melanjutkan ke bagian berikutnya sambil menunggu proses ini selesai

mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
bash scripts/setup_database.sh > logs/database_setup.log 2>&1 &

Download biner Toolbox

Kita akan menggunakan MCP Toolbox dalam tutorial ini. Untungnya, MCP Toolbox dilengkapi dengan biner bawaan yang siap digunakan di lingkungan Linux. Sekarang, mari kita download di latar belakang karena prosesnya cukup lama. Jalankan perintah berikut untuk mendownload biner dan memeriksa log output di logs/toolbox_dl.log . Anda dapat melanjutkan ke bagian berikutnya sambil menunggu proses ini selesai

cd ~/build-agent-adk-toolbox-cloudsql
curl -O https://storage.googleapis.com/mcp-toolbox-for-databases/v1.0.0/linux/amd64/toolbox > logs/toolbox_dl.log 2>&1 &

Memahami skrip penyiapan scripts/setup_database.sh

Sekarang, mari kita coba memahami skrip penyiapan yang kita konfigurasi sebelumnya. Proses ini melakukan hal berikut

  1. Perintah pertama yang kita jalankan di sana adalah perintah gcloud sql instances create dengan flag berikut
  • db-custom-1-3840 adalah tingkat Cloud SQL dengan core khusus terkecil (1 vCPU, RAM 3,75 GB) dalam edisi ENTERPRISE. Anda dapat membaca detail selengkapnya di sini. Core khusus diperlukan untuk integrasi ML Vertex AI — tingkat core bersama (db-f1-micro, db-g1-small) tidak mendukungnya.
  • --root-password menyetel sandi untuk pengguna postgres default.
  • --enable-google-ml-integration memungkinkan integrasi bawaan Cloud SQL dengan Vertex AI, yang memungkinkan Anda memanggil model embedding langsung dari SQL menggunakan fungsi embedding().
  1. Verifikasi apakah instance sudah dalam status RUNNABLE
  2. Beri izin akun layanan instance Cloud SQL untuk memanggil Vertex AI menggunakan perintah gcloud projects add-iam-policy-binding. Hal ini diperlukan untuk fungsi embedding() bawaan yang akan kita gunakan saat mengisi database
  3. Membuat database
  4. Mengeksekusi skrip pengisian data setup_jobs_db.py

Memahami skrip pengurutan scripts/setup_jobs_db.py

Sekarang, beralih ke skrip seeding, skrip ini melakukan hal berikut:

  1. Melakukan inisialisasi koneksi ke instance database
  2. Menginstal dua ekstensi PostgreSQL:
  • google_ml_integration — menyediakan fungsi SQL embedding(), yang memanggil model embedding Vertex AI langsung dari SQL. Ini adalah ekstensi tingkat database yang membuat fungsi ML tersedia di dalam jobs_db. Flag tingkat instance (--enable-google-ml-integration) yang Anda tetapkan selama pembuatan instance memungkinkan VM Cloud SQL menjangkau Vertex AI — ekstensi ini membuat fungsi SQL tersedia dalam database tertentu ini.
  • vector (pgvector) — menambahkan jenis data vector dan operator jarak untuk menyimpan dan membuat kueri penyematan.
  1. Buat tabel, perhatikan bahwa kolom description_embedding adalah vector(3072) — kolom pgvector yang menyimpan vektor 3072 dimensi.
  2. Menambahkan data tugas awal
  3. Buat data embedding dari kolom description dan isi description_embedding menggunakan integrasi Vertex bawaan melalui fungsi embedding()
  • embedding('gemini-embedding-001', description) — memanggil model embedding Gemini Vertex AI langsung dari SQL, dengan meneruskan teks description setiap tugas. Ini adalah ekstensi google_ml_integration yang Anda instal dalam skrip awal.
  • ::vector — mentransmisikan array float yang ditampilkan ke jenis vector pgvector sehingga dapat disimpan dan dikueri dengan operator jarak.
  • UPDATE berjalan di semua 15 baris, menghasilkan satu sematan 3072 dimensi per deskripsi pekerjaan.

Tindakan ini akan menyiapkan data awal yang akan diakses oleh agen kami

5. Mengonfigurasi MCP Toolbox for Databases

Langkah ini memperkenalkan MCP Toolbox for Databases, mengonfigurasinya untuk terhubung ke instance Cloud SQL Anda, dan menentukan dua alat kueri SQL standar.

Apa itu MCP dan mengapa menggunakan Toolbox?

e7b9be2e1c98b4db.png

MCP (Model Context Protocol) adalah protokol terbuka yang menstandardisasi cara agen AI menemukan dan berinteraksi dengan alat eksternal. Model ini menentukan model klien-server: agen menghosting klien MCP, dan alat diekspos oleh server MCP. Klien yang kompatibel dengan MCP dapat menggunakan server yang kompatibel dengan MCP — agen tidak memerlukan kode integrasi kustom untuk setiap alat.

5bf26eeecad2277d.png

MCP Toolbox for Databases adalah server MCP open source yang dibuat khusus untuk akses database. Tanpa itu, Anda akan menulis fungsi Python yang membuka koneksi database, mengelola kumpulan koneksi, membuat kueri berparameter untuk mencegah injeksi SQL, menangani error, dan menyematkan semua kode tersebut di dalam agen Anda. Setiap agen yang memerlukan akses database mengulangi pekerjaan ini. Mengubah kueri berarti men-deploy ulang agen.

Dengan Toolbox, Anda menulis file YAML. Setiap alat dipetakan ke pernyataan SQL berparameter. Toolbox menangani penggabungan koneksi, kueri berparameter, autentikasi, dan kemampuan observasi. Alat tidak terikat dengan agen — perbarui kueri dengan mengedit tools.yaml dan memulai ulang Toolbox, tanpa menyentuh kode agen. Alat yang sama dapat digunakan di ADK, LangGraph, LlamaIndex, atau framework yang kompatibel dengan MCP.

Menulis konfigurasi alat

Sekarang, kita perlu membuat file bernama tools.yaml di Cloud Shell Editor untuk menyiapkan konfigurasi alat

cloudshell edit tools.yaml

File menggunakan YAML multi-dokumen — setiap blok yang dipisahkan oleh --- adalah resource mandiri. Setiap resource memiliki kind yang menyatakan apa resource tersebut (sources untuk koneksi database, tools untuk tindakan yang dapat dipanggil agen) dan type yang menentukan backend (cloud-sql-postgres untuk sumber, postgres-sql untuk alat berbasis SQL). Alat mereferensikan sumbernya berdasarkan name, sehingga Toolbox mengetahui kumpulan koneksi mana yang akan dijalankan. Variabel lingkungan menggunakan sintaksis ${VAR_NAME} dan diselesaikan saat startup.

Sekarang, salin skrip berikut terlebih dahulu ke dalam file tools.yaml

# tools.yaml

# --- Data Source ---
kind: source
name: jobs-db
type: cloud-sql-postgres
project: ${GOOGLE_CLOUD_PROJECT}
region: ${REGION}
instance: ${DB_INSTANCE}
database: ${DB_NAME}
user: postgres
password: ${DB_PASSWORD}

---

Skrip ini menentukan resource berikut:

  • Sumber (jobs-db) — memberi tahu Toolbox cara terhubung ke instance Cloud SQL PostgreSQL Anda. Jenis cloud-sql-postgres menggunakan konektor Cloud SQL secara internal, menangani autentikasi dan koneksi yang aman secara otomatis. Placeholder ${GOOGLE_CLOUD_PROJECT}, ${REGION}, dan ${DB_PASSWORD} di-resolve dari variabel lingkungan saat startup.

Selanjutnya, tambahkan skrip berikut di bawah simbol --- dalam tools.yaml

# --- Tool 1: Search jobs by role and/or tech stack ---
kind: tool
name: search-jobs
type: postgres-sql
source: jobs-db
description: >-
  Search for job listings by role category and/or tech stack.
  Use this tool when the developer wants to browse listings
  by role (e.g., Backend, Frontend, Data) or find jobs
  using a specific technology. Both parameters accept an
  empty string to match all values.
statement: |
  SELECT title, company, role, tech_stack, salary_range, location, openings
  FROM jobs
  WHERE ($1 = '' OR LOWER(role) = LOWER($1))
  AND ($2 = '' OR LOWER(tech_stack) LIKE '%' || LOWER($2) || '%')
  ORDER BY title
  LIMIT 10
parameters:
  - name: role
    type: string
    description: "The role category to filter by (e.g., 'Backend', 'Frontend', 'Data/AI', 'DevOps'). Use empty string for all roles."
  - name: tech_stack
    type: string
    description: "A technology to search for in the tech stack (partial match, e.g., 'Python', 'Kubernetes'). Use empty string for all tech stacks."

---

# --- Tool 2: Get full details for a specific job ---
kind: tool
name: get-job-details
type: postgres-sql
source: jobs-db
description: >-
  Get full details for a specific job listing including its description,
  salary range, location, and number of openings. Use this tool when the
  developer asks about a particular job by title or company.
statement: |
  SELECT title, company, role, tech_stack, salary_range, location, openings, description
  FROM jobs
  WHERE LOWER(title) LIKE '%' || LOWER($1) || '%'
  OR LOWER(company) LIKE '%' || LOWER($1) || '%'
parameters:
  - name: search_term
    type: string
    description: "The job title or company name to look up (partial match supported)."

---

Skrip ini menentukan resource berikut:

  • Alat 1 dan 2 (search-jobs, get-job-details) — alat kueri SQL standar. Setiap peta nama alat (yang dilihat agen) ke pernyataan SQL berparameter (yang dieksekusi database). Parameter menggunakan placeholder posisi $1, $2. Toolbox menjalankan perintah ini sebagai pernyataan yang sudah disiapkan, yang mencegah injeksi SQL.

Lanjutkan, tambahkan skrip berikut di bawah simbol --- dalam tools.yaml

# --- Embedding Model ---
kind: embeddingModel
name: gemini-embedding
type: gemini
model: gemini-embedding-001
project: ${GOOGLE_CLOUD_PROJECT}
location: ${GOOGLE_CLOUD_LOCATION}
dimension: 3072

---

Skrip ini menentukan resource berikut:

  • Model embedding (gemini-embedding) — mengonfigurasi Toolbox untuk memanggil model gemini-embedding-001 Gemini guna membuat embedding teks 3072 dimensi. Toolbox menggunakan Kredensial Default Aplikasi (ADC) untuk melakukan autentikasi — tidak memerlukan kunci API di Cloud Shell atau Cloud Run. Mencatat bahwa dimension yang dikonfigurasi di sini harus sama dengan yang sebelumnya kita konfigurasi untuk mengisi database

Lanjutkan, tambahkan skrip berikut di bawah simbol --- dalam tools.yaml

# --- Tool 3: Semantic search by description ---
kind: tool
name: search-jobs-by-description
type: postgres-sql
source: jobs-db
description: >-
  Find jobs that match a natural language description of what the developer
  is looking for. Use this tool when the developer describes their ideal job
  using interests, work style, career goals, or project type rather than a
  specific role or tech stack. Examples: "I want to work on AI chatbots,"
  "a remote job at a fintech startup," "something involving infrastructure
  and reliability."
statement: |
  SELECT title, company, role, tech_stack, salary_range, location, description
  FROM jobs
  WHERE description_embedding IS NOT NULL
  ORDER BY description_embedding <=> $1
  LIMIT 5
parameters:
  - name: search_query
    type: string
    description: "A natural language description of the kind of job the developer is looking for."
    embeddedBy: gemini-embedding

---

Skrip ini menentukan resource berikut:

  • Alat 3 (search-jobs-by-description) — alat penelusuran vektor. Parameter search_query memiliki embeddedBy: gemini-embedding, yang memberi tahu Toolbox untuk mencegat teks mentah, mengirimkannya ke model embedding, dan menggunakan vektor yang dihasilkan dalam pernyataan SQL. Operator <=> adalah jarak kosinus pgvector — nilai yang lebih kecil berarti deskripsi yang lebih mirip.

Terakhir, tambahkan alat terakhir di bawah simbol --- di tools.yaml

# --- Tool 4: Add a new job listing with automatic embedding ---
kind: tool
name: add-job
type: postgres-sql
source: jobs-db
description: >-
  Add a new job listing to the platform. Use this tool when a user asks
  to post a job that is not currently listed.
statement: |
  INSERT INTO jobs (title, company, role, tech_stack, salary_range, location, openings, description, description_embedding)
  VALUES ($1, $2, $3, $4, $5, $6, CAST($7 AS INTEGER), $8, $9)
  RETURNING title, company
parameters:
  - name: title
    type: string
    description: "The job title (e.g., 'Senior Backend Engineer')."
  - name: company
    type: string
    description: "The company name (e.g., 'Stripe', 'Spotify')."
  - name: role
    type: string
    description: "The role category (e.g., 'Backend', 'Frontend', 'Data/AI', 'DevOps')."
  - name: tech_stack
    type: string
    description: "Comma-separated list of technologies (e.g., 'Python, FastAPI, GCP')."
  - name: salary_range
    type: string
    description: "The salary range (e.g., '$150-200K/year')."
  - name: location
    type: string
    description: "Work location and arrangement (e.g., 'Remote')."
  - name: openings
    type: string
    description: "The number of open positions."
  - name: description
    type: string
    description: "A short description of the job (2-3 sentences)."
  - name: description_vector
    type: string
    description: "Auto-generated embedding vector for the job description."
    valueFromParam: description
    embeddedBy: gemini-embedding

Skrip ini menentukan resource berikut:

  • Alat 4 (add-job) — menunjukkan penyerapan vektor. Parameter description_vector memiliki dua kolom khusus:
  • valueFromParam: description — Toolbox menyalin nilai dari parameter description ke parameter ini. LLM tidak pernah melihat parameter ini.
  • embeddedBy: gemini-embedding — Toolbox menyematkan teks yang disalin ke dalam vektor sebelum meneruskannya ke SQL.

Hasilnya: satu panggilan alat menyimpan teks deskripsi mentah dan embedding vektornya, tanpa agen mengetahui apa pun tentang embedding.

Format YAML multi-dokumen memisahkan setiap resource dengan ---. Setiap dokumen memiliki kolom kind, name, dan type yang menentukan isinya. Singkatnya, kita telah mengonfigurasi semua hal berikut:

  • Menentukan database sumber
  • Tentukan alat ( alat 1 dan 2 ) untuk membuat kueri database dengan filter standar
  • Menentukan model embedding
  • Menentukan alat untuk melakukan penelusuran vektor ( tool 3 ) ke database
  • Tentukan alat untuk melakukan penyerapan data vektor ( alat 4 ) ke database

6. Menjalankan Server MCP Toolbox

Pada langkah sebelumnya, kita telah menetapkan konfigurasi yang diperlukan untuk MCP Toolbox. Sekarang kita siap menjalankan server

Memverifikasi data yang di-seed

Sebelum memulai Toolbox, mari kita konfirmasi bahwa penyiapan database telah selesai. Buat skrip python scripts/verify_database.py menggunakan perintah berikut

cloudshell edit scripts/verify_seed.py

Kemudian, salin kode berikut ke dalam file scripts/verify_seed.py

#!/usr/bin/env python3
"""Verify the database has 15 jobs with embeddings."""

import os
import sys
from pathlib import Path
from dotenv import load_dotenv
from google.cloud.sql.connector import Connector
import pg8000

# Load environment variables
env_path = Path(__file__).parent.parent / '.env'
load_dotenv(env_path)

# Verify required environment variables
required_vars = ['GOOGLE_CLOUD_PROJECT', 'REGION', 'DB_PASSWORD', 'DB_INSTANCE', 'DB_NAME']
missing_vars = [var for var in required_vars if not os.environ.get(var)]

if missing_vars:
    print(f"ERROR: Missing environment variables: {', '.join(missing_vars)}", file=sys.stderr)
    sys.exit(1)


def verify_database():
    """Check that 15 jobs exist with embeddings."""
    connector = Connector()

    try:
        project = os.environ['GOOGLE_CLOUD_PROJECT']
        region = os.environ['REGION']
        password = os.environ['DB_PASSWORD']
        instance = os.environ['DB_INSTANCE']
        database = os.environ['DB_NAME']

        conn = connector.connect(
            f"{project}:{region}:{instance}",
            "pg8000",
            user="postgres",
            password=password,
            db=database
        )
        cursor = conn.cursor()

        # Count jobs and embeddings
        cursor.execute("SELECT COUNT(*) FROM jobs")
        job_count = cursor.fetchone()[0]

        cursor.execute("SELECT COUNT(*) FROM jobs WHERE description_embedding IS NOT NULL")
        embedding_count = cursor.fetchone()[0]

        print(f"Jobs: {job_count}/15")
        print(f"Embeddings: {embedding_count}/15")

        cursor.close()
        conn.close()

        if job_count == 15 and embedding_count == 15:
            print("\n✓ Database ready!")
            return True
        else:
            print("\n✗ Database not ready")
            return False

    except Exception as e:
        print(f"\nERROR: {e}", file=sys.stderr)
        return False
    finally:
        connector.close()


if __name__ == "__main__":
    success = verify_database()
    sys.exit(0 if success else 1)

Skrip ini akan memeriksa jumlah data postingan lowongan kerja dan penyematannya. Jalankan skrip menggunakan perintah berikut

uv run scripts/verify_seed.py

Jika Anda melihat output terminal berikut, berarti data sudah siap

Jobs: 15/15
Embeddings: 15/15

✓ Database ready!

Mulai server Toolbox

Pada langkah penyiapan sebelumnya, kita telah mendownload file yang dapat dieksekusi toolbox. Pastikan file biner ini ada dan berhasil didownload. Jika tidak, download file tersebut dan tunggu hingga selesai

cd ~/build-agent-adk-toolbox-cloudsql
if [ ! -f toolbox ]; then
  curl -O https://storage.googleapis.com/mcp-toolbox-for-databases/v1.0.0/linux/amd64/toolbox
fi
chmod +x toolbox

Kita perlu mengekspos variabel .env ke proses turunan yang dijalankan oleh toolbox MCP. Jalankan perintah berikut untuk memulai server toolbox dan mencatat output konsolnya ke file logs/mcp_toolbox.log

set -a; source .env; set +a
./toolbox --config tools.yaml --enable-api > logs/mcp_toolbox.log 2>&1 &

Anda akan melihat output dalam file logs/mcp_toolbox.log yang mengonfirmasi bahwa server sudah siap seperti yang ditunjukkan di bawah:

... INFO "Initialized 1 sources: jobs-db"
... INFO "Initialized 0 authServices: "
... INFO "Using Vertex AI backend for Gemini embedding" 
... INFO "Initialized 1 embeddingModels: gemini-embedding" 
... INFO "Initialized 4 tools: add-job, search-jobs, get-job-details, search-jobs-by-description" 
...
... INFO "Server ready to serve!"

Memverifikasi alat

Kueri Toolbox API untuk mencantumkan semua alat terdaftar:

curl -s http://localhost:5000/api/toolset | uv run -m json.tool

Anda akan melihat alat beserta deskripsi dan parameternya. Seperti yang ditunjukkan di bawah

...
       "search-jobs-by-description": {
            "description": "Find jobs that match a natural language description of what the developer is looking for. Use this tool when the developer describes their ideal job using interests, work style, career goals, or project type rather than a specific role or tech stack. Examples: \"I want to work on AI chatbots,\" \"a remote job at a fintech startup,\" \"something involving infrastructure and reliability.\"",
            "parameters": [
                {
                    "name": "search_query",
                    "type": "string",
                    "required": true,
                    "description": "A natural language description of the kind of job the developer is looking for.",
                    "authSources": []
                }
            ],
            "authRequired": []
        }
...

Uji alat search-jobs secara langsung:

curl -s -X POST http://localhost:5000/api/tool/search-jobs/invoke \
  -H "Content-Type: application/json" \
  -d '{"role": "Backend", "tech_stack": ""}' | jq '.result | fromjson'

Respons harus berisi dua lowongan pekerjaan backend engineer dari data awal Anda.

[
  {
    "title": "Backend Engineer (Payments)",
    "company": "Square",
    "role": "Backend",
    "tech_stack": "Java, Spring Boot, PostgreSQL, Kafka",
    "salary_range": "$160-220K/year",
    "location": "San Francisco, Hybrid",
    "openings": 3
  },
  {
    "title": "Senior Backend Engineer",
    "company": "Stripe",
    "role": "Backend",
    "tech_stack": "Go, PostgreSQL, gRPC, Kubernetes",
    "salary_range": "$180-250K/year",
    "location": "San Francisco, Hybrid",
    "openings": 3
  }
]

7. Membangun Agen ADK

Sekarang, kita akan menggunakan ADK di Python untuk project ini. Mari tambahkan dependensi yang diperlukan:

uv add google-adk==1.29.0 toolbox-adk==1.0.0
  • google-adk — Agent Development Kit Google, termasuk Gemini SDK
  • toolbox-adk — Integrasi ADK untuk MCP Toolbox for Databases.

Buat struktur direktori agen

ADK mengharapkan tata letak folder tertentu: direktori yang dinamai sesuai agen Anda yang berisi __init__.py, agent.py, dan .env. Untuk membantu hal ini, ada perintah bawaan untuk membuat struktur dengan cepat:

uv run adk create jobs_agent \
    --model gemini-2.5-flash \
    --project ${GOOGLE_CLOUD_PROJECT} \
    --region ${GOOGLE_CLOUD_LOCATION}

Direktori Anda sekarang akan terlihat seperti ini:

build-agent-adk-toolbox-cloudsql/
├── jobs_agent/
│   ├── __init__.py
│   ├── agent.py
│   └── .env
├── logs
├── scripts
└── ...

Selanjutnya, kita perlu mengintegrasikan agen ADK ke server Toolbox yang sedang berjalan dan menguji keempat alat — kueri standar, penelusuran semantik, dan penyerapan vektor. Kode agennya minimal: semua logika database berada di tools.yaml.

Mengonfigurasi lingkungan agen

ADK membaca GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT, dan GOOGLE_CLOUD_LOCATION dari lingkungan shell, yang sudah Anda tetapkan di langkah sebelumnya. Satu-satunya variabel khusus agen adalah TOOLBOX_URL — tambahkan ke file .env agen:

echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env

Memperbarui modul agen

Buka jobs_agent/agent.py di Cloud Shell Editor

cloudshell edit jobs_agent/agent.py

dan timpa konten dengan kode berikut:

# jobs_agent/agent.py
import os

from google.adk.agents import LlmAgent
from toolbox_adk import ToolboxToolset

TOOLBOX_URL = os.environ.get("TOOLBOX_URL", "http://127.0.0.1:5000")

toolbox = ToolboxToolset(TOOLBOX_URL)

root_agent = LlmAgent(
    name="jobs_agent",
    model="gemini-2.5-flash",
    instruction="""You are a helpful assistant at "TechJobs," a tech job listing platform.

Your job:
- Help developers browse job listings by role or tech stack.
- Provide full details about specific positions, including salary range and number of openings.
- Recommend jobs based on natural language descriptions of what the developer is looking for.
- Add new job listings to the platform when asked.

When a developer asks about a specific job by title or company, use the get-job-details tool.
When a developer asks for a specific role category or tech stack, use the search-jobs tool.
When a developer describes what kind of job they want — by interest area, work style,
career goals, or project type — use the search-jobs-by-description tool for semantic search.
When in doubt between search-jobs and search-jobs-by-description, prefer
search-jobs-by-description — it searches job descriptions and finds more relevant matches.

If a position has no openings (openings is 0), let the developer know
and suggest similar alternatives from the search results.

Be conversational, knowledgeable, and concise.""",
    tools=[toolbox],
)

Perhatikan bahwa tidak ada kode database di sini — ToolboxToolset terhubung ke server Toolbox saat startup dan memuat semua alat yang tersedia. Agen memanggil alat berdasarkan nama; Toolbox menerjemahkan panggilan tersebut menjadi kueri SQL terhadap Cloud SQL.

Variabel lingkungan TOOLBOX_URL secara default adalah http://127.0.0.1:5000 untuk pengembangan lokal. Saat men-deploy ke Cloud Run nanti, Anda akan mengganti URL ini dengan URL Cloud Run layanan Toolbox — tidak perlu mengubah kode.

Saat ini, petunjuk hanya merujuk pada dua alat standar (search-jobs dan get-job-details). Anda akan memperluasnya pada langkah berikutnya saat menambahkan alat penyerapan dan penelusuran semantik.

Menguji agen

Mulai UI dev ADK:

cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web --allow_origins "regex:https://.*\.cloudshell\.dev"

Buka URL yang ditampilkan di terminal (biasanya http://localhost:8000) menggunakan fitur Pratinjau Web Cloud Shell atau ctrl + klik URL yang ditampilkan di terminal. Pilih jobs_agent dari dropdown agen di sudut kiri atas.

Menguji kueri standar

Coba perintah ini untuk memverifikasi alat SQL standar:

What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

93ac33e7f73aa0b9.png 240c53376042a916.png

Coba deskripsi bahasa alami yang tidak dipetakan ke peran atau tumpukan teknologi tertentu:

I want a remote job where I can work on AI and machine learning
Find me something in fintech with good work-life balance
I'm interested in infrastructure and reliability engineering

Agen akan mencoba memilih alat yang tepat berdasarkan jenis kueri: filter terstruktur diproses melalui search-jobs, deskripsi bahasa alami diproses melalui search-jobs-by-description.

b0ea629f5c9b4c26.png

Menguji penyerapan vektor

Minta agen untuk menambahkan tugas baru:

Add a new job: 'Robotics Software Engineer' at Boston Dynamics, role Robotics, tech stack: Python, C++, ROS, Computer Vision, salary $160-230K/year, location Waltham MA, Hybrid, 2 openings. Description: Design and implement autonomous navigation and manipulation algorithms for next-generation robots. Work on perception pipelines using computer vision and lidar, develop motion planning software in C++ and Python, and test systems on real hardware in warehouse and logistics environments.

c601a7a9bc0a705b.png

Sekarang coba telusuri:

Find me jobs involving autonomous systems and working with physical hardware

Penyematan dibuat secara otomatis selama INSERT — tidak diperlukan langkah terpisah.

5a3d8e6f523dc18b.png

Sekarang, Anda sudah memiliki aplikasi RAG Agentic yang berfungsi penuh menggunakan ADK, MCP Toolbox, dan CloudSQL. Selamat! Mari kita lanjutkan langkah-langkah untuk men-deploy aplikasi ini ke Cloud Run.

Sekarang, hentikan UI dev dengan menghentikan proses dengan menekan Ctrl+C dua kali sebelum melanjutkan.

8. Men-deploy ke Cloud Run

Agen dan Toolbox berfungsi secara lokal. Langkah ini men-deploy keduanya sebagai layanan Cloud Run sehingga dapat diakses melalui internet. Layanan Toolbox berjalan sebagai server MCP di Cloud Run, dan layanan agen terhubung ke layanan tersebut.

Menyiapkan Toolbox untuk deployment

Buat direktori deployment untuk layanan Toolbox:

cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/

Buat Dockerfile untuk Toolbox. Buka deploy-toolbox/Dockerfile di Cloud Shell Editor:

cloudshell edit deploy-toolbox/Dockerfile

Kemudian, salin skrip berikut ke dalamnya

# deploy-toolbox/Dockerfile
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY toolbox tools.yaml ./
RUN chmod +x toolbox
EXPOSE 8080
CMD ["./toolbox", "--config", "tools.yaml", "--enable-api", "--address", "0.0.0.0", "--port", "8080"]

Biner Toolbox dan tools.yaml dikemas ke dalam image Debian minimal. Cloud Run mengarahkan traffic ke port 8080.

Men-deploy layanan Toolbox

cd ~/build-agent-adk-toolbox-cloudsql
gcloud run deploy toolbox-service \
  --source deploy-toolbox/ \
  --region $REGION \
  --set-env-vars "DB_PASSWORD=$DB_PASSWORD,DB_INSTANCE=$DB_INSTANCE,DB_NAME=$DB_NAME,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,REGION=$REGION,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION" \
  --allow-unauthenticated \
  --quiet > logs/deploy_toolbox.log 2>&1 &

Perintah ini mengirimkan sumber ke Cloud Build, membangun image container, mengirimkannya ke Artifact Registry, dan men-deploy-nya ke Cloud Run. Proses ini akan memakan waktu beberapa menit — kita dapat memeriksa log proses deployment pada file logs/deploy_toolbox.log

Menyiapkan agen untuk deployment

Saat Toolbox membangun, siapkan file deployment agen.

Buat Dockerfile di root project. Buka Dockerfile di Cloud Shell Editor:

cloudshell edit Dockerfile

Kemudian, salin konten berikut

# Dockerfile
FROM ghcr.io/astral-sh/uv:python3.12-trixie-slim
WORKDIR /app
COPY pyproject.toml ./
COPY uv.lock ./
RUN uv sync --no-dev
COPY jobs_agent/ jobs_agent/
EXPOSE 8080
CMD ["uv", "run", "adk", "web", "--host", "0.0.0.0", "--port", "8080"]

Dockerfile ini menggunakan ghcr.io/astral-sh/uv sebagai image dasar, yang mencakup Python dan uv yang telah diinstal sebelumnya — tidak perlu menginstal uv secara terpisah melalui pip.

Buat file .dockerignore untuk mengecualikan file yang tidak diperlukan dari image container:

cloudshell edit .dockerignore

Kemudian, salin skrip berikut ke dalamnya

# .dockerignore
.venv/
__pycache__/
*.pyc
.env
jobs_agent/.env
toolbox
tools.yaml
seed.sql
deploy-toolbox/

Men-deploy layanan agen

Tunggu hingga deployment Toolbox selesai. Periksa kembali proses deployment di logs/deploy_toolbox.log untuk memverifikasi prosesnya. Kemudian, a mbil URL Cloud Run-nya menggunakan perintah berikut

TOOLBOX_URL=$(gcloud run services describe toolbox-service \
  --region=$REGION \
  --format='value(status.url)')
echo "Toolbox URL: $TOOLBOX_URL"

Anda akan melihat output yang serupa seperti ini

Toolbox URL: https://toolbox-service-xxxxxx-xx.a.run.app

Kemudian, mari kita verifikasi bahwa Toolbox yang di-deploy berfungsi:

curl -s "$TOOLBOX_URL/api/toolset" | python3 -m json.tool | head -5

Jika output yang ditampilkan seperti contoh ini, deployment sudah berhasil

{
    "serverVersion": "1.0.0+binary.linux.amd64.c5524d3",
    "tools": {
        "add-job": {
            "description": "Add a new job listing to the platform. Use this tool when a user asks to post a job that is not currently listed.",

Selanjutnya, kita akan men-deploy agen, dengan meneruskan URL Toolbox sebagai variabel lingkungan:

cd ~/build-agent-adk-toolbox-cloudsql
gcloud run deploy jobs-agent \
  --source . \
  --region $REGION \
  --set-env-vars "TOOLBOX_URL=$TOOLBOX_URL,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_GENAI_USE_VERTEXAI=TRUE" \
  --allow-unauthenticated \
  --quiet

Kode agen membaca TOOLBOX_URL dari lingkungan (Anda telah menyiapkannya sebelumnya). Secara lokal, variabel ini mengarah ke http://127.0.0.1:5000; di Cloud Run, variabel ini mengarah ke URL layanan Toolbox. Tidak perlu mengubah kode.

Menguji agen yang di-deploy

Ambil URL Cloud Run agen:

AGENT_URL=$(gcloud run services describe jobs-agent \
  --region=$REGION \
  --format='value(status.url)')
echo "Agent URL: $AGENT_URL"

Buka URL di browser Anda. UI dev ADK dimuat — antarmuka yang sama yang telah Anda gunakan secara lokal, kini berjalan di Cloud Run.

Pilih jobs_agent dari dropdown dan uji:

What backend engineering jobs do you have?
I want a remote job working on AI and machine learning

Kedua kueri berfungsi melalui layanan yang di-deploy: agen di Cloud Run memanggil Toolbox di Cloud Run, yang membuat kueri Cloud SQL.

9. Selamat / Pembersihan

Anda telah membuat dan men-deploy asisten halaman lowongan kerja pintar yang menggunakan MCP Toolbox for Databases untuk menghubungkan agen ADK dan Cloud SQL PostgreSQL — dengan kueri SQL standar dan penelusuran vektor semantik.

Yang telah Anda pelajari

  • Cara MCP menstandardisasi akses alat untuk agen AI, dan cara MCP Toolbox for Databases menerapkannya secara khusus pada operasi database — menggantikan kode database kustom dengan konfigurasi YAML deklaratif
  • Cara mengonfigurasi Cloud SQL PostgreSQL sebagai sumber data Toolbox menggunakan jenis sumber cloud-sql-postgres
  • Cara menentukan alat kueri SQL standar dengan pernyataan berparameter yang mencegah injeksi SQL
  • Cara mengaktifkan penelusuran vektor menggunakan pgvector dan gemini-embedding-001, dengan parameter embeddedBy untuk penyematan kueri otomatis
  • Cara valueFromParam memungkinkan penyerapan vektor otomatis — LLM memberikan deskripsi teks, dan Toolbox secara diam-diam menyalin, menyematkan, dan menyimpan vektor bersama teks
  • Cara ToolboxToolset ADK memuat alat dari server Toolbox yang sedang berjalan, sehingga kode agen tetap minimal dan logika database sepenuhnya terpisah
  • Cara men-deploy server MCP Toolbox dan agen ADK ke Cloud Run sebagai layanan terpisah

Pembersihan

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang dibuat dalam codelab ini, Anda dapat menghapus setiap resource atau menghapus seluruh project.

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 run services delete jobs-agent --region=$REGION --quiet
gcloud run services delete toolbox-service --region=$REGION --quiet
gcloud sql instances delete jobs-instance --quiet
gcloud artifacts repositories delete cloud-run-source-deploy --location=$REGION --quiet 2>/dev/null