1. Einführung
KI-Agenten sind nur so nützlich wie die Daten, auf die sie zugreifen können. Die meisten Daten aus der realen Welt befinden sich in Datenbanken. Wenn Sie Agenten mit Datenbanken verbinden, müssen Sie in der Regel das Verbindungsmanagement, die Abfragelogik und die Einbettungspipelines in Ihren Agentencode schreiben. Jeder KI-Agent, der Datenbankzugriff benötigt, muss diese Arbeit wiederholen. Jede Abfrageänderung erfordert eine erneute Bereitstellung des KI-Agenten.
In diesem Codelab wird ein anderer Ansatz vorgestellt. Sie deklarieren Ihre Datenbanktools in einer YAML-Datei – Standard-SQL-Abfragen, Vektorähnlichkeitssuche und sogar die automatische Einbettungsgenerierung – und die MCP Toolbox for Databases übernimmt alle Datenbankvorgänge als MCP-Server. Ihr Agent-Code bleibt minimal: Laden Sie die Tools und lassen Sie Gemini entscheiden, welches aufgerufen werden soll.
Umfang
Ein Smart Job Board Assistant für „TechJobs“ – ein ADK-Agent, der auf Gemini basiert und Entwicklern hilft, Stellenangebote für technische Berufe mithilfe von Standardfiltern (Rolle, Tech-Stack) zu durchsuchen und Stellen anhand von Beschreibungen in natürlicher Sprache wie „Ich suche einen Remote-Job, bei dem ich an KI-Chatbots arbeiten kann“ zu finden. Der Agent liest Daten aus einer Cloud SQL for PostgreSQL-Datenbank und schreibt Daten in diese Datenbank. Dies geschieht ausschließlich über die MCP Toolbox for Databases, die den gesamten Datenbankzugriff übernimmt, einschließlich der automatischen Einbettungsgenerierung für die Vektorsuche. Am Ende werden sowohl die Toolbox als auch der Agent in Cloud Run ausgeführt.
Lerninhalte
- Wie der MCP-Standard (Model Context Protocol) den Toolzugriff für KI-Agents standardisiert und wie die MCP Toolbox for Databases dies auf Datenbankvorgänge anwendet
- MCP Toolbox for Databases als Middleware zwischen einem ADK-Agenten und Cloud SQL for PostgreSQL einrichten
- Datenbanktools deklarativ in
tools.yamldefinieren – kein Datenbankcode in Ihrem Agent - Einen ADK-Agenten erstellen, der Tools von einem laufenden Toolbox-Server mit
ToolboxToolsetlädt - Vektoreinbettungen mit der integrierten
embedding()-Funktion von Cloud SQL generieren und semantische Suche mitpgvectoraktivieren valueFromParam-Funktion für die automatische Vektorerfassung bei Schreibvorgängen verwenden- Toolbox-Server und ADK-Agent in Cloud Run bereitstellen
Voraussetzungen
- Ein Google Cloud-Konto mit einem Testabrechnungskonto
- Grundkenntnisse in Python und SQL
- Vorkenntnisse mit Cloud Database und ADK sind hilfreich.
2. Umgebung einrichten
In diesem Schritt wird Ihre Cloud Shell-Umgebung vorbereitet, Ihr Google Cloud-Projekt konfiguriert und das Referenz-Repository geklont.
Cloud Shell öffnen
Öffnen Sie Cloud Shell in Ihrem Browser. Cloud Shell bietet eine vorkonfigurierte Umgebung mit allen Tools, die Sie für dieses Codelab benötigen. Klicken Sie auf Autorisieren, wenn Sie dazu aufgefordert werden.
Klicken Sie dann auf Ansicht -> Terminal, um das Terminal zu öffnen.Die Benutzeroberfläche sollte so aussehen:

Das ist unsere Hauptschnittstelle. Die IDE befindet sich oben und das Terminal unten.
Arbeitsverzeichnis einrichten
Erstellen Sie Ihr Arbeitsverzeichnis. Der gesamte Code, den Sie in diesem Codelab schreiben, befindet sich hier:
mkdir -p ~/build-agent-adk-toolbox-cloudsql
cloudshell workspace ~/build-agent-adk-toolbox-cloudsql && cd ~/build-agent-adk-toolbox-cloudsql
Danach bereiten wir mehrere Verzeichnisse vor, um Dinge wie Seeding-Skripts und Logs zu verwalten.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
Google Cloud-Projekt einrichten
Erstellen Sie die Datei .env mit den Standortvariablen:
# For Vertex AI / Gemini API calls
echo "GOOGLE_CLOUD_LOCATION=global" > .env
# For Cloud SQL, Cloud Run, Artifact Registry
echo "REGION=us-central1" >> .env
Um die Einrichtung des Projekts in Ihrem Terminal zu vereinfachen, laden Sie dieses Skript zur Einrichtung des Projekts in Ihr Arbeitsverzeichnis herunter:
curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh
Führen Sie das Skript aus. Dabei wird Ihr Probeabo-Rechnungskonto überprüft, ein neues Projekt erstellt (oder ein vorhandenes Projekt validiert), Ihre Projekt-ID in einer .env-Datei im aktuellen Verzeichnis gespeichert und das aktive Projekt in gcloud festgelegt.
bash setup_verify_trial_project.sh && source .env
Das Skript führt Folgendes aus:
- Prüfen, ob Sie ein aktives Testabrechnungskonto haben
- Prüfen Sie, ob in
.envein Projekt vorhanden ist. - Neues Projekt erstellen oder vorhandenes Projekt wiederverwenden
- Test-Rechnungskonto mit Ihrem Projekt verknüpfen
- Speichern Sie die Projekt-ID in
.env. - Projekt als aktives
gcloud-Projekt festlegen
Prüfen Sie, ob das Projekt richtig eingestellt ist. Sehen Sie dazu im Cloud Shell-Terminal-Prompt nach dem gelben Text neben Ihrem Arbeitsverzeichnis. Dort sollte Ihre Projekt-ID angezeigt werden.

Erforderliche API aktivieren
Als Nächstes müssen wir mehrere APIs für das Produkt aktivieren, mit dem wir interagieren werden:
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): Ihr Agent verwendet Gemini-Modelle und Toolbox verwendet die Embedding API für die Vektorsuche. - Cloud SQL Admin API (
sqladmin.googleapis.com): Sie stellen eine PostgreSQL-Instanz bereit und verwalten sie. - Compute Engine API (
compute.googleapis.com): Erforderlich zum Erstellen von Cloud SQL-Instanzen. - Cloud Run, Cloud Build, Artifact Registry: Werden im Bereitstellungsschritt weiter unten in diesem Codelab verwendet.
3. Skripts für die Datenbankinitialisierung vorbereiten
In diesem Schritt wird die Cloud SQL-Instanz erstellt und ein automatisiertes Einrichtungsskript ausgeführt, das wartet, bis die Instanz bereit ist. Anschließend wird die Datenbank erstellt, mit Stellenangeboten gefüllt und es werden Einbettungen generiert – alles in einem Vorgang.
Fügen Sie zuerst das Datenbankpasswort in die Datei .env ein und laden Sie sie neu:
echo "DB_PASSWORD=techjobs-pwd" >> .env
echo "DB_INSTANCE=jobs-instance" >> .env
echo "DB_NAME=jobs_db" >> .env
source .env
Bash-Skript zum Erstellen von Instanzen und Datenbanken erstellen
Erstellen Sie dann das scripts/setup_database.sh-Skript mit dem folgenden Befehl:
mkdir -p ~/build-agent-adk-toolbox-cloudsql/scripts
cloudshell edit scripts/setup_database.sh
Kopieren Sie dann den folgenden Code in die Datei 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 ""
Python-Script für Data Seed erstellen
Erstellen Sie dann mit dem folgenden Befehl die Python-Datei scripts/setup_jobs_db.py für das Seeding-Skript.
cloudshell edit scripts/setup_jobs_db.py
Kopieren Sie dann den folgenden Code in die Datei 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()
Kommen wir nun zum nächsten Schritt.
4. Datenbank erstellen und initialisieren
Jetzt können unsere Skripts ausgeführt werden. Wir benötigen Python, um unser vorbereitetes Skript auszuführen. Bereiten wir es also zuerst vor.
Python-Projekt einrichten
uv ist ein schneller Python-Paket- und Projektmanager, der in Rust geschrieben wurde ( uv-Dokumentation). In diesem Codelab wird er verwendet, um das Python-Projekt schnell und einfach zu verwalten.
Initialisieren Sie ein Python-Projekt und fügen Sie die erforderlichen Abhängigkeiten hinzu:
uv init
uv add cloud-sql-python-connector --extra pg8000
uv add python-dotenv
Wir verwenden hier das cloud-sql-python-connector Python SDK, um eine sichere Verbindung mit unserer Datenbankinstanz zu initialisieren, die mit Standardanmeldedaten für Anwendungen authentifiziert wird.
Setup-Skript ausführen
Jetzt können wir das Einrichtungs-Script im Hintergrund ausführen und die Konsolenausgabe, die in die Datei logs/atabase_setup.log geschrieben wird, mit dem folgenden Befehl prüfen. Sie können mit dem nächsten Abschnitt fortfahren, während Sie darauf warten, dass dieser Vorgang abgeschlossen wird.
mkdir -p ~/build-agent-adk-toolbox-cloudsql/logs
bash scripts/setup_database.sh > logs/database_setup.log 2>&1 &
Toolbox-Binärdatei herunterladen
In dieser Anleitung verwenden wir die MCP Toolbox. Glücklicherweise ist eine vorkompilierte Binärdatei enthalten, die in der Linux-Umgebung verwendet werden kann. Laden wir es jetzt im Hintergrund herunter, da es eine Weile dauert. Führen Sie den folgenden Befehl aus, um die Binärdatei herunterzuladen und das Ausgabeprotokoll auf dem logs/toolbox_dl.log zu prüfen . Sie können mit dem nächsten Abschnitt fortfahren, während Sie darauf warten, dass dieser Vorgang abgeschlossen wird.
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 &
Das Einrichtungsskript scripts/setup_database.sh
Sehen wir uns nun das Setup-Skript an, das wir zuvor konfiguriert haben. Dabei wird folgender Prozess durchlaufen:
- Der erste Befehl, den wir dort ausführen, ist der Befehl
gcloud sql instances createmit dem folgenden Flag:
db-custom-1-3840ist die kleinste Cloud SQL-Stufe mit dedizierten Kernen (1 vCPU, 3,75 GB RAM) in derENTERPRISE-Version. Weitere Informationen Für die Vertex AI ML-Integration ist ein dedizierter Core erforderlich. Shared-Core-Tarife (db-f1-micro,db-g1-small) werden nicht unterstützt.- Mit
--root-passwordwird das Passwort für den Standardnutzerpostgresfestgelegt. --enable-google-ml-integrationaktiviert die integrierte Einbindung von Cloud SQL in Vertex AI. So können Sie Einbettungsmodelle mit der Funktionembedding()direkt über SQL aufrufen.
- Prüfen Sie, ob die Instanz bereits den Status
RUNNABLEhat. - Gewähren Sie dem Dienstkonto der Cloud SQL-Instanz die Berechtigung, Vertex AI mit dem Befehl
gcloud projects add-iam-policy-bindingaufzurufen. Dies ist für die integrierteembedding()-Funktion erforderlich, die wir beim Seeding der Datenbank verwenden. - Datenbank erstellen
- Das Seeding-Skript
setup_jobs_db.pyausführen
Grundlegendes zum Seed-Skript scripts/setup_jobs_db.py
Das Seeding-Script führt folgende Aktionen aus:
- Verbindung zur Datenbankinstanz initialisieren
- Installiert zwei PostgreSQL-Erweiterungen:
google_ml_integration: Stellt die SQL-Funktionembedding()bereit, mit der Vertex AI-Einbettungsmodelle direkt über SQL aufgerufen werden. Dies ist eine Erweiterung auf Datenbankebene, die ML-Funktionen injobs_dbverfügbar macht. Das Flag auf Instanzebene (--enable-google-ml-integration), das Sie beim Erstellen der Instanz festlegen, ermöglicht es der Cloud SQL-VM, Vertex AI zu erreichen. Die Erweiterung macht die SQL-Funktionen in dieser bestimmten Datenbank verfügbar.vector(pgvector): Fügt den Datentypvectorund Distanzoperatoren zum Speichern und Abfragen von Einbettungen hinzu.
- Erstellen Sie die Tabelle. Beachten Sie, dass die Spalte
description_embeddingvector(3072)ist – einepgvector-Spalte, in der 3.072-dimensionale Vektoren gespeichert werden. - Erste Jobdaten übertragen
- Generieren Sie die Einbettungsdaten aus dem Feld
descriptionund füllen Siedescription_embeddingmithilfe der integrierten Vertex-Integration über die Funktionembedding()aus.
embedding('gemini-embedding-001', description)– ruft das Gemini-Einbettungsmodell von Vertex AI direkt über SQL auf und übergibt dendescription-Text jedes Jobs. Das ist diegoogle_ml_integration-Erweiterung, die Sie im Seed-Script installiert haben.::vector: Wandelt das zurückgegebene Float-Array in denvector-Typ von pgvector um, damit es mit Distanzoperatoren gespeichert und abgefragt werden kann.- Die
UPDATEwird für alle 15 Zeilen ausgeführt und generiert ein 3.072-dimensionales Embedding pro Stellenbeschreibung.
Dadurch werden erste Daten vorbereitet, auf die unser Agent zugreifen kann.
5. MCP-Toolbox für Datenbanken konfigurieren
In diesem Schritt wird die MCP Toolbox for Databases eingeführt, für die Verbindung zu Ihrer Cloud SQL-Instanz konfiguriert und zwei Standard-SQL-Abfragetools definiert.
Was ist das MCP und warum sollte ich die Toolbox verwenden?

MCP (Model Context Protocol) ist ein offenes Protokoll, das standardisiert, wie KI-Agents externe Tools erkennen und mit ihnen interagieren. Es wird ein Client-Server-Modell definiert: Der Agent hostet einen MCP-Client und Tools werden von MCP-Servern bereitgestellt. Jeder MCP-kompatible Client kann jeden MCP-kompatiblen Server verwenden. Der Agent benötigt also keinen benutzerdefinierten Integrationscode für jedes Tool.

Die MCP Toolbox für Datenbanken ist ein Open-Source-MCP-Server, der speziell für den Datenbankzugriff entwickelt wurde. Andernfalls müssten Sie Python-Funktionen schreiben, die Datenbankverbindungen öffnen, Verbindungspools verwalten, parametrisierte Abfragen erstellen, um SQL-Injection zu verhindern, Fehler verarbeiten und den gesamten Code in Ihren Agent einbetten. Jeder Agent, der Datenbankzugriff benötigt, wiederholt diese Schritte. Wenn Sie eine Abfrage ändern, müssen Sie den Agenten neu bereitstellen.
Mit Toolbox schreiben Sie eine YAML-Datei. Jedes Tool wird einer parametrisierten SQL-Anweisung zugeordnet. Die Toolbox übernimmt das Verbindungs-Pooling, parametrisierte Abfragen, die Authentifizierung und die Beobachtbarkeit. Tools sind vom Agent entkoppelt – Sie können eine Anfrage aktualisieren, indem Sie tools.yaml bearbeiten und die Toolbox neu starten, ohne den Agent-Code zu ändern. Die gleichen Tools funktionieren mit dem ADK, LangGraph, LlamaIndex oder einem anderen MCP-kompatiblen Framework.
Toolkonfiguration schreiben
Als Nächstes müssen wir im Cloud Shell-Editor eine Datei mit dem Namen tools.yaml erstellen, um die Konfiguration unserer Tools einzurichten.
cloudshell edit tools.yaml
Die Datei verwendet YAML mit mehreren Dokumenten. Jeder Block, der durch --- getrennt ist, ist eine eigenständige Ressource. Jede Ressource hat einen kind, der angibt, was sie ist (sources für Datenbankverbindungen, tools für von Agenten aufrufbare Aktionen) und einen type, der das Backend angibt (cloud-sql-postgres für die Quelle, postgres-sql für SQL-basierte Tools). Ein Tool verweist mit name auf seine Quelle. So weiß Toolbox, welcher Verbindungspool verwendet werden soll. Umgebungsvariablen verwenden die ${VAR_NAME}-Syntax und werden beim Start aufgelöst.
Kopieren wir nun die folgenden Skripts zuerst in die Datei 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}
---
In diesem Skript wird die folgende Ressource definiert:
- Quelle (
jobs-db): Gibt an, wie Toolbox eine Verbindung zu Ihrer Cloud SQL for PostgreSQL-Instanz herstellt. Der Typcloud-sql-postgresverwendet intern den Cloud SQL-Connector und übernimmt automatisch die Authentifizierung und sichere Verbindungen. Die Platzhalter${GOOGLE_CLOUD_PROJECT},${REGION}und${DB_PASSWORD}werden beim Start aus Umgebungsvariablen aufgelöst.
Fügen Sie als Nächstes das folgende Skript in der tools.yaml unter dem Symbol --- ein.
# --- 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)."
---
In diesem Skript wird die folgende Ressource definiert:
- Tools 1 und 2 (
search-jobs,get-job-details): Standard-SQL-Abfragetools. Jede Zuordnung ordnet einen Toolnamen (was der Agent sieht) einer parametrisierten SQL-Anweisung (was die Datenbank ausführt) zu. Für Parameter werden die Positionsparameter$1und$2verwendet. Die Toolbox führt diese als vorbereitete Anweisungen aus, was SQL-Injection verhindert.
Fügen Sie das folgende Skript unter dem Symbol --- in der Datei tools.yaml ein:
# --- Embedding Model ---
kind: embeddingModel
name: gemini-embedding
type: gemini
model: gemini-embedding-001
project: ${GOOGLE_CLOUD_PROJECT}
location: ${GOOGLE_CLOUD_LOCATION}
dimension: 3072
---
In diesem Skript wird die folgende Ressource definiert:
- Einbettungsmodell (
gemini-embedding): Konfiguriert die Toolbox so, dass dasgemini-embedding-001-Modell von Gemini zum Generieren von 3.072-dimensionalen Texteinbettungen aufgerufen wird. Die Toolbox verwendet Standardanmeldedaten für Anwendungen (Application Default Credentials, ADC) für die Authentifizierung. In Cloud Shell oder Cloud Run ist kein API-Schlüssel erforderlich. Hinweise: Die hier konfiguriertedimensionmuss mit der übereinstimmen, die wir zuvor zum Seeden der Datenbank konfiguriert haben.
Fügen Sie das folgende Skript unter dem Symbol --- in der Datei tools.yaml ein:
# --- 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
---
In diesem Skript wird die folgende Ressource definiert:
- Tool 3 (
search-jobs-by-description): ein Vektorsuchtool. Der Parametersearch_queryhat den WertembeddedBy: gemini-embedding. Dadurch wird Toolbox angewiesen, den Roh-Text abzufangen, an das Einbettungsmodell zu senden und den resultierenden Vektor in der SQL-Anweisung zu verwenden. Der Operator<=>ist die Kosinusdistanz von pgvector. Kleinere Werte bedeuten ähnliche Beschreibungen.
Hängen Sie schließlich das letzte Tool unter dem Symbol --- in der Datei tools.yaml an.
# --- 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
In diesem Skript wird die folgende Ressource definiert:
- Tool 4 (
add-job): Hier wird die Vektoraufnahme demonstriert. Der Parameterdescription_vectorhat zwei spezielle Felder: valueFromParam: description: Die Toolbox kopiert den Wert aus dem Parameterdescriptionin diesen Parameter. Das LLM sieht diesen Parameter nie.embeddedBy: gemini-embedding: Die Toolbox bettet den kopierten Text in einen Vektor ein, bevor sie ihn an den SQL-Code übergibt.
Das Ergebnis: Bei einem Tool-Aufruf werden sowohl der Rohbeschreibungstext als auch die zugehörige Vektoreinbettung gespeichert, ohne dass der Agent etwas über Einbettungen weiß.
Im YAML-Format mit mehreren Dokumenten wird jede Ressource durch --- getrennt. Jedes Dokument hat die Felder kind, name und type, die definieren, was es ist. Zusammenfassend haben wir bereits Folgendes konfiguriert:
- Quelldatenbank definieren
- Definieren Sie Tools ( Tool 1 und 2), um die Datenbank mit einem Standardfilter abzufragen.
- Einbettungsmodell definieren
- Tool für die Vektorsuche ( Tool 3) für die Datenbank definieren
- Tool zum Aufnehmen von Vektordaten ( Tool 4) in die Datenbank definieren
6. MCP-Toolbox-Server ausführen
Im vorherigen Schritt haben wir bereits die erforderliche Konfiguration für unsere MCP Toolbox festgelegt. Jetzt können wir den Server ausführen.
Seed-Daten prüfen
Bevor wir Toolbox starten, prüfen wir, ob die Datenbank eingerichtet wurde. Erstellen Sie mit dem folgenden Befehl ein Python-Skript scripts/verify_database.py:
cloudshell edit scripts/verify_seed.py
Kopieren Sie dann den folgenden Code in die Datei 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)
Mit diesem Skript wird die Anzahl der Jobpost-Daten und ihr Embedding geprüft. Führen Sie das Skript mit dem folgenden Befehl aus:
uv run scripts/verify_seed.py
Wenn Sie die folgende Terminalausgabe sehen, sind die Daten bereit.
Jobs: 15/15 Embeddings: 15/15 ✓ Database ready!
Toolbox-Server starten
Im vorherigen Einrichtungsschritt haben wir die ausführbare Datei toolbox bereits heruntergeladen. Prüfen Sie, ob diese Binärdatei vorhanden ist und erfolgreich heruntergeladen wurde. Wenn nicht, laden Sie sie herunter und warten Sie, bis der Vorgang abgeschlossen ist.
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
Wir müssen unsere .env-Variablen für den untergeordneten Prozess verfügbar machen, der von der MCP-Toolbox ausgeführt wird. Führen Sie den folgenden Befehl aus, um den Toolbox-Server zu starten und die Konsolenausgabe in der Datei logs/mcp_toolbox.log zu protokollieren.
set -a; source .env; set +a
./toolbox --config tools.yaml --enable-api > logs/mcp_toolbox.log 2>&1 &
In der logs/mcp_toolbox.log-Datei sollte eine Ausgabe angezeigt werden, die bestätigt, dass der Server bereit ist. Diese sieht in etwa so aus:
... 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!"
Tools überprüfen
Fragen Sie die Toolbox API ab, um alle registrierten Tools aufzulisten:
curl -s http://localhost:5000/api/toolset | uv run -m json.tool
Sie sollten Tools mit ihren Beschreibungen und Parametern sehen. Wie unten gezeigt
...
"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": []
}
...
Testen Sie das search-jobs-Tool direkt:
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'
Die Antwort sollte die beiden Backend-Engineering-Jobs aus Ihren Ausgangsdaten enthalten.
[
{
"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. ADK-Agent erstellen
Jetzt verwenden wir das ADK in Python für dieses Projekt. Fügen wir die erforderlichen Abhängigkeiten hinzu:
uv add google-adk==1.29.0 toolbox-adk==1.0.0
google-adk– Das Agent Development Kit von Google, einschließlich des Gemini SDKtoolbox-adk– ADK-Integration für die MCP Toolbox for Databases.
Agent-Verzeichnisstruktur erstellen
Das ADK erwartet ein bestimmtes Ordnerlayout: ein Verzeichnis, das nach Ihrem Agenten benannt ist und __init__.py, agent.py und .env enthält. Dazu gibt es einen integrierten Befehl, mit dem die Struktur schnell erstellt werden kann:
uv run adk create jobs_agent \
--model gemini-2.5-flash \
--project ${GOOGLE_CLOUD_PROJECT} \
--region ${GOOGLE_CLOUD_LOCATION}
Ihr Verzeichnis sollte nun so aussehen:
build-agent-adk-toolbox-cloudsql/ ├── jobs_agent/ │ ├── __init__.py │ ├── agent.py │ └── .env ├── logs ├── scripts └── ...
Als Nächstes müssen wir den ADK-Agenten in den laufenden Toolbox-Server einbinden und alle vier Tools testen: Standardabfragen, semantische Suche und Vektor-Ingestion. Der Agent-Code ist minimal: Die gesamte Datenbanklogik befindet sich in tools.yaml.
Umgebung des Agents konfigurieren
Das ADK liest GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT und GOOGLE_CLOUD_LOCATION aus der Shell-Umgebung, die Sie bereits im vorherigen Schritt festgelegt haben. Die einzige agentspezifische Variable ist TOOLBOX_URL. Hängen Sie sie an die .env-Datei des Agents an:
echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env
Agent-Modul aktualisieren
jobs_agent/agent.py im Cloud Shell-Editor öffnen
cloudshell edit jobs_agent/agent.py
und überschreiben Sie den Inhalt mit dem folgenden Code:
# 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],
)
Beachten Sie, dass hier kein Datenbankcode vorhanden ist – ToolboxToolset stellt beim Start eine Verbindung zum Toolbox-Server her und lädt alle verfügbaren Tools. Der Agent ruft Tools anhand des Namens auf. Toolbox übersetzt diese Aufrufe in SQL-Abfragen für Cloud SQL.
Die Umgebungsvariable TOOLBOX_URL hat standardmäßig den Wert http://127.0.0.1:5000 für die lokale Entwicklung. Wenn Sie die Anwendung später in Cloud Run bereitstellen, wird dieser Wert mit der Cloud Run-URL des Toolbox-Dienstes überschrieben. Es sind keine Codeänderungen erforderlich.
Die Anleitung bezieht sich derzeit nur auf die beiden Standardtools (search-jobs und get-job-details). Sie wird im nächsten Schritt erweitert, wenn Sie Tools für die semantische Suche und die Aufnahme hinzufügen.
Agent testen
Starten Sie die ADK-Entwicklungsoberfläche:
cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web --allow_origins "regex:https://.*\.cloudshell\.dev"
Öffnen Sie die im Terminal angezeigte URL (in der Regel http://localhost:8000) mit der Funktion Webvorschau von Cloud Shell oder indem Sie Strg + Klicken auf die im Terminal angezeigte URL ausführen. Wählen Sie links oben im Drop-down-Menü für den Agenten jobs_agent aus.
Standardabfragen testen
Mit diesen Prompts können Sie die Standard-SQL-Tools testen:
What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

Semantische Suche testen
Versuchen Sie es mit Beschreibungen in natürlicher Sprache, die keiner bestimmten Rolle oder keinem bestimmten Technologie-Stack zugeordnet sind:
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
Der Agent versucht, das richtige Tool basierend auf dem Abfragetyp auszuwählen: Strukturierte Filter werden über search-jobs verarbeitet, Beschreibungen in natürlicher Sprache über search-jobs-by-description.

Testen der Vektorerfassung
Bitten Sie den Kundenservicemitarbeiter, einen neuen Job hinzuzufügen:
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.

Versuchen Sie jetzt, danach zu suchen:
Find me jobs involving autonomous systems and working with physical hardware
Das Einbetten wurde automatisch während des INSERT-Vorgangs generiert. Es ist kein separater Schritt erforderlich.

Sie haben jetzt bereits eine voll funktionsfähige agentische RAG-Anwendung, die ADK, MCP Toolbox und Cloud SQL nutzt. Das wars! Im nächsten Schritt stellen wir diese Apps in Cloud Run bereit.
Stoppen Sie nun die Entwickler-UI, indem Sie den Prozess beenden. Drücken Sie dazu zweimal Strg+C, bevor Sie fortfahren.
8. In Cloud Run bereitstellen
Der Agent und die Toolbox funktionieren lokal. In diesem Schritt werden beide als Cloud Run-Dienste bereitgestellt, sodass sie über das Internet zugänglich sind. Der Toolbox-Dienst wird als MCP-Server in Cloud Run ausgeführt und der Agent-Dienst stellt eine Verbindung zu ihm her.
Toolbox für die Bereitstellung vorbereiten
Erstellen Sie ein Bereitstellungsverzeichnis für den Toolbox-Dienst:
cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/
Erstellen Sie das Dockerfile für die Toolbox. Öffnen Sie deploy-toolbox/Dockerfile im Cloud Shell-Editor:
cloudshell edit deploy-toolbox/Dockerfile
Kopieren Sie das folgende Skript in die Datei.
# 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"]
Die Toolbox-Binärdatei und tools.yaml werden in ein minimales Debian-Image gepackt. Cloud Run leitet Traffic an Port 8080 weiter.
Toolbox-Dienst bereitstellen
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 &
Mit diesem Befehl wird die Quelle an Cloud Build gesendet, ein Container-Image erstellt, in Artifact Registry gepusht und in Cloud Run bereitgestellt. Das dauert einige Minuten. Wir können das Log des Bereitstellungsprozesses in der Datei logs/deploy_toolbox.log einsehen.
Agent für die Bereitstellung vorbereiten
Während die Toolbox erstellt wird, richten Sie die Bereitstellungsdateien des Agents ein.
Erstellen Sie im Stammverzeichnis des Projekts eine Dockerfile. Öffnen Sie Dockerfile im Cloud Shell-Editor:
cloudshell edit Dockerfile
Kopieren Sie dann den folgenden Inhalt.
# 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"]
Dieses Dockerfile verwendet ghcr.io/astral-sh/uv als Basis-Image, das sowohl Python als auch uv vorinstalliert enthält. uv muss also nicht separat über pip installiert werden.
Erstellen Sie eine .dockerignore-Datei, um unnötige Dateien aus dem Container-Image auszuschließen:
cloudshell edit .dockerignore
Kopieren Sie dann das folgende Skript hinein.
# .dockerignore
.venv/
__pycache__/
*.pyc
.env
jobs_agent/.env
toolbox
tools.yaml
seed.sql
deploy-toolbox/
Agent-Dienst bereitstellen
Warten Sie, bis die Bereitstellung der Toolbox abgeschlossen ist. Prüfen Sie den Bereitstellungsprozess noch einmal auf logs/deploy_toolbox.log, um ihn zu bestätigen. Rufen Sie dann die Cloud Run-URL mit dem folgenden Befehl ab:
TOOLBOX_URL=$(gcloud run services describe toolbox-service \
--region=$REGION \
--format='value(status.url)')
echo "Toolbox URL: $TOOLBOX_URL"
Die Ausgabe sollte in etwa so aussehen:
Toolbox URL: https://toolbox-service-xxxxxx-xx.a.run.app
Prüfen Sie dann, ob die bereitgestellte Toolbox funktioniert:
curl -s "$TOOLBOX_URL/api/toolset" | python3 -m json.tool | head -5
Wenn die Ausgabe wie in diesem Beispiel aussieht, war die Bereitstellung bereits erfolgreich.
{
"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.",
Als Nächstes stellen wir den Agent bereit und übergeben die Toolbox-URL als Umgebungsvariable:
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
Der Agent-Code liest TOOLBOX_URL aus der Umgebung (die Sie zuvor eingerichtet haben). Lokal verweist sie auf http://127.0.0.1:5000, in Cloud Run auf die Toolbox-Dienst-URL. Es sind keine Codeänderungen erforderlich.
Bereitgestellten KI-Agenten testen
Rufen Sie die Cloud Run-URL des Agents ab:
AGENT_URL=$(gcloud run services describe jobs-agent \
--region=$REGION \
--format='value(status.url)')
echo "Agent URL: $AGENT_URL"
Rufen Sie die URL in Ihrem Browser auf. Die ADK-Entwickler-UI wird geladen – dieselbe Oberfläche, die Sie lokal verwendet haben, wird jetzt in Cloud Run ausgeführt.
Wählen Sie im Drop-down-Menü jobs_agent aus und testen Sie:
What backend engineering jobs do you have?
I want a remote job working on AI and machine learning
Beide Abfragen funktionieren über die bereitgestellten Dienste: Der Agent in Cloud Run ruft die Toolbox in Cloud Run auf, die Cloud SQL abfragt.
9. Glückwunsch / Bereinigen
Sie haben einen intelligenten Assistenten für die Jobsuche erstellt und bereitgestellt, der die MCP Toolbox for Databases verwendet, um einen ADK-Agenten und Cloud SQL for PostgreSQL zu verbinden – sowohl mit Standard-SQL-Abfragen als auch mit semantischer Vektorsuche.
Lerninhalte
- Wie MCP den Toolzugriff für KI-Agenten standardisiert und wie die MCP Toolbox for Databases dies speziell auf Datenbankvorgänge anwendet – benutzerdefinierter Datenbankcode wird durch deklarative YAML-Konfiguration ersetzt
- Cloud SQL PostgreSQL als Toolbox-Datenquelle mit dem Quelltyp
cloud-sql-postgreskonfigurieren - Standard-SQL-Abfragetools mit parametrisierten Anweisungen definieren, um SQL-Injection zu verhindern
- Vektorsuche mit pgvector und
gemini-embedding-001aktivieren und verwenden, mit dem ParameterembeddedByfür die automatische Abfrageeinbettung - Wie
valueFromParamdie automatische Vektoreingabe ermöglicht: Das LLM liefert eine Textbeschreibung und Toolbox kopiert, bettet den Vektor ein und speichert ihn zusammen mit dem Text. - Wie
ToolboxToolsetdes ADK Tools von einem laufenden Toolbox-Server lädt, wodurch der Agent-Code minimal und die Datenbanklogik vollständig entkoppelt bleibt - Bereitstellung des Toolbox-MCP-Servers und des ADK-Agenten als separate Dienste in Cloud Run
Aufräumen
Damit Ihrem Google Cloud-Konto die in diesem Codelab erstellten Ressourcen nicht in Rechnung gestellt werden, können Sie entweder die einzelnen Ressourcen oder das gesamte Projekt löschen.
Option 1: Projekt löschen (empfohlen)
Am einfachsten bereinigen Sie, indem Sie das Projekt löschen. Dadurch werden alle mit dem Projekt verknüpften Ressourcen entfernt.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
Option 2: Einzelne Ressourcen löschen
Wenn Sie das Projekt behalten, aber nur die in diesem Codelab erstellten Ressourcen entfernen möchten:
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
