מסד נתונים ככלי: RAG מבוסס-סוכן עם ADK, ערכת הכלים MCP ו-Cloud SQL

1. מבוא

התועלת של סוכני AI תלויה בנתונים שאליהם יש להם גישה. רוב הנתונים בעולם האמיתי נמצאים במסדי נתונים – ובדרך כלל, כדי לקשר סוכנים למסדי נתונים צריך לכתוב ניהול חיבורים, לוגיקה של שאילתות וצינורות הטמעה בתוך קוד הסוכן. כל נציג שזקוק לגישה למסד הנתונים צריך לחזור על הפעולות האלה, וכל שינוי בשאילתה מחייב פריסה מחדש של הנציג.

בשיעור הזה מוצגת גישה שונה. מצהירים על כלי מסד הנתונים בקובץ YAML – שאילתות SQL סטנדרטיות, חיפוש דמיון וקטורי, ואפילו יצירה אוטומטית של הטמעה – וארגז הכלים של MCP למסדי נתונים מטפל בכל פעולות מסד הנתונים כשרת MCP. קוד הסוכן נשאר מינימלי: טוענים את הכלים ומאפשרים ל-Gemini להחליט באיזה כלי להשתמש.

מה תפַתחו

עוזר חכם ללוח דרושים בשם TechJobs – סוכן ADK שמבוסס על Gemini ועוזר למפתחים לעיין ברשימות של משרות בתחום הטכנולוגיה באמצעות מסננים סטנדרטיים (תפקיד, חבילת טכנולוגיות) ולמצוא משרות באמצעות תיאורים בשפה טבעית, כמו "אני רוצה משרה עם עבודה מרחוק בתחום של צ'אטבוטים מבוססי-AI". הסוכן קורא ממסד נתונים של Cloud SQL PostgreSQL וכותב אליו דרך MCP Toolbox for Databases, שמטפל בכל הגישה למסד הנתונים – כולל יצירה אוטומטית של הטמעה לחיפוש וקטורי. בסיום, גם ערכת הכלים וגם הסוכן יפעלו ב-Cloud Run.

eb6de681c40990c1.jpeg

מה תלמדו

  • איך MCP‏ (Model Context Protocol) מתקנן את הגישה לכלי סוכני AI, ואיך MCP Toolbox for Databases מיישם את זה על פעולות במסדי נתונים
  • הגדרת MCP Toolbox for Databases כתוכנת ביניים בין סוכן ADK לבין Cloud SQL PostgreSQL
  • הגדרת כלי מסד נתונים באופן הצהרתי ב-tools.yaml – אין קוד מסד נתונים בסוכן
  • בניית סוכן ADK שמעמיס כלים משרת Toolbox פעיל באמצעות ToolboxToolset
  • יצירת הטבעות וקטוריות באמצעות הפונקציה המובנית embedding() של Cloud SQL והפעלת חיפוש סמנטי באמצעות pgvector
  • שימוש בתכונה valueFromParam להוספה אוטומטית של וקטורים בפעולות כתיבה
  • פריסת שרת Toolbox וסוכן ADK ב-Cloud Run

דרישות מוקדמות

  • חשבון Google Cloud עם חשבון לחיוב בתקופת ניסיון
  • היכרות בסיסית עם Python ו-SQL
  • לא נדרש ניסיון קודם ב-ADK, ב-MCP Toolbox או ב-pgvector

2. הגדרת הסביבה

בשלב הזה מכינים את סביבת Cloud Shell, מגדירים את הפרויקט ב-Google Cloud ומשכפלים את מאגר ההפניות.

פתיחת Cloud Shell

פותחים את Cloud Shell בדפדפן. ‫Cloud Shell מספק סביבה שהוגדרה מראש עם כל הכלים שדרושים ל-codelab הזה. כשמופיעה בקשה, לוחצים על Authorize

אחר כך לוחצים על View (תצוגה) -> Terminal (טרמינל) כדי לפתוח את הטרמינל.הממשק אמור להיראות בערך כך:

86307fac5da2f077.png

זה יהיה הממשק הראשי שלנו, סביבת הפיתוח המשולבת (IDE) בחלק העליון והטרמינל בחלק התחתון

הגדרת ספריית העבודה

יוצרים את ספריית העבודה. כל הקוד שכותבים ב-Codelab הזה נמצא כאן:

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

הגדרת הפרויקט ב-Google Cloud

יוצרים את קובץ .env עם משתני המיקום:

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

מורידים את סקריפט הגדרת הפרויקט לספריית העבודה:

curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh

מריצים את הסקריפט. הסקריפט מאמת את החשבון לחיוב שלכם בתקופת הניסיון, יוצר פרויקט חדש (או מאמת פרויקט קיים), שומר את מזהה הפרויקט בקובץ .env בספרייה הנוכחית ומגדיר את הפרויקט הפעיל ב-gcloud.

bash setup_verify_trial_project.sh && source .env

הסקריפט:

  1. אימות שיש לכם חשבון לחיוב פעיל לתקופת ניסיון
  2. בודקים אם יש פרויקט קיים ב-.env (אם יש)
  3. יוצרים פרויקט חדש או משתמשים בפרויקט קיים
  4. קישור החשבון לחיוב בתקופת הניסיון לפרויקט
  5. שומרים את מזהה הפרויקט ב-.env
  6. הגדרת הפרויקט כפרויקט פעיל ב-gcloud

כדי לוודא שהפרויקט מוגדר בצורה נכונה, בודקים את הטקסט הצהוב שליד ספריית העבודה בהנחיה של טרמינל Cloud Shell. מזהה הפרויקט צריך להופיע בו.

dcba35ce1389f313.png

אם סשן Cloud Shell יתאפס בשלב כלשהו במהלך ה-codelab הזה, צריך לחזור לספריית העבודה ולהריץ מחדש את הפקודה bash setup_verify_trial_project.sh && source .env כדי לשחזר את הגדרות הפרויקט. מוודאים שהטקסט הצהוב של מזהה הפרויקט מופיע שוב בהנחיית המסוף.

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) – הסוכן משתמש במודלים של Gemini, וכלי העזר משתמש ב-Embedding API לחיפוש וקטורי.
  • Cloud SQL Admin API‏ (sqladmin.googleapis.com) – אתם מקצים ומנהלים מופע PostgreSQL.
  • Compute Engine API ‏ (compute.googleapis.com) – נדרש ליצירת מופעים של Cloud SQL.
  • Cloud Run, ‏ Cloud Build, ‏ Artifact Registry – השירותים האלה ישמשו בשלב הפריסה בהמשך ה-codelab הזה

3. יצירת מכונת מסד הנתונים

בשלב הזה מתבצעת ברקע יצירה של מכונת Cloud SQL – המכונה מוקצית בזמן שאתם ממשיכים בהדרכה.

התחלת יצירת המופע

מוסיפים את הסיסמה למסד הנתונים לקובץ .env וטוענים אותו מחדש:

echo "DB_PASSWORD=techjobs-pwd-2025" >> .env
source .env

מתחילים ליצור את המכונה של Cloud SQL. הפעולה הזו מתבצעת ברקע, כך שאפשר להמשיך לעבוד:

gcloud sql instances create jobs-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 &
  • db-custom-1-3840 הוא הרמה הקטנה ביותר של Cloud SQL עם ליבה ייעודית (‎1 vCPU, ‏ ‎3.75 GB RAM) במהדורת ENTERPRISE. פרטים נוספים זמינים כאן. נדרשת ליבה ייעודית לשילוב של Vertex AI ML – שכבות של ליבה משותפת (db-f1-micro, db-g1-small) לא תומכות בה.
  • --root-password מגדיר את הסיסמה למשתמש ברירת המחדל postgres.
  • --enable-google-ml-integration מאפשרת את השילוב המובנה של Cloud SQL עם Vertex AI, שמאפשר לכם לקרוא למודלים של הטמעה ישירות מ-SQL באמצעות הפונקציה embedding().
  • הפקודה & מריצה את הפקודה ברקע.

הפעולה הזו תפעל ברקע. בשלב הבא נוריד את הקובץ הבינארי של MCP Toolbox. אפשר לעשות את זה באותו מסוף

הורדת קובץ הבינארי של Toolbox

במדריך הזה נשתמש ב-MCP Toolbox. למרבה המזל, הוא מגיע עם קובץ בינארי מוכן מראש שאפשר להשתמש בו בסביבת Linux. נתחיל להוריד אותו ברקע כי זה ייקח זמן

cd ~/build-agent-adk-toolbox-cloudsql
curl -O https://storage.googleapis.com/genai-toolbox/v0.27.0/linux/amd64/toolbox &

מאפשרים לתהליך הזה לפעול בכרטיסייה הנוכחית (אנחנו כבר מריצים אותו ברקע, אבל הפלט עדיין יוצג). כדי שנוכל להתמקד יותר, נפתח כרטיסיית טרמינל חדשה ב-Cloud Shell (לוחצים על סמל הפלוס).

b01e3fbd89f17332.png

חוזרים לספריית העבודה ומפעילים את הפרויקט באמצעות סקריפט ההגדרה הקודם.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

בשלב הזה מגדירים את פרויקט Python, מתקינים יחסי תלות ויוצרים את ספריית הסוכן של ADK.

4. הפעלת הפרויקט של הסוכן

הגדרת פרויקט Python

uv הוא מנהל פרויקטים וחבילות Python מהיר שנכתב ב-Rust ( מסמכי uv ). אנחנו משתמשים בו ב-Codelab הזה כדי להשיג מהירות ופשטות.

מאתחלים פרויקט Python ומוסיפים את התלויות הנדרשות:

uv init
uv add google-adk==1.25.0 toolbox-adk==0.6.0
  • google-adk — Google's Agent Development Kit, כולל Gemini SDK
  • toolbox-adk — שילוב של ADK עם MCP Toolbox for Databases.

יצירת מבנה ספריות של סוכנים

ה-ADK מצפה לפריסת תיקיות ספציפית: ספרייה שנקראת על שם הסוכן שלכם ומכילה את הקבצים __init__.py, agent.py ו-.env. כדי לעזור לכם בכך, יש פקודה מובנית ליצירת המבנה במהירות:

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

עכשיו הספריה אמורה להיראות כך:

build-agent-adk-toolbox-cloudsql/
├── jobs_agent/
│   ├── __init__.py
│   ├── agent.py
│   └── .env
├── pyproject.toml
├── .env              (project setup — already exists)
└── .venv/

5. הוספת נתונים למסד הנתונים של כרטיסי מוצר (משרות)

בשלב הזה נכתבים נתוני ה-seed, המערכת מחכה עד שהקצאת המשאבים של מופע Cloud SQL מסתיימת, וטוענת את הטבלה jobs עם 15 פרסומי משרות והטמעת התיאור שלהם

כתיבת ה-SQL של ה-seed

ניצור קובץ בשם seed.sql ב-Cloud Shell Editor עם תוכן של רשימת משרות. כך נוצרת הטבלה jobs עם תמיכה ב-pgvector ומוכנסות 15 מודעות דרושים בחברות טכנולוגיה.

קודם יוצרים את הקובץ seed.sql באמצעות הפקודה הבאה:

cloudshell edit seed.sql

לאחר מכן, מעתיקים את הסקריפטים האלה לקובץ

-- seed.sql
-- DISCLAIMER: These job listings are entirely fictional and created for tutorial
-- purposes only. Company names are used for illustrative context — the positions,
-- salaries, and descriptions do not reflect real openings.

CREATE EXTENSION IF NOT EXISTS google_ml_integration;
CREATE EXTENSION IF NOT EXISTS vector;

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)
);

INSERT INTO jobs (title, company, role, tech_stack, salary_range, location, openings, description) VALUES
('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.');

סקריפט ההגדרה הראשונית מתקין שני תוספים של PostgreSQL:

  • google_ml_integration – מספק את פונקציית ה-SQL‏ embedding(), שמפעילה מודלים של הטמעה ב-Vertex AI ישירות מ-SQL. זהו תוסף ברמת מסד הנתונים שמאפשר להשתמש בפונקציות של למידת מכונה בתוך jobs_db. הדגל ברמת המופע (--enable-google-ml-integration) שאתם מגדירים במהלך יצירת המופע מאפשר למכונה הווירטואלית של Cloud SQL להגיע אל Vertex AI – התוסף מאפשר להשתמש בפונקציות SQL במסד הנתונים הספציפי הזה.
  • vector (pgvector) – מוסיף את סוג הנתונים vector ואת אופרטורי המרחק לאחסון ולשאילתות של הטמעות.

העמודה description_embedding היא vector(3072) – עמודה מסוג pgvector שמאחסנת וקטורים תלת-ממדיים בגודל 3,072. בשלב הזה הערך הוא NULL. בשלב הבא תיצרו ותמלאו את ההטמעות באמצעות הפונקציה embedding().

סיום הגדרת מסד הנתונים

יכול להיות שיצירת מופע Cloud SQL שהתחלתם בשלב הקודם עדיין פועלת ולא הסתיימה. בודקים שהמכונה מוכנה:

gcloud sql instances describe jobs-instance --format="value(state)"

הפלט הבא אמור להתקבל

RUNNABLE

34f5b48006b4cb3a.png

לאחר מכן, נותנים לחשבון השירות של מופע Cloud SQL הרשאה לקרוא ל-Vertex AI. הפרמטר הזה נדרש לפונקציה המובנית embedding() שתשתמשו בה בשלב הבא:

SERVICE_ACCOUNT=$(gcloud sql instances describe jobs-instance --format="value(serviceAccountEmailAddress)")

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

לאחר מכן, יוצרים מסד נתונים ייעודי לפרסום המשרות:

gcloud sql databases create jobs_db --instance=jobs-instance

אמור להופיע פלט שמאשר שהמסד נתונים נוצר:

Creating Cloud SQL database...done.                                                                         
Created database [jobs_db].
instance: jobs-instance
name: jobs_db
project: workshop-xxxxxxx

חיבור למסד הנתונים ואתחול שלו

מפעילים את שרת ה-proxy ל-Cloud SQL Auth (cloud-sql-proxy מותקן מראש ב-Cloud Shell). הפעולה הזו מספקת חיבור מאובטח ומאומת מ-Cloud Shell למכונה של Cloud SQL:

d72e56478b517b5c.jpeg

cloud-sql-proxy ${GOOGLE_CLOUD_PROJECT}:${REGION}:jobs-instance --port 5432 &

אם ה-proxy יופעל, הפלט הבא יופיע במסוף:

... Authorizing with Application Default Credentials
... [workshop-xxxxxx:your-location:jobs-instance] Listening on 127.0.0.1:5432
... The proxy has started successfully and is ready for new connections!

עכשיו, במסוף הנוכחי מוצג הפלט של יומן הרישום של Cloud SQL Proxy באופן רציף. כדי שנוכל להתמקד יותר, נפתח כרטיסיית טרמינל חדשה ב-Cloud Shell (לוחצים על סמל הפלוס).

b01e3fbd89f17332.png

חוזרים לספריית העבודה ומפעילים את הפרויקט באמצעות סקריפט ההגדרה הקודם.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

לאחר מכן, מריצים את סקריפט ההגדרה הראשונית.

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" -f seed.sql

יוצג פלט בטרמינל כמו זה

CREATE EXTENSION
CREATE EXTENSION
CREATE TABLE
INSERT 0 15

בוא נאמת את הנתונים

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" \
  -c "SELECT title, company, role, openings FROM jobs ORDER BY role, title;"

יוצגו 15 משרות בתפקידים שונים:

             title              |    company     |   role    | openings
---------------------------------+----------------+-----------+----------
 Senior Backend Engineer         | Stripe         | Backend   |        3
 Backend Engineer (Payments)     | Square         | Backend   |        3
 Cloud Architect                 | Google Cloud   | Cloud     |        1
 ...
(15 rows)

יצירת הטמעות לתיאורי משרה

העמודה description_embedding בטבלה jobs היא כרגע NULL. תוסף google_ml_integration המובנה של Cloud SQL מספק פונקציה embedding() שקוראת ל-Vertex AI ישירות מ-SQL – לא צריך סקריפט Python או SDK חיצוני.

מתחילים את יצירת ההטמעה ברקע. הפעולה הזו קוראת ל-Vertex AI כדי ליצור וקטור תלת-ממדי של 3,072 ממדים באמצעות מודל gemini-embedding-001 לכל אחד מ-15 תיאורי המשרות:

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" \
  -c "UPDATE jobs SET description_embedding = embedding('gemini-embedding-001', description)::vector;" &

הסקריפט מבצע את הפעולות הבאות:

  • embedding('gemini-embedding-001', description) — קוראת למודל ההטמעה של Gemini ב-Vertex AI ישירות מ-SQL, ומעבירה את description הטקסט של כל משרה. זהו התוסף google_ml_integration שהתקנתם בסקריפט ה-seed.
  • ::vector — מבצע המרה של מערך המספרים הממשיים שמוחזר לסוג vector של pgvector, כדי שאפשר יהיה לאחסן אותו ולבצע עליו שאילתות באמצעות אופרטורים של מרחק.
  • המודל UPDATE פועל על כל 15 השורות, ויוצר הטמעה אחת בת 3,072 ממדים לכל תיאור משרה.
  • & מריץ את הפקודה ברקע, כך שתוכלו להמשיך לעבוד בזמן ש-Vertex AI מעבד את ההטמעות.

בדומה להרצה קודמת של תהליך ברקע, הפלט של התהליך יוצג במסוף הנוכחי. כדי שנוכל להתמקד יותר, נפתח כרטיסיית טרמינל חדשה ב-Cloud Shell (לוחצים על סמל הפלוס).

b01e3fbd89f17332.png

חוזרים לספריית העבודה ומפעילים את הפרויקט באמצעות סקריפט ההגדרה הקודם.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

לאחר מכן, נוכל להמשיך לתהליך הבא

6. הגדרת MCP Toolbox for Databases

בשלב הזה נציג את MCP Toolbox for Databases, נגדיר אותו להתחבר למופע Cloud SQL ונגדיר שני כלי שאילתות SQL סטנדרטיים.

מה זה MCP ולמה כדאי להשתמש בארגז הכלים?

e7b9be2e1c98b4db.png

MCP (Model Context Protocol) הוא פרוטוקול פתוח שמבצע סטנדרטיזציה של האופן שבו סוכני AI מגלים כלים חיצוניים ומבצעים אינטראקציה איתם. הוא מגדיר מודל לקוח-שרת: הסוכן מארח לקוח MCP, והכלים נחשפים על ידי שרתי MCP. כל לקוח שתואם ל-MCP יכול להשתמש בכל שרת שתואם ל-MCP – לא צריך קוד שילוב מותאם אישית לסוכן עבור כל כלי.

d5baa77423f0f465.png

MCP Toolbox for Databases הוא שרת MCP בקוד פתוח שנבנה במיוחד לגישה למסדי נתונים. בלי זה, תצטרכו לכתוב פונקציות Python שפותחות חיבורים למסד נתונים, מנהלות מאגרי חיבורים, בונות שאילתות עם פרמטרים כדי למנוע הזרקת SQL, מטפלות בשגיאות ומשבצות את כל הקוד הזה בתוך הסוכן. כל נציג שזקוק לגישה למסד הנתונים חוזר על הפעולה הזו. שינוי שאילתה מחייב פריסה מחדש של הסוכן.

באמצעות ארגז הכלים, כותבים קובץ YAML. כל כלי ממופה להצהרת SQL עם פרמטרים. ערכת הכלים מטפלת בחיבורים, בשאילתות עם פרמטרים, באימות ובאפשרות הצפייה. הכלים מופרדים מהסוכן – אפשר לעדכן שאילתה על ידי עריכת tools.yaml והפעלה מחדש של Toolbox, בלי לגעת בקוד של הסוכן. אותם כלים פועלים ב-ADK, ב-LangGraph, ב-LlamaIndex או בכל framework שתואם ל-MCP.

כתיבת ההגדרה של כלי

עכשיו צריך ליצור קובץ בשם tools.yaml ב-Cloud Shell Editor כדי להגדיר את כלי ההגדרה

cloudshell edit tools.yaml

הקובץ משתמש ב-YAML עם כמה מסמכים – כל בלוק שמופרד על ידי --- הוא משאב עצמאי. לכל משאב יש מאפיין kind שמצהיר מהו (sources לחיבורי מסד נתונים, tools לפעולות שאפשר להתקשר אליהן באמצעות סוכן) ומאפיין type שמציין את העורף (cloud-sql-postgres למקור, postgres-sql לכלים מבוססי SQL). כלי מפנה למקור שלו באמצעות name, וכך ארגז הכלים יודע מול איזה מאגר חיבורים לבצע את הפעולה. משתני הסביבה משתמשים בתחביר ${VAR_NAME} ונפתרים בזמן האתחול.

עכשיו מעתיקים את הסקריפטים הבאים לקובץ tools.yaml

# tools.yaml

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

---

הסקריפט הזה מגדיר את המשאב הבא:

  • מקור (jobs-db) – מציין לארגז הכלים איך להתחבר למופע Cloud SQL PostgreSQL. הסוג cloud-sql-postgres משתמש באופן פנימי במחבר Cloud SQL, ומטפל באימות ובחיבורים מאובטחים באופן אוטומטי. ה-placeholders‏ ${GOOGLE_CLOUD_PROJECT} , ‏ ${REGION} ו-${DB_PASSWORD} נפתרים ממשתני סביבה בזמן ההפעלה.

בשלב הבא, מוסיפים את הסקריפט הבא מתחת לסמל --- בקובץ tools.yaml

# --- Tool 1: Search jobs by role and/or tech stack ---
kind: tools
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: tools
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)."

---

הסקריפט הזה מגדיר את המשאב הבא:

  • Tools 1 and 2 (search-jobs, get-job-details) – כלים לשאילתות SQL סטנדרטיות. כל אחד מהם ממפה שם של כלי (מה שהסוכן רואה) להצהרת SQL עם פרמטרים (מה שמסד הנתונים מבצע). הפרמטרים משתמשים בפלייסהולדרים של מיקום $1, $2. ערכת הכלים מפעילה את הפקודות האלה כהצהרות מוכנות, וכך מונעת הזרקת SQL.

ממשיכים ומוסיפים את הסקריפט הבא מתחת לסמל --- בקובץ tools.yaml

# --- Embedding Model ---
kind: embeddingModels
name: gemini-embedding
type: gemini
model: gemini-embedding-001
dimension: 3072

---

הסקריפט הזה מגדיר את המשאב הבא:

  • מודל הטמעה (gemini-embedding) – מגדיר את Toolbox לקריאה למודל gemini-embedding-001 של Gemini כדי ליצור הטמעות טקסט תלת-ממדיות של 3,072. האימות ב-Toolbox מתבצע באמצעות Application Default Credentials ‏ (ADC) – לא נדרש מפתח API ב-Cloud Shell או ב-Cloud Run. הערות שdimension שהוגדר כאן חייב להיות זהה למה שהוגדר קודם כדי לאכלס את מסד הנתונים

ממשיכים ומוסיפים את הסקריפט הבא מתחת לסמל --- בקובץ tools.yaml

# --- Tool 3: Semantic search by description ---
kind: tools
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

---

הסקריפט הזה מגדיר את המשאב הבא:

  • כלי 3 (search-jobs-by-description) – כלי לחיפוש וקטורי. הפרמטר search_query מכיל את הערך embeddedBy: gemini-embedding, שמורה ל-Toolbox ליירט את הטקסט הגולמי, לשלוח אותו למודל ההטמעה ולהשתמש בווקטור שמתקבל בהצהרת ה-SQL. האופרטור <=> הוא המרחק הקוסינוסי של pgvector – ערכים קטנים יותר מציינים תיאורים דומים יותר.

לבסוף, מוסיפים את הכלי האחרון מתחת לסמל --- בקובץ tools.yaml

# --- Tool 4: Add a new job listing with automatic embedding ---
kind: tools
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

הסקריפט הזה מגדיר את המשאב הבא:

  • כלי 4 (add-job) – הדגמה של הטמעה של וקטורים. לפרמטר description_vector יש שני שדות מיוחדים:
  • valueFromParam: description — הכלי מעתיק את הערך מהפרמטר description אל הפרמטר הזה. ה-LLM אף פעם לא רואה את הפרמטר הזה.
  • embeddedBy: gemini-embedding — Toolbox מטמיע את הטקסט שהועתק בווקטור לפני שהוא מעביר אותו ל-SQL.

התוצאה: קריאה אחת לכלי מאחסנת גם את טקסט התיאור הגולמי וגם את הטמעת הווקטור שלו, בלי שהסוכן יודע דבר על הטמעות.

בפורמט YAML של כמה מסמכים, כל משאב מופרד באמצעות ---. לכל מסמך יש שדות kind, name ו-type שמגדירים מהו המסמך. בקיצור, כבר הגדרנו את כל הדברים הבאים:

  • הגדרת מסד הנתונים של המקור
  • הגדרת כלים ( tool 1 ו-tool 2 ) לשליחת שאילתות למסד נתונים עם מסנן רגיל
  • הגדרת מודל להטמעה
  • הגדרת כלי לביצוע חיפוש וקטורי ( כלי 3 ) במסד הנתונים
  • הגדרת כלי להטמעת נתוני וקטור ( כלי 4 ) במסד נתונים

אימות ההטמעות

לפני שמתחילים להשתמש ב-Toolbox, צריך לוודא שההטמעה ברקע הושלמה. בודקים שלכל המשרות יש הטמעות:

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" \
  -c "SELECT title, (description_embedding IS NOT NULL) AS has_embedding FROM jobs ORDER BY title;"

בכל שורה צריך להופיע הערך t (true) בעמודה has_embedding. אם לא, אפשר לחכות עד שתהליך יצירת ההטמעה של כל השורות יסתיים.

           title            | has_embedding 
-----------------------------+---------------
 AI Engineer                 | t
 Backend Engineer (Payments) | t
 Cloud Architect             | t
 Data Engineer               | t
 DevOps Engineer             | t
 Frontend Engineer           | t
 Full Stack Engineer         | t

הפעלת השרת של ארגז הכלים

בשלב ההגדרה, כבר הורדנו את קובץ ההפעלה toolbox. מוודאים שהקובץ הבינארי הזה קיים והורד בהצלחה. אם לא, מורידים אותו וממתינים עד לסיום ההורדה.

cd ~/build-agent-adk-toolbox-cloudsql
if [ ! -f toolbox ]; then
  curl -O https://storage.googleapis.com/genai-toolbox/v0.27.0/linux/amd64/toolbox
fi
chmod +x toolbox

מייצאים את משתני הסביבה הנדרשים ומפעילים את Toolbox. המשתנים GOOGLE_CLOUD_LOCATION ו-GOOGLE_GENAI_USE_VERTEXAI נדרשים כי ההגדרה כוללת מודל הטמעה – GOOGLE_GENAI_USE_VERTEXAI אומר ל-Gemini SDK לבצע ניתוב דרך Vertex AI (במקום דרך Gemini API לצרכנים), ו-GOOGLE_CLOUD_LOCATION אומר לו באיזו נקודת קצה אזורית להשתמש.

export GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT
export GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION
export GOOGLE_GENAI_USE_VERTEXAI=true
export DB_PASSWORD=$DB_PASSWORD
export REGION=$REGION
./toolbox --tools-file tools.yaml &

הפלט אמור להיראות כך:

... INFO "Initialized 0 authServices: " 
... 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!"

בדומה לשלב הקודם, ייווצר תהליך נוסף ויוצגו פלטים. כדי שנוכל להתמקד יותר, נפתח כרטיסיית טרמינל חדשה ב-Cloud Shell (לוחצים על סמל הפלוס).

b01e3fbd89f17332.png

חוזרים לספריית העבודה ומפעילים את הפרויקט באמצעות סקריפט ההגדרה הקודם.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

אימות הכלים

כדי לראות רשימה של כל הכלים הרשומים, שולחים שאילתה ל-Toolbox API:

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

יוצגו כלים עם התיאורים והפרמטרים שלהם. כמו שמוצג בהמשך

...
       
"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": []
        }
...

בודקים את הכלי 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'

התשובה צריכה לכלול את שתי משרות הנדסת ה-Backend מנתוני ה-Seed.

[
  {
    "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

בשלב הזה, סוכן ה-ADK מחובר לשרת Toolbox הפועל, ונבדקים כל ארבעת הכלים – שאילתות רגילות, חיפוש סמנטי והטמעה של וקטורים. הקוד של הסוכן מינימלי: כל הלוגיקה של מסד הנתונים נמצאת ב-tools.yaml.

הגדרת הסביבה של הסוכן

‫ADK קורא את GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT ו-GOOGLE_CLOUD_LOCATION מסביבת המעטפת, שכבר הגדרתם בשלב קודם. המשתנה הספציפי לסוכן היחיד הוא TOOLBOX_URL – צריך לצרף אותו לקובץ .env של הסוכן:

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

עדכון מודול הסוכן

פתיחה של jobs_agent/agent.py ב-Cloud Shell Editor

cloudshell edit jobs_agent/agent.py

ומחליפים את התוכן בקוד הבא:

# 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],
)

שימו לב שאין כאן קוד של מסד נתונים – ToolboxToolset מתחבר לשרת של Toolbox בהפעלה וטוען את כל הכלים הזמינים. הסוכן קורא לכלים לפי שם, ו-Toolbox מתרגם את הקריאות האלה לשאילתות SQL ב-Cloud SQL.

משתנה הסביבה TOOLBOX_URL מוגדר כברירת מחדל ל-http://127.0.0.1:5000 לפיתוח מקומי. כשפורסים ל-Cloud Run בהמשך, מחליפים את כתובת ה-URL הזו בכתובת ה-URL של שירות Toolbox ב-Cloud Run – אין צורך לשנות את הקוד.

ההוראה מתייחסת כרגע רק לשני הכלים הרגילים (search-jobs ו-get-job-details). בשלב הבא תרחיבו אותה כשתוסיפו כלים להטמעה ולחיפוש סמנטי.

בדיקת הסוכן

מפעילים את ממשק המשתמש של ADK למפתחים:

cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web

פותחים את כתובת ה-URL שמוצגת במסוף (בדרך כלל http://localhost:8000) באמצעות התכונה Web Preview של Cloud Shell או באמצעות Ctrl + click על כתובת ה-URL שמוצגת במסוף. בוחרים באפשרות jobs_agent מהתפריט הנפתח של הסוכן בפינה הימנית העליונה.

בדיקת שאילתות רגילות

כדי לאמת את הכלים של SQL סטנדרטי, אפשר לנסות את ההנחיות הבאות:

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

93ac33e7f73aa0b9.png 240c53376042a916.png

נסו להשתמש בתיאורים בשפה טבעית שלא מתאימים לתפקיד ספציפי או לסט טכנולוגיות מסוים:

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

הסוכן ינסה לבחור את הכלי הנכון על סמך סוג השאילתה: מסננים מובנים עוברים דרך search-jobs, ותיאורים בשפה טבעית עוברים דרך search-jobs-by-description.

b0ea629f5c9b4c26.png

בדיקה של הטמעת וקטורים

מבקשים מהנציג להוסיף משרה חדשה:

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

c601a7a9bc0a705b.png

עכשיו נסו לחפש אותו:

Find me jobs involving autonomous systems and working with physical hardware

ההטמעה נוצרה אוטומטית במהלך הפעולה INSERT – לא נדרש שלב נפרד.

5a3d8e6f523dc18b.png

עכשיו יש לכם אפליקציית Agentic RAG שעובדת באופן מלא ומבוססת על ADK, על MCP Toolbox ועל CloudSQL. מזל טוב! בשלב הבא נסביר איך פורסים את האפליקציות האלה ב-Cloud Run.

עכשיו, כדי להמשיך, צריך לעצור את ממשק המשתמש למפתחים על ידי סגירת התהליך. לשם כך, מקישים על Ctrl+C פעמיים.

8. פריסה ב-Cloud Run

הסוכן וארגז הכלים פועלים באופן מקומי. בשלב הזה פורסים את שניהם כשירותי Cloud Run, כך שאפשר לגשת אליהם דרך האינטרנט. שירות Toolbox פועל כשרת MCP ב-Cloud Run, ושירות הסוכן מתחבר אליו.

הכנת ערכת הכלים לפריסה

יוצרים ספריית פריסה לשירות Toolbox:

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

יוצרים את קובץ ה-Dockerfile עבור ערכת הכלים. פותחים את deploy-toolbox/Dockerfile ב-Cloud Shell Editor:

cloudshell edit deploy-toolbox/Dockerfile

מעתיקים אליו את הסקריפט הבא

# 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", "--tools-file", "tools.yaml", "--address", "0.0.0.0", "--port", "8080"]

קובץ ההפעלה של Toolbox ו-tools.yaml נארזים בתמונת Debian מינימלית. תנועת הנתונים ב-Cloud Run מנותבת ליציאה 8080.

פריסת שירות Toolbox

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

הפקודה הזו שולחת את המקור ל-Cloud Build, יוצרת קובץ אימג' של קונטיינר, מעבירה אותו בדחיפה ל-Artifact Registry ופורסת אותו ב-Cloud Run. התהליך יימשך כמה דקות. כדאי לפתוח כרטיסיית טרמינל חדשה ב-Cloud Shell (לוחצים על סמל הפלוס) כדי שנוכל להתמקד יותר.

b01e3fbd89f17332.png

חוזרים לספריית העבודה ומפעילים את הפרויקט באמצעות סקריפט ההגדרה הקודם.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

הכנת הסוכן לפריסה

בזמן שהכלי לבניית אפליקציות נבנה, מגדירים את קובצי הפריסה של הסוכן.

יוצרים קובץ Dockerfile בתיקיית הבסיס של הפרויקט. פותחים את Dockerfile ב-Cloud Shell Editor:

cloudshell edit Dockerfile

לאחר מכן, מעתיקים את התוכן הבא

# 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 הזה משתמש ב-ghcr.io/astral-sh/uv כקובץ האימג' הבסיסי, שכולל את Python ואת uv שהותקנו מראש – אין צורך להתקין את uv בנפרד דרך pip.

יוצרים קובץ .dockerignore כדי להחריג קבצים מיותרים מתמונת הקונטיינר:

cloudshell edit .dockerignore

לאחר מכן מעתיקים לתוכו את הסקריפט הבא

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

פריסת שירות הסוכן

ממתינים לסיום הפריסה של Toolbox. מאחזרים את כתובת ה-URL של Cloud Run באמצעות הפקודה הבאה

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

הפלט שיוצג יהיה דומה לזה:

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

עכשיו נבדוק שה-Toolbox שפרסתם פועל:

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

אם הפלט נראה כמו בדוגמה הזו, הפריסה כבר הצליחה

{
    "serverVersion": "0.27.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.",

בשלב הבא, פורסים את הסוכן ומעבירים את כתובת ה-URL של ערכת הכלים כמשתנה סביבה:

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

קוד הסוכן קורא את TOOLBOX_URL מהסביבה (הגדרתם את זה קודם). באופן מקומי, הוא מצביע על http://127.0.0.1:5000. ב-Cloud Run הוא מצביע על כתובת ה-URL של שירות Toolbox. אין צורך לשנות את הקוד.

בדיקת הסוכן שנפרס

מאחזרים את כתובת ה-URL של הסוכן ב-Cloud Run:

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

פותחים את כתובת ה-URL בדפדפן. ממשק המשתמש של ADK Dev נטען – אותו ממשק שבו השתמשתם באופן מקומי, ועכשיו הוא פועל ב-Cloud Run.

בוחרים באפשרות jobs_agent מהתפריט הנפתח ובודקים:

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

שתי השאילתות פועלות דרך השירותים שנפרסו: הסוכן ב-Cloud Run קורא ל-Toolbox ב-Cloud Run, ששולח שאילתה ל-Cloud SQL.

9. Congratulations / Clean Up

בניתם ופרסתם עוזר חכם ללוח דרושים שמשתמש ב-MCP Toolbox for Databases כדי לגשר בין סוכן ADK לבין Cloud SQL PostgreSQL – עם שאילתות SQL רגילות וחיפוש וקטורי סמנטי.

מה למדתם

  • איך MCP מתקנן את הגישה לכלי סוכני AI, ואיך MCP Toolbox for Databases מיישם את זה באופן ספציפי על פעולות במסדי נתונים – החלפת קוד מותאם אישית של מסד נתונים בהגדרת YAML הצהרתית
  • איך מגדירים את Cloud SQL PostgreSQL כמקור נתונים ב-Toolbox באמצעות cloud-sql-postgres סוג המקור
  • איך מגדירים כלי שאילתות SQL סטנדרטי עם הצהרות פרמטריות שמונעות הזרקת SQL
  • איך מפעילים חיפוש וקטורי באמצעות pgvector ו-gemini-embedding-001, עם הפרמטר embeddedBy להטמעת שאילתות אוטומטית
  • איך valueFromParam מאפשרת הטמעה אוטומטית של וקטורים – מודל ה-LLM מספק תיאור טקסט, וכלי העזר מעתיק, מטמיע ומאחסן את הווקטור לצד הטקסט באופן שקוף
  • איך ADK‏ ToolboxToolset טוען כלים משרת Toolbox פעיל, כך שקוד הסוכן נשאר מינימלי והלוגיקה של מסד הנתונים מופרדת לחלוטין
  • איך פורסים את שרת ה-MCP של Toolbox ואת סוכן ה-ADK ב-Cloud Run כשירותים נפרדים

פינוי נפח

כדי להימנע מחיובים בחשבון Google Cloud על המשאבים שנוצרו ב-Codelab הזה, אתם יכולים למחוק את המשאבים בנפרד או למחוק את הפרויקט כולו.

הדרך הקלה ביותר לנקות את המשאבים היא למחוק את הפרויקט. הפעולה הזו תסיר את כל המשאבים שמשויכים לפרויקט.

gcloud projects delete $GOOGLE_CLOUD_PROJECT

אפשרות 2: מחיקת משאבים ספציפיים

אם אתם רוצים לשמור את הפרויקט אבל להסיר רק את המשאבים שנוצרו ב-Codelab הזה:

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