Agents והלולאה האגנטית

מה זה בעצם Agent?

Agent הוא LLM שמופעל בלולאה, עם מטרה וסט כלים. בכל סיבוב המודל רואה את כל מה שקרה עד עכשיו — הבקשה המקורית, הכלים שהפעיל והתוצאות שקיבל — ומחליט: להפעיל כלי נוסף, או לסיים ולהחזיר תשובה.

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

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

הלולאה האגנטית (Agentic Loop)

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

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

מודלים מודרניים יכולים גם לבקש כמה כלים באותו סיבוב — למשל לקרוא שלושה קבצים בבת אחת. ה-harness מריץ את כולם (לרוב במקביל) ומחזיר את כל התוצאות יחד לפני הסיבוב הבא.

TypeScript
async function runAgentLoop(goal: string, tools: Tool[], maxSteps = 20): Promise<string> {
  const messages: Message[] = [{ role: "user", content: goal }];

  for (let step = 0; step < maxSteps; step++) {
    const response = await callModel(messages, tools);
    messages.push(response.message);

    if (response.toolCalls.length === 0) {
      return response.text; // המודל החליט שהמשימה הושלמה
    }

    // המודל יכול לבקש כמה כלים באותו סיבוב - מריצים את כולם
    const results = await Promise.all(response.toolCalls.map(executeTool));
    messages.push(...results); // התוצאות נכנסות לקונטקסט של הסיבוב הבא
  }

  throw new Error(`הסוכן לא סיים תוך ${maxSteps} צעדים`);
}
תרשים מעגלי עם שלושה צמתים המחוברים בחצים כחולים עם כיוון השעון: תצפית (סמל עין), תכנון (סמל הסתעפות — החלטה על הצעד הבא), ופעולה (סמל גלגל שיניים — קריאה לכלי). על החץ שחוזר מהפעולה אל התצפית מופיע סמל מסמך, המייצג את תוצאת הכלי שנכנסת לקונטקסט. במרכז המעגל סמל חזרה. מצומת התכנון יוצא חץ כתום מקווקו אל בועת תשובה עם סימן ✓ — היציאה מהלולאה כשהמודל מחליט שאין צורך בכלי נוסף.
הלולאה האגנטית: תצפית → תכנון → פעולה, ותוצאת הכלי חוזרת לקונטקסט — עד שבשלב התכנון המודל מחליט להחזיר תשובה סופית

במה זה שונה מקריאה בודדת ל-LLM?

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

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

דוגמה מלאה: סוכן שעונה על שאלה לגבי קובץ

המשתמש שואל: "מה עושה הפונקציה calculateTotal בקובץ cart.ts?"

סיבוב 1 (קריאה ראשונה למודל): המודל מקבל רק את השאלה. אין לו את תוכן הקובץ, ולכן במקום לנחש הוא מחזיר בקשה להפעיל את הכלי read_file (בקוד למטה).

בין הסיבובים: ה-harness קורא את הקובץ מהדיסק ומוסיף את התוכן שלו לקונטקסט כתוצאת הכלי. זה לא סיבוב — המודל לא מעורב בשלב הזה בכלל.

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

JSON
{
  "type": "tool_call",
  "name": "read_file",
  "input": {
    "path": "src/cart.ts"
  }
}

מתי הלולאה נעצרת, ולמה זה לא תמיד פשוט

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

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

אלה הגבולות הראשונים שה-harness אוכף מבחוץ, בלי לסמוך על שיקול הדעת של המודל; בפרק 5 נראה את השאר. אבל קודם, בפרק הבא, שאלה בסיסית יותר: מתי בכלל צריך סוכן, ומתי מספיק workflow עם מסלול קבוע שנכתב בקוד.