تصور کنید یک عامل مالی وظیفه بازگرداندن وجه را دارد؛ در چنین سیستمی نمیتوان ریسک استقلال کامل را پذیرفت و حتماً باید یک انسان بین تصمیم مدل و انتقال پول قرار بگیرد. طبق مستندات فنی منتشر شده در ۶ اوت ۲۰۲۶، LangGraph.js راهکاری برای پیادهسازی الگوی «انسان در حلقه» (Human-in-the-Loop) ارائه داده است تا سیستم در انتظار پاسخهای طولانیمدت دچار فروپاشی نشود.
بسیاری از پیادهسازیهای ابتدایی هوش مصنوعی، در زمان انتظار برای پاسخ انسان، یک Promise را مسدود میکنند. این روش برای ۹۰ ثانیه جواب میدهد، اما با اولین ریاستارت سرور، استقرار نسخه جدید یا حتی یک استراحت کوتاه کاربر، کل فرآیند متوقف و از بین میرود. برای حل این مشکل، LangGraph.js از مکانیزمی به نام interrupt استفاده میکند که اجرای برنامه را معلق کرده و وضعیت فعلی را در یک پایگاهداده ذخیره میکند.

سازوکار توقف (Interrupt)
تابع interrupt یک سیگنال خاص ارسال میکند که توسط گراف دریافت میشود. در این لحظه، اجرا در همان گره متوقف شده و یک نقطه بازرسی (Checkpoint) — شبیه به ذخیره کردن بازی در یک مرحله خاص برای بازگشت در آینده — ایجاد میشود. سپس سیستم یک خروجی __interrupt__ به فراخواننده برمیگرداند؛ به این معنا که هیچ دادهای در حافظه فعال باقی نمیماند و هیچ پردازشی مسدود نمیشود.
به نقل از توسعهدهندگان این ابزار، توصیه میشود به جای ارسال رشتههای متنی آماده، دادههای خام (مانند شناسه سفارش یا مبلغ بازپرداخت) را به تابع توقف بفرستید. این رویکرد برای جلوگیری از خطاهای رایج در محیطهای عملیاتی است، چرا که استفاده از رشتههای متنی در پرامپتها اغلب منشأ خطاهای پنهان در مقیاس تولید میشود. این کار باعث میشود رابط کاربری (UI) بتواند مستقل از منطق داخلی عامل، محیط تصمیمگیری را برای کاربر رندر کند.
جزئیات پیادهسازی
- گره تأیید: یک تابع تأیید با استفاده از
interrupt({ kind: "refund_approval", ... })اجرا را متوقف میکند و بر اساس تصمیم انسان، مقدار boolean (تأیید یا رد) را برمیگرداند. - خواندن وضعیت توقف: وقتی
graph.invokeبازمیگردد، توسعهدهنده مقدارresult.__interrupt__را بررسی میکند. این مقدار به صورت آرایه است زیرا یک گراف میتواند همزمان در چندین شاخه متوقف شود. - بررسیهای تایپشده: این کتابخانه برای جلوگیری از خطاهای دسترسی مستقیم، کلیدهای
isInterruptedوINTERRUPTرا صادر کرده است. - صفبندی: پس از شناسایی توقف، شناسه رشته (
threadId) و محموله دادهها معمولاً به یک صف بررسی برای اقدام انسانی ارسال میشوند.
همانطور که در تحلیلهای پیشین ما درباره امنیت مدلهای عاملمحور اشاره کردیم، حذف استقلال کامل در عملیات حساس، تنها راه جلوگیری از خطاهای فاجعهبار است. این تفکیک دقیق بین بررسی و اجرا، مشابه معماری SlackOps است که برای ایمنسازی دسترسیهای نوشتاری عاملهای هوش مصنوعی طراحی شده است.
ازسرگیری وضعیت
برای بازگرداندن یک عامل متوقف شده، به یک thread_id نیاز است که مانند اشارهگری به نقطه بازرسی ذخیرهشده عمل میکند. اگر این شناسه را به جای یک UUID تصادفی، از یک شیء دامنه (مثلاً refund-order123) مشتق کنید، میتوانید بدون نیاز به جدول جستوجوی جداگانه، اجراهای متوقف شده را بیابید.
برای شروع مجدد، از تابع Command({ resume }) استفاده میشود. این قابلیت اجازه میدهد فراخوانی اولیه interrupt() مقداری را برگرداند و گره دقیقاً از همان خطی که متوقف شده بود ادامه دهد؛ حتی اگر اکنون روی ماشین یا پردازش متفاوتی در حال اجرا باشد. در این حالت، کل گفتگو، نتایج ابزارها و وضعیت انباشته شده از نقطه بازرسی بازیابی میشوند.

تله «گراف گیر کرده»
تفاوت حیاتی در نحوه فراخوانی invoke روی رشتههای موجود وجود دارد. استفاده از یک شیء ساده، یک دور جدید از گراف را آغاز میکند، اما Command({ resume }) مشخصاً به یک توقف در انتظار پاسخ میدهد.
اشتباه گرفتن این دو منجر به وضعیتی میشود که گراف «گیر کرده» به نظر میرسد. بهویژه استفاده از Command({ update }) برای نوبتهای بعدی اشتباه است؛ زیرا این دستور از آخرین گره اجرا شده ادامه میدهد، نه از نقطه ورود. نتیجه این است که اجرا بلافاصله بازمیگردد بدون اینکه هیچ عملیاتی انجام داده باشد.
جایگذاری استراتژیک
محل قرارگیری توقف تعیین میکند که آیا این وقفه مفید است یا خیر. توقف باید در یک گره مجزا و دقیقاً قبل از اثر جانبی (Side Effect) قرار گیرد. فراخوانی interrupt() داخل گره issueRefund — یعنی پس از اینکه API پرداخت فراخوانی شده است — هیچ حفاظتی ایجاد نمیکند.
علاوه بر این، توقفها باید شرطی باشند. برای مثال، گراف میتواند با یک لبه شرطی، بازپرداختهای بالای ۱۰۰ دلار را به گره تأیید بفرستد و مبالغ کمتر را مستقیماً پردازش کند. ایجاد یک مرحله انسانی برای هر اجرا، صفی ایجاد میکند که هیچکس توان مدیریت آن را نخواهد داشت.
الزامات محیط عملیاتی و نقاط شکست
بسیاری از توسعهدهندگان در محیط عملیاتی با استفاده از MemorySaver شکست میخورند؛ زیرا این حافظه در داخل پردازش است و با هر بار استقرار (Deploy) کد، تمام تأییدهای در انتظار پاک میشوند. برای استفاده واقعی، استفاده از نقاط بازرسی پایدار مانند Postgres یا SQLite از بستههای @langchain/langgraph-checkpoint-* اجباری است. این رویکرد برای کاهش تأخیر در چرخههای تکرار، سوییچ به معماریهای محلی و بهینهسازی ارتباطات را توصیه میکند تا وابستگی به درخواستهای REST کاهش یابد.
این ذخیرهساز پایدار اکنون به دادههای عملیاتی تبدیل میشود و الزامات سختگیرانهای دارد:
- پشتیبانگیری: از دست رفتن یک نقطه بازرسی یعنی یک درخواست بازپرداخت برای همیشه معلق میماند.
- مهاجرت دادهها: تغییرات در کد میتواند باعث شود نقاط بازرسی قدیمی دیگر قابل ازسرگیری نباشند.
- مدیریت ماندگاری: اجراهای متوقف شده انباشته میشوند و باید مدیریت گردند.
به همین دلیل، سیاست «زمان انقضا» (Timeout) ضروری است. بازپرداختی که ماهها در انتظار تأیید بماند، عملاً رها شده است. روش پیشنهادی، پاکسازی دورهای پایگاهداده است تا درخواستهای قدیمی (مثلاً بعد از ۷ روز) بهطور خودکار رد شوند. رد کردن پیشفرض ایمنتر از معلق نگه داشتن ابدی وضعیت است.

توقفهای موازی
در جریانهای کاری پیچیده، ممکن است دو شاخه مختلف از گراف در یک مرحله متوقف شوند. در این حالت، آرایه result[INTERRUPT] شامل چندین ورودی است.
توسعهدهندگان باید تمام توقفهای در انتظار را با استفاده از یک نقشه از شناسههای توقف (مثلاً Record<string, string>) پاسخ دهند. ارسال یک پاسخ تکمقداری در حالی که دو توقف وجود دارد، تنها یکی را پاسخ میدهد و دیگری را معلق میگذارد که دقیقاً شبیه به گیر کردن گراف است.
این قابلیت، عامل را از یک حلقه ساده به یک پردازش پایدار تبدیل میکند و اجازه میدهد هوش مصنوعی وظایف حساس — مانند تغییر زیرساختها یا جابهجایی پول — را مدیریت کند، چرا که تضمین میکند انسان میتواند در هر زمان دلخواهی مداخله کند. این قویترین دلیل برای استفاده از چارچوبهای گرافی به جای حلقههای استاندارد است.
گام بعدی شما
- اگر از
MemorySaverاستفاده میکنید، فوراً آن را با یک Checkpointer پایدار مانند SQLite جایگزین کنید تا با هر ریاستارت، وضعیت عاملهایتان پاک نشود. - برای هر عملیات حساس (مانند ارسال ایمیل انبوه یا تراکنش مالی)، یک گره
approvalمجزا قبل از گره عملیاتی تعریف کنید. - یک اسکریپت پاکسازی برای حذف نقاط بازرسی قدیمیتر از ۷ روز در پایگاهداده خود پیادهسازی کنید.
اما مدیریت حافظه در مقیاس میلیونی چالشهای دیگری دارد — به تحلیل ما درباره بهینهسازی KV Cache در مدلهای زبانی مراجعه کنید.




گفتگو