تصور کنید ابزاری ساختهاید که قرار است هر روز دهها فرصت شغلی ایدهآل را برای شما پیدا کند و هر شب با پیام «همه چیز عالی است» شما را میخواباند، اما هفتههاست هیچ ایمیلی دریافت نکردهاید. این دقیقاً همان کابوسی است که تیم AIdeazz AI Lab با آن دستوپنجه نرم کرد.
به گزارش این آزمایشگاه، یک عامل (Agent) — شبیه به دستیاری دیجیتال که میتواند بهجای شما تصمیم بگیرد و ابزارها را اجرا کند — در طول یک هفته ۲۶ بار گزارش داد که «امروز اقدام کردم»، اما در نهایت تنها ۲ فرصت شغلی واقعی به صف بررسی کاربر رسید. این تضاد که در یادداشتی میدانی به تاریخ ۶ اکتبر ۲۰۲۶ منتشر شد، دستهای خطرناک از «شکستهای خاموش» در جریانهای کاری عاملمحور را افشا میکند.
بسیاری از توسعهدهندگان برای بررسی سلامت سیستم به لاگها تکیه میکنند. اما وقتی سیستم پیش از تأیید نهاییِ اقدام در لایههای بعدی، گزارش موفقیت صادر میکند، لاگ در واقع «تلاش» را اندازه میگیرد، نه «نتیجه» را. در این مورد، داشبورد عامل سبز بود، اما خروجیها در مسیر ناپدید میشدند. کاربر متوجه شد که روزهاست هیچ موقعیت شغلی جدیدی دریافت نکرده است، در حالی که موتور جستوجو دو بار در روز اجرا میشد و گزارش میداد: «انجام شد — ۳۰ شغل جدید».
این وضعیت شبیه به سرویس پست است که به محض خروج بسته از انبار، وضعیت را به «تحویل شده» تغییر دهد، بدون اینکه اهمیت دهد بسته اصلاً به درب خانه شما میرسد یا خیر. همانطور که در تحلیلهای پیشین ما دربارهی امنیت و پایداری مدلهای عاملمحور اشاره کردیم، تکیه بر تاییدیه (Acknowledgement) بدون بررسی خروجی نهایی، بزرگترین نقطه کور مهندسی در سیستمهای AI است. در این پرونده، موتور ساعتی هر منبع را با تیک سبز تأیید میکرد، اما سیستم مدیریت مشتریان (CRM) داستان دیگری میگفت: آخرین شغل جدید سه روز پیش وارد شده بود.
کالبدشکافی یک شکست خاموش
بر اساس مستندات AIdeazz، این سیستم از چهار نقص مجزا رنج میبرد که هر کدام پشت یک پیام موفقیت گمراهکننده پنهان شده بود:
- ثبت گزارش زودهنگام: مؤلفه جستوجو پیش از ارسال دادهها به CRM، عبارت «امروز اقدام کردم» را چاپ میکرد و هرگز پاسخ سیستم مقصد را نمیخواند. از ۲۹ سپتامبر، این خط ۲۶ بار برای ۱۰ شغل مختلف چاپ شد، اما فقط ۲ مورد به قرارداد تبدیل شدند. ۱۲ مورد از تأییدیهها نام شرکت را خالی ارسال کردند چون کد بهجای مسیر لینک، زیردامنه را میخواند (مثلاً کلمه "jobs" در لینکهای Lever را بهجای مسیر اصلی میخواند)؛ CRM این موارد را با خطای HTTP 400 رد کرد، اما سیستم هرگز این خطاها را نخواند. ۱۲ مورد دیگر از تطبیقها تکراری بودند — برخی قبلاً بهعنوان «نامناسب» بسته شده بودند — بنابراین CRM صرفاً یک یادداشت اضافه کرد و وضعیت قرارداد را تغییر نداد. این چالشها یادآور تلاشهای تیم VibeJobHunterAI برای توقف نشت دادههای شغلی است که با اصلاحات سریع سعی در رفع نقصهای مشابه در استخراج دادهها داشتند.
- بلعیدن استثناها: یک بورد شغلی منطقهای از ۲ اکتبر ۲۰۲۶ تمام درخواستها را با خطای HTTP 400 رد میکرد. کد استخراج داده، پاسخهای غیر از ۲۰۰ را نادیده میگرفت و استثناها را «میبلعید»، سپس هر ساعت چاپ میکرد: «✅ ۰ شغل یافت شد». این یعنی یک قطعی کامل، شبیه به یک جستوجوی موفق اما بینتیجه جلوه کرد.
- خطاهای منطقی در حافظه: لیست «دیده شدهها» بهجای سن دادهها، بر اساس ترتیب هش (Hash) پاک میشد. این باعث شد شغلهای جدید از حافظه بیفتند و هر ۱۲ ساعت دوباره بهعنوان «جدید» شناسایی شوند. در نتیجه، ۴۸۸ ردیف پردازش شده تنها نماینده ۳۷۹ شغل متمایز بود. برای جلوگیری از چنین تکرارهای ناخواستهای، استفاده از کلیدهای عملیاتی به عنوان راهکاری برای مدیریت دستورات در عاملهای هوش مصنوعی پیشنهاد شده است.
- شکستهای مدیریتنشده API: یکسوم جستوجوهای پولی بهدلیل بدنه خالی یا غیر JSON شکست خوردند. بدون مکانیزم تلاش مجدد (Retry)، هر شکست صرفاً بهعنوان «→ ۰ نتیجه» ثبت میشد.
اصلاحات مهندسی
برای حل این بحران، تیم محرکِ ثبت گزارش را از «فرستنده» به «گیرنده» منتقل کرد. اکنون هر خط موفقیت منتظر میماند تا سیستمی که باید روی داده اقدام کند، پاسخ دهد. حالا عامل ابتدا پاسخ CRM را میخواند و تنها برای قراردادهای واقعاً جدید، عبارت «امروز اقدام کردم» را ثبت میکند. وضعیتهای دیگر صراحتاً لاگ میشوند: موارد تکراری بهعنوان «قبلاً در CRM موجود است (مرحله ...) — جدید نیست» و موارد رد شده بهعنوان «توسط CRM رد شد (کد HTTP: پیام خطا)».
سایر اصلاحات فنی عبارت بودند از:
- تجزیه بر اساس مسیر: نام شرکتها اکنون از مسیر لینک خوانده میشود و نه از زیردامنه. برای موارد خالی، یک سیستم جایگزین برای عنوانها طراحی شد که در برابر ۸۹۰ عنوان واقعیِ خالی تست شده است تا دقت آن تضمین شود.
- ثبت سختگیرانه خطاها: برای بورد شغلی متخلف، بهجای دور زدن، وضعیت «❌ ۰ شغل — ۳/۳ درخواست شکست خورد (HTTP 400)» جایگزین تیک سبز شد، زیرا شرایط استفاده از آن سایت اجازه استخراج داده (Scraping) را نمیداد. تیم یک آژانس جایگزین منطقهای را اضافه کرد که حقوق و شرایط صلاحیت را بهطور شفاف اعلام میکرد.
- حافظه FIFO: لیست دیده شدهها اکنون بهدرستی قدیمیترین ورودی را اول حذف میکند (First-In, First-Out).
- منطق تلاش مجدد: بدنههای خالی جستوجو پیش از علامتگذاری بهعنوان شکست، یک بار دیگر امتحان میشوند.
- همراستاسازی پروفایل: هدفگذاری عامل با پروفایل حرفهای منتشر شدهی کاربر همراستا شد و ۱۱ عنوان شغلی جدید اضافه شد که لایههای قبلی هرگز آنها را جستوجو نمیکردند.
اندازهگیری نتایج
تأثیر این تغییرات فوری بود. در ۵ دقیقه اول پس از استقرار، ۸ شغل جدید وارد صف اقدام شدند؛ در حالی که نرخ قبلی تنها ۲ شغل در هفته بود.
اعتبارسنجی بهجای لاگ، مستقیماً روی CRM انجام شد. بازپخش یک شغل که کاربر قبلاً بسته بود، پاسخ «تکراری، تصمیمگرفتهشده، بستهشده» را داد و لاگ CRM از «قبلاً موجود است — بهروزرسانی یادداشت» به «قبلاً تصمیمگیری شده — بدون تغییر رها شد» تغییر کرد. همچنین یک مجموعه ارزیابی شامل ۸۶۲ تست روی سرور عملیاتی اجرا شد. بازپخش قبل و بعد توسط یک «داور AI» تأیید کرد که مدل ۳ مورد از ۳ نقش مرتبط را تأیید و ۳ مورد نامرتبط را رد کرده است.
تحلیل: تلهٔ تأییدیه
این حادثه نقص بنیادین در نظارت بر عاملهای AI را افشا میکند. در سیستمهای ناهمگام (Asynchronous) — که از صفها، وبهوکها یا کارهای پسزمینه استفاده میکنند — یک پاسخ اغلب فقط «دریافت» را ثابت میکند، نه «پردازش» را. این همان «تلهٔ تأییدیه» است.
وقتی کاری را به یک ابزار ناهمگام میسپارید، پاسخ یعنی «دریافت کردم»، نه «انجام دادم». در بسیاری از موارد، حتی به معنای «قصد دارم انجام دهم» هم نیست. این ریشه بسیاری از حوادث «ناپدید شدن دادهها» است: فرستنده موفقیت را ثبت میکند، گیرنده هرگز داده را پردازش نمیکند و هر دو در انزوای خود سالم به نظر میرسند. صفی که پیام را میپذیرد اما هرگز نمیخواند، دقیقاً شبیه صفی است که درست کار میکند. این نوع آسیبپذیریهای سیستمی مشابه شکافهای امنیتی است که در Agent ID مورد بررسی قرار گرفت و نشان میدهد چگونه یک خطای کوچک در لایههای میانی میتواند منجر به اختلالات گسترده شود.
برای توسعهدهندگان، لایههای دفاعی به ترتیب قدرت عبارتاند از:
۱. بر اساس تأییدیه تصمیم نگیرید: اگر منطق جایگزین شما میگوید «اگر ارسال شکست خورد، خودم انجام دهم»، این کد هرگز اجرا نمیشود چون ارسال همیشه «موفق» گزارش میشود.
۲. مسیر محلی را بدون شرط کنید و اجازه دهید سیستم تکراریها (Idempotency) را جذب کند.
۳. از سمت مقابل تأیید بگیرید: بهجای اعتماد به رسید، یک نقطه انتهایی (Endpoint) وضعیت، رکورد نتیجه یا یک کالبک (Callback) را چک کنید.
۴. ضربالاجل تعیین کنید: اگر نتیجه در N دقیقه ظاهر نشد، آن را شکست تلقی کنید.
شکست خاموش در برابر سلامت اثباتپذیر
تیم AIdeazz اشاره میکند که شکست خاموش، «کرش» یا توقف کامل نیست. کرش بلند است و سریعاً تعمیر میشود. شکست خاموش زمانی است که یک مؤلفه تصمیمی منطقی در سطح محلی میگیرد — مثلاً حذف یک پیام یا بازگرداندن یک رشته خالی — اما هیچکس در لایههای بعدی از این موضوع باخبر نمیشود. از بیرون، یک سیستم کاملاً سالم و یک سیستم کاملاً مرده میتوانند مشاهده یکسانی داشته باشند: «هیچ اتفاقی نیفتاد».
راهکار، صرفاً «افزودن لاگهای بیشتر» نیست، بلکه «اثباتپذیر کردن حالت سالم» است. این کار نیازمند دو استراتژی است:
- ثبت نتیجه، نه تلاش: عبارت «در حال ارسال اعلان» بیفایده است. عبارت «اعلان تحویل شد (شناسه ۴۶۶۱)» در مقابل «اعلان رد شد ۴۰۰» تمام داستان را میگوید.
- اجرای کاناری (Canary): یک تراکنش مصنوعی که بهصورت زمانبندی شده از مسیر واقعی عبور کند؛ اگر این تراکنش به مقصد نرسید، سیستم باید فریاد بزند. بدون آن، شما برای فهمیدن قطعی سیستم، به گزارش مشتری متکی هستید.
اعتبارسنجی بهجای پیکربندی
تیم AIdeazz نسبت به اعتبارسنجی سیستمها از طریق فایلهای پیکربندی هشدار میدهد. وجود یک کلید API یا یک زمانبندی تنظیمشده، بیانگر «قصد» است، نه «رفتار». شکاف بین این دو، جایی است که طولانیترین قطعیها در آن رخ میدهند، چون خواندن تنظیمات شبیه به اعتبارسنجی به نظر میرسد.
این منجر به جملات مطمئن اما غلطی میشود: «کلید تنظیم شده، پس سرویسدهنده کار میکند» یا «زمانبندی روی ۱۵ دقیقه است، پس اجرا میشود». برای جلوگیری از این خطا، مهندسان باید:
- وابستگی را تست کنند، نه اعتبارنامه را بخوانند: یک کلید API هیچ چیز درباره موجودی حساب یا فعال بودن اکانت پشت آن نمیگوید.
- به دنبال خطِ اقدام بگردند، نه خطِ راهاندازی: بنر استارتآپ ثابت میکند پروسه شروع شده، نه اینکه کاری انجام داده است.
- برچسبهای زمانی را بعد از استقرار مقایسه کنند: اگر پروسه در حال اجرا قدیمیتر از فایل روی دیسک است، یعنی هنوز نسخه قبلی از حافظه اجرا میشود.
قانون نهایی این حادثه: هرگز رفتار سیستم را از روی پیکربندی آن گزارش نکنید. خطی را پیدا کنید که ثابت کند رفتار رخ داده است و آن را نقل کنید.
گام بعدی شما
- لاگهای سیستم خود را بازبینی کنید و هر جا عبارت «در حال ارسال» یا «درخواست شد» میبینید، آن را به «تأیید شد توسط [مقصد]» تغییر دهید.
- یک تراکنش مصنوعی (Canary) طراحی کنید که هر ساعت یک داده تستی را از ابتدا تا انتهای زنجیره عاملهایتان عبور دهد.
- بهجای چک کردن فایل
.envیا تنظیمات Cron، یک اسکریپت ساده بنویسید که آخرین خروجی واقعی در دیتابیس را با زمان فعلی مقایسه کند.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو