فاز 14 · درس 34

حافظه در مخزن کد و وضعیت ماندگار ایجنت‌های هوش مصنوعی

نوع
ساختنی
زمان
حدود 60 دقیقه
زبان‌ها
Python (stdlib + `jsonschema` optional)
پیش‌نیاز
فاز 14 · 32 (حداقل میز کار)
یک مهر فلزی بر روی یک سند فنی شفاف که نقشه‌ی ساختار JSON روی آن کشیده شده قرار گرفته و نشان از ماندگاری و اعتبارسنجی دارد.
فهرست مطالب
  1. اهداف یادگیری
  2. صورت مسئله
  3. مفهوم
  4. چه داده‌هایی به حافظه‌ی مخزن تعلق دارند
  5. رویکرد اسکیما‌محور در مدیریت وضعیت
  6. عملیات نوشتن اتمیک
  7. مهاجرت‌های ساختاری
  8. پیاده‌سازی
  9. الگوهای محیط پروداکشن در دنیای واقعی
  10. کاربرد در عمل
  11. تحویل نهایی
  12. تمرین‌ها
  13. اصطلاحات کلیدی
  14. برای مطالعه‌ی بیشتر

یکی از خطاهای رایج در پروژه‌های مبتنی بر ایجنت‌های هوش مصنوعی، تکیه بر تاریخچه‌ی گفت‌وگو (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) به شمار می‌رود.

مفهوم

بلهخیرحلقه‌ی ایجنتStateManageragent_state.schema.jsonمعتبر است؟agent_state.jsonرد + خطا

چه داده‌هایی به حافظه‌ی مخزن تعلق دارند

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

آزمون اصلی، ماندگاری است: آیا این داده 3 ماه بعد در اجرای مجدد CI به‌کار می‌آید؟ اگر بله، جایش در مخزن است؛ اگر نه، باید به سامانه‌ی دورسنجی (telemetry) برود.

رویکرد اسکیما‌محور در مدیریت وضعیت

اسکیمای JSON همان قرارداد نهایی است. بدون آن، هر ایجنتی برای خودش فیلدهای تازه می‌سازد، هر بازبینی باید ساختار جدیدی یاد بگیرد و هر اسکریپت CI مجبور است برای نسخه‌های قبلی استثنا قائل شود. با اسکیما، هر نوشتن نامعتبری مساوی است با ردشدن قطعی عملیات.

اسکیما موارد زیر را پوشش می‌دهد:

  • کلیدهای الزامی.
  • مقادیر مجاز برای status.
  • مقادیر ممنوعه (مثلاً null برای آرایه‌ها).
  • محدودیت‌های الگویی (شناسه‌ی وظایف باید با الگوی T-\d{3,} مطابقت داشته باشد).
  • فیلد نگارش برای مهاجرت‌های ساختاری داده‌ها.

عملیات نوشتن اتمیک

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

مهاجرت‌های ساختاری

هر زمان که اسکیما تغییر می‌کند، همراه با افزایش شماره‌ی نسخه، باید اسکریپت مهاجرت (migration) آن هم ارائه شود. فایل وضعیت فیلدی به نام schema_version دارد؛ مدیر وضعیت از بارگذاری فایلی با نسخه‌ای که قادر به مهاجرت آن نباشد، خودداری می‌کند.

حافظه ریپوماندگاری وضعیت فراتر از مرز نشست
REPO MEMORYThe chat bubbles dissolve when the session ends; the state file does not. A write goes through the schema check before it lands, the revision advances atomically, and the next session, the next agent, and the reviewer all read the same versioned file instead of re-deriving where the work left off.چت (فرار)اجازه دهید بررسی کنم...ویرایش utils.pyانجام شد، فکر کنمپایان نشستریپو (ماندگار)اسکماagent_state.jsonنسخه 6نسخه 7 · نوشتن اتمیکنشست بعدیخواندن همان فایلچت تبخیر می‌شود؛ ریپو به خاطر می‌سپارد
پیام‌های چت با پایان نشست محو می‌شوند؛ اما فایل وضعیت باقی می‌ماند. هر نوشتن پیش از ثبت از اعتبارسنجی اسکِما عبور می‌کند، نسخه به‌صورت اتمیک ارتقا می‌یابد، و نشست بعدی، ایجنت بعدی و بازبین همگی همان فایل نسخه‌بندی‌شده را می‌خوانند؛ بدون نیاز به بازتولید نقطه‌ای که کار در آن متوقف شده بود.

پیاده‌سازی

فایل 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 پایتونی متصل به مکانیزم نوشتن اتمیک، و یک قالب اولیه برای مهاجرت تولید می‌کند تا ارتقای بعدی اسکیما، کارکرد میز کار را مختل نکند.

تمرین‌ها

  1. یک برچسب زمانی با نام last_human_touch اضافه کنید. کاری کنید اگر ویرایش دستی انسان کمتر از 5 ثانیه قبل ثبت شده بود، از هرگونه نوشتن ایجنت جلوگیری شود.
  2. اعتبارسنج را توسعه دهید تا از oneOf پشتیبانی کند؛ به‌طوری‌که یک وظیفه بتواند وظیفه‌ی ساخت (build) یا وظیفه‌ی بازبینی (review) با فیلدهای الزامی متفاوت باشد.
  3. یک فیلد schema_version اضافه کنید و اسکریپت مهاجرت از نسخه‌ی 1 به 2 را بنویسید (نام فیلد blockers به risks تغییر یابد).
  4. بک‌اند ذخیره‌سازی را از فایل محلی به SQLite منتقل کنید، طوری که API کلاس StateManager دست‌نخورده باقی بماند.
  5. دو ایجنت را هم‌زمان با یک وضعیت رقابتی 50 میلی‌ثانیه‌ای روی یک فایل وضعیت اجرا کنید. چه مشکلی پیش می‌آید و عملیات تغییر نام اتمیک چگونه شما را نجات می‌دهد؟

اصطلاحات کلیدی

اصطلاح آنچه مصطلح است معنای واقعی
حافظه‌ی مخزن (Repo memory) «فایل یادداشت‌ها» وضعیتی که در قالب فایل‌های ردیابی‌شده در مخزن کد و تحت یک اسکیما ذخیره می‌شود
رویکرد اسکیما‌محور (Schema-first) «ورودی‌ها را بررسی کن» تعریف قرارداد پیش از نویسنده و رد کردن هرگونه انحراف ساختاری
نوشتن اتمیک (Atomic write) «فقط تغییر نام» نوشتن روی فایل موقت، ثبت با fsync و سپس تغییر نام تا خطاهای نیمه‌کاره داده‌ها را خراب نکنند
مهاجرت (Migration) «ارتقای اسکیما» اسکریپتی که وضعیت را از نگارش N به N+1 تغییر می‌دهد
سیستم مرجع (System of record) «مبنای حقیقت» دست‌سازه‌ای که میز کار آن را مرجع معتبر و نهایی می‌داند

برای مطالعه‌ی بیشتر

خودآزمایی

به سؤال‌ها جواب بدهید تا ببینید چقدر از درس در ذهنتان مانده است.

  1. پیش از درسمعیار سنجش ماندگاری برای این‌که مشخص شود یک داده متعلق به حافظه ریپو است یا خیر چیست؟
  2. پیش از درسکدام فیلد اسکما نسخه قرارداد ایجنت را حمل می‌کند؟
  3. حین درسنوشتن اتمیک چگونه کار می‌کند؟
  4. حین درسچرا کلیدهای یکتایی تراکنش برای فراخوانی‌های غیریکنواخت ابزارها ضروری هستند؟
  5. حین درسدست‌سازه‌های بزرگ (CSVها، رونوشت‌های طولانی، فایل‌های تولیدشده) نسبت به فایل وضعیت باید کجا نگهداری شوند؟
  6. پس از درسبه‌کارگیری Event Sourcing برای بازرسی همراه با اسنپ‌شات برای ازسرگیری چه مزیتی فراهم می‌کند؟
  7. پس از درسطبق درس، هنگام عدم تطابق schema_version چه اتفاقی رخ می‌دهد؟

سؤالات متداول

چه داده‌هایی باید در حافظه‌ی مخزن ذخیره شوند و چه داده‌هایی در تاریخچه‌ی چت؟

شناسه‌ی وظیفه‌ی فعال، لیست فایل‌های دست‌خورده، فرضیات ایجنت، موانع باز و گام بعدی باید در مخزن ذخیره شوند؛ اما رونوشت خام چت، ردگیری توکن‌ها و احساسات کاربر جایی در مخزن ندارند.

چرا نوشتن وضعیت باید به صورت اتمیک انجام شود؟

اگر هنگام نوشتن مستقیم فایل وضعیت، برنامه کرش کند، فایل نیمه‌کاره و فاسد ذخیره می‌شود. نوشتن اتمیک ابتدا روی فایل موقت می‌نویسد، آن را با fsync تثبیت می‌کند و سپس با تغییر نام، جایگزین فایل نهایی می‌سازد تا از ذخیره‌ی فایل معیوب پیشگیری شود.

نقش schema_version در فایل وضعیت ایجنت چیست؟

این متغیر عددی مشخص می‌کند ساختار داده از کدام نسخه پیروی می‌کند؛ اگر اسکیما ارتقا یابد، مدیر وضعیت متوجه تفاوت شده و تا زمان اجرای اسکریپت مهاجرت (Migration)، از بارگذاری ساختار ناشناخته جلوگیری می‌کند.

ما رو توی گوگل بیشتر ببین

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