پرش به محتوای اصلی
پرش به محتوای مقاله

«بازیابی‌پذیری در مقیاس»؛ هدف جدید ماشین‌های وضعیت در سیستم‌های AI

·۳ شهریور ۱۴۰۵۱۳ دقیقه مطالعه۱ بازدید
راهنما
آموزش ساخت گردش کار عامل هوشمند با صف توانی و قابلیت بازیابی
آموزش ساخت گردش کار عامل هوشمند با صف توانی و قابلیت بازیابی
اشتراک‌گذاری
واقعاً چه چیز جدید است؟

معرفی متدولوژی «کلید هم‌توان» و «ماشین وضعیت» برای تبدیل اجرای خطی عامل‌های AI به جریان‌های کاری بازیابی‌پذیر؛ تفکیک صریح بین شکست منطقی تسک و عدم در دسترس بودن سرویس‌های بالادستی (مانند اشتراک ChatGPT).

تصور کنید یک عامل هوش مصنوعی در حال مدیریت صدها مخزن کد است و ناگهان در میانه راه کرش می‌کند؛ حالا باید تصمیم بگیرید که آیا همه چیز را از اول اجرا کنید یا ریسک تکرار عملیات حساس مثل پرداخت یا ارسال کد را بپذیرید. اگر هنوز از حلقه‌های ساده‌ی «تلاش مجدد» (Retry) استفاده می‌کنید، احتمالاً با کابوسی از کامیت‌های تکراری، اعلان‌های redundant و هزینه‌های سرسام‌آور API رو‌به‌رو هستید. در واقع، وقتی یک عامل هوش مصنوعی تنها یک فایل را مدیریت می‌کند، «تلاش مجدد پس از شکست» حرکتی کم‌ریسک است، اما به محض اینکه وظایف به ده‌ها مخزن، صدها فایل یا چندین رابط خارجی گسترش می‌یابند، اجرای مجدد ساده باعث بازنویسی وضعیت‌ها (State Overwrites) و اتلاف هزینه‌ها می‌شود.

به نقل از راهنمای فنی منتشر شده در dev.to در ۲۵ اوت ۲۰۲۶، معماری مبتنی بر صف‌های هم‌توان (Idempotent Queues) می‌تواند اسکریپت‌های شکننده را به جریان‌های کاری مهندسی قابل بازیابی تبدیل کند. اکثر توسعه‌دهندگان اجرای عامل‌ها را یک وضعیت دوگانه (موفق یا شکست‌خورده) می‌بینند، اما در مقیاس صنعتی، این نگاه باعث می‌شود سیستم نتواند تشخیص دهد که یک عملیات حساس — مثل یک git push یا فعال‌سازی یک پرداخت — دقیقاً قبل از شکست انجام شده یا بعد از آن.

همان‌طور که در تحلیل قبلی ما درباره‌ی کاهش هزینه‌های عملیاتی در AWS Kiro اشاره کردیم که چگونه ادغام GPT-5.6 هزینه‌های تسک را تا ۸۲٪ کاهش داد، تمرکز صنعت اکنون از «بهره‌وری خام» به «پایداری عملیاتی» تغییر کرده است. برای رسیدن به این پایداری، یک سیستم باید بتواند به چهار پرسش کلیدی پاسخ دهد: وضعیت فعلی چیست؟ آیا این ورودی قبلاً پردازش شده است؟ بازیابی باید از کجا شروع شود؟ و چگونه یک انسان می‌تواند با ایمنی کامل کنترل را به دست بگیرد؟

معماری ماشین وضعیت

عامل‌های قابل‌اعتماد باید از حلقه‌های ساده به یک ماشین وضعیت (State Machine) — شبیه به یک نقشه راه دقیق که هر مرحله را تایید می‌کند تا هیچ قدمی جا نماند — منتقل شوند. به جای استفاده از یک حلقه ساده مانند for repo in repositories: run_agent(repo) که توسعه‌دهنده را در این مورد که آیا مخزن هفدهم قبل یا بعد از کامیت شکست خورده است به حدس و گمان وا می‌دارد، هر تسک باید در یکی از شش وضعیت صریح زیر باشد:

  • در انتظار (Pending): منتظر تخصیص به یک Worker برای دریافت اجاره (Lease)؛ در این وضعیت تلاش مجدد خودکار مجاز است.
  • در حال اجرا (Running): در حال اجرا با یک اجاره فعال. سیستم در اینجا شناسه Worker و زمان اجاره را ثبت می‌کند و تلاش مجدد خودکار غیرفعال است.
  • تلاش مجدد (Retry): شکست موقت در انتظار یک دوره عقب‌نشینی (Backoff)؛ تسک پس از یک تأخیر دوباره وارد صف می‌شود و تلاش مجدد مجاز است.
  • بازبینی (Review): نتایج پرریسک یا مبهم که نیاز به مداخله انسانی دارد. تسک برای تأیید دستی متوقف می‌شود و تلاش مجدد خودکار غیرفعال است.
  • انجام شده (Done): تکمیل و تایید شده. سیستم خلاصه‌ای از نتیجه را ذخیره می‌کند و تلاش مجدد غیرفعال است.
  • شکست خورده (Failed): اتمام بودجه تلاش‌ها (Retry Budget). شواهد خطا برای عیب‌یابی حفظ شده و تلاش مجدد غیرفعال است.

این ساختار تضمین می‌کند که یک تسک «انجام شده» به‌طور تصادفی دوباره توسط یک Worker اجرا نشود و تسک‌های «بازبینی» توسط یک تایمر به‌طور خودکار از سر گرفته نشوند. تمام تغییرات باید از طریق انتقال‌های کنترل‌شده بین این وضعیت‌ها رخ دهد.

پیاده‌سازی کلیدهای هم‌توان

برای جلوگیری از اجرای تکراری یک ورودی، این چارچوب از کلید هم‌توان (Idempotency Key) استفاده می‌کند تا «یک رویداد تجاری واحد» را شناسایی کند. این کلید نباید شامل اعداد تصادفی یا برچسب‌های زمانی جاری باشد، زیرا در این صورت هر تلاش مجدد به عنوان یک تسک کاملاً جدید شناخته می‌شود و هدف هم‌توانی از بین می‌رود.

بر اساس مستندات این راهنما، پیشنهاد می‌شود از هش SHA-256 یک شیء JSON استاندارد (Canonical) شامل موارد زیر استفاده شود:

  • نام مخزن (به صورت نرمال‌شده: حروف کوچک و حذف فضاهای خالی)
  • شاخه هدف (Target Branch)
  • نوع عملیات (مثلاً generate-tests)
  • محتوای ورودی (مانند ID تیکت DEV-1024 و مسیرهای مشخص فایل‌ها)
  • نسخه جریان کاری (مثلاً 2026-08-25-v1)

با گنجاندن workflow_version (نسخه جریان کاری)، توسعه‌دهندگان می‌توانند سیستم را مجبور کنند تا تسک‌های قدیمی را در صورت تغییر پرامپت، قوانین پذیرش یا منطق عامل، دوباره پردازش کند. اگر ورودی یکسان باقی بماند، محدودیت‌های یکتایی (Unique Constraint) در پایگاه‌داده از ایجاد رکوردهای تکراری جلوگیری می‌کند. این امر باعث حذف Race Conditionهای رایج در منطق «بررسی سپس درج» (check-then-insert) می‌شود؛ جایی که دو پروسه ممکن است هم‌زمان تشخیص دهند تسکی وجود ندارد و هر دو اقدام به ایجاد آن کنند.

مکانیزم صف SQLite و اجاره

برای ابزارهای محلی یا ابزارهایی با هم‌زمانی پایین، استفاده از SQLite توصیه شده است. در این مدل، علاوه بر وضعیت، یک «اجاره» (Lease) تعریف می‌شود که مالکیت محدود به زمانِ یک تسک را برای یک Worker مشخص می‌کند. جدول agent_jobs در دیتابیس شامل فیلدهایی برای idempotency_key (یکتا)، attempts (تعداد تلاش‌ها)، max_attempts (پیش‌فرض ۳)، leased_by (توسط چه کسی اجاره شده)، lease_until (تا چه زمانی اجاره شده) و next_run_at (زمان اجرای بعدی) است.

جزئیات پیاده‌سازی صف:

  • طراحی طرحواره: جدول agent_jobs از یک INTEGER PRIMARY KEY AUTOINCREMENT و یک ایندکس idx_agent_jobs_ready روی ستون‌های (status, next_run_at, lease_until) استفاده می‌کند تا عملیات Polling توسط Workerها بهینه شود.
  • امنیت: داده‌های موجود در payload_json باید فقط شامل حداقل اطلاعات مورد نیاز برای اجرا باشد. اطلاعات حساس مانند رمزهای عبور ChatGPT، کوکی‌ها، نشست‌ها (Sessions)، اطلاعات پرداخت یا API Keyها نباید در دیتابیس ذخیره شوند و باید در زمان اجرا از طریق Key Storeهای سیستم‌عامل یا CI Secrets تزریق گردند.
  • کنترل هم‌زمانی: سیستم از دستور INSERT OR IGNORE بر اساس کلید هم‌توان یکتا استفاده می‌کند. این تضمین می‌کند که اولین درخواست ثبت (Enqueue) مقدار True برگرداند و درخواست‌های مشابه بعدی بدون ایجاد تکرار، مقدار False برگردانند.

اجاره‌ها مانع از آن می‌شوند که چندین Worker هم‌زمان یک تسک را بردارند. اگر یک Worker کرش کند، اجاره منقضی شده و Worker دیگری می‌تواند با ایمنی کامل تسک را بازپس گیرد. راهنما هشدار می‌دهد که زمان اجاره باید محافظه‌کارانه باشد؛ برای یک تسک دو دقیقه‌ای، اجاره پنج دقیقه‌ای توصیه می‌شود. تسک‌های طولانی‌مدت باید یک مکانیزم Heartbeat (ضربان قلب) برای تمدید اجاره پیاده کنند تا تایید شود که شناسه leased_by هنوز مربوط به Worker فعلی است. برای عملیات‌های برگشت‌ناپذیر — مانند کسر وجه از مشتری یا حذف منابع — سیستم باید به جای تکیه صرف بر Timeoutهای اجاره، از نقاط بازرسی (Checkpoints) صریح استفاده کند.

طبقه‌بندی خطاها و حضور انسان در حلقه

همه خطاها یکسان نیستند. سیستم برای جلوگیری از اتلاف اعتبار API و جلوگیری از ایجاد حلقه‌های خودکار خطرناک، بین شکست‌های گذرا و دائمی تمایز قائل می‌شود:

  • قابل تلاش مجدد (Retryable): شامل Timeoutهای شبکه، Resetهای اتصال، خطاهای 503 و محدودیت‌های نرخ 429. این خطاها باعث فعال شدن یک «عقب‌نشینی نمایی» (Exponential Backoff) می‌شوند (مثلاً 15 * (2^attempt)) که با مقداری Jitter تصادفی همراه است تا از مشکل Thundering Herd (هجوم هم‌زمان درخواست‌ها) جلوگیری شود.
  • نیازمند بازبینی (Review Required): خطاهای دسترسی 401/403، نتایج مبهم خارجی (مثلاً قطع اتصال بلافاصله بعد از یک git push) یا تست‌هایی که علی‌رغم تغییرات کد، مدام شکست می‌خورند. این موارد تسک را به صف بازبینی انسانی منتقل می‌کنند زیرا تلاش مجدد خودکار در این شرایط معمولاً بی‌معنی است.
  • شکست قطعی (Failed): خطاهای اعتبارسنجی ورودی (مانند نبود مخزن یا شاخه مورد نظر) که اجرای تسک را اساساً غیرممکن می‌کند.

در محیط عملیاتی، پیش‌فرض قرار دادن وضعیت «بازبینی» ایمن‌تر از تلاش‌های مجدد بی‌نهایت است. همچنین، این خطاها باید بر اساس انواع Exceptionهای خاص SDK طبقه‌بندی شوند، نه از طریق تطبیق ساده رشته‌های متنی (String Matching).

جداسازی تاییدیه از اشتراک سرویس

این چارچوب تاکید می‌کند که ادعای «پایان کار» توسط یک عامل، به معنای سیگنال تکمیل واقعی نیست. یک مرحله تاییدیه (Verification) — مانند اجرای pytest -q یا git diff --check — الزامی است تا پیش از تغییر وضعیت به «انجام شده»، یک Digest از نتیجه تولید شود. برای دایرکتوری‌های پرریسک که شامل احراز هویت، صورت‌حساب یا استقرار (Deployment) هستند، سیستم باید قانونی را اجرا کند که تمام تغییرات فارغ از گزارش موفقیت عامل، وارد وضعیت «بازبینی» شوند.

نکته کلیدی این است که سیستم باید «در دسترس نبودن سرویس» را از «شکست تسک» تفکیک کند. برای کاربرانی که از ChatGPT Plus، Pro یا Codex استفاده می‌کنند، انقضای اشتراک، شکست در پرداخت یا محدودیت‌های مصرف باید به عنوان رویدادهای سرویس بالادستی (Upstream Service Events) با برچسب‌هایی مانند symptom: service_unavailable ثبت شوند، نه اینکه تسک کدنویسی به عنوان «شکست خورده» علامت‌گذاری شود.

جزئیات مدیریت اشتراک:

  • ثبت رویدادها: شکست‌های بالادستی باید با فیلدهای غیرحساس ثبت شوند: service (مثلاً "codex"), check_time, account_tier_expected (مثلاً "plus_or_pro") و job_id متأثر.
  • پروتکل تاییدیه: هنگام بررسی موفقیت شارژ مجدد حساب‌های ChatGPT Plus، Pro یا Codex، توسعه‌دهندگان باید فقط صفحات رسمی حساب و وضعیت سفارشات را بررسی کنند. آن‌ها هرگز نباید رمز عبور، کوکی یا توکن‌های نشست را در اختیار اسکریپت قرار دهند.
  • مسیر بازیابی: پس از بازیابی حساب، تسک‌ها باید از آخرین نقطه بازرسی (Checkpoint) خود ادامه یابند، نه اینکه کل صف پاک شود.

اعتبارسنجی از طریق تزریق خطا

برای اثبات اینکه سیستم واقعاً بازیابی‌پذیر است، راهنما پیشنهاد می‌کند خطاهایی را به‌صورت عمدی در مراحل خاص تزریق کنید: مثلاً کرش کردن سیستم بلافاصله بعد از نوشتن یک فایل، خروج بعد از اجرای تست‌ها، یا شبیه‌سازی یک Timeout. یک سیستم بازیابی‌پذیر واقعی باید نشان دهد که شمارنده attempts افزایش می‌یابد اما هیچ اثر جانبی تکراری (Duplicate Side Effect) در هنگام شروع مجدد رخ نمی‌دهد.

سناریوهای تست توصیه شده عبارتند از:

  • کرش کردن Worker بلافاصله پس از دریافت یک تسک.
  • به دست گرفتن تسک توسط Worker دوم پس از انقضای اجاره اول.
  • تلاش‌های هم‌زمان برای ثبت یک کلید هم‌توان یکسان در صف.
  • رسیدن به حد max_attempts.
  • موفقیت در یک اقدام خارجی اما گم شدن پاسخ (که باید منجر به وضعیت «بازبینی» شود).

تمام زمان‌های ذخیره شده باید از UTC استفاده کنند تا از Drift منطقه زمانی جلوگیری شود. اگر زمان اجرای یک تسک از زمان اجاره بیشتر شود، تمدید Heartbeat باید هم از Job ID و هم از Worker ID استفاده کند تا از بازنویسی تصادفی اجاره توسط یک Worker قدیمی جلوگیری شود.

تحلیل: تغییر پارادایم عامل‌های هوش مصنوعی

این رویکرد، عامل هوش مصنوعی را از یک «چت‌بات با اسکریپت» به یک سیستم توزیع‌شده در سطح تولید (Production-grade) تبدیل می‌کند. برای یک توسعه‌دهنده، این یعنی تفاوت بین گذراندن یک آخر هفته برای پاک‌سازی PRهای تکراری و داشتن سیستمی که بتوان آن را با اطمینان شبانه اجرا کرد.

متریک‌های کلیدی مشاهده باید بر «اقدام» متمرکز باشند، نه فقط لاگ‌ها. توسعه‌دهندگان باید موارد زیر را ردیابی کنند:

  • تعداد تسک‌های Pending در مقابل Running
  • نرخ تلاش مجدد (Retry Rate) که نشان‌دهنده ناپایداری سرویس‌های خارجی است.
  • نرخ بازبینی (Review Rate) که نشان‌دهنده تقسیم‌بندی ضعیف تسک‌ها یا مشکلات دسترسی است.
  • تکرار Timeoutهای اجاره که نشان می‌دهد تسک‌ها بیش از حد ریز هستند یا Heartbeatها شکست می‌خورند.

با تلقی کردن LLM به عنوان یک جزء غیرقابل‌اعتماد در یک پوشش (Wrapper) قابل‌اعتماد، بار مهندسی از «تنظیم پرامپت» به «مدیریت وضعیت» منتقل می‌شود. این تکامل ضروری است تا عامل‌ها بتوانند عملیات‌های حساس مانند صورت‌حساب یا استقرار زیرساخت را مدیریت کنند، جایی که یک اقدام تکراری می‌تواند فاجعه‌بار باشد.

برای پیاده‌سازی این مدل، توسعه‌دهندگان باید ابتدا اسکریپت‌های فعلی خود را برای شناسایی «اثرات جانبی نامرئی» بازبینی کنند و با پیاده‌سازی یک جدول وضعیت ساده در SQLite برای پرتکرارترین تسک‌های خود شروع نمایند.

  • اسکریپت‌های فعلی عامل‌های خود را برای شناسایی «اثرات جانبی نامرئی» (مانند تغییرات دیتابیس بدون لاگ) بازبینی کنید.
  • برای تسک‌های پرتکرار، یک جدول وضعیت ساده در SQLite پیاده‌سازی کنید تا از اجرای تکراری جلوگیری شود.
  • استراتژی عقب‌نشینی نمایی را برای مدیریت خطاهای 429 (Rate Limit) در APIهای هوش مصنوعی جایگزین حلقه‌های ساده کنید.

اما مدیریت حافظه در این مقیاس چالش‌های پیچیده‌تری دارد — به تحلیل ما درباره‌ی پروتکل زمینه مدل (MCP) مراجعه کنید.

چرا این موضوع مهم است؟

این معماری با تکیه بر استانداردهای مهندسی نرم‌افزار (تخصص در سیستم‌های توزیع‌شده)، ریسک مالی و عملیاتی استفاده از AI Agents را در مقیاس سازمانی به شدت کاهش می‌دهد. اکنون توسعه‌دهندگان می‌توانند عامل‌ها را برای عملیات‌های طولانی‌مدت رها کنند بدون اینکه نگران تکرار تراکنش‌ها یا اتلاف بودجه API باشند.

تأثیر برای ایران

برای توسعه‌دهندگان ایرانی که با محدودیت‌های API و قطع‌وشدهای احتمالی دسترسی رو‌به‌رو هستند، پیاده‌سازی این سیستم بازیابی ضروری است تا از اتلاف اعتبارهای گران‌قیمت API در اثر کرش‌های ناگهانی جلوگیری شود.

·نگاه ما
تحریریه دات‌هوش

این رویکرد، پارادایم عامل‌های هوش مصنوعی را از «چت‌باتی که اسکریپت اجرا می‌کند» به «سیستم‌های توزیع‌شده در سطح تولید» تغییر می‌دهد. با تبدیل LLM به یک جزء غیرقابل‌اعتماد در یک پوشش (Wrapper) قابل‌اعتماد، بار مهندسی از «تنظیم پرامپت» به «مدیریت وضعیت» منتقل می‌شود. این تنها راه برای سپردن عملیات‌های حساس مثل مدیریت زیرساخت یا پرداخت‌ها به عامل‌هاست، جایی که یک اقدام تکراری می‌تواند فاجعه‌بار باشد.

منابع

این گزارش با خط‌لولهٔ خودکار دات‌هوش از منابع معتبر جهانی تدوین و زیر نظر تحریریه منتشر شده است. روش کار ما

گفتگو

پنج‌شنبه‌های هوش‌محور

بسته‌ی هفتگی دات‌هوش

۵ خبر، ۲ ابزار، ۱ پرامپت در هر شماره. به‌زودی راه‌اندازی می‌شود — هر پنج‌شنبه صبح.

خبر کلیدی
ابزار کاربردی
پرامپت حرفه‌ای
تحلیل پژوهش
به‌زودی
زاویه‌ی ایرانی
به‌زودی
تمرین این هفته
به‌زودی

راهنماهای دات‌هوش

راهنماهای کاربردیِ دات‌هوش برای کار با هوش مصنوعی — از همین‌جا شروع کنید:

دات‌هوش

راهنمای فارسی هوش مصنوعی — با نگاه به ایران

اخبار روزانه، معرفی ابزارها و مدل‌ها، و آموزشِ کار با هوش مصنوعی؛ همیشه با این پرسش که از ایران چه چیزی کار می‌کند و چه چیزی نه.