arc/docs/AI_AGENT_RUNTIME_CAPABILITIES_SCENARIO.md

13 KiB
Raw Permalink Blame History

سناریوی قابلیت‌های runtime ایجنت — subagent، ابزار موازی، context پایدار

تاریخ: ۱۴۰۵/۰۵/۲۸ (۱۸ اوت ۲۰۲۶)
وضعیت: فازهای PRM-04 ۰–۱، TOOL-06 A–B+D، AGT-06 ۰–۲ پیاده شد — UI موازی و دانش-به‌ابزار موکول
مرجع ممیزی: AI_AGENT_SYSTEM_AUDIT.md (AGT-06، TOOL-06، PRM-04)
رقیب مرجع: Cursor Task/subagent، Claude Code، ChatGPT agent teams، OpenAI Agents SDK

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


۱. جمع‌بندی سریع

قابلیت در سیستم امروز کجا شکاف با سطح جهانی
ساخت و هدایت subagent هست (فاز ۰–۲) spawn_subagent / await_subagent / cancel_subagent روی حلقهٔ تو در تو analyzer UI تایم‌لاین و persist SQL هنوز نیست
چند ابزار در یک نوبت، موازی هست (read) مدل می‌تواند چند tool_calls بدهد؛ بک‌اند read را تا ۴تایی موازی و write را سریال اجرا می‌کند UI موازی‌بودن را نشان نمی‌دهد؛ نوبت اول سوال complex با tool_choice روی یک ابزار plan قفل می‌شود
تکرار بینش/حافظه/دانش در هر سوال لایهٔ semi_static cacheپذیر static + semi_static (حافظه/بینش/کانکتور) + dynamic (datetime/دانش/…) دانش سوال‌وابسته هنوز در system است اگر RAG لازم باشد

نتیجه برای فرض سوم: فرض «این اطلاعات داخل تاریخچهٔ گفت‌وگو تکرار می‌شود» دقیق نیست. پیام‌های ذخیره‌شدهٔ جلسه فقط user/assistant/tool هستند. آنچه تکرار می‌شود بلاک runtime سیستم است که بدون آن مدل در درخواست بعدی آن را به یاد ندارد. راه‌حل درست حذف از تاریخچه نیست (آنجا نیست)؛ راه‌حل لایهٔ cache نیمه‌پایدار و ارسال مجدد فقط وقتی محتوا عوض شده است.


۲. یافتهٔ ۱ — Subagent

۲.۱ آنچه در کد هست

  • یک حلقهٔ ایجنت در chat_completion_stream با بودجه، todo، continuation، write guard.
  • Run persist در ai_agent_runs و ادامه با POST .../runs/{run_id}/continue (AGT-01). هنوز همان درخواست/همان حلقه است (AGT-02).
  • هیچ ابزار spawn_subagent / delegate_task در registry نیست.
  • GAP-07 (چند شخصیت حسابدار/انباردار) با این قابلیت یکی نیست: آن نقش ثابت است؛ subagent اجرای موقت با هدف و allowlist است.

۲.۲ رفتار مطلوب (Cursor / Claude)

  1. والد تشخیص می‌دهد کار چنددامنه‌ای است (مثلاً فروش + موجودی + بدهکاران).
  2. یک یا چند subagent با goal، tool_allowlist، max_iterations، execution_mode=analyzer ساخته می‌شود.
  3. والد می‌تواند صبر کند، ادامه بدهد، یا subagent را قطع کند.
  4. خروجی subagent یک envelope است (یافته‌ها + citations + خطا)؛ والد آن را نقد می‌کند و پاسخ نهایی را می‌سازد.
  5. subagent حق write ندارد مگر والد صریحاً بسپارد (پیش‌فرض ممنوع).

۲.۳ فاز اجرا

فاز کار معیار پذیرش ریسک
۰ — قرارداد ✓ ابزار spawn_subagent + store درون‌پردازه‌ای ai_subagent_runs schema در function_registry + intent + l10n بدون UI هنوز
۱ — حلقهٔ تو در تو ✓ AIService با operation=subagent، سقف نوبت ۴، allowlist، approve_writes=False تست واحد: دو read در فرزند؛ write در فرزند fail-closed انفجار هزینه اگر سقف نباشد
۲ — کنترل والد ✓ tool result شامل subagent_id؛ ابزار await_subagent / cancel_subagent والد بعد از cancel دیگر token فرزند را مصرف نکند race با SSE والد
۳ — ادغام envelope استاندارد + citation از فرزند به والد پاسخ نهایی بدون عدد بدون منبع از فرزند نشت PII بین دامنه
۴ — UI گام trace_step با kind=subagent در تایم‌لاین کاربر ببیند کدام زیر-اجرا زنده/تمام/قطع است شلوغی God Widget

سقف پیشنهادی محصول: حداکثر ۲ subagent همزمان، حداکثر ۴ نوبت ابزار برای هر کدام، فقط کانال چت درون‌برنامه (تلگرام/CRM/ورک‌فلو نه در فاز ۱).

سناریوی پذیرش دستی

  1. «گزارش فروش این ماه، موجودی کالاهای کم، و سه بدهکار برتر را یکجا بده.»
  2. انتظار: والد plan می‌سازد؛ حداقل یک spawn؛ نتایج در پاسخ نهایی با منبع.
  3. کاربر Stop روی والد: فرزند هم cancel شود.
  4. سوال ساده «موجودی کالای X؟» نباید spawn کند.

۳. یافتهٔ ۲ — اجرای موازی ابزار

۳.۱ آنچه در کد هست (انجام‌شده)

  • اگر مدل در یک پیام assistant چند tool_calls بدهد، handle_function_calls_async آن‌ها را به run_tool_calls_partitioned می‌دهد.
  • Read حداکثر MAX_PARALLEL_READ_TOOLS = 4 با semaphore؛ هر write سد سریال است؛ ترتیب مدل حفظ می‌شود.
  • Prompt مسیریابی صریحاً می‌گوید: «ابزارهای read-only مستقل را در یک نوبت parallel صدا بزن» (ai_tool_routing_prompt.py).
  • parallel_tool_calls=false در OpenAI و disable_parallel_tool_use در Anthropic ست نشده — یعنی ارائه‌دهنده موازی را اجازه می‌دهد.
  • تست: tests/test_ai_tool_parallel.py.

۳.۲ آنچه نیست

  • UI: تایم‌لاین ابزارها را پشت‌سرهم نشان می‌دهد حتی اگر موازی اجرا شده باشند.
  • نوبت صفر سوال complex: tool_choice روی create_session_plan است → در آن نوبت موازی عملاً قفل است (عمدی).
  • مدل گاهی هنوز سریالی کار می‌کند؛ این محدودیت مدل است نه بک‌اند.

۳.۳ فاز اجرا (تکمیل، نه ساخت از صفر)

فاز کار معیار پذیرش
A — مشاهده ✓ لاگ AI_METRIC با tool_calls_in_round و parallel_read_count رویداد tool_round_parallel
B — eval ✓ کیس طلایی «فروش+موجودی+بدهکار» assertion که حداقل دو tool در یک round باشد ai_eval_assertions + DEFAULT_EVAL_CASES
C — UI در trace، ابزارهای هم‌نوبت با یک bundleId نمایش موازی کاربر زمان انتظار را کوتاه‌تر حس کند
D — سقف ✓ اگر مدل >۴ read بدهد، همان semaphore فعلی کافی است؛ در prompt سقف را بنویس stampede DB رخ ندهد

سناریوی پذیرش دستی

  1. همان سوال چنددامنه‌ای پس از ساخته‌شدن plan.
  2. در لاگ سرور یک round با ≥۲ function هم‌زمان (زمان شروع هم‌پوشان).
  3. Write (مثلاً ایجاد فاکتور) هرگز با write دیگر موازی نشود.

۴. یافتهٔ ۳ — بینش و context در هر سوال جدید

۴.۱ مسیر واقعی هر پیام کاربر

POST .../messages?stream=true
  → persist پیام user
  → build_system_prompt_stream
       static_core     = نقش + سیاست untrusted          ← cacheپذیر
       business_anchor = شناسه کسب‌وکار + تقویم         ← cacheپذیر
       semi_static     = حافظه + بینش + کانکتور         ← cacheپذیر جدا
       execution/plan  = حالت اجرا + todos
       runtime         = datetime، دانش، مهارت، پیوست، todo
  → تاریخچه جلسه (حداکثر ۴۰ پیام؛ در صورت تنگی بودجه خلاصه)
  → حلقهٔ مدل + ابزار

بینش (format_insights_for_prompt) حدود چند خط KPI است (فروش امروز/هفته، بدهکاران، کم‌موجود) و با TTL ۳۰۰ ثانیه در حافظهٔ فرایند کش می‌شود تا SQL تکرار نشود. متن همان KPI هر نوبت دوباره در system می‌آید.

دانش فقط اگر query_needs_knowledge(user_query) باشد لود می‌شود — یعنی وابسته به سوال است و نباید cache بلندمدت شود.

تاریخچهٔ DB شامل بینش نیست. پس «تکرار در تاریخچه» رخ نمی‌دهد؛ «تکرار در ورودی مدل» رخ می‌دهد و برای HTTP stateless طبیعی است.

Prompt cache (ai_prompt_cache.py) دو breakpoint دارد: static_core + business_anchor و لایهٔ semi_static (حافظه/بینش/کانکتور). datetime و دانش در dynamic_system می‌مانند.

۴.۲ راه‌حل پیشنهادی (ترتیب امن)

نباید بینش را به‌کلی حذف کرد: مدل بدون آن در سوال «وضعیت امروز چطوره؟» مجبور به چند tool اضافه می‌شود. هدف کاهش توکن تکراری است نه حذف قابلیت.

فاز کار معیار پذیرش
۰ — اندازه ✓ در context_usage فیلدهای runtime_tokens / insights_tokens / static_tokens / semi_static_tokens عدد واقعی در لاگ AI_METRIC context_usage
۱ — لایهٔ نیمه‌پایدار ✓ semi_static = بینش + حافظهٔ دستورات + کانکتور؛ hash محتوا در cache_key برای Anthropic، cache_read_tokens در نوبت ۲+ همان جلسه > ۰ وقتی KPI عوض نشده
۲ — دانش فقط با ابزار دانش را از system درآور؛ search_knowledge اجباری وقتی RAG لازم است سوال غیر دانش‌محور runtime بدون بلوک دانش
۳ — datetime جدا ✓ ساعت همیشه dynamic بماند (نباید کل cache را بشکند) breakpoint cache قبل از datetime
۴ — اختیاری اگر hash بینش عوض شد (فروش جدید)، یک خط «بینش به‌روز شد» در runtime مدل عدد کهنه ندهد

آنچه نباید کرد

  • چسباندن بینش به پیام assistant در تاریخچه (تاریخچه را آلوده می‌کند و با خلاصه قاطی می‌شود).
  • حذف کامل بینش از نوبت‌های بعدی بدون cache لایهٔ سیستم (مدل کور می‌شود).
  • گذاشتن دانش بازیابی‌شدهٔ هر سوال داخل prefix ثابت (cache غلط و پاسخ کهنه).

سناریوی پذیرش دستی

  1. دو سوال پشت‌سرهم در یک جلسه: «سلام» سپس «فروش امروز چقدر بود؟»
  2. انتظار: نوبت دوم SQL بینش نزند اگر TTL نگذشته (کش ۳۰۰ثانیه).
  3. پس از فاز ۱: usage نوبت دوم cache_read داشته باشد؛ متن بینش در پیام‌های DB نباشد.

۵. ترتیب پیشنهادی اجرا

  1. PRM-04 فاز ۰–۱ ✓
  2. TOOL-06 تکمیل A–B ✓ (+ سقف prompt فاز D)
  3. AGT-06 فاز ۰–۲ ✓ — فاز ۳–۴ (ادغام citation در UI / تایم‌لاین) بعدی است.

وابستگی: subagent موازیِ چند فرزند روی همان run_tool_calls_partitioned سوار می‌شود؛ سقف ۲ همزمان و ۴ نوبت اعمال شده.


۶. چک‌لیست PR وقتی یکی از فازها پیاده شد

  • ابزار جدید: registry + permission + intent + l10n + write guard
  • تست واحد مسیر اصلی + مسیر شکست (cancel subagent، write در فرزند، cache miss)
  • کیس eval یا سناریوی دستی بالا
  • به‌روز کردن وضعیت آیتم در ممیزی و یک سطر تاریخچه
  • متریک AI_METRIC برای spawn / parallel_round / cache_hit