Run SDK ورسل: اجرای کد ایجنتها توی سندباکس
خلاصهٔ کاملتر
ورسل پکیج Run SDK رو معرفی کرده، ابزاری برای اجرای کد جاوااسکریپت و تایپاسکریپتی که بهش اعتماد نداری. تو این مقاله اومده که مسئله از اینجا شروع میشه که ایجنتها دیگه فقط یه تابع صدا نمیزنن، بلکه کل برنامه مینویسن؛ و اگه اون برنامه رو با eval اجرا کنی، دقیقاً همون دسترسیای رو داره که خود اپلیکیشنت داره، یعنی سکرتها و سرویسهای داخلی. هیچ راه پایداری هم نداری که وسط کار برای تأیید یا لاگین وایسی.
Run SDK کد رو توی یه کانتکست تازهٔ QuickJS (یه موتور جاوااسکریپت خیلی سبک) داخل یه worker thread اجرا میکنه که نه راه مستقیمی به Node داره نه به شبکه. اپلیکیشن فقط چندتا عملیات مشخص رو از طریق hostFunctions باز میکنه و همونا داخل سندباکس مثل متغیر گلوبال قابل صدا زدنن. یعنی کلاینت دیتابیس و کلیدهاش بیرون پیش اپلیکیشن میمونن و کد مهمون فقط نتیجه رو میگیره:
const result = await run({
source: `
const orders = await store.listOrders("customer_123");
const total = orders.reduce((sum, order) => sum + order.amount, 0);
return { count: orders.length, total };
`,
hostFunctions: { store: { listOrders } },
});این همون ماژولیه که پشت code mode توی AI SDK کار میکنه. به گفتهٔ ورسل وقتی به ایجنت بهجای یه فراخوانی تکی، یه برنامه میدی، واحد کار عوض میشه: مدل توی یه جواب هم میگه چه فراخوانیهایی لازمه هم منطق بینشون رو مینویسه. تو مثال مقاله دو درخواست همزمان میرن، فیلتر کردن فاکتورها داخل خود برنامه انجام میشه و فقط خروجی مفید برمیگرده، نه کل پاسخ سرویس بیلینگ.
خوندن فاکتور با ریفاند کردن فرق داره، برای همین host function میتونه وسط اجرا کار رو نگه داره و منتظر تصمیم آدم بمونه:
const context = getHostFunctionContext();
if (context.resume === undefined) {
context.interrupt({ kind: 'approval', message: `Publish ${draftId}?` });
}
if (context.resume.resolution !== true) {
return { published: false };
}خروجی یه اجرای متوقفشده یه توکن امضاشده داره که اپلیکیشن کنار درخواست تأیید ذخیرهش میکنه و بعد از تصمیم، باهاش اجرا رو ادامه میده. موقع ادامه برنامه دوباره پخش میشه، ولی فراخوانیهایی که قبلاً جواب گرفتن نتیجهٔ ضبطشدهٔ خودشون رو برمیگردونن، پس کار تکراری انجام نمیشه. یعنی ورکر لازم نیست کل مدت انتظار زنده بمونه؛ همین مکانیزم برای صبر کردن تا احراز هویت هم جواب میده.
برای کدی که بینهایت لوپ میزنه یا خروجی غولپیکر میسازه هم createRunner() محدودیتهای مشترکی مثل timeoutMs و memoryLimitBytes میذاره که هر اجرا هم میتونه جداگونه سفتشون کنه. هر بار یه کانتکست تازهٔ QuickJS ساخته میشه، ارزیابی داینامیک غیرفعاله و پروتوتایپهای داخلی هاردن شدن. ورسل تأکید میکنه این مرز فقط برای برنامهٔ تولیدشدهست و خود host functionها کد معتمد اپلیکیشنن، پس باید چکهای دسترسی همیشگیشون رو انجام بدن.
نکات کلیدی:
- نصب با pnpm add run؛ کد داخل QuickJS و توی worker thread اجرا میشه، بدون راه مستقیم به Node یا شبکه.
- فقط hostFunctions به داخل سندباکس باز میشه و فراخوانیها با serialization از مرز رد میشن؛ host function میتونه promise برگردونه.
- context.interrupt() اجرا رو برای تأیید انسانی یا احراز هویت نگه میداره و با یه توکن امضاشده ادامه پیدا میکنه، بدون اجرای دوبارهٔ کارهای تمامشده.
- createRunner() با timeoutMs و memoryLimitBytes سقف میذاره؛ مقدارهای مثال مقاله ۱۰ ثانیه و ۳۲ مگابایته.
- ریشهاش js-exec داخل پروژهٔ just-bash بوده؛ برای کارهایی که سیستمعامل یا نصب پکیج میخوان، Vercel Sandbox پیشنهاد شده.




