اگر امروز در حال توسعهی یک عامل هوش مصنوعی هستید، احتمالاً با کابوسِ «وضعیتهای ناسازگار» پس از یک خطای ابزاری دستوپنجه نرم میکنید. این مشکل ریشه در یک اشتباه بنیادین در معماری اکثر عاملهای فعلی دارد: اتکا به یک حلقهی تکرار ساده برای مدیریت حافظه.
معماری استاندارد برای عاملهای هوش مصنوعی در واقع یک اسکریپت پیشرفته است: یک حلقهی while (true) که مدام یک شیء وضعیت (State) واحد را بهروزرسانی میکند. این طراحی که در ابزارهایی مانند Claude Code، Codex، Pi و اکثر عاملهای متنباز استفاده شده است، یک نقطهی شکست بحرانی ایجاد میکند؛ جایی که هرگونه وقفه یا خطای ابزاری، عامل را در وضعیتی ناسازگار رها میکند. در واقع، وابستگی شدید مقیاسپذیری عاملها به این معماری حلقوی است که باعث میشود در محیطهای پیچیده با شکست مواجه شوند.
اکثر کدهای مربوط به عاملها از یک اسکلت مشابه پیروی میکنند: let state = {}; while (true) { const plan = await llm.plan(state); const results = await runTools(plan); state = updateState(state, results); if (isDone(state)) break; }. این اولین طراحی طبیعی است که در آن مدل زبانی بزرگ (LLM) نقش مغز، حلقه نقش قلب و وضعیت (State) صرفاً کیسهای از اشیاء انباشتهشده را ایفا میکند. در حالی که این مدل برای دموها کاربرد دارد، اما در محیطهای عملیاتی (Production) شکست میخورد.
همانطور که در تحلیلهای پیشین ما دربارهی مدیریت حافظه در مدلهای زبانی اشاره کردیم، تکیه بر حافظه کوتاهمدت بدون ساختار، منجر به توهمات مدل در جلسات طولانی میشود. طبق گزارش فنی مفصلی که در ۱۸ اوت ۲۰۲۶ در وبسایت dev.to منتشر شد، همین الگوی «حلقه» دلیل اصلی عدم قابلیت اطمینان عاملها در محیطهای واقعی است. وقتی یک فرآیند در میانه راه متوقف میشود یا ابزاری پاسخ نمیدهد، وضعیت تغییرپذیر مدل، دروغی درباره اتفاقات رخداده به توسعهدهنده میگوید.
شکافهای موجود در معماری حلقوی
در سیستمهای مبتنی بر حلقه، چندین مشکل ساختاری و سیستمیک بروز میکند:
- توقفها بهعنوان یک راهکار موقت (Hack): اگر کاربر فرآیند را در میانه یک نوبت متوقف کند یا مدل برای شفافسازی سوالی بپرسد، شما با یک تکرار نیمهتمام در وضعیت مدل مواجه میشوید. در این حالت، شما مجبورید یا کل آن تکرار را دور بریزید یا آن را در همان مکان وصلهپینه کنید.
- مدیریت پیچیدهی خطاهای خاص: شکست ابزارها نیازمند بلوکهای پیچیدهی try/catch است. توسعهدهندگان در نهایت با دهها شاخهی کدِ موردی (ad-hoc) مواجه میشوند تا نوبتهایی را که بهطور تمیز به پایان نرسیدهاند، مدیریت کنند. این پیچیدگیها باعث میشود که تست عاملها باید از اعتبارسنجی صرف کد به سمت ارزیابی رفتار تغییر کند تا بتوان نقصهای عملیاتی را شناسایی کرد.
- موازیسازی دشوار و ناشیانه: وقتی مدل میخواهد همزمان دو دستور (مثلاً read و grep) را اجرا کند، حلقه باید یا آنها را بهصورت متوالی اجرا کند و یا Promiseها را ایجاد کرده و نتایج را پیش از اجرای
llm.plan()بعدی بازسازی کند. این امر سربار مدیریت وضعیت را افزایش میدهد. - عدم قابلیت بازگشت (Rewind): چون وضعیت مجموعهای از اشیاء تغییرپذیر است، شما نمیتوانید از یک نقطهی خاص در گذشته شاخه بزنید یا دقیقاً آنچه مدل دیده است را بازپخش کنید، مگر اینکه کل جلسه را بهصورت دستی بازسازی کنید.
تصور کنید عامل شما یک آشپز است. در معماری حلقوی، آشپز فقط وضعیت فعلی غذا را به یاد میآورد. اگر تابه از دستش بیفتد، ممکن است فراموش کند که قبلاً نمک زده است و در نتیجه غذا را خراب کند. برای حل این مشکل، توسعهدهندگان معمولاً لایههای پیچیدهای از مدیریت خطا و شاخههای موردی اضافه میکنند که فقط بدهی فنی (Technical Debt) را افزایش میدهد.
جایگزین: رویکرد EventStore
راهکار پیشنهادی این است که بهجای یک شیء وضعیت تغییرپذیر، از «لاگ» (Log) بهعنوان منبع حقیقت (Source of Truth) استفاده شود. در این مدل، وضعیت تنها برآیند یا تصویری (Projection) از آن لاگ است. هر پیام، فراخوانی ابزار، نتیجه و ویرایش فایل به یک ردیف در پایگاهدادهای به نام EventStore تبدیل میشود.
ساختار دادهای زیربنایی این سیستم به شکل زیر است:CREATE TABLE events ( sequence INTEGER PRIMARY KEY, event_id TEXT, type TEXT, payload_json TEXT, caused_by TEXT, thread_id TEXT, ... );
در این حالت، زمان اجرا (Runtime) وضعیت را در حافظه موقت نگه نمیدارد؛ بلکه صرفاً انتهای لاگ را میخواند، رویداد بعدی را به پردازشگر مربوطه میفرستد و نتیجه را دوباره به انتهای لاگ اضافه میکند.

این تغییر، هر «نوبت» (Turn) را از یک تکرار حلقه به یک «انتقال وضعیت» تبدیل میکند. رابط کاربری (UI)، بستر مدل (LLM Context) و درخت جلسات همگی تنها پرسوجوهایی (Query) روی همین لاگ واحد هستند. این معماری قابلیتهای سطح بالایی را فعال میکند:
- درختهای جلسه شبیه به Git: چون هر پیام یک رویداد با اشارهگر
caused_byاست، گفتگو بهطور طبیعی به شکل یک درخت در میآید. شما میتوانید از هر پیام قبلی فورک کنید، به عقب برگردید، شاخه بزنید و ادامه دهید. این یک قابلیت «برگشت» (Undo) ساده نیست، بلکه نتیجهی مستقیم ساختار دادههاست. - بستر نامحدود: دیگر دکمهای برای «شروع چت جدید» وجود ندارد. شما میتوانید روزها، هفتهها یا سالها با همان فضای کاری صحبت کنید. عامل بستر خود را با بازسازی انتهای لاگ مدیریت میکند، بهجای آنکه هر بار با یک چت خالی شروع کند.
- رابطهای یکپارچه: اپلیکیشن دسکتاپ، ترمینال (TUI)، سرور JSON-RPC و CLI تکمرحلهای همگی از یک جریان رویداد واحد (
SessionFacade) تغذیه میشوند. آنها نمایشهای متفاوتی از یک لاگ هستند؛ بنابراین شروع یک جلسه در ترمینال و باز کردن آن در دسکتاپ، دقیقاً همان جریان را نمایش میدهد. - ارتباط بینعاملی: یک عامل در فضای کاری A میتواند یک رویداد «اطلاعرسانی» (tell) به عامل در فضای B بفرستد. فضای B وظیفه را در لاگ رویدادهای خود پردازش کرده و نتیجه را بازمیگرداند. این ساختار تضمین میکند که فایلهای پروژه و بستر فضای B هرگز به لاگ فضای A نشت نکند.
پیادهسازی عملی: عامل Pizza
این مفاهیم در پروژه متنباز Pizza (موجود در github.com/tomsun28/pizza) پیاده شدهاند. Pizza بهجای فهرستی طولانی از ابزارهای خاص (مانند read_file یا write_file یا grep یا git)، از یک ابزار واحد CLI استفاده میکند.
در حالی که دستورات داخلی مثل read و write و edit توسط پردازشگرهای ساختاریافته داخلی مدیریت میشوند، سایر دستورات — از جمله grep و sed و git و npm و python و ls — مستقیماً به شل (Shell) کاربر فرستاده میشوند. این کار مدل را مجبور میکند شل را یاد بگیرد، اما اجازه میدهد خطلولههای (Pipelines) واقعی بسازد. چون هر فراخوانی CLI یک رویداد است، لاگ همیشه سازگار میماند: یک ردیف برای read، یک ردیف برای git diff و یک ردیف برای npm test.
یکی از ویژگیهای برجسته، قابلیت pizza-self-optimization است. این مهارت اختیاری به عامل اجازه میدهد لاگ رویدادهای محلی را بهعنوان مدرک بخواند، مخزن Pizza را فورک کند، باگی را از روی لاگ بازتولید کند، تست بنویسد و یک PR ارسال کند. این تنها بهدلیل وجود رکورد دقیق و بازتولیدپذیر در Event Log ممکن است.
موازنههای مهندسی
البته Event Sourcing بدون هزینه نیست. بر اساس گزارش dev.to، قرار دادن پایگاهداده در مسیر اصلی اجرا (Hot Path) چالشهای جدیدی ایجاد میکند:
- هزینههای عملکردی: توسعهدهندگان باید هزینه بازپخش (Replay) و اندازه لاگ را مدیریت کنند. اگر یک جلسه به چند هزار رویداد برسد، بازسازی بستر از روی لاگ در هر فورک کند میشود و نیاز به «اسنپشاتهای متمرکز» (Materialized Snapshots) دورهای ایجاد میکند.
- از دست رفتن سادگی: دیگر نمیتوان یک شیء بزرگ را بهسادگی در حافظه نگه داشت. اگر زمان اجرا نیاز به دانستن چیزی داشته باشد، آن چیز باید در یک رویداد ثبت شده باشد. هر چیزی خارج از لاگ، یک اثر جانبی نامرئی و در واقع یک باگ احتمالی است.
این چرخش معماری، پیشفرضهای بنیادین طراحی عامل را تغییر میدهد. در حالی که الگوی while(true) همچنان پیشفرض مناسبی برای آموزشهای ساده است، اما انتزاع اشتباهی برای جلسات طولانی و همکاری چندعاملی است. صنعت در حال حرکت از «اسکریپتهایی که LLM را صدا میزنند» به سمت «سامانههای خودمختار دادهمحور» است. برای توسعهدهندگان، این بدان معناست که مشکلات سختِ عیبیابی و همکاری چندعاملی، بهجای کابوسهای پیچیدهی مدیریت وضعیت، به عملیاتهای معمولی پایگاهداده تبدیل میشوند.
گام بعدی شما
- اگر از Agentهای متنباز استفاده میکنید، بررسی کنید آیا وضعیت (State) آنها در صورت کرش کردن سیستم بازیابی میشود یا خیر.
- مخزن Pizza را در گیتهاب بررسی کنید تا ببینید چگونه یک CLI واحد میتواند جایگزین دهها ابزار سختافزاری شود.
- در طراحی سیستمهای خود، بهجای ذخیره وضعیت نهایی، ذخیره «تاریخچه تغییرات» (Event Log) را امتحان کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو