جلسه ۸ از ۱۱، بخش ۱: طراحی ایجنت

هزینه و سرعت ایجنت

متنی ۵۰ دقیقه به‌روز شده در ۱۰ آبان ۱۴۰۵

در این جلسه
  1. اصل اول: کل ماجرا را بسنجید
  2. فرمول هزینه
  3. مسیریابی بین مدل‌ها
  4. هر صرفه‌جویی هزینه‌ی مقابلی دارد
  5. سرعت: مسیر بحرانی، نه مجموع
  6. معماری هارنس
  7. پرسش‌هایی برای فکر کردن
  8. منابع

جلسه‌ی قبل گفت هزینه بخشی از نتیجه است. این جلسه می‌پرسد هزینه دقیقاً از کجا می‌آید و چطور کمش کنیم بی‌آنکه موفقیت پایین بیاید. تمرکز روی هزینه‌ی مدل زبانی است.

اصل اول: کل ماجرا را بسنجید#

ایجنت کارا محاسبه را جایی خرج می‌کند که احتمال یا ارزش موفقیت را تغییر دهد. واحد تحلیل هم یک فراخوانی نیست، کل کار است: برنامه‌ریزی، ابزار، تلاش مجدد، تأیید و اصلاح انسانی.

هزینه‌ی هر اجرا = همه‌ی فراخوانی‌های مدل + ابزارها + سرویس حافظه + اجرای کد + بازبینی انسانی

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

یک مثال از یادداشت‌های درس، ۱۰۰ کار:

خط پایه پیشنهاد جدید
کل هزینه ۱۲۰ دلار ۹۰ دلار
موفقیت ۸۰ ۷۵
هزینه به ازای موفقیت ۱٫۵۰ دلار ۱٫۲۰ دلار

پیشنهاد جدید ارزان‌تر به نظر می‌رسد. اما اگر سیستم شما دست‌کم ۸۰٪ موفقیت لازم دارد، این گزینه اصلاً واجد شرایط نیست. کل مرز کیفیت و هزینه را مقایسه کنید، و اینکه دقیقاً کدام کارها به دست آمدند و کدام از دست رفتند.

فرمول هزینه#

هزینه = کاربران × نشست/کاربر × نوبت/نشست × قدم/نوبت × توکن/قدم × قیمت/توکن

دو جمله‌ی اول با رشد محصول بالا می‌روند و این خوب است. چهار جمله‌ی آخر اهرم‌های شما هستند.

واژه‌ها: یک نشست چند نوبت کاربر دارد. هر نوبت چند قدم دارد که فراخوانی مدل و فراخوانی ابزار به‌تناوب در آن‌ها می‌آیند و نوبت با یک پاسخ به کاربر تمام می‌شود.

۱. نوبت‌های کاربر را کم کنید#

نوبت k‌ام همه‌ی نوبت‌های قبلی را دوباره می‌خواند، پس هزینه‌ی کل تقریباً با مربع تعداد نوبت‌ها رشد می‌کند. کاربر وقتی برمی‌گردد که ایجنت برنامه نداشت، زود متوقف شد یا کارش را بررسی نکرد. راه‌حل‌ها:

  • برنامه‌ریزی جلوتر: هدف و برنامه را یک بار تأیید بگیر
  • تجزیه‌ی ساخت‌یافته: زیرکارها با معیار پایان
  • خودتأییدی: پیش از برگرداندن نتیجه تست‌ها را اجرا کن

هدف این است که ایجنت کار را خودش و بدون برگشتن پیش کاربر تمام کند. در داده‌های نشست‌های Claude Code دانشجویان درس، ۶۸٪ نشست‌های تمرین اول و ۷۵٪ نشست‌های تمرین دوم فقط یک پرامپت داشتند؛ بیشتر دانشجوها برای هر کار نشست تازه باز می‌کردند. چند نفر هم نشست‌های ماراتنی با بیش از ۱۰۰ نوبت داشتند.

۲. قدم‌ها در هر نوبت را کم کنید#

در داده‌های دانشجویان درس، میانه‌ی قدم در هر نوبت ۳ تا ۴ بود ولی بعضی نوبت‌ها به نزدیک ۱۰۰۰ قدم رسیدند. عامل اصلی تعداد قدم، تنظیم effort (متوسط یا زیاد) بود. هر فراخوانی مدل کل کانتکست را دوباره می‌خواند، پس فراخوانی کمتر یعنی پول کمتر:

  • فراخوانی‌های مستقل را دسته کنید، مثلاً خواندن پنج فایل در یک قدم
  • اول برنامه، بعد دسته: دو فراخوانی مدل به جای چهار
one call per action:  M → T → M → T → M → T → M     (4 model calls)
plan, then batch:     M → [T ‖ T ‖ T] → M            (2 model calls)
  • برنامه‌ها و skillها را دوباره استفاده کنید
  • کانتکست لازم را از اول بار کنید

تصمیم‌های قطعی را به کد منتقل کنید. یک «عمل کدی» می‌تواند چند عملیات ابزار را در یک نوبت ترکیب کند (ایده‌ی CodeAct). مثلاً یک اسکریپت که جستجو، تست و تشخیص را با هم اجرا می‌کند، و مدل فقط نتیجه را تفسیر می‌کند و در صورت شکست دوباره برنامه می‌ریزد.

۳. توکن در هر قدم: بیشتر هزینه «خواندن از کش» است#

داده‌های نشست‌های دانشجویان درس:

میانه‌ی توکن در هر قدم صدک ۹۰
ایجنت اصلی ۲۰۰ تا ۳۰۰ هزار (۲۰۸ هزار در تمرین ۱، ۳۰۱ هزار در تمرین ۲) ۶۰۰ تا ۷۰۰ هزار
زیرایجنت حدود ۸۰ هزار حدود ۲۰۰ هزار

کانتکست سریع جمع می‌شود: نزدیک قدم ۵۰۰ به حدود ۶۷۰ هزار (تمرین ۱) و ۶۵۰ هزار (تمرین ۲) رسید. و ۹۷٫۶٪ توکن‌ها خواندن از کش بودند. به زبان نسبت‌ها: خروجی حدود ۵ برابر کمتر از prefill تازه (نوشتن در کش) بود، و prefill تازه حدود ۱۰۰ برابر کمتر از خواندن از کش.

نسبت قیمت تقریبی:

نوع توکن قیمت نسبی
خواندن از کش ۱
ورودی تازه ۱۰
خروجی ۵۰

نتیجه‌ی غیرمنتظره: حتی با اینکه خواندن از کش ده برابر ارزان‌تر است، چون حجمش صدها برابر است، بخش بزرگی از صورت‌حساب همین است. پس کوچک نگه داشتن کانتکست هنوز مهم است.

کاهش توکن ورودی (همان راهبردهای جلسه‌ی ۴):

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

یک جمله از اسلاید که ارزش حفظ کردن دارد: توکنی که در کانتکست می‌ماند، در هر قدم بعدی دوباره پولش را می‌دهید.

پژوهش‌هایی که اسلاید برای کاهش ورودی نام می‌برد (بخش «پیشرفته»، برای مطالعه‌ی بیشتر):

دسته پژوهش سال نتیجه یا ایده
فشرده‌سازی تاریخچه ACON ۲۰۲۵ حداکثر کانتکست ۲۶ تا ۵۴٪ کمتر
Active Context Compression ۲۰۲۶ ایجنت خودش را فشرده می‌کند؛ ۲۳٪ توکن کمتر
TRACE ۲۰۲۶ نشان می‌دهد خلاصه‌ها باعث دوباره‌کاری می‌شوند
فشرده‌سازی پرامپت LLMLingua ۲۰۲۳ تا ۲۰ برابر توکن کمتر
LongLLMLingua و LLMLingua-2 ۲۰۲۴ نسخه‌های بعدی همان ایده
Prompt Compression in the Wild ۲۰۲۶ فقط روی پرامپت‌های طولانی سود دارد
کانتکست به‌عنوان حافظه‌ی بیرونی MemGPT ۲۰۲۳ کانتکست حکم حافظه‌ی سریع را دارد
Scroll ۲۰۲۶ لاگ بیرونی بی‌اتلاف؛ کد انتخاب می‌کند مدل چه ببیند
داده‌ی ابزار بیرون از کانتکست اجرای کد با MCP ۲۰۲۵ فیلتر نتایج در کد؛ از ۱۵۰ هزار به ۲ هزار توکن
Tool Search ۲۰۲۵ ۸۵٪ توکن ابزار کمتر
Programmatic Tool Calling ۳۷٪ توکن کمتر

استفاده‌ی دوباره از برنامه، skill و تجربه. پژوهش‌هایی که اسلاید نام می‌برد: کتابخانه‌ی skill (Voyager، SkillRL)، بینش از تجربه (ExpeL، ReasoningBank)، کش کردن برنامه (Test-Time Plan Caching) و حافظه‌ی پایدار (Mem0، LightMem، SimpleMem). هشدار: استفاده‌ی دوباره فقط وقتی سود دارد که کارها تکرار شوند؛ نگه‌داری حافظه و مدخل‌های کهنه می‌تواند صرفه‌جویی را از بین ببرد.

کاهش توکن خروجی:

  • محدودیت در پرامپت: طول، قالب و چیزهایی که نباید بیاید را بگویید. نمونه‌ها: «حداکثر ۱۰۰ کلمه»، «فقط JSON»، «یک جمله»، «سه مورد اول»، «صورت مسئله را تکرار نکن»، «استدلالت را توضیح نده». یک پرامپت سیستمی کوتاه هم کمک می‌کند: «Be concise; omit background unless requested.»
  • سقف max_tokens (یا max_output_tokens): ساده است، اما ممکن است جواب را وسط جمله ببرد. آن را با پرامپت «کوتاه بنویس» جفت کنید. نکته‌ی ظریف: استدلال ممکن است کل سقف را بخورد.
  • خروجی ساخت‌یافته: شِمایی با فقط فیلدهای لازم؛ enum و فیلدهای اختیاری را محدود کنید تا مدل نتواند چیز اضافه بنویسد. برای ایجنت ابزارمحور مناسب است، چون متن دور یک فراخوانی ابزار هزینه‌ی خالص است.
  • تلاش استدلالی تطبیقی: بودجه‌ی فکر را با قدم جور کنید؛ کم برای جستجو و قالب‌بندی، زیاد برای برنامه‌ریزی و اشکال‌زدایی. برای هر فراخوانی یا هر قدم، به شکل reasoning effort یا بودجه‌ی توکن فکر.
{"action": "search", "argument": "KV cache"}     ← structured output: only the needed fields

lookup step:  effort="low"
debug step:   effort="high"

پژوهش‌هایی که اسلاید برای کاهش خروجی نام می‌برد:

دسته پژوهش سال نتیجه یا ایده
پرامپت و بودجه Concise CoT ۲۰۲۴ درخواست کوتاه‌نویسی
CCoT ۲۰۲۴ سقف کلمه در زنجیره‌ی فکر
Chain of Draft ۲۰۲۵ پیش‌نویس‌های فشرده به جای استدلال کامل
TALE ۲۰۲۴ بودجه‌ی توکن برای استدلال
تلاش استدلالی تطبیقی Ares ۲۰۲۶ انتخاب effort برای هر قدم
When to Plan ۲۰۲۵ برنامه‌ریزی فقط وقتی مفید است
s1 و L1 ۲۰۲۵ اعمال بودجه‌ی فکر
Reason Efficiently و ShorterBetter استدلال کوتاه‌تر
خروجی ساخت‌یافته و decoding Let Me Speak Freely? ۲۰۲۴ قالب‌های سخت‌گیرانه می‌توانند به استدلال آسیب بزنند
XGrammar و SGLang ۲۰۲۴ decoding محدود به گرامر
JSONSchemaBench ۲۰۲۵ بنچمارک خروجی با شِمای JSON
فقط چیزی که عوض می‌شود AdaEdit ۲۰۲۶ انتخاب بین diff و کل فایل
CodeStruct ۲۰۲۶ ویرایش در سطح AST
ایجنت‌های ابزارساز ۲۰۲۶ ابزار قابل استفاده‌ی دوباره؛ ۵۸٪ توکن خروجی کمتر

هزینه‌ی پنهان فشرده‌سازی

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

۴. قیمت هر توکن: کش و batch#

قیمت‌های نسبی API در Claude:

نوع قیمت نسبی ورودی
ورودی پایه ۱×
ورودی کش‌شده ۰٫۱×
batch ۰٫۵×
batch + کش ۰٫۰۵×
خروجی ۵×

دو کار ساده و پرسود:

  1. پیشوند را ثابت نگه دارید: پرامپت سیستمی، تعریف ابزارها و ابتدای تاریخچه. هرگز زمان، شناسه‌ی اجرا یا حالت متغیر را در پیشوند نگذارید.
  2. کارهای غیرفوری مثل ارزیابی و پردازش‌های دسته‌ای را با batch API اجرا کنید.

پژوهش‌های کش پیشوند که اسلاید نام می‌برد: vLLM با PagedAttention (۲۰۲۳)، SGLang با RadixAttention (۲۰۲۴) و Prompt Cache (۲۰۲۴) با استفاده‌ی دوباره‌ی ماژولار. سازوکار این‌ها در جلسه‌های بعدی درس، بخش سرویس‌دهی، می‌آید.

# بد: هر اجرا پیشوند متفاوتی دارد و کش هرگز استفاده نمی‌شود
system = f"Today is {datetime.now()}. Run id: {run_id}. You are a coding agent..."

# خوب: پیشوند ثابت، اطلاعات متغیر در پیام کاربر
system = "You are a coding agent..."          # ثابت ← قابل کش
user = f"[run {run_id}, {date.today()}]\n{task}"

مسیریابی بین مدل‌ها#

روش ایده چطور
انتخاب از اول پیش از تولید، برای هر نوبت یک مدل انتخاب کن مسیریابی که روی داده‌ی ترجیح آموزش دیده؛ می‌تواند نقش ایجنت‌ها را هم انتخاب کند
آبشاری اول مدل ارزان؛ اگر یک بررسی شکست خورد، بالاتر برو بررسی با امتیازدهنده‌ی آموزش‌دیده، خودتأییدی یا بازخورد اجرا
مسیریابی در هر قدم با رشد مسیر، مدل را دوباره انتخاب کن مسیریابی بر اساس تاریخچه و بودجه؛ یا یک orchestrator که مدل‌ها را مثل ابزار صدا می‌زند

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

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

پژوهش‌های مسیریابی در اسلاید: RouteLLM و MasRouter (انتخاب از اول؛ MasRouter نقش ایجنت‌ها را هم انتخاب می‌کند)، FrugalGPT و AutoMix و EcoAssistant (آبشاری)، ToolOrchestra (یک orchestrator که مدل‌ها را مثل ابزار صدا می‌زند)، و BAAR و MTRouter (مسیریابی در هر قدم بر اساس تاریخچه و بودجه).

تکنیک‌های سیستمی که در جلسه‌های بعدی درس می‌آیند و هزینه را از سمت دیگر کم می‌کنند:

  • سمت مدل: MoE و پراکندگی، کوانتیزه‌سازی، pruning، distillation، fine-tune برای بار کاری مشخص
  • سرویس‌دهی: speculative decoding، بهینه‌سازی KV cache، زمان‌بندی بهتر
  • سخت‌افزار: kernelهای سریع‌تر، زمان‌بندی بهتر kernelها، شتاب‌دهنده‌های تخصصی

آیا اصلاً LLM لازم است؟#

  • قدم‌ها هر بار یکسان‌اند؟ از LLM بخواهید یک بار اسکریپت بنویسد و بعد اسکریپت را اجرا کنید.
  • قالب ورودی ثابت است؟ regex، parser یا قالب، با هزینه‌ی صفر.
  • برچسب یا امتیاز محدود؟ یک دسته‌بند کوچک آموزش دهید.
  • روند ثابت با استدلال کم؟ روند را اسکریپت کنید و LLM را فقط جایی صدا بزنید که لازم است.

هر صرفه‌جویی هزینه‌ی مقابلی دارد#

ترفند هزینه‌ی مقابل
compaction خواندن دوباره‌ی فایل‌های حذف‌شده؛ بازنویسی کش
مسیریابی به مدل ارزان شکست طولانی به خاطر برنامه‌ی بد
زیرایجنت تکرار کانتکست و دستورهای مشترک
اقدام پیش‌دستانه هدر رفتن توکن روی حدس غلط؛ رقابت روی ابزار
صرفه‌جویی خالص = صرفه‌جویی ناخالص − هزینه‌ی مقابل

هر دو را روی همان کارها بسنجید.

بودجه و قاعده‌ی توقف#

یک مثال از محدودیت برای هر کار: ۱۰ دلار، ۸۰ فراخوانی مدل، ۱۵ دقیقه زمان ابزار، ۲ تلاش مجدد برای هر قدم. حدها را از روی اجراهای واقعی تعیین کنید، مثلاً دو برابر صدک ۹۵ اجراهای موفق.

اجرا را متوقف کنید وقتی تأییدکننده پاس شد، وقتی در N قدم هیچ تست تازه‌ای پاس نشد، وقتی یک خطا تکرار می‌شود، یا وقتی به حد رسیدید. در توقف، کار را با یک خلاصه تحویل دهید.

هزینه‌ی بهینه‌سازی را هم بشمارید#

جستجوی پرامپت یا روند بهتر خودش هزینه دارد. نقطه‌ی سربه‌سر تقریباً این است:

تعداد کار لازم ≈ (هزینه‌ی راه‌اندازی + به‌روزرسانی) ÷ صرفه‌جویی خالص در هر کار

اگر کشف یک روند بهتر ۲۰۰۰ دلار خرج داشته باشد و در هر کار ۰٫۰۲ دلار صرفه‌جویی کند، ۱۰۰ هزار کار طول می‌کشد تا هزینه برگردد. آزمایش‌های کوتاه ممکن است هرگز به این حجم نرسند.

سرعت: مسیر بحرانی، نه مجموع#

تأخیر را مسیر بحرانی تعیین می‌کند، نه مجموع همه‌ی قدم‌ها. در یک برنامه‌ی موازی، کارگرها هم‌زمان اجرا می‌شوند و یک قدم ادغام مسیر را می‌بندد.

ارزان‌تر می‌تواند کندتر باشد

مدل کوچک ممکن است قدم بیشتری بردارد. موازی‌سازی کل توکن را بیشتر می‌کند ولی انتظار را کم می‌کند. اگر کاری ۲۰٪ سریع‌تر اما ۳۰٪ گران‌تر شد، تأخیر خریده‌اید، نه هزینه کم کرده‌اید. این ممکن است انتخاب درستی باشد، اما جدا گزارشش کنید.

اهرم‌های سرعت:

  • هماهنگی بهتر: اجرای ناهمگام (قدم بعد را وقتی ابزار در حال اجراست شروع کن)، نشست ماندگار (شل یا مرورگر را باز نگه دار)، streaming و pipeline (فراخوانی ابزار را پیش از پایان پاسخ مدل شروع کن)، و اجرای ابزارها کنار مدل
  • ابزار سریع‌تر: build، تست و بارگذاری صفحه ممکن است از فراخوانی مدل طولانی‌تر باشند. پیش از دست بردن در مدل، زمان ابزار در هر قدم را اندازه بگیرید. خواندن‌ها را کش کنید و برای فراخوانی‌های گیرکرده timeout بگذارید.
  • ابزار بهتر و سخت‌افزار بهتر: ابزار سریع‌تر و ارزان‌تر برای همان کار، فراخوانی انتخابی ابزار، و اجرای محاسبه‌ی سنگین روی سرور به جای لپ‌تاپ.
  • موازی‌سازی: خواندن سه فایل پشت سر هم سه انتظار است و موازی یک انتظار؛ همان کار، یک‌سوم انتظار. دو شکل دارد: فراخوانی‌های مستقل ابزار در یک قدم، و زیرایجنت‌های موازی که خلاصه‌شان در آخر ادغام می‌شود. فقط کار مستقل موازی می‌شود؛ حالت مشترک یک قدم ادغام لازم دارد.
Sequential:  [Read A][Read B][Read C]
Parallel:    [Read A]
             [Read B]      ← same work, a third of the wait
             [Read C]

اقدام پیش‌دستانه#

ایده از speculative decoding در سخت‌افزار می‌آید: یک مدل ارزان عمل بعدی را حدس می‌زند، سیستم آن را زودتر اجرا می‌کند و وقتی مدل اصلی تصمیم گرفت، مقایسه می‌کند. اگر حدس درست بود، انتظار حذف شده است. اگر غلط بود، نتیجه دور ریخته می‌شود و فقط یک فراخوانی هدر رفته.

time ─────────────────────────────────────────────────►

without:   [ model thinks ...... ][ search runs ... ][ model thinks ... ]

with:      [ model thinks ...... ][ model thinks ... ]
           [ guessed search ... ]   ← ready when the model asks for it

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

منبع حدس می‌تواند یک مدل کوچک، یک شاخه‌ی زودهنگام از خود مدل، یا الگوهای مسیرهای قبلی باشد. مثلاً بعد از search(q) معمولاً نتیجه‌ی اول باز می‌شود. این روش وقتی بهترین است که حدس‌ها اغلب درست باشند و عمل‌ها قابل برگشت باشند. خواندن امن است. نوشتن به snapshot و rollback نیاز دارد.

سه منبع حدس:

منبع چطور
مدل‌محور یک مدل پیش‌نویس کوچک عمل بعدی مدل بزرگ را پیش‌بینی می‌کند
خودپیش‌بینی یک شاخه‌ی زودهنگام از همان مدل، فراخوانی ابزار خودش را حدس می‌زند
تاریخچه‌محور ردهای قبلی ابزار بعدی را پیش‌بینی می‌کنند و آرگومان‌ها را از نتیجه‌ی قبلی پر می‌کنند

روش‌های بی‌اتلاف همیشه پیش از نگه داشتن نتیجه آن را تأیید می‌کنند. روش‌های با اتلاف مثل SPAgent بعضی بررسی‌ها را حذف می‌کنند.

دو مثال از اسلاید:

  • PASTE: وقتی search(q) شروع می‌شود، الگوی ردهای قبلی می‌گوید معمولاً نتیجه‌ی اول باز می‌شود. پس باز کردن آن صفحه هم‌زمان با فکر کردن مدل شروع می‌شود.
  • SPORK: یک کاوشگر جداشده، استدلال اولیه‌ی مدل را می‌خواند، فراخوانی ابزار پیش‌بینی‌شده را اجرا می‌کند و نتیجه را آماده نگه می‌دارد تا وقتی مدل اصلی همان فراخوانی را بفرستد.

افق پیش‌دستی هم بزرگ‌تر می‌شود: از یک فراخوانی ابزار، به نیت ابزار، به شاخه‌ها و به کل مسیر. پرسش باز این است که فراخوانی‌های پیش‌دستانه را با بودجه‌ی محدود GPU، CPU و API چطور زمان‌بندی کنیم تا زمان صرفه‌جویی‌شده در مسیر بحرانی از کار هدررفته بیشتر باشد.

در یک حلقه بهینه کنید#

اجرا و پروفایل (هر فراخوانی، توکن، ابزار و انتظار را ثبت کن)
  ─◄ منبع هزینه و تأخیر را اندازه بگیر
  ─◄ فقط یک چیز را تغییر بده (compaction، routing، کش یا موازی‌سازی)
  ─◄ روی همان کارها موفقیت، هزینه و تأخیر p95 را دوباره بسنج
  ─◄ تکرار

معماری هارنس#

سه معماری برای هارنس، با یک جهت حرکت: مسئولیت از ایجنت بیرون می‌رود؛ از کد، به رابط، به سرویس.

۱. یکپارچه (monolithic). یک runtime خودش حافظه، ابزار، کانتکست، برنامه‌ریزی و اجرا را پیاده می‌کند:

class CodingAgent:
    def __init__(self):
        self.memory = Memory()
        self.tools = Tools()
        self.context = ContextManager()
        self.planner = Planner()
        self.executor = Executor()

    def run(self, task):
        while not self.finished:
            a = self.planner.plan(task)
            r = self.executor.execute(a)
            self.context.update(r)

مزیت: پیاده‌سازی و اشکال‌زدایی ساده، کمترین سربار ارتباط و اجرا، اشتراک آسان حالت داخلی. عیب: تعویض یک جزء سخت است، اجزا به هم گره می‌خورند، زیرساخت بین ایجنت‌ها مشترک نمی‌شود و ایزوله‌سازی سخت است.

۲. ماژولار. ایجنت هنوز حلقه را کنترل می‌کند، اما به هر جزء از راه یک رابط می‌رسد:

agent = CodingAgent(
    memory_provider=RedisMemory(),
    tool_provider=MCPTools(),
    context_provider=SlidingWindowContext(),
    sandbox_provider=DockerSandbox(),
)
# Docker → Firecracker: swap one provider

مزیت: تعویض آسان اجزا، تست‌پذیری و توسعه‌پذیری بهتر، جدایی روشن مسئولیت‌ها، و امکان وصل کردن پیاده‌سازی‌های شخص ثالث. عیب: کنترل‌گر هنوز مالک چرخه‌ی عمر است، منطق هماهنگی پیچیده می‌شود، دامنه‌ی خرابی ممکن است هنوز مشترک باشد و تنظیم هم‌زمان اجزا ویرایش کنترل‌گر را لازم دارد.

۳. میکروکرنل. یک runtime کوچک فقط حالت، هماهنگی، زمان‌بندی و امنیت را نگه می‌دارد. حافظه، ابزار و اجرا سرویس‌های بیرونی‌اند (پایگاه داده، APIهای ابزار، sandbox) که با یک پروتکل استاندارد صدا زده می‌شوند و می‌توانند در container یا ماشین جدا اجرا شوند. مزیت: مقیاس مستقل سرویس‌ها، ایزوله‌سازی بهتر خرابی (اگر واقعاً اعمال شود) و زیرساخت مشترک و مدیریت متمرکز. عیب: سربار ارتباط بیشتر، حالت‌های خرابی بیشتر، اشکال‌زدایی سرتاسری سخت‌تر، و نیاز به پروتکل و چرخه‌ی عمر استاندارد.

مثال اسلاید برای فرق این سه: اجرای یک تکه کد پایتون.

معماری چه اتفاقی می‌افتد
یکپارچه ایجنت پایتون را خودش محلی اجرا می‌کند. کمترین گام، اما ایزوله‌سازی سخت است.
ماژولار ایجنت SandboxProvider.run(code) را صدا می‌زند. برای عوض کردن sandbox، provider را عوض می‌کنید، نه ایجنت را.
میکروکرنل runtime یک درخواست اجرا به سرویس اجرا می‌فرستد؛ آن سرویس sandbox را تخصیص می‌دهد، کد را اجرا می‌کند و نتیجه را برمی‌گرداند. تخصیص، ایزوله‌سازی و چرخه‌ی عمر sandbox مال سرویس است.
بُعد یکپارچه ماژولار میکروکرنل
اصل طراحی همه‌چیز یکجا انتزاع با رابط هسته‌ی حداقلی + سرویس
کنترل‌گر مرکزی بله بله بله، اما کوچک‌شده
تعویض جزء سخت آسان آسان، اگر پروتکل‌ها جور باشند
ایزوله‌سازی اجرا اختیاری اختیاری تأکید معماری
استقرار اجزا معمولاً با هم با هم یا جدا اغلب مستقل
مقیاس مستقل محدود ممکن قوی
هزینه‌ی ارتباط کم کم تا متوسط احتمالاً بیشتر
کاربرد معمول ایجنت مستقل فریم‌ورک ایجنت زیرساخت چندایجنتی

خلاصه: میکروکرنل سادگی و سربار کم را با ایزوله‌سازی، اشتراک و مقیاس معامله می‌کند. یکپارچه برای ایجنت مستقل، میکروکرنل برای زیرساخت چندایجنتی.

هارنس‌های واقعی، انتخاب‌های متفاوت#

اسلایدها هشت هارنس را مقایسه می‌کنند:

هارنس سازنده و زبان انتخاب‌های طراحی شاخص
Claude Code Anthropic، TypeScript (بسته) یک لایه‌ی سیاست و hookهای نوع‌دار دور مدل
Codex CLI OpenAI، Rust اول sandbox، بعد سؤال: دستورها بدون شبکه اجرا می‌شوند و بیرون رفتن از sandbox تأیید می‌خواهد. patchها از یک گرامر Lark پیروی می‌کنند و در چهار مرحله تطبیق داده می‌شوند.
DeepSeek Harness DeepSeek AI، TypeScript همه چیز plugin است، حتی خود حلقه. هر درخواست یک نمای منجمد از لاگ نشست است. ویرایش‌ها compare-and-swap‌اند: اگر فایل بعد از آخرین خواندن عوض شده باشد، شکست می‌خورند.
OpenCode Anomaly/SST، TypeScript روی Bun یک سرور نشست با کلاینت‌های سبک که یک سرور HTTP مشترک با OpenAPI دارند. نُه روش ویرایش فازی، از تطبیق دقیق تا تطبیق لنگر، با سقف اندازه برای تطبیق فازی. یک مخزن git سایه برای /undo.
Pi Mario Zechner/Earendil، TypeScript هسته‌ی حداقلی با چهار ابزار و بدون MCP، زیرایجنت یا تأیید داخلی. درخواست keep-alive کش را گرم نگه می‌دارد، فقط وقتی صرفه‌جویی مورد انتظار دست‌کم ۵ سنت باشد. کتابخانه‌ی pi-ai از ۴۲ ارائه‌دهنده روی ۱۰ API مختلف پشتیبانی می‌کند.
oh-my-pi Can Bölük/Stencil Labs، TypeScript و Rust انشعابی از Pi با ویرایش hashline (برچسب ۴ رقمی هگز برای فایل به‌همراه شماره‌ی خط)، شل ماندگار، ابزارهای IDE (جستجو، AST، LSP، debugger)، تبدیل تاریخچه‌ی قدیمی به تصویر برای صرفه‌جویی در کانتکست، و تلاش دوباره‌ی TTSR وقتی یک regex منطبق شود
OpenClaw OpenClaw Foundation، TypeScript gateway برای ۲۷ کانال چت با یک صف جدا برای هر نشست. پیش از compaction یک نوبت بی‌صدا یادداشت‌های تاریخ‌دار ذخیره می‌کند. متن نامطمئن حصارکشی می‌شود، خواندن از شبکه کل نوبت را «آلوده» علامت می‌زند و نشانگرهای رمز پایش می‌شوند.
Hermes Agent Nous Research، Python یک شاخه‌ی پس‌زمینه نوبت‌های علامت‌خورده را بازبینی می‌کند و حافظه و skillها را ویرایش می‌کند. compaction را در ۵۰٪ پنجره شروع می‌کند، زودتر از همه. فراخوانی ابزار پیش از اجرای اثر جانبی در پایگاه داده‌ی نشست ثبت می‌شود.

پرسش‌هایی برای فکر کردن#

  • ایجنت شما در هر قدم ۲۰۰ هزار توکن کانتکست دارد و ۹۵٪ آن از کش خوانده می‌شود. اگر compaction کانتکست را نصف کند ولی کش را بشکند، در ۱۰ قدم بعد سود می‌کنید یا ضرر؟ با نسبت قیمت ۱ به ۱۰ حساب کنید.
  • کدام قدم‌های ایجنت شما را می‌شود کاملاً با کد معمولی جایگزین کرد؟

منابع#