1. مقدمة
تعتمد فائدة وكلاء الذكاء الاصطناعي على البيانات التي يمكنهم الوصول إليها. تتوفّر معظم البيانات الواقعية في قواعد البيانات، وعادةً ما يعني ربط الوكلاء بقواعد البيانات كتابة إدارة الاتصال ومنطق طلب البحث وتضمين خطوط الأنابيب داخل رمز الوكيل. ويكرّر كل وكيل يحتاج إلى الوصول إلى قاعدة البيانات هذه العملية، ويتطلّب كل تغيير في طلب البحث إعادة نشر الوكيل.
يوضّح هذا الدرس التطبيقي العملي أسلوبًا مختلفًا. يمكنك تحديد أدوات قاعدة البيانات في ملف YAML، مثل طلبات بحث SQL العادية، وبحث التشابه المتّجهي، وحتى إنشاء عمليات التضمين التلقائية، وتتولّى أداة MCP لقواعد البيانات جميع عمليات قاعدة البيانات كخادم MCP. يبقى رمز الوكيل بسيطًا: حمِّل الأدوات، ودَع Gemini يقرّر الأداة التي سيستخدمها.
ما ستنشئه
مساعد لوحة وظائف ذكية لـ "TechJobs": هو وكيل ADK يستند إلى Gemini ويساعد المطوّرين في تصفّح قوائم الوظائف في مجال التكنولوجيا باستخدام الفلاتر العادية (الدور، مجموعة التكنولوجيا) واكتشاف الوظائف من خلال أوصاف مكتوبة بلغة طبيعية، مثل "أريد وظيفة عن بُعد في مجال تطوير برامج الدردشة المستندة إلى الذكاء الاصطناعي". يقرأ الوكيل من قاعدة بيانات Cloud SQL PostgreSQL ويكتب فيها بالكامل من خلال MCP Toolbox for Databases، الذي يتعامل مع جميع عمليات الوصول إلى قاعدة البيانات، بما في ذلك إنشاء عمليات التضمين التلقائية للبحث المتّجه. في النهاية، سيتم تشغيل كلّ من "مجموعة الأدوات" و"الوكيل" على Cloud Run.
ما ستتعلمه
- كيف يوحّد بروتوكول MCP (Model Context Protocol) إمكانية الوصول إلى الأدوات لوكلاء الذكاء الاصطناعي، وكيف تطبّق أداة MCP Toolbox لقواعد البيانات ذلك على عمليات قواعد البيانات
- إعداد "مجموعة أدوات MCP لقواعد البيانات" كبرنامج وسيط بين وكيل ADK وCloud SQL PostgreSQL
- تحديد أدوات قاعدة البيانات بشكل تعريفي في
tools.yaml، بدون رمز قاعدة بيانات في الوكيل - إنشاء وكيل ADK يحمّل الأدوات من خادم Toolbox قيد التشغيل باستخدام
ToolboxToolset - إنشاء تضمينات متجهة باستخدام الدالة المضمّنة
embedding()في Cloud SQL وتفعيل البحث الدلالي باستخدامpgvector - استخدِم ميزة
valueFromParamلإدخال المتجهات تلقائيًا في عمليات الكتابة - نشر كلّ من خادم Toolbox ووكيل ADK على Cloud Run
المتطلبات الأساسية
- حساب Google Cloud يتضمّن حساب فوترة تجريبيًا
- معرفة أساسية بلغة Python وSQL
- لا يُشترط توفّر خبرة سابقة في "حزمة تطوير التطبيقات على Android" أو "مجموعة أدوات MCP" أو
pgvector
2. إعداد البيئة
تجهّز هذه الخطوة بيئة Cloud Shell وتضبط مشروعك على Google Cloud وتستنسخ مستودع الرموز المرجعي.
فتح Cloud Shell
افتح Cloud Shell في المتصفّح. توفّر Cloud Shell بيئة مُعدّة مسبقًا تتضمّن جميع الأدوات التي تحتاج إليها في هذا الدرس العملي. انقر على تفويض عندما يُطلب منك ذلك
بعد ذلك، انقر على "عرض" -> "وحدة طرفية" لفتح الوحدة الطرفية.يجب أن تبدو واجهتك مشابهة لما يلي

ستكون هذه واجهتنا الرئيسية، مع وضع بيئة التطوير المتكاملة في الأعلى والوحدة الطرفية في الأسفل.
إعداد دليل العمل
أنشئ دليل العمل. يتم تخزين كل الرموز البرمجية التي تكتبها في هذا الدرس التطبيقي حول الترميز هنا:
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
سيؤدي النص البرمجي إلى ما يلي:
- التأكّد من أنّ لديك حساب فوترة تجريبيًا نشطًا
- التحقّق من توفّر مشروع حالي في
.env(إن وُجد) - إنشاء مشروع جديد أو إعادة استخدام المشروع الحالي
- ربط حساب الفوترة التجريبي بمشروعك
- احفظ رقم تعريف المشروع في
.env - ضبط المشروع كمشروع
gcloudنشط
تأكَّد من ضبط المشروع بشكل صحيح من خلال التحقّق من النص الأصفر بجانب دليل العمل في طلب Cloud Shell. يجب أن يعرض رقم تعريف مشروعك.

إذا تمت إعادة ضبط جلسة Cloud Shell في أي وقت خلال هذا الدرس العملي، انتقِل مرة أخرى إلى دليل العمل وأعِد تشغيل 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، وتستخدم "مجموعة الأدوات" واجهة برمجة التطبيقات الخاصة بالتضمين للبحث المتّجه. - واجهة برمجة التطبيقات Cloud SQL Admin (
sqladmin.googleapis.com): يمكنك توفير مثيل PostgreSQL وإدارته. - Compute Engine API (
compute.googleapis.com): مطلوب لإنشاء مثيلات Cloud SQL. - Cloud Run وCloud Build وArtifact Registry: يتم استخدامها في خطوة النشر لاحقًا في هذا الدرس التطبيقي حول الترميز
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 (وحدة معالجة مركزية افتراضية واحدة، وذاكرة وصول عشوائي سعتها 3.75 غيغابايت) في إصدار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 &
السماح بتشغيل هذه العملية في علامة التبويب الحالية (نحن نشغّلها في الخلفية، ولكن سيظل يتم عرض الناتج). لنفتح علامة تبويب جديدة في نافذة Terminal في Cloud Shell (انقر على الرمز +) حتى نتمكّن من التركيز بشكل أكبر.

انتقِل إلى دليل العمل مرة أخرى وفعِّل المشروع باستخدام نص الإعداد البرمجي السابق.
cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env
تُعدّ هذه الخطوة مشروع Python وتثبّت التبعيات وتنشئ بنية دليل وكيل ADK.
4. إعداد "مشروع الوكيل"
إعداد مشروع Python
uv هو مدير حِزم ومشاريع سريع للغة Python مكتوب بلغة Rust ( مستندات uv). يستخدم هذا الدرس التطبيقي حول الترميز هذه الحزمة لتحقيق السرعة والبساطة.
ابدأ مشروع Python وأضِف التبعيات المطلوبة:
uv init
uv add google-adk==1.25.0 toolbox-adk==0.6.0
google-adk: حزمة تطوير الوكلاء من Google، بما في ذلك حزمة تطوير البرامج (SDK) الخاصة بـ Gemini-
toolbox-adk: دمج ADK مع "مجموعة أدوات بروتوكول سياق النموذج لقواعد البيانات"
إنشاء بنية دليل الوكيل
يتوقّع 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- تعبئة قاعدة بيانات بيانات الوظائف
تكتب هذه الخطوة البيانات الأولية، وتنتظر إلى أن تنتهي عملية توفير آلة Cloud SQL الافتراضية، وتحمّل الجدول jobs بـ 15 إعلانًا عن وظائف وتضمين أوصافها.
كتابة SQL الأوّلية
سننشئ ملفًا باسم seed.sql في محرِّر Cloud Shell يتضمّن محتوى بطاقة بيانات الوظائف. يؤدي ذلك إلى إنشاء الجدول 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: توفّر دالة SQLembedding()التي تستدعي نماذج التضمين في Vertex AI مباشرةً من SQL. هذه إضافة على مستوى قاعدة البيانات تتيح استخدام وظائف تعلُّم الآلة داخلjobs_db. تتيح العلامة على مستوى المثيل (--enable-google-ml-integration) التي تضبطها أثناء إنشاء المثيل لجهاز Cloud SQL الظاهري الوصول إلى Vertex AI، ويجعل هذا الامتداد دوال SQL متاحةً في قاعدة البيانات المحدّدة هذه. vector(pgvector): يضيف نوع البياناتvectorوعوامل تشغيل المسافة لتخزين عمليات التضمين والاستعلام عنها.
العمود description_embedding هو vector(3072)، وهو عمود pgvector يخزّن متّجهات ذات 3072 بُعدًا. القيمة هي NULL في الوقت الحالي، وستنشئ عمليات التضمين وتعبئها في الخطوة التالية باستخدام الدالة embedding().
إنهاء عملية إعداد قاعدة البيانات
قد يكون إنشاء مثيل Cloud SQL الذي بدأته في الخطوة السابقة لا يزال قيد التنفيذ ولم ينتهِ بعد. تأكَّد من أنّ الجهاز الافتراضي جاهز:
gcloud sql instances describe jobs-instance --format="value(state)"
من المفترض أن يظهر لك الناتج التالي
RUNNABLE

بعد ذلك، امنح حساب خدمة مثيل 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
ربط قاعدة البيانات وتعبئتها
ابدأ الخادم الوكيل للمصادقة في Cloud SQL (cloud-sql-proxy مثبَّت مسبقًا في Cloud Shell). يوفّر ذلك اتصالاً آمنًا تمت مصادقته من Cloud Shell إلى مثيل Cloud SQL:

cloud-sql-proxy ${GOOGLE_CLOUD_PROJECT}:${REGION}:jobs-instance --port 5432 &
إذا بدأ الوكيل، من المفترض أن تظهر لك النتائج التالية في الوحدة الطرفية:
... 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 بشكل مستمر. لنفتح علامة تبويب جديدة في نافذة Terminal في Cloud Shell (انقر على الرمز +) حتى نتمكّن من التركيز بشكل أكبر.

انتقِل إلى دليل العمل مرة أخرى وفعِّل المشروع باستخدام نص الإعداد البرمجي السابق.
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 لإنشاء متّجه ذي 3072 بُعدًا باستخدام نموذج 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التي ثبَّتها في النص البرمجي الأوّلي.::vector: تحويل مصفوفة الأرقام العشرية التي تم إرجاعها إلى نوعvectorفي pgvector حتى يمكن تخزينها والاستعلام عنها باستخدام عوامل تشغيل المسافة- يتم تشغيل
UPDATEعلى جميع الصفوف الـ 15، ما يؤدي إلى إنشاء تضمين واحد ذي 3072 بُعدًا لكل وصف وظيفي. - ينفّذ الأمر
&في الخلفية، ما يتيح لك مواصلة العمل أثناء معالجة Vertex AI لعمليات التضمين.
وكما هو الحال مع تنفيذ العمليات السابقة في الخلفية، ستعرض الوحدة الطرفية الحالية سجلّ العملية. لنفتح علامة تبويب جديدة في نافذة Terminal في Cloud Shell (انقر على الرمز +) حتى نتمكّن من التركيز بشكل أكبر.

انتقِل إلى دليل العمل مرة أخرى وفعِّل المشروع باستخدام نص الإعداد البرمجي السابق.
cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env
بعد ذلك، يمكننا الانتقال إلى العملية التالية.
6. ضبط إعدادات "مجموعة أدوات MCP" لقواعد البيانات
تقدّم هذه الخطوة "مجموعة أدوات MCP لقواعد البيانات"، وتضبطها للاتصال بمثيل Cloud SQL، وتحدّد أداتَين عاديتَين للاستعلام عن SQL.
ما هي "برنامج الشركاء المتعدّدين القنوات" (MCP) ولماذا يجب استخدام "صندوق الأدوات"؟

بروتوكول Model Context Protocol (MCP) هو بروتوكول مفتوح يوحّد طريقة عثور وكلاء الذكاء الاصطناعي على الأدوات الخارجية والتفاعل معها. يحدّد هذا البروتوكول نموذجًا للعميل والخادم: يستضيف الوكيل عميل MCP، وتوفّر خوادم MCP الأدوات. يمكن لأي برنامج متوافق مع MCP استخدام أي خادم متوافق مع MCP، ولا يحتاج البرنامج إلى رمز دمج مخصّص لكل أداة.

مجموعة أدوات MCP لقواعد البيانات هي خادم MCP مفتوح المصدر مصمَّم خصيصًا للوصول إلى قواعد البيانات. وبدونها، ستكتب دوال Python التي تفتح اتصالات بقاعدة البيانات، وتدير مجموعات الاتصالات، وتنشئ طلبات بحث ذات معلَمات لمنع اختراق SQL، وتعالج الأخطاء، وتضمّن كل هذا الرمز البرمجي داخل برنامجك. ويكرّر كل وكيل يحتاج إلى الوصول إلى قاعدة البيانات هذه العملية. يعني تغيير الاستعلام إعادة نشر الوكيل.
باستخدام Toolbox، يمكنك كتابة ملف YAML. ترتبط كل أداة بعبارة SQL ذات معلَمات. تتعامل "مجموعة الأدوات" مع تجميع الاتصالات، والاستعلامات التي تتضمّن مَعلمات، والمصادقة، وإمكانية المراقبة. الأدوات منفصلة عن الوكيل، ويمكنك تعديل طلب بحث من خلال تعديل tools.yaml وإعادة تشغيل Toolbox بدون تعديل رمز الوكيل. تعمل الأدوات نفسها على جميع إطارات العمل المتوافقة مع MCP، مثل ADK أو LangGraph أو LlamaIndex.
كتابة إعدادات الأدوات
الآن، علينا إنشاء ملف باسم tools.yaml في "محرّر Cloud Shell" لإعداد ضبط الأدوات.
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 داخليًا، ويتعامل مع المصادقة والاتصالات الآمنة تلقائيًا. يتم تحديد قيم العناصر النائبة${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)."
---
يحدّد هذا النص البرمجي المورد التالي:
- الأداتان 1 و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): يضبط هذا النموذج "أداة صندوق الأدوات" لاستخدام نموذجgemini-embedding-001من Gemini لإنشاء عمليات تضمين نصية ذات 3072 بُعدًا. تستخدم Toolbox بيانات الاعتماد التلقائية للتطبيق (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إلى هذه المَعلمة. لا يرى النموذج اللغوي الكبير هذه المَعلمة أبدًا.embeddedBy: gemini-embedding: يضمّن "صندوق الأدوات" النص المنسوخ في متّجه قبل تمريره إلى لغة SQL.
والنتيجة هي أنّ استدعاء أداة واحد يخزّن كلاً من نص الوصف الأولي والتضمين المتجهي، بدون أن يعرف الوكيل أي شيء عن عمليات التضمين.
يفصل تنسيق YAML المتعدد المستندات كل مورد باستخدام ---. يحتوي كل مستند على الحقول kind وname وtype التي تحدّد نوعه. لقد أعددنا بإيجاز كل ما يلي:
- تحديد قاعدة البيانات المصدر
- تحديد الأدوات ( الأداة 1 والأداة 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 (صحيح) في العمود 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 من حزمة تطوير البرامج (SDK) من Gemini التوجيه من خلال 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!"
وكما هو الحال في الخطوة السابقة، سيؤدي ذلك إلى إنشاء عملية أخرى وإخراج النتائج. لنفتح علامة تبويب جديدة في نافذة Terminal في Cloud Shell (انقر على الرمز +) حتى نتمكّن من التركيز بشكل أكبر.

انتقِل إلى دليل العمل مرة أخرى وفعِّل المشروع باستخدام نص الإعداد البرمجي السابق.
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'
يجب أن يتضمّن الرد وظيفتَي هندسة الخلفية من بياناتك الأولية.
[
{
"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 بخادم Toolbox قيد التشغيل وتختبر جميع الأدوات الأربع: طلبات البحث العادية، والبحث الدلالي، واستيعاب المتجهات. رمز الوكيل بسيط: يتم تخزين جميع منطق قاعدة البيانات في tools.yaml.
ضبط بيئة الوكيل
يقرأ ADK GOOGLE_GENAI_USE_VERTEXAI وGOOGLE_CLOUD_PROJECT وGOOGLE_CLOUD_LOCATION من بيئة shell التي سبق أن ضبطتها في الخطوة السابقة. المتغير الوحيد الخاص بالوكيل هو TOOLBOX_URL، ويجب إلحاقه بملف .env الخاص بالوكيل:
echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env
تعديل وحدة وكيل المستخدم
افتح jobs_agent/agent.py في "محرِّر Cloud Shell".
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 الخاص بخدمة Toolbox على Cloud Run، بدون الحاجة إلى إجراء أي تغييرات في الرمز.
تشير التعليمات حاليًا إلى الأداتَين العاديتَين فقط (search-jobs وget-job-details). ستوسّعها في الخطوة التالية عند إضافة أدوات البحث الدلالي والاستيعاب.
اختبار الوكيل
ابدأ واجهة مستخدم مطوّري ADK:
cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web
افتح عنوان URL المعروض في النافذة الطرفية (عادةً http://localhost:8000) باستخدام ميزة المعاينة على الويب في Cloud Shell أو اضغط على ctrl + النقر على عنوان URL المعروض في النافذة الطرفية. اختَر jobs_agent من القائمة المنسدلة الخاصة بالوكيل في أعلى يمين الصفحة.
اختبار طلبات البحث العادية
جرِّب الطلبات التالية للتحقّق من أدوات SQL العادية:
What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

تجربة البحث الدلالي
جرِّب أوصافًا باللغة الطبيعية لا تتوافق مع دور أو مجموعة تقنيات محدّدة:
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.

اختبار عرض المتّجهات
اطلب من الموظف إضافة وظيفة جديدة:
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.

جرِّب البحث عنه الآن:
Find me jobs involving autonomous systems and working with physical hardware
تم إنشاء التضمين تلقائيًا أثناء عملية INSERT، ولا يلزم اتّخاذ أي خطوة منفصلة.

الآن، لديك تطبيق كامل يعمل بنظام RAG المستند إلى الوكيل ويستخدم ADK وMCP Toolbox وCloudSQL. تهانينا! لننتقل إلى خطوة أخرى لنشر هذه التطبيقات على Cloud Run.
الآن، لنوقف واجهة مستخدم أدوات المطوّرين عن طريق إنهاء العملية من خلال الضغط على Ctrl+C مرّتين قبل المتابعة.
8. النشر على Cloud Run
يعمل كلّ من "الوكيل" و"مجموعة الأدوات" على الجهاز. تؤدي هذه الخطوة إلى نشر كليهما كخدمات Cloud Run حتى يمكن الوصول إليهما عبر الإنترنت. تعمل خدمة Toolbox كخادم MCP على Cloud Run، وتتصل بها خدمة الوكيل.
تحضير "صندوق الأدوات" للنشر
أنشئ دليل نشر لخدمة "أدوات المطوّرين":
cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/
أنشئ ملف Dockerfile لـ Toolbox. افتح deploy-toolbox/Dockerfile في "محرِّر Cloud Shell":
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.
نشر خدمة "مجموعة الأدوات"
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 (انقر على الرمز +) حتى نتمكّن من التركيز بشكل أكبر.

انتقِل إلى دليل العمل مرة أخرى وفعِّل المشروع باستخدام نص الإعداد البرمجي السابق.
cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env
تحضير الوكيل للنشر
أثناء إنشاء "مجموعة الأدوات"، يمكنك إعداد ملفات نشر الوكيل.
أنشئ Dockerfile في جذر المشروع. افتح Dockerfile في "محرِّر Cloud Shell":
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/
نشر خدمة الوكيل
انتظِر إلى أن يكتمل نشر "أدوات Google Play للأعمال". استرداد عنوان 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
بعد ذلك، يجب التحقّق من أنّ "أدوات المطوّرين" المنشورة تعمل بشكل صحيح:
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 الخاص بخدمة "مجموعة الأدوات". ولا يلزم إجراء أي تغييرات على الرموز البرمجية.
اختبار الوكيل الذي تم نشره
استرداد عنوان URL الخاص بالوكيل على Cloud Run:
AGENT_URL=$(gcloud run services describe jobs-agent \
--region=$REGION \
--format='value(status.url)')
echo "Agent URL: $AGENT_URL"
افتح عنوان URL في المتصفّح. يتم تحميل واجهة مستخدم مطوّر ADK، وهي الواجهة نفسها التي كنت تستخدمها محليًا، ولكنها تعمل الآن على 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- تهانينا / حذف البيانات
لقد أنشأت ونشرت مساعدًا ذكيًا للوحات الوظائف يستخدم "مجموعة أدوات MCP لقواعد البيانات" لربط وكيل ADK وCloud SQL PostgreSQL، وذلك باستخدام كلّ من طلبات بحث SQL القياسية والبحث الدلالي عن المتجهات.
ما تعلّمته
- كيفية توحيد MCP لإمكانية الوصول إلى الأدوات من أجل وكلاء الذكاء الاصطناعي، وكيفية تطبيق MCP Toolbox for Databases لذلك على عمليات قواعد البيانات على وجه التحديد، أي استبدال رمز قاعدة البيانات المخصّص بإعداد YAML تعريفي
- كيفية ضبط Cloud SQL PostgreSQL كمصدر بيانات في "أدوات Google" باستخدام نوع المصدر
cloud-sql-postgres - كيفية تحديد أدوات طلب بحث SQL العادية باستخدام عبارات ذات مَعلمات تمنع حقن SQL
- كيفية تفعيل البحث المتّجه باستخدام pgvector و
gemini-embedding-001، مع المَعلمةembeddedByلتضمين طلب البحث تلقائيًا - كيف تتيح أداة
valueFromParamإدخال المتجهات تلقائيًا: يقدّم النموذج اللغوي الكبير وصفًا نصيًا، وتعمل "أدوات Google" على نسخ المتجه وتضمينه وتخزينه بصمت إلى جانب النص - كيفية تحميل
ToolboxToolsetفي "مجموعة أدوات Android" للأدوات من خادم Toolbox قيد التشغيل، مع الحفاظ على الحد الأدنى من رمز الوكيل وفصل منطق قاعدة البيانات بالكامل - كيفية نشر كلّ من خادم MCP الخاص بـ "أداة التحكّم" ووكيل ADK على Cloud Run كخدمات منفصلة
إخلاء مساحة
لتجنُّب تحمّل رسوم في حسابك على Google Cloud مقابل الموارد التي تم إنشاؤها في هذا الدرس العملي، يمكنك إما حذف الموارد الفردية أو حذف المشروع بأكمله.
الخيار 1: حذف المشروع (مقترَح)
أسهل طريقة لتنظيف حسابك هي حذف المشروع. يؤدي هذا الإجراء إلى إزالة جميع الموارد المرتبطة بالمشروع.
gcloud projects delete $GOOGLE_CLOUD_PROJECT
الخيار 2: حذف موارد فردية
إذا كنت تريد الاحتفاظ بالمشروع ولكن إزالة الموارد التي تم إنشاؤها في هذا الدرس العملي فقط، اتّبِع الخطوات التالية:
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
