Subagents — האצלת משימות

כשלולאה אחת כבר לא מספיקה

הלולאה האגנטית שראינו בפרק הקודם עובדת מצוין למשימה אחת ומוגדרת, אבל משימה גדולה יותר — למשל "סקור את כל הקבצים בפרויקט ומצא בעיות אבטחה" — עלולה לדרוש עשרות סיבובים של תצפית-תכנון-פעולה, כשכל תוצאת ביניים (תוכן קובץ, תוצאת חיפוש) נשארת בקונטקסט לכל אורך הדרך.

שתי בעיות נובעות מזה: הקונטקסט מתמלא בפרטים שרלוונטיים רק לצעד ביניים ספציפי (למשל תוכן מלא של קובץ שכבר נבדק ולא יידרש שוב), וברגע שהקונטקסט ארוך מדי, גם העלות עולה וגם המודל "רואה" פחות טוב את החלק הרלוונטי לצעד הנוכחי — בדיוק הבעיה שכבר נדונה בפרק ה-Context Window בנושא ה-LLM.

מה זה בעצם Subagent?

Subagent הוא agent "ילד" שה-agent הראשי ("ההורה") מפעיל כדי לבצע חלק מוגדר וממוקד מהמשימה הכוללת. לסאב-אגנט יש קונטקסט משלו — לגמרי נפרד ונקי מקונטקסט ההורה — ולעיתים קרובות גם system prompt וסט כלים משלו, מותאמים ספציפית למשימת המשנה שהוא אמור לבצע.

מבחינה טכנית, הסאב-אגנט מריץ לולאה אגנטית מלאה משלו (בדיוק כמו שנלמד בפרק הקודם) — הוא לא "קורא פונקציה" במובן הרגיל, אלא מפעיל מחדש את כל התהליך של תצפית-תכנון-פעולה, רק על משימה ממוקדת יותר ובקונטקסט ריק שמתחיל מחדש.

יחסי הורה-ילד: האצלה ותקציר בחזרה

ההורה מגדיר לסאב-אגנט משימה ברורה וממוקדת ("בדוק את התיקייה src/auth ומצא בעיות אבטחה"), ואז "שוכח" ממנה עד שהתשובה חוזרת — הוא לא רואה את הצעדים שהסאב-אגנט נקט, איזה קבצים הוא קרא או כמה ניסיונות הוא עשה.

כשהסאב-אגנט מסיים, הוא מחזיר להורה תקציר — תוצאה מסוכמת, לא את כל ה-transcript הפנימי שלו. זו בדיוק הנקודה המרכזית: הקונטקסט של ההורה נשאר נקי ומרוכז במטרה הכוללת, בעוד כל הפרטים המלוכלכים של איך בדיוק בוצעה משימת המשנה נשארים "מבודדים" בתוך הסאב-אגנט ונעלמים כשהוא מסיים.

JSON
{
  "type": "tool_call",
  "name": "spawn_subagent",
  "input": {
    "task": "בדוק את התיקייה src/auth ומצא בעיות אבטחה",
    "tools": ["read_file", "grep"]
  }
}
תרשים המציג תיבת הורה עליונה עם חץ יורד אל תוך מסגרת מקווקווית (המסמלת קונטקסט מבודד) המכילה עיגול עם סמל לולאה פנימית קטנה — הסאב-אגנט הרץ. חץ כתום חוזר מהמסגרת המקווקווית אל בועה קטנה מסומנת בקווים (תקציר), לא בחזרה למסגרת המלאה — ממחיש שרק תקציר, לא כל התהליך הפנימי, חוזר להורה.
ההורה מאציל משימה לסאב-אגנט בקונטקסט מבודד משלו, ומקבל בחזרה רק תקציר — לא את כל התהליך הפנימי

מתי כדאי להשתמש בסאב-אגנט

משימות שאפשר לפרק לחלקים בלתי-תלויים — למשל בדיקת כמה מודולים נפרדים בקוד — יכולות לרוץ כמה סאב-אגנטים במקביל, כל אחד על החלק שלו, ולקצר משמעותית את הזמן הכולל לעומת ריצה טורית אחת אחרי השנייה.

גם כשאין מקביליות, שווה סאב-אגנט כשמשימת המשנה עצמה "רועשת" (הרבה קריאות כלים, תוצאות ארוכות) וההורה לא צריך לדעת את הפרטים — רק את התוצאה הסופית. וכשמשימת המשנה דורשת התמחות ספציפית (persona או סט כלים מצומצם ומותאם, למשל הרשאות קריאה בלבד), סאב-אגנט מאפשר להגדיר את זה בנפרד מהקונפיגורציה של ההורה.

תרשים המשווה שתי דרכי ריצה: למעלה שלושה מלבנים כחולים בשורה אחת רצופה (ריצה טורית, קו סיום מרוחק), למטה שלושה מלבנים כתומים מוערמים זה מעל זה שכולם מתחילים באותה נקודה ומסתיימים הרבה יותר מוקדם (ריצה מקבילה, קו סיום קרוב) — ממחיש את החיסכון בזמן כשסאב-אגנטים בלתי-תלויים רצים במקביל.
משימות בלתי-תלויות שרצות כסאב-אגנטים מקבילים מסתיימות הרבה יותר מהר מריצה טורית אחת אחרי השנייה

המחיר: Latency, עלות ואיבוד מידע

סאב-אגנט הוא לא "חינם": הוא מריץ לולאה אגנטית מלאה משלו, כלומר קריאות API נוספות למודל, שמוסיפות גם latency (חייבים לחכות שהוא יסיים לפני שההורה יכול להמשיך, אלא אם רצים כמה במקביל) וגם עלות ישירה.

יש גם מחיר סמוי: התקציר שחוזר להורה הוא בהכרח דחוס יותר מהתהליך המלא, ולכן פרטים מסוימים עלולים ללכת לאיבוד. אם ההורה יזדקק בהמשך לפרט ספציפי שלא נכלל בתקציר, הוא לא יוכל פשוט "לשאול שוב" בלי להפעיל את הסאב-אגנט מחדש. ההחלטה מתי הפירוק שווה את המחיר הזה היא בדיוק שיקול הדעת ההנדסי המרכזי בעבודה עם סאב-אגנטים.