كيفية استضافة SandBase Harness على خادمك
شغّل SandBase Harness v0.3.2 على VPS تملكه مع تثبيت الإصدار المحدد وملف YAML للوكلاء وخوادم MCP وأنماط العزل وتوجيه Anthropic SDK إلى خادمك.
ما تحصل عليه عند استضافة وقت تشغيل وكيل SandBase بنفسك
تعني استضافة وقت تشغيل وكيل SandBase بنفسك تشغيل SandBase Harness على خادم تملكه، بحيث تبقى الجلسات وبيانات الاعتماد والذاكرة وسجلات التدقيق على قرصك بدلاً من قرص جهة أخرى. وهو خدمة Node. يستمع على 127.0.0.1:3000، ويعرض واجهة HTTP API وفق /v1 ووحدة تحكم ويب، ويحتفظ بحالته في SQLite بجوار ملفات وكيلك.
تأتي واجهة /v1 API وفق بنية Claude Managed Agents (CMA)، وهي واجهة API للوكلاء المُدارين والمستضافة. وهذا ما يجعل وقت التشغيل هذا مهماً في كلا الاتجاهين: يمكنك كتابة التعليمات البرمجية باستخدام Anthropic SDK وتوجيه baseURL فيها إلى خادمك، ثم نقل التعليمات البرمجية نفسها إلى نشر مستضاف لاحقاً.
لا يتضمن SandBase Harness نموذجاً. بل يستدعي نموذجاً. اعتباراً من August 2026، يدعم OpenAI وAnthropic ونقاط النهاية المتوافقة مع OpenAI، ويشمل ذلك البوابات المستضافة ذاتياً وموفّرين مثل DeepSeek V4. وما زلت تحتاج إلى توفير مفتاح API، أو خادم محلي يتحدث OpenAI API.
ما تحتاج إليه قبل البدء
- VPS يعمل بنظام Ubuntu 24.04 وبذاكرة RAM لا تقل عن 2 GB. يُعد بناء TypeScript أثقل خطوة في التثبيت.
- Node.js بإصدار 22 أو أحدث، وnpm بإصدار 10 أو أحدث. هذان شرطان أدنى إلزاميان يحددهما المشروع.
git، بالإضافة إلى مفتاح API لموفر النموذج الذي تنوي استخدامه.- Docker، لكن فقط إذا أردت استخدام حاويات معزولة لكل جلسة.
يأتي Ubuntu 24.04 مع Node 18.19 في مستودعه الخاص، وهذا أقل من الحد الأدنى المطلوب. لذلك ثبّت Node من NodeSource بدلاً من ذلك.
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs git
node -v
npm -vيجب أن يطبع node -v القيمة v22 أو قيمة أعلى، ويجب أن يطبع npm -v القيمة 10 أو قيمة أعلى. إذا كان node -v لا يزال يطبع v18.19.1، فهذا يعني أن حزمة التوزيعة لا تزال مثبتة وتظهر أولاً في PATH. أزلها قبل المتابعة، لأن عملية البناء تستخدم إصدار node الذي يعثر عليه shell.
تثبيت SandBase من الوسم v0.3.2
ثبّت البرنامج من وسم محدد، وليس من فرع متغير. يمنحك الاستنساخ المجرد من main آخر ما أُضيف قبل ساعة، وقد لا تتطابق مفاتيح الإعداد أدناه معه. الإصدار v0.3.2 هو الوسم الحالي في 16 August 2026.
sudo install -d -o "$USER" -g "$USER" /opt/sandbase
cd /opt/sandbase
git clone --branch v0.3.2 --depth 1 https://github.com/sandbaseai/sandbase-harness.git
cd sandbase-harness
npm ci
npm run buildاستخدم npm ci، وليس npm install. يثبّت ci الإصدارات المحددة بدقة في ملف القفل الملتزم به، ولذلك تطابق شجرة العمل الشجرة التي اختبرها المشرفون على المشروع. أما npm install فيُسمح له بحل إصدارات أحدث، وهذا ما يجعل الوسم المثبت يتوقف بهدوء عن كونه مثبتاً.
أنشئ الآن مساحة عمل. مساحة العمل دليل منفصل يحتفظ بملفات الوكيل وكل حالة التشغيل. ويتيح إبقاؤها خارج نسخة المصدر سحب وسم أحدث دون المساس ببياناتك.
mkdir -p /opt/sandbase/workspace
cd /opt/sandbase/workspace
node /opt/sandbase/sandbase-harness/dist/index.js init
node /opt/sandbase/sandbase-harness/dist/index.js startيكتب init دليلاً باسم .managed-agents/ داخل مساحة العمل. يشغّل start وحدة التحكم على http://127.0.0.1:3000/dashboard وواجهة API على http://127.0.0.1:3000/v1. لا يمكن الوصول إلى أي منهما من حاسوبك المحمول بعد، وهذا صحيح وسنغطيه لاحقاً. استخدم SSH للوصول إلى وحدة التحكم في الوقت الحالي:
ssh -N -L 3000:127.0.0.1:3000 you@your-serverسيصبح مسار node .../dist/index.js الطويل مرهقاً، لذا امنحه اسماً.
alias sandbase='node /opt/sandbase/sandbase-harness/dist/index.js'الأوامر أدناه مكتوبة بصيغة sandbase <command> على هذا الأساس.
لا تثبّته من npm
يذكر المشروع ذلك في وثائق التثبيت الخاصة به: حزمة managed-agents غير المقيّدة بالنطاق الظاهرة على npm ليست هذه المشروع. لذلك يجلب npx managed-agents وnpm install -g managed-agents شيئاً لا علاقة له ببيئة التشغيل المطلوبة. ثبّت المشروع من مصدر GitHub ذي الوسم حتى يعلن المشرفون عن حزمة رسمية ذات نطاق. هذه ليست ملاحظة هامشية في تاريخ المشروع؛ إذ أُصدر v0.3.1 أساساً لاستبدال البدء السريع القديم من npm بمسار المصدر ذي الوسم المثبّت.
وجّه مساحة العمل إلى موفّر نماذج
init يكتب .managed-agents/config.yaml. يُضبط موفّر واحد لمساحة العمل بأكملها، ثم يختار كل وكيل معرّفات النماذج الفعلية.
model:
provider: openai
api_key: ${OPENAI_API_KEY}
storage:
metadata:
provider: sqlite
options: {}
artifacts:
provider: local
options:
base_path: filesيأخذ نموذج ${OPENAI_API_KEY} القيمة من بيئة العملية، لذلك يبقى المفتاح خارج ملف الإعداد وخارج كل نسخة احتياطية تنشئها لهذا الملف. ضعه في ملف بيئة لا يستطيع قراءته إلا root، لأن systemd يقرأ EnvironmentFile= بصلاحيات root قبل خفض الامتيازات.
sudo install -d -m 750 /etc/sandbase
sudo touch /etc/sandbase/runtime.env
sudo chmod 600 /etc/sandbase/runtime.envافتح ذلك الملف في محرّر وأضف سطراً واحداً، OPENAI_API_KEY=sk-.... توضع مفاتيح الموفّرات هنا. أما الأسرار التي يستخدمها وكيل أثناء جلسة، فتنتمي إلى خزائن بيانات الاعتماد الخاصة ببيئة التشغيل، وهي مشكلة مختلفة ذات نطاق تأثير مختلف. ويستحق إبقاء الأسرار خارج وكلاء الذكاء الاصطناعي القراءة قبل لصق رمز مميّز للإنتاج في أيٍّ من المكانين.
ملف YAML الخاص بالوكيل: mcp_servers والأدوات وسياسات الأذونات
تُعرَّف الوكلاء في ملفات YAML ضمن دليل مساحة العمل agents/. هذا هو الجزء من بيئة التشغيل الذي ستقضي فيه معظم وقتك فعلياً.
name: Incident commander
description: Triages alerts and coordinates response.
model: gpt-4o
system: |-
You are an on-call incident commander.
mcp_servers:
- name: sentry
type: url
url: https://mcp.sentry.dev/mcp
tools:
- type: agent_toolset_20260401
default_config:
permission_policy: { type: always_ask }
configs:
- name: bash
permission_policy: { type: always_ask }
- type: mcp_toolset
mcp_server_name: sentry
metadata:
template: incident-commanderحمّله وتحقق من استيراده:
sandbase reload
sandbase list
sandbase chat agent_assistant --message "hello"يستورد reload ملف YAML الأساسي إلى SQLite. يجب أن يعرض list الوكيل الآن مع معرّف. إذا لم يعرضه list، فهذا يعني أن الملف لم يُحلَّل، وستجد سبب ذلك في .managed-agents/logs/runtime.log.
يعرّف mcp_servers نقاط نهاية MCP (بروتوكول سياق النموذج). يعني type: url أن بيئة التشغيل تتصل عبر HTTP بخادم يعمل في مكان آخر، لذلك يمكنك استخدام أي خادم تديره مسبقاً، بما في ذلك خوادم MCP المستضافة على VPS نفسه الذي تعمل عليه بيئة التشغيل.
لا يؤدي تعريف خادم إلى إتاحة أدواته للوكيل. تنفّذ قائمة tools ذلك من خلال إدخال mcp_toolset، الذي يجب أن تطابق قيمة mcp_server_name فيه قيمة name المعرّفة أعلاه. إذا تصرّف الوكيل كما لو أن أدوات MCP غير موجودة، فقارن السلسلتين حرفاً بحرف قبل أن تبحث في أي مكان آخر.
agent_toolset_20260401 هي مجموعة الأدوات المضمّنة. اللاحقة التي تتضمن التاريخ هي إصدار المخطط، لذلك يحتفظ الوكيل المثبّت عليها بتعريفات الأدوات التي كُتب من أجلها. تحدد default_config السياسة المطبقة على كل أداة في المجموعة، بينما يستبدل كل إدخال ضمن configs هذه السياسة لأداة واحدة بالاسم، وهي bash في المثال.
permission_policy هو الجزء الذي يمنح بيئة التشغيل قيمة تتجاوز استدعاء نموذج مجرد. توقف always_ask الجلسة مؤقتاً وتنتظر موافقة بشرية على الاستدعاء قبل تشغيله. تسمح always_allow بمروره. يعني ضبط bash على always_ask أن الوكيل لا يستطيع تنفيذ أمر shell من دون أن ترى الأمر الدقيق أولاً، وهو الإجراء نفسه الذي ستستخدمه عند تشغيل Claude Code بأمان على VPS.
أنماط sandbox الثلاثة، ومتى يناسب كل منها
تعمل استدعاءات الأدوات التي تنفّذ التعليمات البرمجية داخل sandbox. ويُحدَّد backend لكل بيئة عبر sandbox_provider في كائن config الخاص بالبيئة، أو من Settings ثم Sandbox في وحدة التحكم. تُنشأ البيئات عبر API على POST /v1/environments.
local ينفّذ التعليمات البرمجية كعملية فرعية من runtime، على المضيف، وباسم مستخدم runtime نفسه. وهو الوضع الافتراضي، ويكون مناسباً عندما تكون المستخدم الوحيد وعندما يقرأ agent الملفات التي تملكينها فقط. لكنه لا يوفر عزلاً. فإذا حذف استدعاء أداة ملفات، فسيحذف ملفاتك، وإذا قرأ استدعاء أداة /etc/sandbase/runtime.env، فسيقرأ مفتاح provider الخاص بك.
docker يشغّل حاوية واحدة لكل جلسة.
{
"sandbox_provider": "docker",
"image": "node:22-slim",
"resources": { "memory": "1g", "cpu": 1 }
}تحصل الجلسة على نظام ملفات خاص بها، وحد أقصى خاص بالذاكرة، وحصة خاصة بها من CPU، وتُزال الحاوية مع انتهاء الجلسة. انتقلي إلى هذا الوضع فوراً عندما ينفّذ agent تعليمة برمجية لم تكتبيها. وتتمثل الكلفة في أن مستخدم runtime يحتاج إلى الوصول إلى Docker socket، وأن العضوية في مجموعة docker تعادل امتلاك صلاحيات root على المضيف. حاويات كل جلسة لها البنية نفسها التي تتمتع بها بيئات sandbox ذاتية الاستضافة لـagent مع حاوية واحدة لكل تشغيل، ولذلك ينطبق هنا كما هو النقاش المتعلق بما يمكن لعملية أفلتت من العزل أن تصل إليه.
kubernetes يشغّل حمل الجلسة على هيئة pod ويديره باستخدام kubectl exec وkubectl cp. يجب أن تتضمن صورة runtime مكوّن kubectl، كما يجب أن يمتلك ServiceAccount الخاص بها صلاحيات RBAC (التحكم في الوصول المستند إلى الأدوار) لإنشاء pods وحذفها والحصول عليها وسردها ومراقبتها في namespace المستهدف، إضافة إلى مورد exec الفرعي. لا يستحق هذا الوضع عناء الإعداد إلا إذا كنت تشغّلين cluster بالفعل.
لماذا يستمع runtime على 127.0.0.1؟
لأنّه يبدأ تشغيله مع تعطيل المصادقة. يفعّل runtime المصادقة باستخدام bearer token عند وجود مفتاح API واحد على الأقل، ولا ينشئ runtime جديد من init أي مفاتيح. كان ربطه بـ 0.0.0.0 بهذه الإعدادات الافتراضية سيعرّض runtime غير موثَّق لوكيل يملك أدوات shell ومفتاح مزوّد الخدمة للإنترنت العام.
لذلك، عندما تريد إتاحة الوصول إليه، اترك عنوان الربط كما هو ونفّذ أمرين آخرين.
أولاً، فعّل المصادقة. اضبط MANAGED_AGENTS_API_KEY في ملف بيئة الخدمة، أو أنشئ مفتاحاً باستخدام POST /v1/api-keys، حيث يعرض الحقل secret_key مرة واحدة ولا يعرضه مجدداً. بعد ذلك، يرسل العملاء Authorization: Bearer <key> مع كل طلب.
ثانياً، ضع reverse proxy أمامه وأنهِ TLS (أمن طبقة النقل) هناك. يقدّم runtime HTTP عاديّاً حسب التصميم، ويتوقع أن تتولى جهة أخرى معالجة الشهادات.
server {
listen 443 ssl;
server_name agents.example.com;
ssl_certificate /etc/letsencrypt/live/agents.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/agents.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
}
}سطران من هذه الأسطر ليسا للزينة. يهم proxy_buffering off لأن الجلسات تُبث عبر server-sent events (SSE)، وعند تفعيل التخزين المؤقت يحتفظ nginx بالاستجابة حتى تمتلئ ذاكرته المؤقتة. لذلك لا تعرض وحدة التحكم شيئاً أثناء عمل الوكيل، ثم تعرض كل شيء دفعة واحدة في النهاية. ويهم proxy_read_timeout 3600s لأن القيمة الافتراضية هي 60 ثانية. لذلك يغلق proxy البث إذا ظل خاملاً لأكثر من دقيقة، في منتصف الجولة، ويبدو الفشل كما لو أنّ runtime قد تعطل.
في إعدادات جدار الحماية، افتح المنفذين 22 و443. اترك المنفذ 3000 مغلقاً، لأن proxy يصل إليه عبر loopback، ولا ينبغي لأي جهة خارج الخادم الوصول إليه.
وجّه Anthropic SDK إلى خادمك الخاص
يطبّق وقت التشغيل واجهة /v1 متوافقة مع CMA، لذلك يتصل به عميل Anthropic SDK بعد تغيير حقل واحد.
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: process.env.MANAGED_AGENTS_API_KEY ?? 'local-dev-key',
baseURL: 'http://127.0.0.1:3000'
});كما يقبل رؤوس beta التي ترسلها عملاء Claude Managed Agents، anthropic-beta: managed-agents-2026-04-01 وanthropic-beta: agent-memory-2026-07-22. وهي اختيارية عند استخدام وقت تشغيل محلي. وُجدت هذه الرؤوس لكي يعمل هنا دون تغيير الكود المكتوب لنشر مستضاف.
التوافق قريب، لكنه ليس كاملاً. اقرأ docs/api-matrix.md في نسخة checkout قبل افتراض توفر واجهة معينة، لأن المشروع يوثّق فجواته هناك، ومنها الأدوات المخصصة من جهة العميل، التي لا تزال تحتاج إلى تسجيل مسمّى فوق بروتوكول نتائج الأحداث الحالي.
يعمل HTTP العادي بالطريقة نفسها، وهو أسرع وسيلة لإثبات أن وقت التشغيل يعمل:
curl -N -X POST http://127.0.0.1:3000/v1/sessions/SESSION_ID/messages \
-H "Content-Type: application/json" \
-d '{"content": "Hello", "stream": true}'الاستجابة السليمة هي تدفق من الأحداث يستمر في الوصول. إذا انقطع الاتصال، فاستأنف من آخر حدث رأيته بدلاً من إعادة تنفيذ الدورة كاملة:
curl -N http://127.0.0.1:3000/v1/sessions/SESSION_ID/events/stream \
-H "Last-Event-ID: EVENT_ID"هذا التدفق القابل للاستئناف هو سبب استمرار الجلسة بعد إغلاق الحاسوب المحمول. تُحفظ الأحداث على الخادم، لذلك يعيد العميل تشغيل سجل بدلاً من الاحتفاظ بالنسخة الوحيدة منه.
مكان بيانات الاعتماد والذاكرة وسجلات التدقيق على القرص
توجد كل البيانات التي يديرها وقت التشغيل ضمن .managed-agents/ في مساحة العمل.
.managed-agents/
├── config.yaml
├── data.db
├── logs/runtime.log
├── files/
├── skills/
├── snapshots/
└── sandbox/- يحتوي
data.dbعلى بيانات SQLite الوصفية: الوكلاء والجلسات وإدخالات مخزن بيانات الاعتماد وإدخالات مخزن الذاكرة ومفاتيح API. - يحتوي
files/على بايتات الملفات المرفوعة، بينما يحتويskills/على حزم المهارات المرفوعة. - يحتوي
snapshots/على لقطات مساحة عمل الجلسات، بينما يحتويsandbox/على أدلة العمل الخاصة بجلسات الوضع المحلي. - يُعد
logs/runtime.logأول مكان يجب فحصه عندما لا يحدث شيء بصمت.
تتكون خزائن بيانات الاعتماد من مجموعات من الأسرار، وتُضاف كل مجموعة باستخدام auth_type مثل environment_variable، ثم تُربط بجلسة عبر vault_ids عند إنشاء الجلسة. تحتوي مخازن الذاكرة على إدخالات مسماة، وتثبّتها في جلسة بصفتها memory_store مع إعداد وصول وتعليمات خاصين بها. توجد الخزائن والمخازن معاً في data.db. وهذا هو الفرق تحديداً بين هذا الأسلوب واستدعاء نموذج خام: يتذكر وقت التشغيل المعلومات عبر الجلسات، ويسجل ما حدث.
بما أنها موجودة في دليل واحد، فانسخها احتياطياً كوحدة واحدة.
sudo systemctl stop sandbase
sudo tar czf /root/sandbase-$(date +%F).tgz -C /opt/sandbase/workspace .managed-agents
sudo systemctl start sandbaseأوقف الخدمة أولاً. قد يؤدي نسخ قاعدة بيانات SQLite أثناء كتابة وقت التشغيل فيها إلى التقاط ملف لن يفتح عند الاستعادة، وقد تكتشف ذلك في اليوم الذي تحتاج فيه إلى النسخة الاحتياطية. إذا كنت تفضّل الاحتفاظ بملفات YAML الخاصة بالوكلاء في git وحالة التشغيل في مكان آخر، فتوثيق النشر يدعم تثبيت موقع الحالة باستخدام --data-dir على start.
تتم الاستعادة بالعكس: اسحب العلامة نفسها إلى خادم جديد، وفك الأرشيف داخل مساحة العمل، ثم شغّل الخدمة. لن يكون مفتاح المزوّد موجوداً في الأرشيف إذا استخدمت صيغة ${OPENAI_API_KEY}، لذلك احتفظ به في مكان ستتمكن من الوصول إليه لاحقاً.
شغِّله عبر systemd
أنشئ مستخدماً مخصصاً لبيئة التشغيل، حتى لا يتمكن استدعاء أداة في وضع sandbox المحلي من التصرف بصلاحياتك.
sudo adduser --system --group --no-create-home --home /opt/sandbase sandbase
sudo chown -R sandbase:sandbase /opt/sandbaseاحفظ هذا باسم /etc/systemd/system/sandbase.service.
[Unit]
Description=SandBase Harness runtime
After=network-online.target
[Service]
User=sandbase
Group=sandbase
WorkingDirectory=/opt/sandbase/workspace
EnvironmentFile=/etc/sandbase/runtime.env
ExecStart=/usr/bin/node /opt/sandbase/sandbase-harness/dist/index.js start --host 127.0.0.1 --port 3000
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetيستدعي مثال النشر الخاص بالمشروع ملفاً تنفيذياً باسم managed-agents من المسار PATH. لا ينشئ التثبيت من المصدر ذي الوسم هذا الملف، لذلك يشغّل ExecStart الأمر node على نقطة الدخول التي جرى بناؤها بدلاً منه.
sudo systemctl daemon-reload
sudo systemctl enable --now sandbase
sudo systemctl status sandbase
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/dashboardالنتيجة السليمة هي active (running) من status و200 من curl. عند ظهور أي نتيجة أخرى، اقرأ journalctl -u sandbase -n 50 أولاً ثم .managed-agents/logs/runtime.log. يمثل enable --now الجزء المهم، لأن العملية التي تبدأها يدوياً تتوقف بعد إعادة التشغيل التالية.
ما الذي يتعطل، والرسالة التي ستظهر لك
npm run build يُنهى دون ظهور خطأ من npm. في VPS بسعة 1 GB، يوقف قاتل نفاد الذاكرة في النواة عملية ترجمة TypeScript. ويسجل النواة هذا الحدث بدلاً من npm. أكّد ذلك باستخدام journalctl -k | grep -i "out of memory"، الذي يطبع سطراً يذكر عملية node التي أُنهيت. أضف swap، أو نفّذ عملية البناء على instance أكبر وانسخ dist/ إليها.
Error: listen EADDRINUSE: address already in use 127.0.0.1:3000. توجد عملية أخرى تستخدم المنفذ مسبقاً. يحدد sudo ss -lntp | grep 3000 هذه العملية. أوقفها، أو شغّل runtime باستخدام --port 3001 وحدّث الـproxy.
لن تُحمّل لوحة المعلومات من حاسوبك المحمول. هذا هو السلوك المقصود، لأن runtime يستمع على loopback. استخدم نفق SSH أعلاه، أو أكمل إعداد الـreverse proxy. لا تعالج المشكلة باستخدام --host 0.0.0.0، لأن المصادقة متوقفة حتى يوجد مفتاح.
تفشل بيئات Docker المعزولة باستخدام permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock. المستخدم sandbase ليس عضواً في المجموعة docker. أصلح ذلك باستخدام sudo usermod -aG docker sandbase ثم أعد تشغيل الخدمة. انتبه إلى الصلاحية التي منحتها: هذه المجموعة تعادل root على المضيف، ولذلك تلغي جزءاً من سبب منح runtime حساب مستخدم خاصاً به.
تفشل بيئات Kubernetes المعزولة باستخدام Error from server (Forbidden). يفتقد ServiceAccount صلاحيات pod أو المورد الفرعي exec. تحقّق من ذلك مباشرة باستخدام kubectl auth can-i create pods/exec -n <namespace>، الذي يعيد yes أو no.
يعيد كل طلب الحالة 401 بعد إضافة API key. تُفعّل المصادقة عند وجود أول مفتاح، وتُطبَّق على console وعلى API أيضاً. أرسل Authorization: Bearer <key>. وإذا فقدت المفتاح، فأنشئ مفتاحاً آخر، لأن secret_key يُعاد مرة واحدة ولا يُخزَّن بصيغة يمكن قراءتها.
لا تظهر أدوات خادم MCP في جلسة. تحقّق من mcp_server_name في كتلة tools وقارنه بـname في mcp_servers. ثم تحقّق من قدرة runtime على الوصول إلى URL من الخادم نفسه باستخدام curl -i <url>. خادم MCP من نوع URL هو اعتماد على الشبكة، ويحل VPS أسماء النطاقات ويوجّه حركة الشبكة بطريقة تختلف عن حاسوبك المحمول.
FAQ
هل يمكنني تشغيل SandBase Harness من دون مفتاح OpenAI أو Anthropic؟
نعم، إذا كان لديك endpoint متوافق مع OpenAI. يدعم runtime موفّري OpenAI وAnthropic والموفّرين المتوافقين مع OpenAI، لذلك يعمل خادم محلي يتحدث عبر OpenAI API. اضبط موفّر مساحة العمل في .managed-agents/config.yaml، ووجّه api_key وendpoint إليه. لا يتضمن runtime نموذجاً خاصاً به، لذلك يجب أن يستجيب شيء ما لهذه الاستدعاءات.
هل من الآمن إتاحة runtime على منفذ عام؟
ليس بالإعداد المثبّت. فهو يستمع على 127.0.0.1:3000 ويبدأ مع تعطيل المصادقة، والحل ليس استخدام عنوان استماع مختلف. أنشئ مفتاح API أو اضبط MANAGED_AGENTS_API_KEY لتفعيل مصادقة bearer token. ثم ضع nginx أو Caddy أمامه لتوفير TLS، وأبقِ المنفذ 3000 مغلقاً في جدار الحماية بحيث يمر المسار الوحيد عبر الـproxy.
ما الفرق بين بيئات العزل المحلية وDocker وKubernetes؟
يشغّل local تعليمات الأدوات كعملية فرعية لـruntime على المضيف، باستخدام صلاحيات مستخدم runtime ومن دون عزل. ينشئ docker حاوية خاصة لكل جلسة، مع نظام ملفات خاص بها وحد للذاكرة وحصة من CPU، ثم يحذفها عند انتهاء الجلسة. يشغّل kubernetes الجلسة كـpod ويديرها باستخدام kubectl exec، الذي يحتاج إلى kubectl داخل صورة runtime، وإلى RBAC على pods، إضافة إلى مورد exec الفرعي في namespace المستهدف.
ما الذي أحتاج إلى نسخه احتياطياً بالتحديد؟
دليل .managed-agents/ داخل مساحة العمل. يحتوي على config.yaml، وقاعدة بيانات SQLite في data.db التي تضم الوكلاء والجلسات وإدخالات مخزن بيانات الاعتماد وإدخالات الذاكرة، إضافة إلى الملفات المرفوعة وحزم المهارات ولقطات الجلسات. أوقف الخدمة قبل نسخه حتى لا تُكتب بيانات SQLite أثناء إنشاء الأرشيف. مفاتيح API الخاصة بالموفّرين المشار إليها باسم ${OPENAI_API_KEY} ليست داخل النسخة الاحتياطية، لذلك خزّنها بشكل منفصل.
لماذا أستنسخ الوسم v0.3.2 بدلاً من main؟
الوسم يمثل شجرة ثابتة، لذلك تكون مفاتيح الإعداد وأوامر CLI التي تقرأ عنها هي نفسها التي ستحصل عليها فعلياً. يتغير main، وقد يُعاد تسمية مفتاح إعداد بين وقت كتابة الدليل ووقت تشغيلك له. ويحذّر المشروع أيضاً من أن حزمة managed-agents غير المحددة النطاق على npm ليست هذا المشروع، لذلك يثبّت npx managed-agents شيئاً غير مرتبط به. يوجد الإصدار v0.3.1 أساساً لاستبدال البدء السريع عبر npm بمسار المصدر المعلَّم والمثبت.