تصور کنید ساعت ۱ صبح است و عامل هوش مصنوعی شما در یک حلقهٔ بیپایان گیر کرده و مدام یک دستور خراب را تکرار میکند؛ این دقیقاً همان نقطهای است که اکثر پروژههای شخصی آخر هفته شکست میخورند. در ۲۰ سپتامبر ۲۰۲۶، یک راهنمای فنی در وبسایت dev.to الگوی سبک «مدارشکن» (Circuit Breaker) را معرفی کرد تا بدون نیاز به بازنویسی کل پلتفرم، جلوی این سقوطهای هزینهبر را بگیرد. نویسنده اشاره میکند که پروژههای جانبی آخر هفته در حوزه عاملها بهندرت بهدلیل نبود کلید API میمیرند؛ بلکه بهخاطر حلقههایی میمیرند که یک ابزار را تکرار میکنند، توکنها را میبلعند و ترمینال را با خطاهای مشابه پر میکنند.
بسیاری از توسعهدهندگان، عامل (Agent) — شبیه به کارمندی که لیستی از وظایف دارد و تا پایان آنها تلاش میکند — را با یک حلقهٔ ساده (while-loop) میسازند که تا زمان دریافت سیگنال پایان از مدل اجرا میشود. این معماری بسیار شکننده است؛ چون وقتی تجزیهٔ JSON شکست میخورد، وقتی یک ابزار جستوجو نتایج خالی برمیگرداند، یا وقتی برنامهریز (Planner) همان پرسوجو را دوباره امتحان میکند، هیچ نقطهٔ توقف طبیعی وجود ندارد. در واقع، تستهای واحد ممکن است تایید کنند که هر ابزار بهتنهایی درست کار میکند، اما آنها بهندرت این موضوع را بررسی میکنند که ترکیب کلی ابزارها باید در نهایت متوقف شود. تستهای سبز برای ابزارها و یک برنامهریز از کنترل خارج شده میتوانند ساعتها در کنار هم وجود داشته باشند، زیرا مجموعه تستها هرگز ادعا نکردند که حلقه باید متوقف شود. این چالشها نشان میدهد چرا بودجهٔ حلقهها باید به عنوان معیار اصلی در سنجش توسعهدهندگان عاملها در نظر گرفته شود.
برای مثال، عاملی را تصور کنید که وظیفه دارد سندی خاص را بیابد. اگر ابزار جستوجو شکست بخورد، یک برنامهریز ساده ممکن است همان پرسوجوی دقیق را تا ابد تکرار کند. این اتفاق نهتنها زمانبر است، بلکه بودجهٔ API شما را میبلعد و ترمینال را با خطاهای یکسان پر میکند. راهکار پیشنهادی، ایجاد یک «حصار» دور حلقهٔ محلی است تا سیستم را مجبور کند در صورت بروز خطا، بهصورت بسته متوقف شود (Fail Closed). این یک دموی محدود برای آخر هفته است، نه یک محصول صنعتی برای پایداری سیستمهای توزیعشده.
سه شرط برای قطع مدار
بر اساس مستندات dev.to، سه شرط مشخص اکثر حالتهای شکست عاملها را پوشش میدهد:
- بودجهٔ گامها (Turn Budget): توقف اجباری پس از تعداد مشخصی گام برنامهریز (مثلاً ۸ گام). این کار مانع از سرگردانی ابدی عامل میشود.
- تلهٔ فراخوانیهای مشابه (Identical Call Tripwire): اگر نام یک ابزار و هش محتوای ورودی آن K بار متوالی (مثلاً ۳ بار) تکرار شود، مدار باز میشود. این تله، «حلقهٔ مرگ» را متوقف میکند، جایی که مدل یک فراخوانی خراب را تکرار میکند. این موضوع یادآور شکست حلقههای خودبهینهساز است که توسط داوران مبتنی بر کلمات کلیدی فریب میخورند و در تکرارهای بیهدف گیر میکنند.
- رشتهٔ خطاها (Error Streak): پس از M خطای متوالی در ابزارها (مثلاً ۳ خطا)، سیستم خاموش میشود تا از فشار آوردن به سرویسهایی که از دسترس خارج شدهاند جلوگیری شود.
یک حصار چهارم اختیاری، تعیین ضربالاجل زمانی (Wall-clock deadline) است. با این حال، این دمو آن را رد کرد زیرا ارزان است اما در لپتاپهایی که به حالت خواب (Sleep) میروند، بهراحتی دچار خطا میشود. برای اینکه تستها قطعی (Deterministic) باقی بمانند، این دمو بهجای استفاده از time.sleep از یک دوره استراحت بر اساس شمارندهٔ درخواستهای ردشده استفاده میکند.
جزئیات پیادهسازی فنی
این سیستم از یک ماشین وضعیت (State Machine) با سه حالت متمایز استفاده میکند: بسته، باز و نیمهباز. مدارشکن قبل از هر فراخوانی ابزار، یک سوال میپرسد: «آیا این حلقه میتواند ادامه یابد؟»
- حالت بسته (Closed): عامل بهطور عادی کار میکند. اگر تعداد گامها کمتر از سقف باشد، فراخوانی جدید باشد و ابزار با موفقیت اجرا شود، مدار بسته میماند.
- حالت باز (Open): این حالت با رسیدن به سقف گامها، تکرار ورودیهای مشابه یا خطاهای متوالی فعال میشود. تمام فراخوانیهای بعدی فوراً رد میشوند.
- حالت نیمهباز (Half-Open): پس از یک دورهٔ استراحت (Cooldown) وارد این حالت میشود. این وضعیت اجازه میدهد یک فراخوانی آزمایشی (Probe) برای تست بازیابی سیستم انجام شود.
منطق انتقال وضعیت
مدارشکن طبق یک جدول تصمیمگیری مشخص برای تعیین وضعیت بعدی عمل میکند:
- بسته $
ightarrow$ بسته: وقتی گامها کمتر از حداکثر است، فراخوانی جدید است و ابزار موفق میشود. - بسته $
ightarrow$ باز: اگر ورودی مشابه K بار تکرار شود، خطاهای متوالی به M برسند یا گامها بهmax_turnsبرسند. - باز $
ightarrow$ باز: اگر دوره استراحت (که با تعداد تلاشهای ردشده سنجیده میشود) هنوز به پایان نرسیده باشد. - باز $
ightarrow$ نیمهباز: زمانی که دوره استراحت تمام شود. سیستم درخواست فعلی را رد میکند اما یک پروب را فعال (Arm) میکند. - نیمهباز $
ightarrow$ بسته: اگر پروب موفق شود؛ در این صورت شمارندهها ریست میشوند. - نیمهباز $
ightarrow$ باز: اگر پروب شکست بخورد؛ دوره استراحت دوباره آغاز میشود.
برای اجازه دادن به بازیابی، سیستم پس از یک دوره استراحت وارد حالت «نیمهباز» میشود. در این دمو، استراحت بهجای زمان واقعی، با شمارندهای از تلاشهای ردشده (مثلاً ۴ رد شدن) اندازهگیری میشود. این انتخاب طراحی تضمین میکند که تستهای واحد قطعی بمانند و تحت تأثیر حالت خواب لپتاپ یا کاهش سرعت CPU قرار نگیرند. اگر پروب موفق شود، وضعیت به بسته بازگشته و شمارندهها ریست میشوند؛ اگر شکست بخورد، به حالت باز برگشته و استراحت از نو شروع میشود.
محدوده و محدودیتها
برای اینکه پروژه در یک آخر هفته قابل مدیریت باشد، طبق گزارش ساخت (Build Log)، محدوده پروژه بهطور عمدی کاهش یافت. هدف، ساخت حصاری بود که برای عملکرد به یک خوشه (Cluster) نیاز نداشته باشد. حصاری برای آخر هفته که به کلاستر نیاز داشته باشد، دیگر یک پروژه آخر هفته نیست.
قابلیتهای پیادهشده:
- ماشین وضعیت درون-فرآیندی (بسته، باز، نیمهباز).
- تلههای مربوط به گامها، فراخوانیهای مشابه و رشتهٔ خطاها.
- پروب نیمهباز که اجازه یک فراخوانی آزمایشی پس از استراحت را میدهد.
- یک درایور عامل اسکریپتی و تستهای واحدی که «باز شدن مدار» را به عنوان موفقیت میبینند.
قابلیتهای حذفشده:
- استفاده از Redis یا هر ذخیرهساز مشترک.
- اجارههای چند-فرآیندی (Liveness متعلق به Heartbeat است، نه این حصار).
- حسابداری هزینه توکنها و فایلهای قفل مدل یا پرامپت.
- داشبورد وب.
- فراخوانیهای HTTP زنده مدل در داخل مجموعه تستها.
تست برای شکست
تستهای سنتی عاملها بررسی میکنند که آیا ابزار JSON درستی برمیگرداند یا خیر. اما این الگو تمرکز را به تأییدات «توقف در حالت بسته» (Fail-closed assertions) تغییر میدهد. مجموعه تستهای ارائه شده، باز شدن مدار را به عنوان یک نتیجه موفقیتآمیز در نظر میگیرند تا تضمین شود حلقه در زمان مناسب واقعاً متوقف میشود.
چهار تست مشخص رفتار لایه کنترل را تثبیت میکنند:
- فراخوانی مشابه: تأیید میکند که ۳ فراخوانی جستوجوی یکسان، دلیل
identical_callرا فعال میکند. - رشتهٔ خطا: تأیید میکند که ۳ شکست متوالی، دلیل
error_streakرا فعال میکند. - حداکثر گامها: تأیید میکند که فراتر رفتن از حد گامها، دلیل
max_turnsرا فعال میکند. - پروب نیمهباز: تأیید میکند که پس از استراحت (۲ رد شدن)، یک پروب موفق مدار را میبندد.
یک نکته ظریف و حیاتی مربوط به هش کردن ورودیها (Payload Hashing) است. این دمو از یک Digest SHA-256 از نام ابزار و نمایش (repr) ورودی استفاده کرده و ۱۶ کاراکتر اول را برمیدارد. در حالی که این روش برای رشتهها، اعداد صحیح و تاپلهای کوچک کار میکند، نویسنده اشاره میکند که این یک فرم استاندارد ضعیف برای دیکشنریهای بدون ترتیب، اشیایی با IDهای متغیر یا برچسبهای زمانی شناور است که توسط برنامهریز تزریق میشوند. این موارد برای شناسایی تکرارها، نیاز به نرمالسازی قبل از هش کردن دارند. برای دستیابی به تکرارپذیری کامل در این سطح، تثبیت سختافزاری در برابر تاریخچهٔ چت راهکاری است که از نوسانات مدل در بررسیهای متوالی جلوگیری میکند.
ادغام با برنامهریزان ابری
گامهای اسکریپتی محلی برای اثبات کارکرد حصار کافی هستند. یک برنامهریز واقعی همچنان به مدل نیاز دارد، اما ترکیب زودهنگام آنها باعث ایجاد تستهای ادغامی میشود که بهدلایلی غیر از مدارشکن شکست میخورند.
برای کسانی که فراتر از اسکریپتهای محلی میروند، این راهنما استفاده از MonkeyCode را برای دسترسی رایگان به مدلها و گزینههای سرور پیشنهاد میکند. توصیه معماری کلیدی این است که تله (Tripwire) در سمت فراخوان (Caller)، یعنی در کنار فراخوانی ابزارها قرار گیرد. این کار تضمین میکند که حصار ایمنی محلی و قطعی باقی بماند، فارغ از رفتار مدل دوردست. مدل اختیاری و قابل جایگزین است؛ اما حصار، ثابت است.
محدودیتهای الگو
این مدارشکن یک کتابخانه صنعتی برای پایداری (Reliability) نیست. نمیتواند بین دو فرآیند مجزای عامل هماهنگ شود، به این معنی که فراخوانیهای دوگانه همچنان ممکن است رخ دهند. همچنین اثرات جانبی ابزارها را بررسی نمیکند؛ اگر یک دستور نوشتاری تخریبی با موفقیت اجرا شود اما حلقه ادامه یابد، مدارشکن نمیتواند آن عمل را لغو کند. این الگو ثابت نمیکند که مدل صادق است؛ فقط ثابت میکند که حلقه متوقف شده است.
چه کسانی نباید از این الگو بهصورت مستقیم استفاده کنند؟
- عاملهای چندمستاجری/پولی: وضعیت درون-فرآیندی یک مرز ایزولاسیون نیست.
- سیستمهای بلادرنگ: دوره استراحت یک شمارنده رد شدن است، نه یک ساعت.
- کاربران موتورهای گردشکار: کسانی که سیستمهای Retry و Saga دارند نباید یک شیء سیاستگذاری دوم را بدون نگاشت وضعیتها روی هم قرار دهند.
- ابزارهای حساس ایمنی: این جایگزینی برای گیتهای ادغام (Merge Gate) برای کدهای تولید شده یا لیست سفید ابزارها نیست. ساخت گیت ادغام برای Diffهای تولید شده، یک پروژه آخر هفته متفاوت است.
روند تکامل طراحی
نسخه نهایی حاصل چندین تکرار برای حذف پیچیدگی بود:
- نسخه اول: تلاش شد کل گفتگو هش شود و در صورت تکرار ردپای گفتگو، مدار باز شود. این روش بیش از حد کلی بود زیرا برنامهریز میتواند بهطور قانونی با یک تغییر کوچک در ورودی، تلاش مجدد کند. این روش با هش کردن نام ابزار و ورودی برای تکرارهای متوالی جایگزین شد تا با شکستِ تکرار سه باره یک جستوجوی یکسان بدون اطلاعات جدید مطابقت داشته باشد.
- نسخه دوم: تایماوتهای زمانی (Wall-clock) امتحان شد. این کار باعث شد تستها در لپتاپهای دارای محدودیت پردازشی ناپایدار شوند. استراحت بر اساس شمارنده رد شدن جایگزین شد تا تستها قطعی بمانند.
- نسخه سوم: ثبت هر قطع مدار در یک فایل JSONL بررسی شد. این کار برای یک دمو غیرضروری تشخیص داده شد؛ فیلد
last_reasonبرای عیبیابی در یک شب یکشنبه کافی بود. - نسخه نهایی: حالت نیمهباز اصلاح شد. در ابتدا، فراخوانیای که دوره استراحت را تمام میکرد، به عنوان پروب اجرا میشد. این کار «من هنوز در حال رد کردن هستم» را با «من در حال تست بازیابی هستم» در یک درخواست ترکیب میکرد. نسخه نهایی، درخواستی را که پروب را فعال میکند رد کرده و دقیقاً یک فراخوانی بعدی را اجازه میدهد. این با طرز فکر اپراتورهای انسانی درباره دورههای استراحت مطابقت دارد: آخرین شکست، حق تلاش مجانی نمیگیرد.
این رویکرد، فرض بنیادی توسعهٔ عاملها را از «امید به اینکه مدل کار را تمام کند» به «تضمین اینکه حلقه متوقف شود» تغییر میدهد. با محدود کردن اجرا، توسعهدهندگان میتوانند روی برنامهریزها تکرار کنند بدون اینکه بترسند صورتحساب API سرسامآور شود یا ترمینال آنها منجمد گردد.
گام بعدی شما
- اگر از حلقههای
whileبرای اجرای عاملها استفاده میکنید، همین امروز یک شمارندهٔ ساده برایmax_turnsاضافه کنید. - برای ابزارهای حساس، یک تابع هش برای ورودیها بنویسید تا تکرار دقیق دستورات را شناسایی کنید.
- در تستهای واحد خود، سناریویی را شبیهسازی کنید که در آن مدار باید «باز» شود و سیستم متوقف گردد.
اما مدیریت هزینههای استنتاج در مقیاس بزرگ، چالش متفاوتی است — به تحلیل ما دربارهی بهینهسازی GPUها مراجعه کنید.




گفتگو