1. Giới thiệu
Các tác nhân AI chỉ hữu ích khi có thể truy cập vào dữ liệu. Hầu hết dữ liệu thực tế đều nằm trong cơ sở dữ liệu và việc kết nối các tác nhân với cơ sở dữ liệu thường có nghĩa là bạn phải viết quy trình quản lý kết nối, logic truy vấn và nhúng các quy trình vào trong mã tác nhân của mình. Mọi tác nhân cần truy cập vào cơ sở dữ liệu đều lặp lại công việc này và mọi thay đổi về truy vấn đều yêu cầu triển khai lại tác nhân.
Lớp học lập trình này trình bày một phương pháp khác. Bạn khai báo các công cụ cơ sở dữ liệu trong một tệp YAML (các truy vấn SQL chuẩn, tìm kiếm mức độ tương đồng của vectơ, thậm chí là tạo vectơ nhúng tự động) và Bộ công cụ MCP dành cho cơ sở dữ liệu sẽ xử lý tất cả các thao tác cơ sở dữ liệu dưới dạng một máy chủ MCP. Mã tác nhân của bạn vẫn ở mức tối thiểu: tải các công cụ, để Gemini quyết định gọi công cụ nào.
Sản phẩm bạn sẽ tạo ra
Trợ lý thông minh cho bảng tin việc làm cho "TechJobs" – một tác nhân ADK dựa trên Gemini, giúp nhà phát triển duyệt xem danh sách tin tuyển dụng trong ngành công nghệ bằng các bộ lọc tiêu chuẩn (vai trò, bộ phần mềm cơ sở) và khám phá việc làm thông qua nội dung mô tả bằng ngôn ngữ tự nhiên như "Tôi muốn làm việc từ xa trong lĩnh vực chatbot AI". Tác nhân này đọc và ghi vào cơ sở dữ liệu Cloud SQL PostgreSQL hoàn toàn thông qua Bộ công cụ MCP cho Cơ sở dữ liệu. Bộ công cụ này xử lý mọi hoạt động truy cập vào cơ sở dữ liệu, bao gồm cả việc tự động tạo vectơ nhúng để tìm kiếm vectơ. Đến cuối cùng, cả Toolbox và tác nhân đều chạy trên Cloud Run.
Kiến thức bạn sẽ học được
- Cách MCP (Giao thức ngữ cảnh mô hình) chuẩn hoá quyền truy cập vào công cụ cho các tác nhân AI và cách MCP Toolbox for Databases áp dụng điều này cho các hoạt động cơ sở dữ liệu
- Thiết lập Bộ công cụ MCP cho cơ sở dữ liệu làm phần mềm trung gian giữa một tác nhân ADK và Cloud SQL PostgreSQL
- Xác định các công cụ cơ sở dữ liệu một cách khai báo trong
tools.yaml– không có mã cơ sở dữ liệu trong tác nhân của bạn - Tạo một tác nhân ADK tải các công cụ từ một máy chủ Bộ công cụ đang chạy bằng cách sử dụng
ToolboxToolset - Tạo các vectơ nhúng bằng hàm
embedding()tích hợp của Cloud SQL và bật tính năng tìm kiếm ngữ nghĩa bằngpgvector - Sử dụng tính năng
valueFromParamđể tự động nhập vectơ trong các thao tác ghi - Triển khai cả máy chủ Toolbox và tác nhân ADK lên Cloud Run
Điều kiện tiên quyết
- Tài khoản Google Cloud có tài khoản thanh toán dùng thử
- Hiểu biết cơ bản về Python và SQL
- Kinh nghiệm sử dụng Cơ sở dữ liệu đám mây và ADK sẽ rất hữu ích
2. Thiết lập môi trường
Bước này chuẩn bị môi trường Cloud Shell, định cấu hình dự án trên đám mây của bạn và sao chép kho lưu trữ tham chiếu.
Mở Cloud Shell
Mở Cloud Shell trong trình duyệt. Cloud Shell cung cấp một môi trường được định cấu hình sẵn với tất cả các công cụ bạn cần cho lớp học lập trình này. Nhấp vào Uỷ quyền khi được nhắc
Sau đó, nhấp vào "View" (Xem) -> "Terminal" (Thiết bị đầu cuối) để mở thiết bị đầu cuối.Giao diện của bạn sẽ trông tương tự như thế này

Đây sẽ là giao diện chính của chúng ta, IDE ở trên cùng, thiết bị đầu cuối ở dưới cùng
Thiết lập thư mục làm việc
Tạo thư mục làm việc. Tất cả mã bạn viết trong lớp học lập trình này đều nằm ở đây:
mkdir -p ~/build-agent-adk-toolbox-cloudsql
cloudshell workspace ~/build-agent-adk-toolbox-cloudsql && cd ~/build-agent-adk-toolbox-cloudsql
Sau đó, hãy chuẩn bị một số thư mục để quản lý những thứ như tập lệnh gieo hạt và nhật ký
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
Thiết lập dự án trên đám mây của bạn
Tạo tệp .env bằng các biến vị trí:
# For Vertex AI / Gemini API calls
echo "GOOGLE_CLOUD_LOCATION=global" > .env
# For Cloud SQL, Cloud Run, Artifact Registry
echo "REGION=us-central1" >> .env
Để đơn giản hoá việc thiết lập dự án trong thiết bị đầu cuối, hãy tải tập lệnh thiết lập dự án này xuống thư mục làm việc của bạn:
curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh
Chạy tập lệnh. Lệnh này xác minh tài khoản thanh toán dùng thử của bạn, tạo một dự án mới (hoặc xác thực một dự án hiện có), lưu mã dự án vào một tệp .env trong thư mục hiện tại và đặt dự án đang hoạt động trong gcloud.
bash setup_verify_trial_project.sh && source .env
Tập lệnh sẽ:
- Xác minh rằng bạn có một tài khoản thanh toán dùng thử đang hoạt động
- Kiểm tra xem có dự án nào trong
.envhay không (nếu có) - Tạo dự án mới hoặc sử dụng lại dự án hiện có
- Liên kết tài khoản thanh toán dùng thử với dự án của bạn
- Lưu mã dự án vào
.env - Đặt dự án làm dự án
gcloudđang hoạt động
Xác minh rằng dự án được thiết lập đúng cách bằng cách kiểm tra văn bản màu vàng bên cạnh thư mục đang hoạt động trong dấu nhắc của thiết bị đầu cuối Cloud Shell. Mã này sẽ hiển thị mã dự án của bạn.

Kích hoạt API bắt buộc
Tiếp theo, chúng ta cần bật một số API cho sản phẩm mà chúng ta sẽ tương tác:
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) – tác nhân của bạn sử dụng các mô hình Gemini và Toolbox sử dụng API nhúng để tìm kiếm vectơ. - Cloud SQL Admin API (
sqladmin.googleapis.com) – bạn cung cấp và quản lý một phiên bản PostgreSQL. - Compute Engine API (
compute.googleapis.com) – bắt buộc để tạo phiên bản Cloud SQL. - Cloud Run, Cloud Build, Artifact Registry – được dùng trong bước triển khai sau này trong lớp học lập trình này
3. Chuẩn bị tập lệnh để khởi chạy cơ sở dữ liệu
Bước này bắt đầu quá trình tạo phiên bản Cloud SQL và chạy một tập lệnh thiết lập tự động. Tập lệnh này sẽ đợi phiên bản sẵn sàng, sau đó tạo cơ sở dữ liệu, gieo dữ liệu vào cơ sở dữ liệu bằng danh sách việc làm và tạo các mục nhúng – tất cả trong một thao tác.
Trước tiên, hãy thêm mật khẩu cơ sở dữ liệu vào tệp .env rồi tải lại tệp đó:
echo "DB_PASSWORD=techjobs-pwd" >> .env
echo "DB_INSTANCE=jobs-instance" >> .env
echo "DB_NAME=jobs_db" >> .env
source .env
Tạo tập lệnh Bash để tạo phiên bản và cơ sở dữ liệu
Sau đó, hãy tạo tập lệnh scripts/setup_database.sh bằng lệnh sau
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
cloudshell edit scripts/setup_database.sh
Sau đó, sao chép mã sau vào tệp 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 ""
Tạo tập lệnh Python để gieo dữ liệu
Sau đó, hãy tạo tệp python tập lệnh gieo hạt scripts/setup_jobs_db.py bằng lệnh bên dưới
cloudshell edit scripts/setup_jobs_db.py
Sau đó, sao chép mã sau vào tệp 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()
Bây giờ, hãy chuyển sang bước tiếp theo
4. Tạo và khởi động cơ sở dữ liệu
Giờ đây, các tập lệnh của chúng ta đã sẵn sàng để thực thi. Chúng ta sẽ cần Python để thực thi tập lệnh đã chuẩn bị, vì vậy, trước tiên, hãy chuẩn bị tập lệnh đó
Thiết lập dự án Python
uv là một trình quản lý dự án và gói Python nhanh được viết bằng Rust ( tài liệu uv ). Lớp học lập trình này sử dụng uv để duy trì dự án Python một cách nhanh chóng và đơn giản
Khởi chạy một dự án Python và thêm các phần phụ thuộc bắt buộc:
uv init
uv add cloud-sql-python-connector --extra pg8000
uv add python-dotenv
Xin lưu ý rằng ở đây, chúng tôi đang sử dụng cloud-sql-python-connector Python SDK để khởi động một kết nối bảo mật với phiên bản cơ sở dữ liệu của chúng tôi. Phiên bản này được xác thực bằng Thông tin xác thực mặc định của ứng dụng.
Thực thi tập lệnh thiết lập
Giờ đây, chúng ta có thể chạy tập lệnh thiết lập ở chế độ nền và kiểm tra đầu ra của bảng điều khiển sẽ được ghi vào tệp logs/atabase_setup.log bằng lệnh sau. Bạn có thể tiếp tục chuyển sang phần tiếp theo trong khi chờ quá trình này hoàn tất
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
bash scripts/setup_database.sh > logs/database_setup.log 2>&1 &
Tải tệp nhị phân của Hộp công cụ xuống
Chúng ta sẽ sử dụng MCP Toolbox trong hướng dẫn này. May mắn là công cụ này đi kèm với một tệp nhị phân được tạo sẵn và sẵn sàng sử dụng trong môi trường Linux. Bây giờ, hãy tải tệp này xuống ở chế độ nền vì quá trình này sẽ mất khá nhiều thời gian. Chạy lệnh sau để tải tệp nhị phân xuống và kiểm tra nhật ký đầu ra trên logs/toolbox_dl.log . Bạn có thể tiếp tục chuyển sang phần tiếp theo trong khi chờ quá trình này hoàn tất
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 &
Tìm hiểu về tập lệnh thiết lập scripts/setup_database.sh
Bây giờ, hãy thử tìm hiểu tập lệnh thiết lập mà chúng ta đã định cấu hình trước đó. Quy trình này thực hiện những việc sau
- Lệnh đầu tiên mà chúng ta thực thi ở đó là lệnh
gcloud sql instances createcó cờ sau
db-custom-1-3840là cấp Cloud SQL nhỏ nhất có lõi chuyên dụng (1 vCPU, RAM 3,75 GB) trong phiên bảnENTERPRISE. Bạn có thể đọc thêm thông tin chi tiết tại đây. Bạn cần có một lõi chuyên dụng để tích hợp Vertex AI ML – các cấp lõi dùng chung (db-f1-micro,db-g1-small) không hỗ trợ tính năng này.--root-passwordđặt mật khẩu cho người dùngpostgresmặc định.--enable-google-ml-integrationcho phép tích hợp sẵn Cloud SQL với Vertex AI, giúp bạn gọi các mô hình nhúng trực tiếp từ SQL bằng hàmembedding().
- Xác minh xem phiên bản đã ở trạng thái
RUNNABLEhay chưa - Cấp cho tài khoản dịch vụ của phiên bản Cloud SQL quyền gọi Vertex AI bằng lệnh
gcloud projects add-iam-policy-binding. Đây là yêu cầu bắt buộc đối với hàmembedding()tích hợp mà chúng ta sẽ dùng khi gieo dữ liệu vào cơ sở dữ liệu - Tạo cơ sở dữ liệu
- Thực thi tập lệnh gieo hạt
setup_jobs_db.py
Tìm hiểu về tập lệnh ban đầu scripts/setup_jobs_db.py
Bây giờ, hãy chuyển sang tập lệnh gieo hạt. Tập lệnh này sẽ thực hiện những việc sau:
- Khởi tạo kết nối đến phiên bản cơ sở dữ liệu
- Cài đặt 2 tiện ích PostgreSQL:
google_ml_integration– cung cấp hàm SQLembedding(), gọi các mô hình nhúng Vertex AI trực tiếp từ SQL. Đây là một tiện ích ở cấp cơ sở dữ liệu giúp các hàm ML có sẵn trongjobs_db. Cờ cấp phiên bản (--enable-google-ml-integration) mà bạn đặt trong quá trình tạo phiên bản cho phép VM Cloud SQL truy cập vào Vertex AI – tiện ích này cung cấp các hàm SQL trong cơ sở dữ liệu cụ thể này.vector(pgvector) – thêm kiểu dữ liệuvectorvà các toán tử khoảng cách để lưu trữ và truy vấn các vectơ nhúng.
- Tạo bảng, lưu ý rằng cột
description_embeddinglàvector(3072)— một cộtpgvectorlưu trữ các vectơ 3072 chiều. - Gieo dữ liệu ban đầu cho các công việc
- Tạo dữ liệu nhúng từ trường
descriptionvà điền vàodescription_embeddingbằng cách sử dụng tính năng tích hợp đỉnh được tích hợp sẵn thông qua hàmembedding()
embedding('gemini-embedding-001', description)– gọi mô hình nhúng Gemini của Vertex AI trực tiếp từ SQL, truyền văn bảndescriptioncủa từng công việc. Đây là tiện íchgoogle_ml_integrationmà bạn đã cài đặt trong tập lệnh ban đầu.::vector– truyền mảng số thực được trả về sang kiểuvectorcủa pgvector để có thể lưu trữ và truy vấn bằng các toán tử khoảng cách.UPDATEchạy trên cả 15 hàng, tạo ra một mục nhúng 3072 chiều cho mỗi nội dung mô tả công việc.
Thao tác này sẽ chuẩn bị dữ liệu ban đầu mà tác nhân của chúng tôi sẽ truy cập
5. Định cấu hình Bộ công cụ MCP cho cơ sở dữ liệu
Bước này giới thiệu Bộ công cụ MCP dành cho cơ sở dữ liệu, định cấu hình bộ công cụ này để kết nối với phiên bản Cloud SQL của bạn và xác định 2 công cụ truy vấn SQL tiêu chuẩn.
MCP là gì và tại sao nên sử dụng Toolbox?

MCP (Giao thức ngữ cảnh mô hình) là một giao thức mở giúp chuẩn hoá cách các tác nhân AI khám phá và tương tác với các công cụ bên ngoài. Nền tảng này xác định một mô hình ứng dụng-máy chủ: tác nhân lưu trữ một ứng dụng MCP và các công cụ được máy chủ MCP hiển thị. Mọi ứng dụng tương thích với MCP đều có thể sử dụng mọi máy chủ tương thích với MCP – tác nhân không cần mã tích hợp tuỳ chỉnh cho từng công cụ.

Bộ công cụ MCP cho cơ sở dữ liệu là một máy chủ MCP nguồn mở được xây dựng dành riêng cho quyền truy cập vào cơ sở dữ liệu. Nếu không có thư viện này, bạn sẽ viết các hàm Python mở kết nối cơ sở dữ liệu, quản lý nhóm kết nối, tạo các truy vấn được tham số hoá để ngăn chặn việc chèn mã SQL, xử lý lỗi và nhúng tất cả mã đó vào trong tác nhân của bạn. Mọi tác nhân cần truy cập vào cơ sở dữ liệu đều lặp lại công việc này. Việc thay đổi một truy vấn có nghĩa là bạn phải triển khai lại tác nhân.
Với Toolbox, bạn sẽ viết một tệp YAML. Mỗi công cụ sẽ ánh xạ đến một câu lệnh SQL được tham số hoá. Hộp công cụ xử lý việc gộp kết nối, truy vấn được tham số hoá, xác thực và khả năng quan sát. Các công cụ được tách biệt khỏi tác nhân – cập nhật một truy vấn bằng cách chỉnh sửa tools.yaml và khởi động lại Toolbox mà không cần chỉnh sửa mã tác nhân. Các công cụ này hoạt động trên ADK, LangGraph, LlamaIndex hoặc bất kỳ khung tương thích với MCP nào.
Viết cấu hình công cụ
Bây giờ, chúng ta cần tạo một tệp có tên là tools.yaml trong Cloud Shell Editor để thiết lập cấu hình công cụ
cloudshell edit tools.yaml
Tệp này sử dụng YAML nhiều tài liệu – mỗi khối được phân tách bằng --- là một tài nguyên độc lập. Mỗi tài nguyên đều có một kind khai báo tài nguyên đó là gì (sources cho các mối kết nối cơ sở dữ liệu, tools cho các thao tác có thể gọi của tác nhân) và một type chỉ định phần phụ trợ (cloud-sql-postgres cho nguồn, postgres-sql cho các công cụ dựa trên SQL). Một công cụ tham chiếu nguồn của nó bằng name, đây là cách Toolbox biết nên thực thi nhóm kết nối nào. Các biến môi trường sử dụng cú pháp ${VAR_NAME} và được phân giải khi khởi động.
Bây giờ, trước tiên hãy sao chép các tập lệnh sau vào tệp 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}
---
Tập lệnh này xác định tài nguyên sau:
- Nguồn (
jobs-db) – cho biết cách Toolbox kết nối với thực thể Cloud SQL PostgreSQL của bạn. Loạicloud-sql-postgressử dụng trình kết nối Cloud SQL nội bộ, tự động xử lý việc xác thực và các kết nối an toàn. Các phần giữ chỗ${GOOGLE_CLOUD_PROJECT},${REGION}và${DB_PASSWORD}được phân giải từ các biến môi trường khi khởi động.
Tiếp theo, hãy thêm tập lệnh sau vào dưới biểu tượng --- trong 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)."
---
Tập lệnh này xác định tài nguyên sau:
- Công cụ 1 và 2 (
search-jobs,get-job-details) – công cụ truy vấn SQL chuẩn. Mỗi mục liên kết một tên công cụ (những gì mà tác nhân nhìn thấy) với một câu lệnh SQL được tham số hoá (những gì mà cơ sở dữ liệu thực thi). Các tham số sử dụng phần giữ chỗ vị trí$1,$2. Hộp công cụ thực thi các câu lệnh này dưới dạng câu lệnh đã chuẩn bị, giúp ngăn chặn việc chèn SQL.
Hãy tiếp tục, thêm tập lệnh sau vào biểu tượng --- trong 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
---
Tập lệnh này xác định tài nguyên sau:
- Mô hình nhúng (
gemini-embedding) – định cấu hình Toolbox để gọi mô hìnhgemini-embedding-001của Gemini nhằm tạo các vectơ nhúng văn bản 3072 chiều. Toolbox sử dụng Thông tin xác thực mặc định của ứng dụng (ADC) để xác thực – không cần khoá API trong Cloud Shell hoặc Cloud Run. Lưu ý rằngdimensionđược định cấu hình ở đây phải giống vớidimensionmà chúng ta đã định cấu hình trước đó để gieo dữ liệu vào cơ sở dữ liệu
Hãy tiếp tục, thêm tập lệnh sau vào biểu tượng --- trong 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
---
Tập lệnh này xác định tài nguyên sau:
- Công cụ 3 (
search-jobs-by-description) – một công cụ tìm kiếm vectơ. Tham sốsearch_querycóembeddedBy: gemini-embedding, cho biết Toolbox sẽ chặn văn bản thô, gửi văn bản đó đến mô hình nhúng và sử dụng vectơ kết quả trong câu lệnh SQL. Toán tử<=>là khoảng cách cosine của pgvector – giá trị càng nhỏ thì nội dung mô tả càng giống nhau.
Cuối cùng, hãy thêm công cụ cuối cùng vào biểu tượng --- trong 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
Tập lệnh này xác định tài nguyên sau:
- Công cụ 4 (
add-job) – minh hoạ việc sử dụng vectơ. Tham sốdescription_vectorcó 2 trường đặc biệt: valueFromParam: description– Hộp công cụ sao chép giá trị từ tham sốdescriptionvào tham số này. LLM không bao giờ thấy tham số này.embeddedBy: gemini-embedding– Hộp công cụ nhúng văn bản đã sao chép vào một vectơ trước khi truyền văn bản đó đến SQL.
Kết quả: một lệnh gọi công cụ lưu trữ cả văn bản mô tả thô và vectơ nhúng của văn bản đó, mà không cần tác nhân biết bất kỳ thông tin nào về các vectơ nhúng.
Định dạng YAML nhiều tài liệu phân tách từng tài nguyên bằng ---. Mỗi tài liệu có các trường kind, name và type xác định nội dung của tài liệu. Tóm lại, chúng ta đã định cấu hình tất cả những điều sau:
- Xác định cơ sở dữ liệu nguồn
- Xác định các công cụ ( công cụ 1 và 2) để truy vấn cơ sở dữ liệu bằng bộ lọc tiêu chuẩn
- Xác định mô hình nhúng
- Xác định công cụ để thực hiện tìm kiếm vectơ ( công cụ 3 ) vào cơ sở dữ liệu
- Xác định công cụ để thực hiện quá trình nhập dữ liệu vectơ ( công cụ 4) vào cơ sở dữ liệu
6. Chạy máy chủ MCP Toolbox
Ở bước trước, chúng ta đã thiết lập cấu hình cần thiết cho MCP Toolbox. Giờ đây, chúng ta đã sẵn sàng chạy máy chủ
Xác minh dữ liệu ban đầu
Trước khi bắt đầu Toolbox, hãy xác nhận rằng bạn đã hoàn tất quá trình thiết lập cơ sở dữ liệu. Tạo tập lệnh python scripts/verify_database.py bằng lệnh sau
cloudshell edit scripts/verify_seed.py
Sau đó, sao chép mã sau vào tệp 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)
Tập lệnh này sẽ kiểm tra số lượng dữ liệu bài đăng tuyển dụng và thông tin nhúng của dữ liệu đó. Chạy tập lệnh bằng lệnh sau
uv run scripts/verify_seed.py
Nếu bạn thấy đầu ra sau đây trên cửa sổ dòng lệnh, tức là dữ liệu đã sẵn sàng
Jobs: 15/15 Embeddings: 15/15 ✓ Database ready!
Khởi động máy chủ Hộp công cụ
Trong bước thiết lập trước đó, chúng ta đã tải tệp thực thi toolbox xuống. Đảm bảo rằng tệp nhị phân này tồn tại và đã tải xuống thành công. Nếu chưa, hãy tải tệp xuống và đợi cho đến khi hoàn tất
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
Chúng ta cần hiển thị các biến .env cho quy trình con do hộp công cụ MCP chạy. Chạy lệnh sau để khởi động máy chủ hộp công cụ và ghi nhật ký đầu ra của bảng điều khiển vào tệp logs/mcp_toolbox.log
set -a; source .env; set +a
./toolbox --config tools.yaml --enable-api > logs/mcp_toolbox.log 2>&1 &
Bạn sẽ thấy kết quả trong tệp logs/mcp_toolbox.log xác nhận rằng máy chủ đã sẵn sàng như minh hoạ bên dưới:
... 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!"
Xác minh các công cụ
Truy vấn Toolbox API để liệt kê tất cả các công cụ đã đăng ký:
curl -s http://localhost:5000/api/toolset | uv run -m json.tool
Bạn sẽ thấy các công cụ cùng với nội dung mô tả và thông số của chúng. Như minh hoạ bên dưới
...
"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": []
}
...
Kiểm thử trực tiếp công cụ search-jobs:
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'
Phản hồi phải chứa 2 công việc kỹ thuật phụ trợ trong dữ liệu ban đầu của bạn.
[
{
"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. Tạo tác nhân ADK
Giờ đây, chúng ta sẽ sử dụng ADK trong Python cho dự án này. Hãy thêm các phần phụ thuộc bắt buộc:
uv add google-adk==1.29.0 toolbox-adk==1.0.0
google-adk– Bộ công cụ phát triển tác nhân của Google, bao gồm cả Gemini SDKtoolbox-adk– Tích hợp ADK cho Bộ công cụ MCP dành cho cơ sở dữ liệu.
Tạo cấu trúc thư mục của tác nhân
ADK yêu cầu một bố cục thư mục cụ thể: một thư mục được đặt tên theo tác nhân của bạn, chứa __init__.py, agent.py và .env. Để giúp giải quyết vấn đề này, công cụ này có sẵn lệnh để nhanh chóng thiết lập cấu trúc:
uv run adk create jobs_agent \
--model gemini-2.5-flash \
--project ${GOOGLE_CLOUD_PROJECT} \
--region ${GOOGLE_CLOUD_LOCATION}
Thư mục của bạn hiện sẽ có dạng như sau:
build-agent-adk-toolbox-cloudsql/ ├── jobs_agent/ │ ├── __init__.py │ ├── agent.py │ └── .env ├── logs ├── scripts └── ...
Tiếp theo, chúng ta sẽ cần tích hợp tác nhân ADK vào máy chủ Toolbox đang chạy và kiểm thử cả 4 công cụ: truy vấn tiêu chuẩn, tìm kiếm ngữ nghĩa và truyền vectơ. Mã tác nhân là tối thiểu: mọi logic cơ sở dữ liệu đều nằm trong tools.yaml.
Định cấu hình môi trường của tác nhân
ADK đọc GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT và GOOGLE_CLOUD_LOCATION từ môi trường shell mà bạn đã thiết lập ở bước trước. Biến duy nhất dành riêng cho nhân viên hỗ trợ là TOOLBOX_URL – hãy thêm biến này vào tệp .env của nhân viên hỗ trợ:
echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env
Cập nhật mô-đun tác nhân
Mở jobs_agent/agent.py trong Trình chỉnh sửa Cloud Shell
cloudshell edit jobs_agent/agent.py
và ghi đè nội dung bằng mã sau:
# 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],
)
Xin lưu ý rằng không có mã cơ sở dữ liệu nào ở đây – ToolboxToolset kết nối với máy chủ Toolbox khi khởi động và tải tất cả các công cụ có sẵn. Tác nhân gọi các công cụ theo tên; Bộ công cụ sẽ dịch những lệnh gọi đó thành các truy vấn SQL đối với Cloud SQL.
Biến môi trường TOOLBOX_URL mặc định là http://127.0.0.1:5000 để phát triển cục bộ. Khi triển khai lên Cloud Run sau này, bạn sẽ ghi đè URL này bằng URL Cloud Run của dịch vụ Toolbox mà không cần thay đổi mã.
Hướng dẫn này hiện chỉ đề cập đến 2 công cụ tiêu chuẩn (search-jobs và get-job-details). Bạn sẽ mở rộng hướng dẫn này ở bước tiếp theo khi thêm các công cụ tìm kiếm và nhập dữ liệu ngữ nghĩa.
Kiểm thử tác nhân
Khởi động giao diện người dùng dành cho nhà phát triển ADK:
cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web --allow_origins "regex:https://.*\.cloudshell\.dev"
Mở URL xuất hiện trong thiết bị đầu cuối (thường là http://localhost:8000) bằng tính năng Xem trước trên web của Cloud Shell hoặc nhấn ctrl + nhấp vào URL xuất hiện trong thiết bị đầu cuối. Chọn jobs_agent trong trình đơn thả xuống của tác nhân ở góc trên bên trái.
Kiểm thử các truy vấn tiêu chuẩn
Hãy thử những câu lệnh sau để xác minh các công cụ SQL chuẩn:
What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

Kiểm thử tính năng tìm kiếm ngữ nghĩa
Hãy thử nội dung mô tả bằng ngôn ngữ tự nhiên không liên kết với một vai trò hoặc bộ phần mềm cơ sở cụ thể:
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
Dựa trên loại truy vấn, tác nhân sẽ cố gắng chọn công cụ phù hợp: bộ lọc có cấu trúc sẽ đi qua search-jobs, nội dung mô tả bằng ngôn ngữ tự nhiên sẽ đi qua search-jobs-by-description.

Kiểm thử việc truyền dẫn vectơ
Yêu cầu trợ lý ảo thêm một công việc mới:
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.

Bây giờ, hãy thử tìm kiếm:
Find me jobs involving autonomous systems and working with physical hardware
Hoạt động nhúng được tạo tự động trong quá trình INSERT – không cần thực hiện bước riêng biệt.

Giờ đây, bạn đã có một ứng dụng Agentic RAG hoạt động đầy đủ, sử dụng ADK, Bộ công cụ MCP và CloudSQL. Xin chúc mừng! Hãy tiến thêm một bước nữa để triển khai các ứng dụng này lên Cloud Run!
Bây giờ, hãy dừng giao diện người dùng dành cho nhà phát triển bằng cách kết thúc quy trình này bằng cách nhấn tổ hợp phím Ctrl+C hai lần trước khi tiếp tục.
8. Triển khai lên Cloud Run
Tác nhân và Hộp công cụ hoạt động cục bộ. Bước này triển khai cả hai dưới dạng các dịch vụ Cloud Run để có thể truy cập qua Internet. Dịch vụ Toolbox chạy dưới dạng một máy chủ MCP trên Cloud Run và dịch vụ tác nhân kết nối với dịch vụ này.
Chuẩn bị Hộp công cụ để triển khai
Tạo một thư mục triển khai cho dịch vụ Toolbox:
cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/
Tạo Dockerfile cho Toolbox. Mở deploy-toolbox/Dockerfile trong Trình chỉnh sửa Cloud Shell:
cloudshell edit deploy-toolbox/Dockerfile
Sao chép tập lệnh sau vào đó
# 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"]
Tệp nhị phân Toolbox và tools.yaml được đóng gói thành một hình ảnh Debian tối thiểu. Cloud Run định tuyến lưu lượng truy cập đến cổng 8080.
Triển khai dịch vụ Hộp công cụ
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 &
Lệnh này gửi nguồn đến Cloud Build, tạo một hình ảnh vùng chứa, đẩy hình ảnh đó vào Artifact Registry và triển khai hình ảnh đó lên Cloud Run. Quá trình này sẽ mất vài phút – chúng ta có thể kiểm tra nhật ký quy trình triển khai trên tệp logs/deploy_toolbox.log
Chuẩn bị tác nhân để triển khai
Trong khi Toolbox đang tạo, hãy thiết lập các tệp triển khai của tác nhân.
Tạo một Dockerfile trong thư mục gốc của dự án. Mở Dockerfile trong Trình chỉnh sửa Cloud Shell:
cloudshell edit Dockerfile
Sau đó, hãy sao chép nội dung sau
# 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 này sử dụng ghcr.io/astral-sh/uv làm hình ảnh cơ sở, bao gồm cả Python và uv được cài đặt sẵn – không cần cài đặt uv riêng biệt thông qua pip.
Tạo tệp .dockerignore để loại trừ các tệp không cần thiết khỏi hình ảnh vùng chứa:
cloudshell edit .dockerignore
Sau đó, sao chép tập lệnh sau vào đó
# .dockerignore
.venv/
__pycache__/
*.pyc
.env
jobs_agent/.env
toolbox
tools.yaml
seed.sql
deploy-toolbox/
Triển khai dịch vụ tác nhân
Chờ quá trình triển khai Toolbox hoàn tất. Kiểm tra lại quy trình triển khai trên logs/deploy_toolbox.log để xác minh quy trình. Sau đó, hãy truy xuất URL Cloud Run của ứng dụng bằng lệnh sau
TOOLBOX_URL=$(gcloud run services describe toolbox-service \
--region=$REGION \
--format='value(status.url)')
echo "Toolbox URL: $TOOLBOX_URL"
Bạn sẽ thấy kết quả tương tự như sau
Toolbox URL: https://toolbox-service-xxxxxx-xx.a.run.app
Sau đó, hãy xác minh rằng Toolbox đã triển khai đang hoạt động:
curl -s "$TOOLBOX_URL/api/toolset" | python3 -m json.tool | head -5
Nếu kết quả đầu ra hiển thị như ví dụ này, thì quá trình triển khai đã thành công
{
"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.",
Tiếp theo, hãy triển khai tác nhân bằng cách truyền URL của Hộp công cụ dưới dạng một biến môi trường:
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
Mã tác nhân đọc TOOLBOX_URL từ môi trường (bạn đã thiết lập mã này trước đó). Theo cách cục bộ, nó trỏ đến http://127.0.0.1:5000; trên Cloud Run, nó trỏ đến URL dịch vụ Toolbox. Bạn không cần thay đổi mã.
Kiểm thử nhân viên hỗ trợ đã triển khai
Truy xuất URL Cloud Run của nhân viên hỗ trợ:
AGENT_URL=$(gcloud run services describe jobs-agent \
--region=$REGION \
--format='value(status.url)')
echo "Agent URL: $AGENT_URL"
Mở URL trong trình duyệt. Giao diện người dùng ADK dev sẽ tải – đây là giao diện mà bạn đã sử dụng cục bộ, hiện đang chạy trên Cloud Run.
Chọn jobs_agent trong trình đơn thả xuống rồi kiểm thử:
What backend engineering jobs do you have?
I want a remote job working on AI and machine learning
Cả hai truy vấn đều hoạt động thông qua các dịch vụ đã triển khai: tác nhân trên Cloud Run gọi Toolbox trên Cloud Run, truy vấn Cloud SQL.
9. Chúc mừng / Dọn dẹp
Bạn đã tạo và triển khai một trợ lý bảng tin tuyển dụng thông minh sử dụng Bộ công cụ MCP cho cơ sở dữ liệu để kết nối một tác nhân ADK và Cloud SQL PostgreSQL – bằng cả truy vấn SQL chuẩn và tìm kiếm vectơ ngữ nghĩa.
Kiến thức bạn học được
- Cách MCP chuẩn hoá quyền truy cập vào công cụ cho các tác nhân AI và cách MCP Toolbox for Databases áp dụng điều này cụ thể cho các thao tác cơ sở dữ liệu – thay thế mã cơ sở dữ liệu tuỳ chỉnh bằng cấu hình YAML khai báo
- Cách định cấu hình Cloud SQL PostgreSQL làm nguồn dữ liệu Toolbox bằng loại nguồn
cloud-sql-postgres - Cách xác định các công cụ truy vấn SQL chuẩn bằng các câu lệnh có tham số giúp ngăn chặn việc chèn SQL
- Cách bật tính năng tìm kiếm vectơ bằng pgvector và
gemini-embedding-001, với tham sốembeddedByđể nhúng truy vấn tự động - Cách
valueFromParamcho phép tự động nhập vectơ – LLM cung cấp nội dung mô tả bằng văn bản và Toolbox sẽ sao chép, nhúng và lưu trữ vectơ cùng với văn bản một cách âm thầm - Cách
ToolboxToolsetcủa ADK tải các công cụ từ một máy chủ Bộ công cụ đang chạy, giúp mã đại lý ở mức tối thiểu và logic cơ sở dữ liệu hoàn toàn tách biệt - Cách triển khai cả máy chủ MCP Toolbox và tác nhân ADK lên Cloud Run dưới dạng các dịch vụ riêng biệt
Dọn dẹp
Để tránh bị tính phí vào tài khoản Google Cloud cho các tài nguyên được tạo trong lớp học lập trình này, bạn có thể xoá từng tài nguyên hoặc xoá toàn bộ dự án.
Cách 1: Xoá dự án (nên dùng)
Cách dọn dẹp dễ nhất là xoá dự án. Thao tác này sẽ xoá tất cả tài nguyên liên kết với dự án.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Cách 2: Xoá từng tài nguyên
Nếu bạn muốn giữ lại dự án nhưng chỉ xoá các tài nguyên được tạo trong lớp học lập trình này, hãy làm như sau:
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
