SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-28

SandBase agent runtime নিজে হোস্ট করার নিয়ম

আপনার নিজস্ব VPS-এ SandBase Harness v0.3.2 সেটআপ করার পূর্ণাঙ্গ নির্দেশিকা। এতে ট্যাগড ইনস্টল, এজেন্ট YAML কনফিগারেশন, MCP সার্ভার এবং Anthropic SDK কানেকশনের বিস্তারিত ধাপ রয়েছে।

SandBase agent runtime নিজে হোস্ট করলে আপনি যা পাবেন

SandBase agent runtime নিজে হোস্ট করার অর্থ হলো আপনার নিজস্ব সার্ভারে SandBase Harness চালানো। এর ফলে সেশন, ক্রেডেনশিয়াল, মেমোরি এবং অডিট ট্রেইল অন্য কারো সার্ভারের পরিবর্তে আপনার নিজের ডিস্কে সংরক্ষিত থাকে। এটি একটি Node সার্ভিস। এটি 127.0.0.1:3000 পোর্টে লিসেন করে, একটি /v1 HTTP API এবং ওয়েব কনসোল পরিবেশন করে এবং আপনার এজেন্ট ফাইলের পাশাপাশি SQLite-এ এর স্টেট বা অবস্থা বজায় রাখে।

/v1 API-টি Claude Managed Agents (CMA)-এর আদলে তৈরি, যা একটি হোস্ট করা ম্যানেজড-এজেন্ট API। এই কারণেই এই রানটাইমটি উভয় ক্ষেত্রেই কার্যকর: আপনি Anthropic SDK ব্যবহার করে কোড লিখতে পারেন এবং এর baseURL আপনার নিজস্ব সার্ভারের দিকে নির্দেশ করতে পারেন, পরবর্তীতে একই কোড কোনো হোস্ট করা ডিপ্লয়মেন্টে স্থানান্তর করা সম্ভব।

SandBase Harness কোনো মডেল সরবরাহ করে না। এটি মডেল কল করে। 2026 সালের আগস্ট মাস পর্যন্ত এটি OpenAI, Anthropic এবং OpenAI-এর সাথে সামঞ্জস্যপূর্ণ এন্ডপয়েন্ট সমর্থন করে, যার মধ্যে সেলফ-হোস্টেড গেটওয়ে এবং DeepSeek V4-এর মতো প্রোভাইডার অন্তর্ভুক্ত রয়েছে। আপনাকে নিজস্ব API কি (key) ব্যবহার করতে হবে অথবা এমন একটি লোকাল সার্ভার থাকতে হবে যা OpenAI API সমর্থন করে।

শুরু করার আগে আপনার যা প্রয়োজন

  • অন্তত 2 GB RAM সহ Ubuntu 24.04 চালিত একটি VPS। TypeScript build হলো ইনস্টলেশনের সবচেয়ে ভারী ধাপ।
  • Node.js 22 বা তার নতুন সংস্করণ এবং npm 10 বা তার নতুন সংস্করণ। প্রজেক্টের নিয়ম অনুযায়ী এই দুটিই সর্বনিম্ন প্রয়োজনীয় সংস্করণ।
  • git, এবং আপনি যে মডেল প্রোভাইডার ব্যবহার করতে চান তার একটি API key।
  • Docker, তবে এটি শুধুমাত্র তখনই প্রয়োজন যদি আপনি প্রতি সেশনের জন্য আলাদা container sandbox ব্যবহার করতে চান।

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-এ সেটিই প্রাধান্য পাচ্ছে। পরবর্তী ধাপে যাওয়ার আগে এটি মুছে ফেলুন, কারণ build প্রক্রিয়াটি শেল যে node খুঁজে পাবে তার ওপর ভিত্তি করেই চলবে।

v0.3.2 ট্যাগ থেকে SandBase ইনস্টল করা

সবসময় একটি নির্দিষ্ট ট্যাগ থেকে ইনস্টল করুন, কোনো পরিবর্তনশীল ব্রাঞ্চ থেকে নয়। main ব্যবহার করে বেয়ার ক্লোন করলে আপনি সর্বশেষ আপডেটগুলো পাবেন, যা কনফিগারেশন কি-এর সাথে সামঞ্জস্যপূর্ণ নাও হতে পারে। 16 আগস্ট 2026 অনুযায়ী v0.3.2 হলো বর্তমান ট্যাগ।

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 install এর পরিবর্তে npm ci ব্যবহার করুন। 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 এ কনসোল এবং http://127.0.0.1:3000/v1 এ API চালু করে। এই মুহূর্তে আপনার ল্যাপটপ থেকে এগুলোর কোনোটিই অ্যাক্সেসযোগ্য নয়, যা স্বাভাবিক এবং পরবর্তীতে বিস্তারিত আলোচনা করা হয়েছে। আপাতত 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 থেকে এটি ইনস্টল করবেন না

প্রকল্পটি তাদের নিজস্ব ইনস্টলেশন নথিতে এটি স্পষ্টভাবে উল্লেখ করেছে: npm-এ দৃশ্যমান unscoped managed-agents প্যাকেজটি এই প্রকল্পের নয়। তাই npx managed-agents এবং npm install -g managed-agents কমান্ডগুলো আপনার কাঙ্ক্ষিত runtime-এর সাথে সম্পর্কহীন কিছু ডাউনলোড করবে। রক্ষণাবেক্ষণকারীরা আনুষ্ঠানিকভাবে কোনো scoped প্যাকেজ ঘোষণা না করা পর্যন্ত GitHub-এর tagged source থেকে এটি ইনস্টল করুন। প্রকল্পের ইতিহাসে এটি কোনো ছোটখাটো বিষয় নয়: v0.3.1 সংস্করণটি মূলত পুরনো npm quick start পদ্ধতিকে সরিয়ে pinned tagged-source পাথ ব্যবহারের জন্য আনা হয়েছে।

মডেল প্রোভাইডারের দিকে ওয়ার্কস্পেস নির্দেশ করুন

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} ফর্মটি প্রসেস এনভায়রনমেন্ট থেকে মান গ্রহণ করে, তাই কি (key) কনফিগারেশন ফাইলের বাইরে থাকে এবং ফাইলের কোনো ব্যাকআপেও তা অন্তর্ভুক্ত হয় না। এটি এমন একটি এনভায়রনমেন্ট ফাইলে রাখুন যা শুধুমাত্র root পড়তে পারে, কারণ systemd প্রিভিলেজ কমানোর আগেই root হিসেবে EnvironmentFile= পড়ে নেয়।

sudo install -d -m 750 /etc/sandbase
sudo touch /etc/sandbase/runtime.env
sudo chmod 600 /etc/sandbase/runtime.env

ফাইলটি একটি এডিটরে খুলুন এবং OPENAI_API_KEY=sk-... লাইনটি যোগ করুন। প্রোভাইডার কি (key) এখানেই থাকা উচিত। সেশন চলাকালীন কোনো এজেন্ট যে সিক্রেটগুলো ব্যবহার করে, সেগুলো বরং রানটাইমের ক্রেডেনশিয়াল ভল্টে রাখা উচিত। এটি একটি ভিন্ন সমস্যা যার প্রভাবের পরিধিও ভিন্ন, এবং কোনো প্রোডাকশন টোকেন কোথাও পেস্ট করার আগে AI এজেন্ট থেকে সিক্রেট দূরে রাখা বিষয়টি পড়ে নেওয়া জরুরি।

এজেন্ট YAML: mcp_servers, tools এবং permission policies

এজেন্টগুলোকে ওয়ার্কস্পেসের agents/ ডিরেক্টরিতে YAML ফাইল হিসেবে সংজ্ঞায়িত করা হয়। রানটাইমের এই অংশটিতেই আপনি মূলত কাজ করবেন। আপনি যখন নিজে হাতে একটি ছোট এজেন্ট লুপ লিখবেন, তখন এই কি (keys) গুলো আরও পরিষ্কারভাবে বুঝতে পারবেন। কারণ, প্রতিটি কি এমন একটি নিয়ন্ত্রক হিসেবে কাজ করে যা আপনাকে অন্যথায় কোড করতে হতো: যেমন সিস্টেম প্রম্পট, টুলের তালিকা এবং টুল চালানোর আগে যে চেকটি সম্পন্ন হয়।

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 সিড (seed) YAML ফাইলটিকে SQLite-এ ইমপোর্ট করে। list কমান্ডটি এখন এজেন্টটিকে একটি ID সহ প্রদর্শন করবে। যদি list-এ এটি দেখা না যায়, তবে ফাইলটি পার্স করা হয়নি এবং .managed-agents/logs/runtime.log ফাইলে এর কারণ লেখা থাকবে।

mcp_servers MCP (model context protocol) endpoint ঘোষণা করে। type: url-এর অর্থ হলো runtime অন্য কোথাও চলমান একটি server-এর সঙ্গে HTTP ব্যবহার করে যোগাযোগ করে। তাই আপনি আগে থেকেই পরিচালনা করেন এমন যেকোনো কিছু এখানে ব্যবহার করা যায়, যার মধ্যে runtime-এর মতো একই VPS-এ hosted MCP server-ও রয়েছে। Web search সাধারণত মানুষ প্রথমে যে tool ব্যবহার করে। তবে এটি সংযুক্ত করার আগে নিজের SearXNG instance-এ agent-কে প্রবেশাধিকার দেওয়ার বিষয়টি পড়ে নেওয়া উপকারী। কারণ অপরিচিত ব্যক্তিদের লেখা page ফেরত দেওয়া একটি tool untrusted text সরাসরি model-এর context-এ ঢুকিয়ে দেয়। শুরুতে আরও নিরাপদ পদ্ধতি হলো এর বিপরীত ধরনের একটি read-only endpoint ব্যবহার করা, যা আপনার মালিকানাধীন data-এর ওপর কাজ করে। openGym workout tracker-এর পাশেই এমন endpoint প্রকাশ করে। ফলে agent আপনার training history সম্পর্কে প্রশ্নের উত্তর দিতে পারে, কিন্তু সেই data-এর কোনো অংশ rewrite করতে পারে না।

একটি সার্ভার ঘোষণা করলেই তার টুলগুলো এজেন্টের কাছে চলে যায় না। tools তালিকাটি তা সম্পন্ন করে, যেখানে একটি mcp_toolset এন্ট্রির mcp_server_name অংশটি উপরের name-এর সাথে মিলতে হয়। যদি এজেন্ট এমন আচরণ করে যেন MCP টুলগুলো নেই, তবে অন্য কোথাও খোঁজার আগে এই দুটি স্ট্রিং অক্ষর অনুযায়ী মিলিয়ে দেখুন।

agent_toolset_20260401 হলো বিল্ট-ইন টুল সেট। তারিখযুক্ত সাফিক্সটি হলো স্কিমা ভার্সন, তাই কোনো এজেন্ট যদি এর সাথে পিন করা থাকে, তবে সেটি সেই টুল ডেফিনিশনগুলোই বজায় রাখে যা দিয়ে এটি লেখা হয়েছিল। default_config এই সেটের প্রতিটি টুলের জন্য পলিসি নির্ধারণ করে এবং configs-এর অধীনে প্রতিটি এন্ট্রি নাম অনুযায়ী একটি টুলকে ওভাররাইড করে, যেমন উদাহরণে bash করা হয়েছে।

permission_policy হলো সেই জায়গা যেখানে একটি রানটাইম সাধারণ মডেল কলের চেয়ে বেশি কার্যকর হয়ে ওঠে। always_ask সেশনটিকে থামিয়ে দেয় এবং টুলটি চালানোর আগে মানুষের অনুমোদনের জন্য অপেক্ষা করে। always_allow এটিকে অনুমতি দেয়। bash-কে always_ask হিসেবে সেট করার মানে হলো, আপনি সরাসরি না দেখে এজেন্ট কোনো শেল কমান্ড চালাতে পারবে না। এটি সেই একই নিয়ন্ত্রণ ব্যবস্থা যা আপনি নিরাপদে VPS-এ Claude Code চালানোর সময় ব্যবহার করবেন। আপনি যদি DeepSeek Harness ব্যবহার করেন, তবে একই নিয়ন্ত্রণ ব্যবস্থা সেখানে YAML কি-এর পরিবর্তে অ্যাড-অন হিসেবে আসে এবং বাজেট সীমাবদ্ধকারী ও টুল কল নিয়ন্ত্রণকারী প্লাগিনগুলো এই ব্লকের সবচেয়ে কাছাকাছি বিকল্প।

তিনটি স্যান্ডবক্স মোড এবং কোনটি কখন ব্যবহার করবেন

কোড এক্সিকিউট করে এমন টুল কলগুলো একটি স্যান্ডবক্সের ভেতরে চলে। এনভায়রনমেন্টের config অবজেক্টের ভেতরে sandbox_provider-এর মাধ্যমে অথবা কনসোলের Settings থেকে Sandbox-এ গিয়ে ব্যাকএন্ড নির্বাচন করা হয়। POST /v1/environments-এ API-এর মাধ্যমে এনভায়রনমেন্ট তৈরি করা হয়।

local মোড কোডটিকে রানটাইমের একটি চাইল্ড প্রসেস হিসেবে হোস্ট মেশিনে, রানটাইমের নিজস্ব ব্যবহারকারীর অধীনে চালায়। এটি ডিফল্ট মোড এবং আপনি যখন একমাত্র ব্যবহারকারী হন এবং এজেন্ট শুধুমাত্র আপনার মালিকানাধীন ফাইলগুলো পড়ে, তখন এটি ব্যবহার করা যুক্তিসঙ্গত। এটি কোনো আইসোলেশন বা বিচ্ছিন্নতা প্রদান করে না। কোনো টুল কল ফাইল ডিলিট করলে তা আপনার ফাইলগুলোই ডিলিট করবে এবং কোনো টুল কল /etc/sandbase/runtime.env পড়লে তা আপনার প্রোভাইডার কি (key) পড়ে ফেলবে।

docker মোড প্রতি সেশনের জন্য একটি করে কন্টেইনার চালু করে।

{
  "sandbox_provider": "docker",
  "image": "node:22-slim",
  "resources": { "memory": "1g", "cpu": 1 }
}

সেশনটি নিজস্ব ফাইলসিস্টেম, মেমোরি লিমিট এবং CPU শেয়ার পায় এবং সেশন শেষ হলে কন্টেইনারটি মুছে ফেলা হয়। আপনি নিজে লেখেননি এমন কোড যখনই কোনো এজেন্ট রান করবে, তখনই এই মোডে সুইচ করুন। এর অসুবিধা হলো, রানটাইমের ব্যবহারকারীর Docker সকেটে অ্যাক্সেস থাকা প্রয়োজন এবং docker গ্রুপের সদস্যপদ থাকা মানেই হোস্ট মেশিনে root-এর সমান ক্ষমতা থাকা। প্রতি-সেশন কন্টেইনারগুলো প্রতি রান একটি কন্টেইনার বিশিষ্ট সেলফ-হোস্টেড এজেন্ট স্যান্ডবক্স-এর মতোই, তাই কোনো প্রসেস এস্কেপ করলে তা কী কী অ্যাক্সেস করতে পারবে, সেই সংক্রান্ত যুক্তি এখানেও অপরিবর্তিত থাকে।

kubernetes মোড সেশনের ওয়ার্কলোডকে একটি পড (pod) হিসেবে চালায় এবং kubectl exec ও kubectl cp দিয়ে তা নিয়ন্ত্রণ করে। রানটাইম ইমেজে kubectl থাকা প্রয়োজন এবং এর ServiceAccount-এর টার্গেট নেমস্পেসে পড তৈরি, ডিলিট, গেট, লিস্ট এবং ওয়াচ করার জন্য RBAC (role-based access control) পারমিশন থাকতে হবে, সেই সাথে exec সাব-রিসোর্সের পারমিশনও প্রয়োজন। আপনি যদি আগে থেকেই কোনো ক্লাস্টার ব্যবহার করেন, কেবল তখনই এই মোড সেটআপ করা লাভজনক।

রানটাইম কেন 127.0.0.1-এ আবদ্ধ (bound) থাকে?

কারণ এটি কোনো প্রমাণীকরণ (authentication) ছাড়াই শুরু হয়। যখন অন্তত একটি API key থাকে, তখন রানটাইম bearer-token প্রমাণীকরণ সক্রিয় করে, কিন্তু একটি নতুন init কোনো key তৈরি করে না। ডিফল্ট অবস্থায় 0.0.0.0-এ বাইন্ড করলে একটি প্রমাণীকরণহীন এজেন্ট রানটাইম পাবলিক ইন্টারনেটে উন্মুক্ত হয়ে যেত, যার কাছে শেল টুলস এবং আপনার প্রোভাইডার কি (key) থাকতো।

তাই যখন আপনি এটিকে অ্যাক্সেসযোগ্য করতে চান, তখন বাইন্ড অ্যাড্রেস পরিবর্তন না করে অন্য দুটি কাজ করুন।

প্রথমত, প্রমাণীকরণ চালু করুন। সার্ভিস এনভায়রনমেন্ট ফাইলে MANAGED_AGENTS_API_KEY সেট করুন, অথবা POST /v1/api-keys দিয়ে একটি কি (key) তৈরি করুন, যা একবার একটি secret_key ফিল্ড প্রদান করবে এবং পরে আর দেখাবে না। ক্লায়েন্টরা তখন প্রতিটি অনুরোধে Authorization: Bearer <key> পাঠাবে। একটি কি মানে একটি শেয়ারড আইডেন্টিটি, তাই যদি আপনি প্রতিটি টিমমেটের জন্য আলাদা স্যান্ডবক্সড এজেন্ট এবং একটি গেটওয়েতে প্রোভাইডার কি রাখতে চান, তবে OneCLI এই কাঠামোর জন্য তৈরি।

দ্বিতীয়ত, সামনে একটি reverse proxy বসান এবং সেখানে TLS (transport layer security) টার্মিনেট করুন। রানটাইম ডিজাইন অনুযায়ী plain 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 সেকেন্ড, তাই এক মিনিটের বেশি সময় কোনো স্ট্রিম নীরব থাকলে প্রক্সি সংযোগ বিচ্ছিন্ন করে দেয়, যা দেখে মনে হয় রানটাইম ক্র্যাশ করেছে।

ফায়ারওয়ালে 22 এবং 443 পোর্ট ওপেন রাখুন। 3000 পোর্ট বন্ধ রাখুন, কারণ প্রক্সি এটি loopback-এর মাধ্যমে অ্যাক্সেস করে এবং বক্সের বাইরের কারো এটি ব্যবহারের প্রয়োজন নেই।

Anthropic SDK-কে আপনার নিজস্ব সার্ভারের দিকে নির্দেশ করুন

রানটাইমটি একটি CMA-আকৃতির /v1 ইন্টারফেস ইমপ্লিমেন্ট করে, তাই একটি 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'
});

এটি Claude Managed Agents ক্লায়েন্টদের পাঠানো বিটা হেডারগুলোও গ্রহণ করে, যেমন anthropic-beta: managed-agents-2026-04-01 এবং anthropic-beta: agent-memory-2026-07-22। লোকাল রানটাইমের ক্ষেত্রে এগুলো ঐচ্ছিক। এগুলো রাখা হয়েছে যাতে হোস্ট করা ডেপ্লয়মেন্টের জন্য লেখা কোড এখানে কোনো পরিবর্তন ছাড়াই চলতে পারে।

সামঞ্জস্যতা প্রায় সম্পূর্ণ, তবে পুরোপুরি নয়। কোনো ইন্টারফেস আছে বলে ধরে নেওয়ার আগে চেকআউটে থাকা docs/api-matrix.md পড়ুন, কারণ প্রকল্পটি সেখানে তার নিজস্ব সীমাবদ্ধতাগুলো নথিভুক্ত করে। এর মধ্যে ক্লায়েন্ট-সাইড কাস্টম টুলও অন্তর্ভুক্ত, যা বর্তমান ইভেন্ট-রেজাল্ট প্রোটোকলের উপরে নামসহ রেজিস্ট্রেশন দাবি করে।

Plain 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 কি (keys)।
  • 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-এ এবং স্টেট অন্য কোথাও রাখতে চান, তবে ডেপ্লয়মেন্ট ডকুমেন্টেশন start-এ --data-dir ব্যবহার করে স্টেটের অবস্থান নির্ধারণ করার সুবিধা দেয়।

রিস্টোর করার প্রক্রিয়াটি বিপরীত: একটি নতুন বক্সে একই ট্যাগ চেক আউট করুন, আর্কাইভটি ওয়ার্কস্পেসে আনপ্যাক করুন এবং সার্ভিসটি চালু করুন। আপনি যদি ${OPENAI_API_KEY} ফর্ম ব্যবহার করে থাকেন তবে আপনার প্রোভাইডার কি (key) আর্কাইভে থাকবে না, তাই সেটি এমন কোথাও রাখুন যেখানে আপনি পরবর্তীতে তা খুঁজে পাবেন।

systemd-এর অধীনে চালানো

রানটাইমটিকে নিজস্ব ব্যবহারকারীর অধীনে চালান যাতে লোকাল স্যান্ডবক্স মোডে কোনো টুল কল আপনার হয়ে কাজ করতে না পারে।

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

প্রজেক্টের নিজস্ব ডিপ্লয়মেন্ট উদাহরণে PATH-এ একটি managed-agents বাইনারি কল করা হয়। ট্যাগড-সোর্স ইনস্টলেশন এটি তৈরি করে না, তাই 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

একটি সঠিক ফলাফল হলো status থেকে active (running) এবং curl থেকে 200। অন্য কিছু হলে, প্রথমে journalctl -u sandbase -n 50 এবং দ্বিতীয়ত .managed-agents/logs/runtime.log পড়ুন। enable --now হলো গুরুত্বপূর্ণ অংশ, কারণ হাতে শুরু করা কোনো প্রসেস পরবর্তী রিবুটের পর আর থাকে না।

কী কী সমস্যা হতে পারে এবং আপনি যে বার্তাগুলো দেখবেন

npm run build কোনো ত্রুটি বার্তা ছাড়াই npm থেকে বন্ধ হয়ে যায়। 1 GB RAM-এর VPS-এ TypeScript কম্পাইল করার সময় কার্নেলের out-of-memory killer প্রক্রিয়াটিকে বন্ধ করে দেয়। এটি npm-এর পরিবর্তে কার্নেল লগে রিপোর্ট করা হয়। journalctl -k | grep -i "out of memory" চালিয়ে এটি নিশ্চিত করুন, যা বন্ধ হয়ে যাওয়া node প্রসেসের নামসহ একটি লাইন দেখাবে। swap যোগ করুন অথবা বড় কোনো ইনস্ট্যান্সে বিল্ড করে dist/ ফাইলটি কপি করে আনুন।

Error: listen EADDRINUSE: address already in use 127.0.0.1:3000। অন্য কোনো প্রসেস ইতিমধ্যে পোর্টটি দখল করে রেখেছে। sudo ss -lntp | grep 3000 কমান্ডটি সেই প্রসেসের নাম দেখাবে। হয় সেই প্রসেসটি বন্ধ করুন, অথবা --port 3001 ব্যবহার করে রানটাইম শুরু করুন এবং প্রক্সি আপডেট করুন।

আপনার ল্যাপটপ থেকে ড্যাশবোর্ড লোড হচ্ছে না। এটিই প্রত্যাশিত আচরণ, কারণ রানটাইমটি loopback-এ বাইন্ড করা থাকে। উপরের SSH টানেল ব্যবহার করুন অথবা রিভার্স প্রক্সি সেটআপ সম্পন্ন করুন। --host 0.0.0.0 ব্যবহার করে এটি ঠিক করার চেষ্টা করবেন না, কারণ কি (key) তৈরি না হওয়া পর্যন্ত অথেন্টিকেশন বন্ধ থাকে।

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-এর সমান ক্ষমতা রাখে, যা রানটাইমকে আলাদা ইউজার দেওয়ার মূল উদ্দেশ্যকে আংশিকভাবে নষ্ট করে দেয়।

Kubernetes স্যান্ডবক্স Error from server (Forbidden) ত্রুটির কারণে ব্যর্থ হচ্ছে। ServiceAccount-এর পড পারমিশন বা exec সাবরিসোর্সের অভাব রয়েছে। kubectl auth can-i create pods/exec -n <namespace> দিয়ে সরাসরি এটি পরীক্ষা করুন, যা yes অথবা no উত্তর দেবে।

API কি যোগ করার পর প্রতিটি অনুরোধে 401 ত্রুটি দেখাচ্ছে। প্রথম কি (key) তৈরি হওয়ার সাথে সাথে অথেন্টিকেশন চালু হয়ে যায় এবং এটি API-এর পাশাপাশি কনসোলের ক্ষেত্রেও প্রযোজ্য। Authorization: Bearer <key> পাঠান। যদি কি-টি হারিয়ে ফেলেন, তবে নতুন একটি তৈরি করুন, কারণ secret_key শুধুমাত্র একবারই দেখানো হয় এবং এটি পড়ার যোগ্য কোনো ফরম্যাটে সংরক্ষিত থাকে না।

MCP সার্ভারের টুলগুলো সেশনে দেখা যাচ্ছে না। tools ব্লকের mcp_server_name-এর সাথে mcp_servers-এর name মিলিয়ে দেখুন। এরপর নিশ্চিত করুন যে রানটাইম সার্ভার থেকে সরাসরি curl -i <url> ব্যবহার করে সেই URL-এ পৌঁছাতে পারছে কি না। URL-ভিত্তিক MCP সার্ভার একটি নেটওয়ার্ক ডিপেন্ডেন্সি, এবং একটি VPS আপনার ল্যাপটপের চেয়ে ভিন্নভাবে নাম রেজলভ করে ও ট্রাফিক রাউট করে।

FAQ

আমি কি OpenAI বা Anthropic-এর কি (key) ছাড়া SandBase Harness চালাতে পারি?

হ্যাঁ, যদি আপনার কাছে OpenAI-এর সাথে সামঞ্জস্যপূর্ণ (compatible) কোনো endpoint থাকে। এই রানটাইম OpenAI, Anthropic এবং OpenAI-এর সাথে সামঞ্জস্যপূর্ণ প্রোভাইডারদের সমর্থন করে, তাই OpenAI API সমর্থন করে এমন যেকোনো লোকাল সার্ভার এখানে কাজ করবে। .managed-agents/config.yaml-এ ওয়ার্কস্পেস প্রোভাইডার সেট করুন এবং api_key ও endpoint-কে সেটির দিকে নির্দেশ করুন। এই রানটাইমের নিজস্ব কোনো মডেল নেই, তাই কলগুলোর উত্তর দেওয়ার জন্য কোনো একটি সার্ভিসের প্রয়োজন হবে।

রানটাইমকে পাবলিক পোর্টে এক্সপোজ করা কি নিরাপদ?

ইনস্টল করা অবস্থায় এটি নিরাপদ নয়। এটি 127.0.0.1:3000-এ বাইন্ড হয় এবং কোনো অথেন্টিকেশন ছাড়াই চালু হয়, আর এর সমাধান কেবল ভিন্ন কোনো বাইন্ড অ্যাড্রেস ব্যবহার করা নয়। একটি API কি তৈরি করুন অথবা MANAGED_AGENTS_API_KEY সেট করুন, যাতে বিয়ারার-টোকেন (bearer-token) অথেন্টিকেশন চালু হয়। এরপর TLS-এর জন্য সামনে nginx বা Caddy বসান এবং ফায়ারওয়ালে পোর্ট 3000 বন্ধ রাখুন, যাতে প্রক্সি ছাড়া অন্য কোনো পথে প্রবেশ করা না যায়।

লোকাল, Docker এবং Kubernetes স্যান্ডবক্সের মধ্যে পার্থক্য কী?

local টুল কোডকে হোস্টের রানটাইম ব্যবহারকারীর পারমিশন অনুযায়ী চাইল্ড প্রসেস হিসেবে চালায়, যেখানে কোনো আইসোলেশন থাকে না। docker প্রতিটি সেশনের জন্য আলাদা ফাইলসিস্টেম, মেমোরি লিমিট এবং CPU শেয়ারসহ নিজস্ব কন্টেইনার তৈরি করে এবং সেশন শেষ হলে তা মুছে ফেলে। kubernetes সেশনটিকে একটি পড হিসেবে চালায় এবং kubectl exec দিয়ে নিয়ন্ত্রণ করে, যার জন্য রানটাইম ইমেজের ভেতরে kubectl এবং টার্গেট নেমস্পেসে পড ও exec সাবরিসোর্সের ওপর RBAC পারমিশন প্রয়োজন হয়।

ব্যাকআপ নেওয়ার জন্য ঠিক কী কী প্রয়োজন?

ওয়ার্কস্পেসের .managed-agents/ ডিরেক্টরি। এতে config.yaml, এজেন্ট, সেশন, ক্রেডেনশিয়াল ভল্ট এন্ট্রি ও মেমোরি এন্ট্রি সম্বলিত data.db SQLite ডেটাবেস, এবং আপলোড করা ফাইল, স্কিল প্যাকেজ ও সেশন স্ন্যাপশট থাকে। কপি করার আগে সার্ভিসটি বন্ধ করে নিন যাতে আর্কাইভ করার সময় SQLite-এ কোনো ডেটা লেখা না হয়। ${OPENAI_API_KEY} হিসেবে উল্লেখ করা প্রোভাইডার API কিগুলো এই ব্যাকআপের ভেতরে থাকে না, তাই সেগুলো আলাদাভাবে সংরক্ষণ করুন।

main ব্রাঞ্চের পরিবর্তে v0.3.2 ট্যাগ ক্লোন করব কেন?

একটি ট্যাগ হলো একটি নির্দিষ্ট কোডবেস, তাই আপনি যে কনফিগারেশন কি (key) এবং CLI কমান্ডগুলো সম্পর্কে পড়ছেন, সেগুলোই আপনি পাবেন। main প্রতিনিয়ত পরিবর্তিত হয় এবং গাইড লেখার সময় থেকে আপনার রান করার সময়ের মধ্যে কোনো কনফিগারেশন কি-এর নাম বদলে যেতে পারে। প্রজেক্টটি আরও সতর্ক করে যে, npm-এ থাকা আনস্কোপড managed-agents প্যাকেজটি এই প্রজেক্ট নয়, তাই npx managed-agents ইনস্টল করলে ভিন্ন কিছু ইনস্টল হয়ে যাবে। রিলিজ v0.3.1 মূলত সেই npm কুইক স্টার্টের পরিবর্তে পিন করা ট্যাগড-সোর্স পাথ ব্যবহারের জন্য আনা হয়েছে।