یک جلسهٔ سه ساعته برای بازسازی کد با Claude Code میتواند تا ۱.۲ میلیون توکن ورودی مصرف کند، اگر عامل مدام فایلهای پیکربندی تکراری را بخواند. آنتروپیک (Anthropic) با معرفی کشینگ نتایج ابزار، این هزینه را برای گردشکارهای متکی به خواندن، ۴۰ تا ۶۰ درصد کاهش داده است.
این بهینهسازی درست زمانی رخ میدهد که توسعهدهندگان از پرامپتهای تکمرحلهای به سمت جلسات طولانی عاملمحور (Agentic) — شبیه به استخدام یک دستیار که ساعتها روی یک پروژه کار میکند و جزئیات را به خاطر میسپارد — حرکت میکنند. همانطور که در تحلیل قبلی ما دربارهی استفاده غیربرنامهنویسان از Claude Code برای ساخت ابزارهای امنیتی اشاره کردیم، تمرکز اکنون از «توانایی پایه» به «بهرهوری عملیاتی» تغییر کرده است. در یک جلسه معمولی، یک عامل ممکن است برای تأیید تایپها یا ایمپورتها، ۱۵ بار فایل package.json و ۱۲ بار tsconfig.json را بخواند.
تصور کنید توسعهدهندهای با عامل مانند یک سیستم بدون حافظه برخورد کند؛ هر وظیفه جدید باعث خواندن دوباره تمام فایلها شود، حتی اگر تغییری نکرده باشند. بدون کشینگ، خواندن ۱۰ باره یک فایل ۵ کیلوبایتی حدود ۱۲,۰۰۰ توکن هزینه دارد، اما با کشینگ، این رقم به ۱,۶۵۰ توکن میرسد. این یک تفاوت عظیم در هزینههای API است. عامل در حالت عادی نمیتواند تفاوت بین «نیاز به فایل چون هرگز آن را ندیدهام» و «نیاز به فایل برای تأیید چیزی که میدانم» را تشخیص دهد؛ کشینگ نتایج ابزار دقیقاً این شکاف را پر میکند.
هزینه پنهان تکرار
به گزارش منابع فنی، بیشتر مشکلات عملکردی عاملها ناشی از خواندن دهها باره یک فایل در طول یک جلسه است. فایلهای کاربردی اصلی هر بار که Claude نیاز به بررسی یک امضای تایپ یا مسیر ایمپورت دارد، خوانده میشوند و هر بار توکن میسوزانند. هر دستور شل که درخت وابستگی یا نتایج تست یکسانی را برمیگرداند نیز هزینه اضافی دارد. این موضوع مستقیماً با تحلیل ما دربارهی نسبت ورودیهای تکراری مرتبط است که نشان داد چگونه اتلاف بودجه در عاملهای کدنویسی رخ میدهد.
در یک جلسه سه ساعته، این فراخوانیهای تکراری ۴۰ تا ۶۰ درصد از کل مصرف توکن را تشکیل میدهند. مشکل زمانی تشدید میشود که توسعهدهندگان عامل را بدون وضعیت (Stateless) فرض کنند: هر وظیفه جدید باعث ایجاد دستهای از خوانشهای تازه میشود، حتی زمانی که فایلهای زیربنایی تغییر نکردهاند. برای مثال، Claude ممکن است یک فایل پیکربندی ۲۰۰ خطی را در ساعت ۱۰:۰۰، ۱۰:۱۵، ۱۰:۳۰ و ۱۱:۰۰ بخواند، چون جلسه حافظهای از نتیجه قبلی ندارد.
تأثیر ساختار جلسه
جلسات طولانی و خوشساختار — جایی که عامل روی یک کدبیس پایدار با الگوهای دسترسی پیشبینیپذیر کار میکند — میتوانند بدون افت کیفیت، به ۴۰ تا ۶۰ درصد صرفهجویی در توکن برسند. با این حال، حالت شکست زمانی رخ میدهد که توسعهدهندگان درک نکنند کشینگ در چه زمانی اعمال میشود. ساختاردهی ناخواسته به جلسات به گونهای که مانع کشینگ شود، منجر به نرخ مصرف توکنی میشود که دقیقاً مشابه جلسات بدون کش است. این نیاز به مدیریت دقیقتر وضعیت، دلیل آن است که رانتایمهای بادوام در حال جایگزینی حلقههای ساده در معماری عاملها هستند تا پایداری عملیاتی افزایش یابد.
سازوکار کشینگ چگونه کار میکند
بر اساس گزارشی که در ۲۸ آگوست ۲۰۲۶ در dev.to منتشر شد، کشینگ در سطح API رخ میدهد و نه در کلاینت. وقتی Claude یک ابزار را فراخوانی میکند، API یک هش (Hash) قطعی از نام ابزار، پارامترها و محتوای نتیجه میسازد. این هش به عنوان کلیدی در وضعیت سمت سرور جلسه ذخیره میشود.

اگر فراخوانی ابزاری با همان پارامترها دوباره تکرار شود — همان ابزار و همان پارامترها — API ابتدا کش را بررسی میکند. در صورت یافتن نتیجه (Hit)، مقدار ذخیرهشده جایگزین اجرای مجدد میشود. عامل همچنان محتوا را در گفتگو «میبیند»، اما هزینه از اندازه کامل نتیجه به یک هزینه اندک برای ارجاع به کش کاهش مییابد.
واجدین شرایط برای کشینگ به دو دسته اصلی تقسیم میشوند:
- خواندن فایلها: این موارد بهطور خودکار واجد شرایطاند. خواندن
/src/utils/types.tsتا زمان تغییر فایل کش میشود. خواندن یک فایل ۵ کیلوبایتی در بار اول حدود ۱,۲۰۰ توکن ورودی هزینه دارد، اما در دفعات بعد تنها حدود ۵۰ توکن. - دستورات شل: تنها اگر خروجی قطعی (Deterministic) باشد و دستور تغییری در وضعیت ایجاد نکند. برای مثال
npm list --depth=0قابل کش شدن است چون درخت وابستگی پایدار است. اماgit statusکش نمیشود چون وضعیت درخت کاری میتواند بین دو فراخوانی تغییر کند.
جزئیات فنی: قطعیت و هشینگ
برای بهینهسازی دستورات شل، توسعهدهندگان باید دستورات وابسته به وضعیت را از خوانشهای خالص جدا کنند. API میتواند یک راهنمای متادیتای cacheable را بپذیرد تا از نتایج قدیمی (Stale Hits) جلوگیری کند.
- الگوهای قطعی: دستوراتی مثل
npm list،cat،head،tail،grep،findوlsمعمولاً برای کشینگ امن هستند چون وضعیت ایستا را میخوانند. - الگوهای غیرقطعی: دستوراتی مثل
date،git status،git diff،ps،dfوuptimeدر هر بار فراخوانی خروجی متفاوتی دارند یا وضعیت تغییرپذیر را منعکس میکنند. اینها کشینگ را بهطور خاموش میشکنند.
اگر توسعهدهندهای ls -la را در پوشهای اجرا کند که فایلها در آن اضافه یا حذف میشوند، در هر بار یک کلید کش جدید ساخته شده و توکنهای کامل مصرف میشوند. حالت شکست در اینجا، علامتگذاری یک دستور غیرقطعی به عنوان قطعی است، که منجر به نتایج قدیمی میشود و عامل را درباره وضعیت مخزن کد گمراه میکند.
گردشکار تشخیص
از آنجایی که API متادیتای مربوط به Hit یا Miss شدن کش را در پاسخهای استاندارد نمایش نمیدهد، توسعهدهندگان باید رفتار را از روی رونوشتهای جلسه استنباط کنند. گردشکار تشخیص ساده است:
- استخراج رونوشت: شناسایی فراخوانیهای ابزار با پارامترهای یکسان.
- مقایسه تعداد توکنها: بررسی تفاوت ۲۰ برابری بین اولین فراخوانی و دفعات بعدی برای تأیید Hit شدن کش.
- تحلیل نسبتها: نسبت ۱ به ۱ در فراخوانیهای یکسان، نشانه Miss شدن کش یا فعال شدن محرک ابطال است.
- پایش نوسانات: دستورات شل با خروجی متغیر، مانند
git diffبعد از کامیتها، هزینههای نوسانی نشان میدهند چون نتیجه تغییر میکند، حتی اگر دستور یکسان باشد.
مدیریت ابطال کش
کشینگ ریسک «دادههای قدیمی» را ایجاد میکند اگر محیط خارج از دید عامل تغییر کند. سیستم ابطال را بر اساس نوع ابزار متفاوت مدیریت میکند.
نوشتن در فایلها باعث ابطال فوری میشود. اگر عامل در config.ts چیزی بنویسد، کش خواندن آن فایل پاک میشود. اما تغییرات خارجی — مثل ویرایش فایل توسط توسعهدهنده در VS Code در حالی که Claude در حال اجراست — شناسایی نمیشوند. عامل تا پایان جلسه از نسخه قدیمی کش استفاده میکند. این موضوع میتواند منجر به افزودن وابستگیهایی شود که از قبل وجود دارند یا ارجاع به فیلدهای پیکربندی که حذف شدهاند. در این زمینه، بررسی امنیت سیستمفایل و محیطهای ایزوله اهمیت ویژهای دارد تا از دسترسیهای غیرمجاز یا تداخلات محیطی جلوگیری شود.

دستورات شل ابطال خودکار ندارند. اگر توسعهدهندهای بستهای را از ترمینال جداگانه نصب کند، یک فراخوانی کششده از npm list اطلاعات قدیمی را برمیگرداند. برای مقابله با این موضوع، توسعهدهندگان از «ترفند برچسب زمانی» استفاده میکنند و یک کامنت منحصربهفرد مثل # ${Date.now()} به دستور اضافه میکنند تا اجباراً Cache Miss رخ دهد. چون API کلید کش را از کل رشته دستور محاسبه میکند، یک برچسب زمانی متغیر در هر بار یک کلید منحصربهفرد تولید میکند.
ریسکهای محیطی
کشینگ نتایج ابزار فرض میکند محیط پایدار است. در توسعه زنده، توسعهدهندگان اغلب در ادیتورها تکرار میکنند و دستورات را در ترمینالهایی خارج از دید عامل اجرا میکنند. API نمیتواند این تغییرات را بدون نظارت بر سیستم فایل (Filesystem Watch) یا نظرسنجی (Polling) تشخیص دهد، که هر دو باعث ایجاد تأخیر میشوند.
بنابراین، کشینگ در محیطهای ایزوله بیشترین قابلیت اطمینان را دارد: خط لولههای CI، کانتینرهای سندباکس و جلسات تککاربره که عامل تنها نویسنده است. در محیطهای مشترک یا گردشکارهایی که چندین فرآیند بهطور همزمان فایلهای یکسانی را تغییر میدهند، قابلیت اطمینان آن بهتدریج کاهش مییابد.
مثلث بهرهوری: کشینگ، فشردهسازی و حافظه
کشینگ یک راهکار مستقل نیست، بلکه بخشی از استراتژی سه لایه بهرهوری است. در حالی که کشینگ خوانشهای تکراری در یک جلسه را بهینه میکند، ابزارهای دیگر ابعاد مختلفی از حجیم شدن (Bloat) را مدیریت میکنند:
۱. کشینگ نتایج ابزار: حذف فراخوانیهای تکراری در یک جلسه. جلوگیری از خواندن مکرر یک فایل.
۲. فشردهسازی گفتگو (/compact): حذف پیامهای قدیمی و نامرتبط برای آزاد کردن پنجره زمینه (Context Window). این کار تاریخچه گفتگوهای مربوط به خوانشها را پس از اینکه دیگر کاربردی نداشتند، حذف میکند.
۳. ابزارهای حافظه: ذخیره حقایق ساختاریافته (مثلاً «پروژه از TypeScript 5.3 استفاده میکند») برای جلسات آینده. این به جلسات آتی اجازه دهد بدون خواندن مجدد فایلهای بنیادی مثل tsconfig.json به دانش دسترسی داشته باشند.

تیمهایی که هر سه را به کار میگیرند، کاهش ۶۰ تا ۷۰ درصدی توکن کل را گزارش کردهاند. یک جلسه بازسازی کد میتواند از ۸۰۰,۰۰۰ توکن به ۳۰۰,۰۰۰ توکن کاهش یابد (۶۲٪ کاهش). این سود توزیع شده است: کشینگ ۴۰٪ از خوانشهای تکراری، فشردهسازی ۱۵٪ از گفتگوهای قدیمی و حافظه ۷٪ از بازکشفهای بینجلسهای را حذف میکند.
نقشهای مکمل
اشتباه است که این ابزارها را جایگزین هم بدانیم. الگوی تعامل آنها خاص است:
- کشینگ در برابر فشردهسازی: جلسهای که فقط کشینگ دارد، همچنان با حجیم شدن گفتگو مواجه است. جلسهای که فقط فشردهسازی دارد، همچنان برای خواندن فایلهای تکراری توکن میسوزاند.
- کشینگ در برابر حافظه: کشینگ خوانشهای تکراری در یک جلسه را بهینه میکند، اما حافظه انتقال دانش را بین جلسات بهینه میکند. جلسهای که فقط حافظه دارد، همچنان فاقد بهرهوری درونجلسهای است.
گردشکار عملی: کشینگ را بهطور پیشفرض برای خوانشها و دستورات قطعی فعال کنید، هر ۱۰۰ تا ۱۵۰ پیام دستور /compact را اجرا کنید و از ابزارهای حافظه برای ثبت الگوهای کدبیس استفاده کنید. در شروع جلسات جدید، حقایق حافظه را بارگذاری کنید به جای اینکه فایلهای بنیادی را دوباره بخوانید.
بنچمارکهای عملکرد و حالتهای شکست
دادههای عملیاتی نشان میدهد کشینگ در گردشکارهای متکی به خواندن (مثل بررسی کد، بررسی باگ و تولید مستندات) بیشترین اثر را دارد و صرفهجویی به ۵۰٪ میرسد. در این سناریوها، یک جلسه بدون کشینگ ۸۰۰,۰۰۰ تا ۱.۲ میلیون توکن ورودی در سه ساعت مصرف میکند؛ با کشینگ، این رقم به ۴۰۰,۰۰۰ تا ۶۰۰,۰۰۰ توکن کاهش مییابد.
در مقابل، گردشکارهای متکی به نوشتن — مانند ساخت ویژگیهای جدید یا مهاجرت APIها — تنها ۲۰ تا ۳۰ درصد سود میبرند. دلیل آن است که نوشتنهای مکرر مدام کش را ابطال میکند. در جلسهای که عامل در هر ساعت در ۱۰ فایل مینویسد، این بهینهسازی تا حد زیادی خنثی میشود.
منحنی زمانی مصرف
مصرف توکن در طول جلسه غیرخطی است:
- ساعت اول: بیشترین مصرف. عامل کدبیس را میکاود و فایلهای بنیادی را برای اولین بار میخواند.
- ساعت دوم: مصرف کمتر. بیشتر فایلها اکنون کش شدهاند.
- ساعت سوم: کمترین مصرف. عامل ساختار را درونی کرده و بهندرت به فایل جدید نیاز دارد.
نسبت ۲ به ۱ توکنهای ورودی در ساعت سوم نسبت به ساعت اول، نشانه کشینگ مؤثر است. نسبت ۱ به ۱ نشانه ابطال بیش از حد کش یا فراخوانی ابزارهای غیرقابل کش است.
پرسشهای متداول و تلههای عملیاتی
- آیا کشینگ با
/compactکار میکند؟ بله. فشردهسازی پیامها را حذف میکند اما روی کش نتایج ابزار اثر ندارد. کلید کش بر اساس فراخوانی ابزار است، نه تاریخچه گفتگو. - اعتبار نتیجه چقدر است؟ نتایج تا پایان جلسه (معمولاً ۸ تا ۱۲ ساعت) یا تا بستن جلسه توسط کلاینت باقی میمانند.
- آیا میتوان کش را دستی ابطال کرد؟ خیر. باید پارامتر را تغییر داد (ترفند برچسب زمانی) یا جلسه را ریاستارت کرد.
- در جلسات زیر-عامل (Subagent) کار میکند؟ خیر. هر زیر-عامل کش ایزوله خود را دارد تا از آلودگی بین زمینههای مختلف جلوگیری شود.
- اگر فایلی خارجی حذف شود چه میشود؟ API محتوای کش شده را برمیگرداند انگار فایل هنوز وجود دارد، و عامل روی دادههای قدیمی کار میکند.
این تغییر معماری یعنی کارآمدترین عاملها آنهایی خواهند بود که نوشتنها را در انتهای وظیفه دستهبندی کنند، نه اینکه آنها را با خواندنها ترکیب کنند. نقش توسعهدهنده از پرامپتنویسی ساده به مدیریت وضعیت عامل و پایداری محیط تغییر میکند. برای به حداکثر رساندن این سود، باید رونوشت جلسات فعلی خود را برای شناسایی فراخوانیهای تکراری ابزار بررسی کنید و یک سیاست سختگیرانه «فقط عامل بنویسد» را در طول جلسات فعال اجرا کنید تا از خطاهای دادههای قدیمی جلوگیری شود.
گام بعدی شما
- رونوشت جلسات فعلی خود را برای شناسایی فراخوانیهای تکراری ابزار بررسی کنید.
- در جلسات فعال، سیاست «فقط عامل بنویسد» را اجرا کنید تا از خطاهای دادههای قدیمی جلوگیری شود.
- برای دستورات شل که خروجی متغیر دارند اما نیاز به بهروزرسانی دارید، از ترفند
${Date.now()}استفاده کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.




گفتگو