یکی از خطاهای رایج در پروژههای مبتنی بر ایجنتهای هوش مصنوعی، تکیه بر تاریخچهی گفتوگو (Chat History) برای پیگیری کارها است. با بسته شدن پنجرهی گفتوگو یا شروع نوبت کاری جدید، ایجنت زمینهی کاری را از دست میدهد، فایلهای قدیمی را مبنا قرار میدهد و کارهای پایانیافته را دوباره بازنویسی میکند. این رفتارهای تکراری مستقیماً زمان و هزینهی توکن را هدر میدهند.
راهحل این چالش، تعریف «حافظهی مخزن» (Repo Memory) است؛ روشی که در آن وضعیت ایجنت بهجای رشتههای گذرا، درون فایلهای ساختاریافتهی JSON در خودِ گیت ذخیره میشود. با تعریف قرارداد از طریق JSON Schema و استفاده از تکنیک نوشتن اتمیک (Atomic Write)، فایلهای پروژه دچار خرابی ناشی از خطاهای لحظهای نمیشوند و اعضای تیم در بازبینی کدها دید کاملی نسبت به وضعیت هر وظیفه دارند.
تاریخچهی چت فرّار است، اما مخزن کد ماندگار. میز کار (workbench)، وضعیت ایجنت را در فایلهای دارای نسخهبندی ذخیره میکند تا نشست بعدی، ایجنت بعدی و بازبین بعدی، همگی از یک مبنای حقیقت واحد بخوانند.
اهداف یادگیری
- تعیین مرز میان دادههایی که به حافظهی مخزن تعلق دارند و دادههایی که جایشان در تاریخچهی چت است.
- تدوین اسکیمای JSON برای فایلهای
agent_state.jsonوtask_board.json. - ساخت یک مدیر وضعیت (state manager) که وضعیت را بهصورت اتمیک بارگذاری، اعتبارسنجی، دگرگون و پایدار کند.
- استفاده از اسکیما برای پسزدن دادههای نامعتبر پیش از خرابشدن میز کار.
صورت مسئله
نوبت کاری ایجنت تمام میشود. پنجرهی چت بسته میشود. نشست بعدی باز میشود و میپرسد کار را از کجا شروع کند. مدل میگوید: «بگذارید فایلها را بررسی کنم»، یادداشتهای بیاتشده را میخواند و کاری را که قبلاً انجام شده بود دوباره از نو تکرار میکند. یا بدتر، فایلی نهاییشده را بازنویسی میکند، چون هیچکس نگفته بود کار آن فایل تمام شده است.
راهحل میز کار برای این مشکل، حافظهی مخزن (repo memory) است: وضعیت درون فایلهای JSON در خودِ مخزن مینشیند، مطابق یک اسکیما نوشته میشود، بهصورت اتمیک ذخیره میگردد و بازبینی تفاوتهایش (diff) در کد ساده است. چت، فیدی گذرا و موقتی است؛ این مخزن است که سیستم مرجع (system of record) به شمار میرود.
مفهوم
چه دادههایی به حافظهی مخزن تعلق دارند
| جایشان در مخزن است | جایشان در مخزن نیست |
|---|---|
| شناسهی وظیفهی فعال | متن خام تاریخچهی چت |
| فایلهای دستخورده در این نشست | ردگیری محاسبات استدلال در سطح توکن |
| فرضیاتی که ایجنت در نظر گرفته است | جملاتی مثل «بهنظر میرسید کاربر کلافه شده» |
| موانع و بلاکرهای باز | پاسخهای تکمیلی نمونهگیریشده (sampled completions) |
| اقدام بعدی | شناسهی مدلها بر اساس سرویسدهندهی خاص |
آزمون اصلی، ماندگاری است: آیا این داده 3 ماه بعد در اجرای مجدد CI بهکار میآید؟ اگر بله، جایش در مخزن است؛ اگر نه، باید به سامانهی دورسنجی (telemetry) برود.
رویکرد اسکیمامحور در مدیریت وضعیت
اسکیمای JSON همان قرارداد نهایی است. بدون آن، هر ایجنتی برای خودش فیلدهای تازه میسازد، هر بازبینی باید ساختار جدیدی یاد بگیرد و هر اسکریپت CI مجبور است برای نسخههای قبلی استثنا قائل شود. با اسکیما، هر نوشتن نامعتبری مساوی است با ردشدن قطعی عملیات.
اسکیما موارد زیر را پوشش میدهد:
- کلیدهای الزامی.
- مقادیر مجاز برای
status. - مقادیر ممنوعه (مثلاً
nullبرای آرایهها). - محدودیتهای الگویی (شناسهی وظایف باید با الگوی
T-\d{3,}مطابقت داشته باشد). - فیلد نگارش برای مهاجرتهای ساختاری دادهها.
عملیات نوشتن اتمیک
عملیات نوشتن وضعیت باید در برابر خرابیهای مقطعی جان سالم به در ببرد: نوشتن داده روی یک فایل موقت، اجرای fsync برای اطمینان از ثبت روی دیسک، و سپس جایگزینی نام روی مقصد نهایی. فایل وضعیت، مبنای حقیقت است؛ فایلی که نصفهنیمه ذخیره شود، از نبودنش بدتر است.
مهاجرتهای ساختاری
هر زمان که اسکیما تغییر میکند، همراه با افزایش شمارهی نسخه، باید اسکریپت مهاجرت (migration) آن هم ارائه شود. فایل وضعیت فیلدی به نام schema_version دارد؛ مدیر وضعیت از بارگذاری فایلی با نسخهای که قادر به مهاجرت آن نباشد، خودداری میکند.
پیادهسازی
فایل code/main.py موارد زیر را پیادهسازی میکند:
- فایلهای
agent_state.schema.jsonوtask_board.schema.json. - یک اعتبارسنج متکی صرفاً به کتابخانهی استاندارد (زیرمجموعهای از اسکیمای JSON شامل: required ،type ،enum ،pattern و items).
- متدهای
StateManager.load،StateManager.updateوStateManager.commitهمراه با عملیات نوشتن اتمیک از طریق فایل موقت و تغییر نام. - یک نمونهی نمایشی که وضعیت را تغییر میدهد، ذخیره میکند، مجدداً بارگذاری میکند و درستی چرخهی رفتوبرگشت داده را اثبات مینماید.
اجرایش کنید:
python3 code/main.py
این اسکریپت دو فایل workdir/agent_state.json و workdir/task_board.json را مینویسد، آنها را طی 2 نوبت گفتوگو دستکاری میکند و وضعیت اعتبارسنجیشده را در هر گام در خروجی چاپ میکند.
الگوهای محیط پروداکشن در دنیای واقعی
چهار الگو حداقلهای آموزشی این درس را به چیزی تبدیل میکنند که یک مونوریپوی چندایجنتی بتواند بر پایهی آن دوام بیاورد:
نوشتن اتمیک با فایل موقت و تغییر نام، اختیاری نیست. گزارش باگی در اسفند 1404 (مارس 2026) در پروژهی Hive این حالت شکست را بهخوبی مستند کرده است: فایل state.json با متد write_text() نوشته میشد و استثناها بدون هشدار لاپوشانی میشدند. عملیاتهای ناقص باعث شدند نشستهای بعدی بدون ارسال هیچ نشانهای بر پایهی وضعیتی فاسد بالا بیایند. راهحل همیشگی این است: ساخت فایل با tempfile.mkstemp در همان دایرکتوری مقصد، نوشتن محتوا، فراخوانی fsync و اجرای os.replace (تغییر نام اتمیک در POSIX و Windows). متد atomic_write در این درس دقیقاً همین کار را میکند.
کلید یکتایی تراکنش برای تکتک فراخوانیهای غیرتکرارپذیر ابزار. اگر ایجنت ابزاری را فراخوانی کند و قبل از ثبت چکپوینت نتیجه از کار بیفتد، فرآیند بازیابی، فراخوانی ابزار را تکرار میکند. این کار برای عملیات خواندن بیخطر است، اما برای ارسال ایمیل، درج در دیتابیس یا آپلود فایل فاجعه میآفریند. الگو به این شکل است: شناسهی هر فراخوانی ابزار را پیش از اجرا در فایلی مثل pending_calls.jsonl ثبت کنید. هنگام تلاش مجدد، ابتدا شناسه را چک کنید؛ اگر ثبت شده بود، از فراخوانی چشمپوشی کرده و همان نتیجهی ذخیرهشده را بخوانید. توصیههای سال 2026 در Anthropic و LangChain بر این الگو تأکید دارند؛ چکپوینتر LangGraph نیز برای جلوگیری از همین خطا عملیاتهای در صفِ نوشتن را پایدار میکند.
دستسازههای حجیم را از فایل وضعیت جدا کنید. از ریختن دادههای CSV، تاریخچههای طولانی یا فایلهای تولیدشده در agent_state.json خودداری کنید. این دستسازهها را در فایلی جداگانه نگه دارید (یا در فضای ذخیرهسازی شیء بارگذاری کنید) و در فایل وضعیت صرفاً به مسیر آنها ارجاع دهید. با این ساختار، چکپوینتها سبک و سریع میمانند و دستسازهها بهطور مستقل حجم میگیرند.
سورسینگ رویداد برای حسابرسی، اسنپشات برای ادامهی کار. هر تغییر وضعیت را به انتهای یک فایل لاگ وقایع (state.events.jsonl) الصاق کنید و بهصورت دورهای از آن یک اسنپشات در state.json بگیرید. برای ازسرگیری، سیستم ابتدا اسنپشات را میخواند و سپس رویدادهای ثبتشده پس از برچسب زمانیِ اسنپشات را بازپخش میکند. این کار فضای دیسک بیشتری میگیرد، اما به شما امکان میدهد تصمیمات ایجنت را عیناً کلمهبهکلمه بازپخش کنید؛ ویژگی حیاتی برای دیباگکردن اجراهای بلندمدت. پایگاه دادهی Postgres نیز در لایهی ذخیرهسازی برای گزارشهای پیشنویس تراکنشها (WAL) از همین ترکیب لاگ و چکپوینت استفاده میکند، هرچند این کار را در لایهای بسیار پایینتر از رویدادهای اپلیکیشن پیاده کرده است.
مهاجرت اسکیما یا ردِ کامل بارگذاری. عدد صحیح schema_version متن اصلی قرارداد است. اگر مدیر وضعیت فایلی را با نسخهای ناشناخته پیدا کند، باید از خواندن آن سر باز بزند. همیشه کنار تغییرات اسکیما یک اسکریپت مهاجرت تحویل دهید؛ tools/migrate_state.py باید در هر بار راهاندازی، بهصورتی پایا و تکرارپذیر اجرا شود.
کاربرد در عمل
در پروداکشن:
- سیستمهای چکپوینتگیری LangGraph. مفهوم ثابت است، بستر ذخیرهسازی فرق میکند. چکپوینتر، وضعیت گراف را در SQLite ،Postgres یا بکاندی اختصاصی ذخیره میکند. اسکیمایی که در این درس یاد میگیرید دقیقاً ابزاری است که وقتی سیستم چکپوینت کرش کرد و ناچار شدید وضعیت را دستی بررسی کنید، به دادتان میرسد.
- بلوکهای حافظهی Letta. بلوکهای ماندگار با اسکیماهای ساختاریافته (فاز 14 · 08). همان انضباط که اینبار در دامنهی پرسوناهای بلندمدت به کار گرفته شده است.
- مخزن نشست در OpenAI Agents SDK. دارای لایههای ماژولار و هماهنگ با اسکیما. فایل وضعیتی که در این درس میسازید، در اصل همان بکاند فایل محلی است.
تحویل نهایی
فایل outputs/skill-state-schema.md یک جفت اسکیمای JSON متناسب با پروژه (وضعیت + بورد)، یک کلاس StateManager پایتونی متصل به مکانیزم نوشتن اتمیک، و یک قالب اولیه برای مهاجرت تولید میکند تا ارتقای بعدی اسکیما، کارکرد میز کار را مختل نکند.
تمرینها
- یک برچسب زمانی با نام
last_human_touchاضافه کنید. کاری کنید اگر ویرایش دستی انسان کمتر از 5 ثانیه قبل ثبت شده بود، از هرگونه نوشتن ایجنت جلوگیری شود. - اعتبارسنج را توسعه دهید تا از
oneOfپشتیبانی کند؛ بهطوریکه یک وظیفه بتواند وظیفهی ساخت (build) یا وظیفهی بازبینی (review) با فیلدهای الزامی متفاوت باشد. - یک فیلد
schema_versionاضافه کنید و اسکریپت مهاجرت از نسخهی 1 به 2 را بنویسید (نام فیلدblockersبهrisksتغییر یابد). - بکاند ذخیرهسازی را از فایل محلی به SQLite منتقل کنید، طوری که API کلاس
StateManagerدستنخورده باقی بماند. - دو ایجنت را همزمان با یک وضعیت رقابتی 50 میلیثانیهای روی یک فایل وضعیت اجرا کنید. چه مشکلی پیش میآید و عملیات تغییر نام اتمیک چگونه شما را نجات میدهد؟
اصطلاحات کلیدی
| اصطلاح | آنچه مصطلح است | معنای واقعی |
|---|---|---|
| حافظهی مخزن (Repo memory) | «فایل یادداشتها» | وضعیتی که در قالب فایلهای ردیابیشده در مخزن کد و تحت یک اسکیما ذخیره میشود |
| رویکرد اسکیمامحور (Schema-first) | «ورودیها را بررسی کن» | تعریف قرارداد پیش از نویسنده و رد کردن هرگونه انحراف ساختاری |
| نوشتن اتمیک (Atomic write) | «فقط تغییر نام» | نوشتن روی فایل موقت، ثبت با fsync و سپس تغییر نام تا خطاهای نیمهکاره دادهها را خراب نکنند |
| مهاجرت (Migration) | «ارتقای اسکیما» | اسکریپتی که وضعیت را از نگارش N به N+1 تغییر میدهد |
| سیستم مرجع (System of record) | «مبنای حقیقت» | دستسازهای که میز کار آن را مرجع معتبر و نهایی میداند |
برای مطالعهی بیشتر
- مستندات مشخصات اسکیمای JSON
- سیستمهای چکپوینتگیری LangGraph
- بلوکهای حافظهی Letta
- راهنمای کاربردی چکپوینتگیری وضعیت ایجنتهای هوش مصنوعی در Fast.io — چکپوینتگیری مبتنی بر اسکیما همراه با کلید یکتایی تراکنش
- بهترین الگوهای پایداری وضعیت جریانهای کاری ایجنتها در سال 2026 در Fast.io — کنترل همروندی، زمان حیات (TTL) و سورسینگ رویداد
- گزارش باگ شمارهی 6263 پروژهی Hive — نادیدهگرفتن خاموش خطاهای نوشتن غیراتمیک state.json — نقص عملکرد در یک پروژهی واقعی
- سامانههای چکپوینت/بازیابی در eunomia؛ روند توسعه، تکنیکها و کاربردها در ایجنتهای هوش مصنوعی — اعمال مفاهیم سیستمعامل روی ایجنتها
- هفت استراتژی پایداری وضعیت برای ایجنتهای بلندمدت در سال 2026 در Indium
- چارچوب ایجنت مایکروسافت، متراکمسازی (Compaction) — سیستم مدیریت چکپوینت سرویسدهنده
- فاز 14 · 08 — بلوکهای حافظه و محاسبات زمان استراحت
- فاز 14 · 32 — حداقل استاندارد سه فایلی که این درس برای آن اسکیما تعیین کرد
- فاز 14 · 40 — بستههای تحویل کار که از همین اسکیما میخوانند
