מהו AI agent: חמישה סוגים קלאסיים ושתי הגדרות יריבות
עולם השואב נשבר ארבע פעמים, וכל שבירה מזכה באחד מחמשת סוגי ה-agent הקלאסיים — עד שכלי אחד מנפח קריאה מ-39 ל-420 token.
בעמוד הזה
הנה אותה שאלה, שנשאלה פעמיים מאותו מודל, עם אותם משקלים ו-greedy decoding. ההבדל היחיד הוא שבפעם השנייה היה כלי אחד בקטלוג.
no tools in the catalogue
turn 1 prompt= 39 out= 8 finish=stop TEXT "The capital of France is Paris."
=> model calls=1 prompt tokens=39 output=8 wall=974 ms
one tool in the catalogue: get_temperature(city)
turn 1 prompt= 185 out= 20 finish=tool_calls CALL get_temperature({"city": "Paris"})
tool get_temperature -> {"city":"Paris","celsius":11}
turn 2 prompt= 235 out= 18 finish=stop TEXT "The capital of France is Paris. It is
currently at 11 degrees Celsius."
=> model calls=2 prompt tokens=420 output=38 wall=6,685 msקריאה אחת הפכה לשתיים. שלושים ותשעה input tokens הפכו ל-420, פי 10.8. פחות משנייה הפכה לכמעט שבע. והתשובה קיבלה עובדה שאף אחד לא ביקש, מכלי שהמודל בחר לקרוא לו עבור שאלה שלא הזכירה מזג אוויר.
המערכת השנייה היא מה שרוב התעשייה ב-2026 קוראת לו agent. או שהיא לא, תלוי איזו משתי ההגדרות הנקראות ביותר אתם פותחים — ושתי אלה אינן אומרות אותו דבר. אחת מהן אפילו לא מסכימה עם עצמה.
המחלוקת הזו היא הפרק הזה. זו לא מריבת אוצר מילים: שתי ההגדרות מותחות את הגבול על צירים שונים, והציר שבוחרים קובע מה בונים ועל מה משלמים. שתיהן נשענות על טקסונומיה ישנה יותר, והדרך הזולה ביותר להרוויח אותה היא לבנות את ה-agent הגרוע בעולם.
הצגת פרטים
מה הפרק הזה צריך מהקודמים.
- פרק 13 מדד כמה קריאה יחידה עולה בזמן; הפרק הזה מכפיל זאת במספר התורות.
- פרק 15: ה-prompt הוא המצב המלא של המודל, כי שום דבר לא שורד את הקריאה.
- פרק 16: input tokens גדלים עם ריבוע השיחה.
- פרק 18: קטלוג הכלים, והמסע הלוך-חזור שבו המודל מבקש והקוד שלכם מבצע.
אין כאן טנזורים. הפרק הוא TypeScript, במקום שבו כלל השפה של פרק 14 מציב אותו, והלולאה שלו היא האב הקדמון הישיר של זו שבפרק 23.
רובוט עם שני חדרים
קישור למקטע: רובוט עם שני חדריםהדוגמה הוותיקה ביותר בתחום היא שואב אבק בעולם של שני ריבועים, A ו-B, שכל אחד מהם נקי או מלוכלך.1 היא שורדת בכל ספר לימוד כי זה העולם הקטן ביותר שבו agent יכול להיות צודק או טועה.
ה-percept הוא זוג — איפה אני, והאם מלוכלך כאן — והפעולות הן SUCK, LEFT ו-RIGHT. כל התוכנית היא שורה אחת.
type Percept = { dirty: boolean; where?: "A" | "B" };
type Action = "SUCK" | "LEFT" | "RIGHT";
const textbook = (p: Percept): Action =>
p.dirty ? "SUCK" : p.where === "A" ? "RIGHT" : "LEFT"; הריצו אותה מול כל תצורת פתיחה של עולם שני הריבועים:
A dirty, B dirty, start A -> steps=3 clean=true
A clean, B dirty, start A -> steps=2 clean=true
A dirty, B clean, start B -> steps=2 clean=trueזהו simple reflex agent: הוא פועל לפי ה-percept הנוכחי בלבד, בלי זיכרון של שום דבר שהיה לפניו. זו לא קטגוריית צעצוע — תרמוסטט הוא כזה, וכך גם קריאה יחידה למודל שפה בלי שיחה מצורפת.
עכשיו נשבור אותו כפי שהמציאות שוברת. לרובוט שואב אמיתי יש חיישן לכלוך ופגוש, לא ריבוע שמסומן A מתחת לשטיח. הוציאו את המיקום מה-percept ואל תשנו שום דבר אחר:
const dirtOnly = (p: Percept): Action => (p.dirty ? "SUCK" : "RIGHT");A dirty, B dirty, start A -> steps=3 clean=true still dirty=0
t=0 at=A percept={dirty:true} -> SUCK
t=1 at=A percept={dirty:false} -> RIGHT
t=2 at=B percept={dirty:true} -> SUCK
A dirty, B clean, start B -> steps=500 clean=false still dirty=1
t=0 at=B percept={dirty:false} -> RIGHT
t=1 at=B percept={dirty:false} -> RIGHT
t=2 at=B percept={dirty:false} -> RIGHT
t=3 at=B percept={dirty:false} -> RIGHTאותה תוכנית, שני ריבועים. ממצב פתיחה אחד היא מסיימת בשלושה צעדים; מאחר היא נוסעת לתוך הקיר הימני חמש מאות פעמים והייתה ממשיכה עד שהסוללה הייתה מתה. היא לא יכולה לתפוס את ההבדל בין שני המצבים, ולכן לא יכולה לפעול בהם אחרת. Russell ו-Norvig מנסחים את התוצאה הכללית בשורה אחת: לולאות אינסופיות הן לעיתים קרובות בלתי נמנעות עבור simple reflex agents בסביבות נצפות חלקית.1
יש תיקון שעולה שורה אחת וללא זיכרון, וכדאי למדוד אותו לפני שנושיט יד למשהו חכם יותר.
let seed = 12345;
const rnd = () => ((seed = (seed * 1103515245 + 12345) & 0x7fffffff) / 0x7fffffff);
const coin = (p: Percept): Action => (p.dirty ? "SUCK" : rnd() < 0.5 ? "LEFT" : "RIGHT"); אלפיים הרצות של מסדרון שכולו מלוכלך בשלושה גדלים, עם מחולל seeded אחד לכל האורך:
| חדרים | צעדים בממוצע | חציון | הגרוע מתוך 2,000 | מעולם לא סיים |
|---|---|---|---|---|
| 2 | 4.0 | 4 | 13 | 0 |
| 4 | 16.6 | 14 | 81 | 0 |
| 8 | 68.7 | 52 | 306 | 0 |
אקראיות מסירה את הלולאה לגמרי. היא גם עולה: שמונה חדרים דורשים חמישה-עשר מהלכים אם יודעים מה עושים, וה-agent הזה עומד בממוצע על 68.7 ופעם אחת לקח 306. זה כל הפרק במיניאטורה. כל יכולת שאנחנו מוסיפים קונה נכונות במקרה שה-agent הקודם לא יכול היה לטפל בו, וגובה עליה במטבע שצריך קודם לתת לו שם.
לתת שמות לחלקים, עכשיו כשהם נחוצים
קישור למקטע: לתת שמות לחלקים, עכשיו כשהם נחוציםagent תופס את הסביבה שלו דרך חיישנים ופועל דרך מפעילים. תוכנית ה-agent היא הפונקציה מ-percepts לפעולות — כל דוגמת קוד לעיל היא כזו. רצף ה-percepts הוא כל מה שנתפס עד כה, ו-simple reflex agent מתעלם מכולו חוץ מהפריט האחרון.
רציונליות היא המילה שרוב המאמרים טועים בה, ולהבין אותה נכון הופך את שאר הפרק לשמיש. agent אינו רציונלי או לא רציונלי בפני עצמו. Russell ו-Norvig מגדירים agent רציונלי ככזה שבוחר, עבור כל רצף percepts אפשרי, את הפעולה שצפויה למקסם את מדד הביצוע שלו, בהינתן הראיות של אותו רצף וכל ידע מובנה שיש לו.1 מדד הביצוע אינו בתוך ה-agent: הוא שייך למתכנן, ורציונליות מוגדרת רק ביחס אליו.
את המפרט נהוג לכתוב כארבעה דברים, PEAS: מדד ביצוע, סביבה, מפעילים, חיישנים.
| רובוט השואב | support agent בפרודקשן | |
|---|---|---|
| מדד ביצוע (P) | ריבועים נקיים, ליחידת סוללה | כרטיסים שנפתרו, לדולר, בלי הסלמה |
| סביבה (E) | הרצפה, הלכלוך, הרהיטים, השטיח | תור הכרטיסים, מסד הנתונים שלכם, הלקוח |
| מפעילים (A) | גלגלים, שאיבה | tool calls |
| חיישנים (S) | חיישן לכלוך, פגוש | הודעת המשתמש, תוצאות כלים |
שימו לב איזו שורה יוצאת דופן. כמעט כל צוות שבונה agents ב-2026 כותב את E, A ו-S — סכמות הכלים, האינטגרציות, פורמט ההודעות — כי הקוד לא ירוץ בלעדיהם. כמעט אף אחד לא כותב את P. בלעדיו, ל-"ה-agent שלנו מצליח" אין משמעות שאפשר לבדוק, ו-"רציונלי" לא יכול לחול על המערכת בכלל, רק על הדגמה. פרק 29 עוסק בהפיכת P למספר, וזו הסיבה שהוא קיים.
┌───────────────────────── the environment ─────────────────────────┐
│ │
│ ┌──────────────────────── the agent ─────────────────────┐ │
│ │ │ │
───┼──►│ sensors ──► the agent program ──► actuators ─────┼──────┼──►
percept │ │ action
│ └────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
▲
the performance measure lives out here, in the head of
whoever built the thing, and the agent cannot change itסביבות משימה מסווגות עוד לאורך שבעה צירים, שחמישה מהם קובעים את רוב הקושי כאן: נצפות במלואן או חלקית, דטרמיניסטיות או לא, אפיזודיות או רציפות, סטטיות או דינמיות, ידועות או לא ידועות.1 agent שמדבר עם כלים אמיתיים מעל רשת אמיתית נמצא בפינה הקשה של כל החמישה — לא דטרמיניסטי אפילו בטמפרטורה אפס (פרק 17), ובמיוחד, החלק שממעיטים בערכו, לא ידוע, כי אין לכם מודל אמין של מה הכלים שלכם עצמם עושים לעולם. לכן הלולאה של פרק 23 צריכה טיפול בשגיאות יותר משהיא צריכה תכנון.
מוסיפים זיכרון, ומוצאים את הקיר הבא
קישור למקטע: מוסיפים זיכרון, ומוצאים את הקיר הבארצפות אמיתיות אינן חד-ממדיות, לכן נעלה את העולם לתוכנית. סימני סולמית הם קירות, כוכביות הן לכלוך, והרובוט מתחיל בחדר האמצעי:
col 0 1 2 3 4 5 6
row 0 * . . # . . *
row 1 . # . # . # .
row 2 . # . S . # . S = the robot starts here
row 3 . # . # . # .
row 4 * . . # . . *השדרוג המתבקש הוא זיכרון. ה-agent שומר מפה: כל ריבוע שעליו עמד וכל ריבוע שבו הפגוש הופעל. הכלל שלו הוא ללכת לריבוע סמוך שלא ביקר בו — ימינה, ואז למטה, ואז שמאלה, ואז למעלה — ולסגת כשכל מה שסביבו ידוע. זהו model-based reflex agent: הוא מחזיק מצב פנימי מהיסטוריית ה-percepts, ולכן יכול לפעול לפי מה שאינו רואה כרגע.
זה שיפור אמיתי, ועדיין לא מספיק:
5,000 steps allowed -> steps=5,000 distinct squares visited=13/25 still dirty=2/4חמשת אלפים מהלכים, חצי מהרצפה מעולם לא נראתה. המפה נכונה והכללים נכונים. מה שה-agent לא יכול לעשות הוא להשתמש במפה כדי להגיע למקום כלשהו: הכללים שלו עונים רק על "לאיזה מארבעת השכנים שלי כדאי לי להיכנס", ולכן ברגע שנגמרים לו ריבועים לא מבוקרים לידו, אין לו דרך לבטא את המחשבה יש ריבוע לא מבוקר שמונה מהלכים מכאן והייתי רוצה לעמוד עליו. הוא יודע איפה הוא. הוא לא יודע איפה הוא רוצה להיות.
יעד, ואז סיבה להעדיף מסלול אחד על אחר
קישור למקטע: יעד, ואז סיבה להעדיף מסלול אחד על אחרgoal-based agent מחזיק, מעל המודל שלו של העולם, תיאור של המצב שהוא רוצה להביא אליו, ובוחר פעולות באמצעות חיפוש על פני רצפים שלהן עד שהוא מוצא רצף שמסתיים שם. יעדים הופכים בחירת פעולה מחיפוש בטבלה לחיפוש ממש.
היעד הוא "לא נשאר אף ריבוע מלוכלך". החיפוש הוא הליכה לרוחב אל הריבוע המלוכלך הקרוב ביותר, והנתיב שהוא מחזיר הוא התוכנית.
goal-based (fewest moves) -> moves=27 battery=52 still dirty=0
from 2,3 -> 4,6 via 5 moves: 2,3 2,4 3,4 4,4 4,5 4,6
from 4,6 -> 0,6 via 4 moves: 4,6 3,6 2,6 1,6 0,6
from 0,6 -> 4,0 via 10 moves: 0,6 0,5 0,4 1,4 2,4 2,3 2,2 3,2 4,2 4,1 4,0
from 4,0 -> 0,0 via 4 moves: 4,0 3,0 2,0 1,0 0,0עשרים ושבעה מהלכים, הרצפה נקייה. אבל הביטו בעמודת הסוללה ובמקטע האחרון של התוכנית. עמודה 0 מכוסה שטיח: חציית ריבוע עם שטיח עולה שש יחידות סוללה, ריבוע מרוצף עולה אחת. ה-agent חזר הביתה במעלה עמודה 0 כי זה ארבעה מהלכים במקום שמונה, וארבעת המהלכים על השטיח עלו 24, בעוד שהמעקף בן שמונת המהלכים היה עולה 13.
הוא לא יכול אחרת. יעד הוא מבחן בינארי: הרצפה נקייה או שלא. כל תוכנית שמסתיימת ברצפה נקייה מספקת אותו באותה מידה, ולכן כשכמה תוכניות מצליחות ל-agent אין על בסיס מה לבחור ביניהן. כדי להעדיף הצלחה אחת על אחרת צריך מספר על פני תוצאות, והמספר הזה הוא פונקציית תועלת. agent שממקסם אותה הוא utility-based agent.
השינוי בקוד הוא איבר אחד בתוך החיפוש. חיפוש לרוחב סופר מהלכים; גרמו לו לספור עלות במקום, וקיבלתם את האלגוריתם של Dijkstra ו-agent אחר:
const nd = dist.get(k)! + (byCost ? cell.cost : 1); // <- the entire differencegoal-based (fewest moves) -> moves=27 battery=52 still dirty=0
utility-based (cheapest route) -> moves=31 battery=41 still dirty=0
from 4,0 -> 0,0 via 8 moves: 4,0 4,1 4,2 3,2 2,2 1,2 0,2 0,1 0,0ארבעה מהלכים נוספים, אחת-עשרה יחידות סוללה פחות: זול יותר בעשרים ואחד אחוז. אותו יעד, אותה מפה, אותו קוד חוץ מאיבר אחד. שני ה-agents שונים רק במה שהם מנסים להיות טובים בו, והם בוחרים דרכים שונות הביתה.
זו גם הנקודה הראשונה שבה ה-agent צריך משהו שהוא לא יכול לייצר. מישהו צריך להחליט כמה שווה יחידת סוללה ביחס למהלך. תועלת היא מדד הביצוע שנכתב בצורה שה-agent יכול לחשב איתה, והכתיבה שלו היא תפקיד המתכנן. כשאנשים אומרים ש-agent "ביצע אופטימיזציה לדבר הלא נכון" הם כמעט אף פעם לא מתכוונים לבאג. הם מתכוונים שהשורה הזו נכתבה ברשלנות.
הסוג החמישי, והדרך שבה הוא משתבש
קישור למקטע: הסוג החמישי, והדרך שבה הוא משתבשעכשיו תנו ללכלוך לחזור. ארבעה חדרים מתלכלכים שוב בארבעה קצבים שונים, וה-agent לעולם לא מקבל אותם. הוא מבקר בחדר אחד בכל tick ורואה רק את החדר הזה. מדד הביצוע הוא room-ticks שבילו מלוכלכים לאורך 4,000 ticks — נמוך יותר טוב יותר.
learning agent, בפירוק של ספר הלימוד, הוא כל אחד מאלה לעיל בתוספת שלושה חלקים: רכיב למידה שמשנה את ה-agent, מבקר שאומר לו איך ה-agent מתפקד מול תקן ביצוע קבוע, ו-מחולל בעיות שמציע פעולות שכדאי לנסות בגלל מה שילמדו.1 שלוש מדיניות באותה סביבה. הראשונה לא לומדת; השנייה והשלישית לומדות אותו דבר ומשתמשות בו אחרת.
| מדיניות | dirty-room-ticks לאורך 4,000 | ביחס לסיור |
|---|---|---|
| סיור round-robin קבוע, בלי למידה | 2,290 | — |
| learner A: הערכת קצב הלכלוך של כל חדר, ואז ללכת למקום שבו סביר ביותר שיש לכלוך | 11,820 | גרוע פי 5.2 |
| learner B: אותן הערכות, משוקללות לפי הזמן מאז הביקור האחרון | 1,576 | טוב יותר ב-31 % |
הקצבים הנסתרים היו 0.35 למטבח, 0.05 למסדרון, 0.02 לחדר העבודה ו-0.01 לעליית הגג — ו-learner A מצא אותם. הוא זיהה נכון את המטבח כחדר המלוכלך ביותר בבית, ואז הלך למטבח בכל tick עד סוף הסימולציה, בעוד שלושת האחרים נשארו מלוכלכים לנצח. הוא גרוע פי חמישה מלא ללמוד בכלל, והוא לא מקולקל.
הלקח הוא של סעיף התועלת. learner A מיקסם "ההסתברות שהחדר שאני עומד לבקר בו מלוכלך". מדד הביצוע היה "room-ticks שבילו מלוכלכים". מספרים שונים; השני הוא מה שהמבקר ניקד, ואף אחד לא אמר זאת ל-agent. learner B מכפיל את אותו קצב שנלמד בזמן שעבר מאז הביקור האחרון — הלכלוך שהוא מצפה למצוא, ולא הסיכוי למצוא בכלל — ומנצח את הסיור שממנו התחיל.
פרט מימוש אחד הכריע את התוצאה. בגרסה הראשונה של learner B, חדר שבו לא הופיע לכלוך בשלושה ביקורים קיבל קצב של בדיוק אפס — ואפס כפול כל דבר הוא אפס, לכן לא ביקרו בו שוב לעולם וההערכה לא יכלה להתעדכן. החלקת השבר, הצלחות ועוד אחת מעל ניסיונות ועוד שתיים, הפכה 11,895 ל-1,576. "עדיין לא נצפה" ו-"נמדד ויצא אפס" הן טענות שונות, ומערכת ששומרת אותן באותו שדה מקבלת החלטות שאינה יכולה לבטל.
חמשת הסוגים, ומה הם ב-2026
קישור למקטע: חמשת הסוגים, ומה הם ב-2026 1 simple reflex percept ────────────────────────────────► rules ────► action
2 model-based percept ──► [state] ──────────────────► rules ────► action
3 goal-based percept ──► [state] ──► [goal] ──────► search ───► action
4 utility-based percept ──► [state] ──► [goal] ──► [U] ──► argmax ► action
5 learning all of the above, plus [critic] ──► changes the parts aboveכל אחד מהחמישה נמצא היום בפרודקשן בשם אחר.
| סוג קלאסי | מה הוא נושא בין percepts | צורתו ב-2026 | מה הוא לא יכול לעשות |
|---|---|---|---|
| simple reflex | כלום | קריאת מודל אחת בלי היסטוריה: מסווג, endpoint לחילוץ, השלמה בתור אחד | כל דבר שתלוי בתור הקודם |
| model-based reflex | מצב פנימי שנבנה מהיסטוריית ה-percepts | צ'אט: התמליל, שנשלח מחדש במלואו בכל קריאה | לבחור לאן השיחה אמורה להגיע |
| goal-based | מצב ועוד תיאור של המצב הרצוי | לולאת reason-and-act עם תנאי עצירה2 | להעדיף תוכנית מוצלחת אחת על אחרת |
| utility-based | מצב, יעד ומספר על פני תוצאות | לולאות מעריך–ממקסם, ודירוג תשובות מועמדות לפי קריטריון כתוב (פרק 25) | להמציא את הקריטריון |
| learning | כל זה, ועוד מבקר ומחולל בעיות | Reflexion, שכותב את הלקחים של עצמו לתוך buffer אפיזודי במקום לעדכן משקלים;3 זיכרון משתמש מתמיד (פרק 24) | לבחור את התקן שהמבקר מנקד מולו |
שתי שורות קרובות יותר מאנלוגיה, באופן שעולה כסף.
צ'אט הוא model-based reflex agent שהמודל שלו אינו פנימי. בספר הלימוד המצב הוא משתנה בתוך תוכנית ה-agent. בצ'אט הוא התמליל: הוא חי בצד שלכם, נשלח מחדש במלואו בכל קריאה, ונבנה מאפס בתוך המודל בכל פעם. זה החשבון הריבועי של פרק 16, וזה אותו אובייקט שספר הלימוד צייר כתיבה שכותרתה "state". הנה ההבדל, כפי שנמדד על שאלת המשך אחת עם ובלי שתי ההודעות שלפניה:
with the transcript prompt=67 "The current temperature in Lisbon, Portugal is 15°C."
without the transcript prompt=29 "Lisbon is the capital of Portugal, not a city in Portugal."אותו מודל, אותן שלוש מילים של קלט משתמש, והשני הוא רובוט המסדרון שנוסע לתוך הקיר. לא היו כלים בהרצה הזו, לכן ה-15 מומצא — אבל המצב הוא מה שגורם לשאלת ההמשך להיות בעלת משמעות בכלל. אתם בונים אותו מחדש בכל פעם ומשלמים עליו פי 2.3 input tokens בשיחה בת שני תורים. פרק 16 מדד לאן המכפיל הזה מגיע בתור ארבעים.
Reflexion הוא learning agent שמשנה את הקלט שלו ולא את התוכנית שלו. בפירוק של ספר הלימוד רכיב הלמידה משנה את רכיב הביצוע. Reflexion משאיר את המשקלים כפי שהם וכותב טקסט רפלקטיבי לתוך buffer אפיזודי שהניסיון הבא קורא.3 רכיב הלמידה הוא prompt, הזיכרון הוא שורת מסד נתונים, רכיב הביצוע הוא מודל קפוא — והתרשים הוא זה של ספר הלימוד, בלי שינוי.
וזה הגבול הכנה של המיפוי. חמשת הסוגים מסווגים את תוכנית ה-agent. ב-2026 התוכנית הזו מפוצלת באמצע: חלק ממנה הוא הקוד שלכם, חלק ממנה נמצא בתוך משקלים שלא אימנתם. כשמודל מחליט בעצמו לקרוא לכלי, האם מבחן היעד נמצא בתוכנית שלכם או במודל? לטקסונומיה אין תשובה, כי כשנכתבה לא היה לו שום מקום אחר להיות בו — והשאלה הזו היא בדיוק המקום שבו שתי ההגדרות המודרניות נפרדות.
לענות, לקרוא ולעצור, ב-trace אחד
קישור למקטע: לענות, לקרוא ולעצור, ב-trace אחדההגדרות הן ויכוחים על התנהגות, והרבה יותר קל לשפוט אותן כשיש trace מול העיניים.
הלולאה למטה שולחת את השיחה למודל; אם התשובה מכילה tool call היא מבצעת את הכלי, מצרפת את התוצאה ושולחת את הכול שוב. היא רצה מול Qwen2.5-0.5B-Instruct מקומי מאחורי endpoint בצורת OpenAI על המכונה הזו — התפר מפרק 14, כך שללולאה לא אכפת ואינה יודעת מה נמצא מאחורי הפורט.
const BASE = process.env.LLM_BASE_URL ?? "http://127.0.0.1:8799/v1";
async function loop(question: string, maxTurns = 6) {
const messages: Msg[] = [
{ role: "system", content: SYSTEM },
{ role: "user", content: question },
];
for (let turn = 1; turn <= maxTurns; turn++) {
const reply = await call(messages, TOOLS);
const calls = reply.choices[0].message.tool_calls ?? [];
messages.push(reply.choices[0].message);
if (!calls.length) return messages;
for (const c of calls) {
const out = runTool(c.function.name, JSON.parse(c.function.arguments));
messages.push({ role: "tool", name: c.function.name, content: out });
}
}
throw new Error("turn cap reached");
}שתי שורות נושאות את כל הרעיון, ושתיהן מסומנות; כל היתר הוא הנהלת חשבונות. כל שלוש ההתנהגויות נראות בהרצה אחת. כששואלים אותו משהו שהוא יכול לעשות בעצמו, המודל עונה. כששואלים אותו משהו שאינו יכול, הוא קורא:
=== a question the model cannot answer, one tool available
turn 1 prompt= 187 out= 21 finish=tool_calls CALL get_temperature({"city": "Oslo"})
tool get_temperature -> {"city":"Oslo","celsius":4}
turn 2 prompt= 238 out= 12 finish=stop TEXT "The current temperature in Oslo is 4
degrees Celsius."
=> model calls=2 prompt tokens=425 output=33 wall=6,257 ms
=> stopped by: the model produced text instead of a callוהוא עוצר — ההתנהגות השלישית, והקלה ביותר לפספס, כי היא נראית כמו כלום. הלולאה מסתיימת כי תור 2 חזר בלי tool call. אף אחד לא החליט את זה; המודל החליט, באמצעות פליטת פרוזה. תנאי הסיום של התוכנית הזו הוא סימן של היעדר.
עוד שתי הרצות שוות את המקום. כשמבקשים ממנו להשוות שתי ערים, המודל מוציא שתי tool calls באותו תור, מקבל את שתי הקריאות בחזרה, וטועה בהשוואה:
turn 1 prompt= 188 out= 43 finish=tool_calls CALL get_temperature({"city": "Oslo"}),
get_temperature({"city": "Lisbon"})
tool get_temperature -> {"city":"Oslo","celsius":4}
tool get_temperature -> {"city":"Lisbon","celsius":19}
turn 2 prompt= 284 out= 13 finish=stop TEXT "Oslo is currently warmer than Lisbon
at 4°C."הכלים עבדו. הקריאה המקבילית עבדה. הלולאה עבדה. התשובה שקרית, כששני המספרים הנכונים יושבים בתמליל. לעטוף מודל בלולאה לא גורם לו לחשוב; זה נותן למודל שטועה את היכולת לפעול על סמך הטעות שלו — שזה פרק 30 מראש, וחצי מפרק 29.
עכשיו מחקו את ה-return המסומן ותנו ללולאה לרוץ עד המכסה שלה במקום. אותה שאלה, אותו מודל:
turn 1 prompt= 187 out= 21 CALL get_temperature({"city": "Oslo"})
turn 2 prompt= 238 out= 12 TEXT "The current temperature in Oslo is 4 degrees Celsius."
turn 3 prompt= 261 out= 30 TEXT "Could you please specify the exact location you're..."
turn 4 prompt= 302 out= 14 TEXT "Sure! Could you tell me which city you're interested in?"
turn 5 prompt= 327 out= 35 TEXT "I'm sorry, but I need more details to provide an..."
turn 6 prompt= 373 out= 12 TEXT "Which city would you like to know the temperature for?"
=> model calls=6 prompt tokens=1,688 output=124 wall=25,261 ms stopped by: turn capפי ארבעה input tokens, פי ארבעה זמן שעון, וסיום שבו ה-agent שכח מה שאלו אותו והוא חוקר את המשתמש על שאלה שכבר ענה עליה בתור הראשון. התשובה הנכונה הייתה על המסך בתור 2, וכל תור אחריו החמיר את התמליל.
לכן agent אינו לולאה. הוא לולאה בתוספת כלל ליציאה ממנה, ולזה יש בדיוק כלל אחד כזה. פרק 23 מוצא חמישה, ומראה מה נשבר כשכל אחד חסר.
שתי ההגדרות, זו לצד זו
קישור למקטע: שתי ההגדרות, זו לצד זושתיהן מצוטטות ולא מנוסחות מחדש, כי הניסוחים מחדש הם המקום שבו הבלבול מיוצר.
הגדרה אחת שמה את הגבול בשאלה מי שולט בזרימה. Building effective agents של Anthropic נותן שם לעמימות ופוסק לגביה:
"ב-Anthropic, אנחנו מסווגים את כל הווריאציות האלה כ-agentic systems, אבל מותחים הבחנה ארכיטקטונית חשובה בין workflows לבין agents: Workflows הן מערכות שבהן LLMs וכלים מתוזמרים דרך נתיבי קוד מוגדרים מראש. Agents, לעומת זאת, הן מערכות שבהן LLMs מכוונים באופן דינמי את התהליכים ואת השימוש בכלים של עצמם, ושומרים על שליטה באופן שבו הם מבצעים משימות."4
המבחן הוא שאלה על קוד המקור שלכם: מי בחר את הצעד הבא? switch בתוכנית שלכם: workflow. המודל: agent. אותו מסמך אומר ש-agents "הם בדרך כלל פשוט LLMs שמשתמשים בכלים על בסיס משוב סביבתי בלולאה" — וזה בדיוק הקוד שלמעלה.
הגדרה שתיים שמה את הגבול בעצמאות מהמשתמש. A practical guide to building agents של OpenAI פותח את עמוד ההגדרה שלו כך:
"בעוד שתוכנה קונבנציונלית מאפשרת למשתמשים לייעל ולאוטומט workflows, agents מסוגלים לבצע את אותם workflows בשם המשתמשים בדרגת עצמאות גבוהה. Agents הם מערכות שמבצעות משימות באופן עצמאי בשמכם."5
שני משפטים אחר כך, באותו עמוד, הוא מחריג:
"אפליקציות שמשלבות LLMs אבל לא משתמשות בהם כדי לשלוט בביצוע workflow — חשבו על chatbots פשוטים, LLMs של תור יחיד, או מסווגי סנטימנט — אינן agents."5
קראו את הציטוטים האלה לפי הסדר. משפטי הפתיחה מותחים את הקו ב-עצמאות: האם הדבר הזה יוצא ומסיים את העבודה בלי שאני שם? הרביעי מותח אותו ב-שליטה בביצוע, שזה בדיוק הקו של Anthropic. מבחנים שונים, אותו עמוד, ויש מערכות אמיתיות שעליהן הם לא מסכימים.
מתחת לזה יש התנגשות אוצר מילים, והיא גורמת לוויכוחים בישיבות אמיתיות. במסמך הראשון workflow הוא ארכיטקטורה, והוא הדבר שאינו agent. בשני workflow הוא "רצף של צעדים שיש לבצע כדי להשיג את מטרת המשתמש" — העבודה עצמה, שלכל agent יש אחת כזו. "החלפנו את ה-workflow ב-agent" הוא משפט קוהרנטי לפי ההגדרה הראשונה וכמעט חסר משמעות לפי השנייה.
שלוש מערכות, מסווגות פעמיים
קישור למקטע: שלוש מערכות, מסווגות פעמייםשלוש מערכות שקיימות ב-2026, תחת שתי ההגדרות.
coding agent בטרמינל
קישור למקטע: coding agent בטרמינלאתם מתארים משימה; הוא קורא קבצים, מריץ את חבילת הבדיקות, עורך, מריץ אותן שוב, ועוצר כשהן עוברות או כשהוא מוותר. שום דבר בקוד שלכם לא מחליט שהצעד הבא הוא "להריץ את הבדיקות" — המודל עושה זאת, לפי מה שהכלי האחרון החזיר.
הגדרה אחת: agent, כי המודל מכוון את התהליך של עצמו. הגדרה שתיים: agent, כי הוא מבצע את המשימה באופן עצמאי, מזהה השלמה ומחזיר שליטה. שני המסמכים מציינים את הצורה הזו כדוגמה המרכזית שלהם.
pipeline לילי למיון כרטיסים
קישור למקטע: pipeline לילי למיון כרטיסיםעבור כל כרטיס תמיכה חדש, שלוש קריאות מודל בסדר קבוע — לסווג, לחלץ את השדות, לנסח את התשובה — ואז הוא שולח. אף מודל לא בוחר מה קורה אחר כך; לולאת for עושה זאת. הוא רץ ב-03:00 ואף אחד לא צופה בו.
הגדרה אחת: לא agent. זה prompt chaining, שמופיע בשם כ-workflow. הגדרה שתיים: שתי התשובות. לפי משפטי הפתיחה הוא מבצע משימות באופן עצמאי בשמכם; לפי המשפט הרביעי הוא לא משתמש במודל כדי לשלוט בביצוע workflow, ולכן מוחרג. המערכת הזו היא הסיבה שקוראים את כל העמוד ולא את הציטוט שנשלף ממנו.
עוזר צ'אט עם כלי חיפוש
קישור למקטע: עוזר צ'אט עם כלי חיפושתור משתמש אחד. המודל מחליט בעצמו אם לחפש לפני שהוא עונה, ואז עונה וממתין לכם.
הגדרה אחת: agent, כי המודל מכוון באופן דינמי את שימוש הכלים שלו לפי תוצאות מהסביבה, שזה המבחן המוצהר. הגדרה שתיים: לא agent, כי אין עצמאות — תור אחד, ואז הוא מחזיר — ו-"chatbots פשוטים" נמצאים ברשימת ההחרגות בשם.
שניים מתוך השלושה מחליפים צד. זה לא כישלון של אף אחד מהמסמכים. זו אזהרה מפני סוג ישיבה שבו שני אנשים שמסכימים לגמרי על מה מערכת עושה מבלים שעה בוויכוח איך לקרוא לה.
הדרך החוצה היא שני צירים, לא אחד
קישור למקטע: הדרך החוצה היא שני צירים, לא אחדההגדרות מתנגשות כי כל אחת דוחסת שתי שאלות בלתי תלויות למילה אחת. הפרידו ביניהן והמחלוקת הופכת לטבלה, שהיא שימושית יותר מפסק דין.
| הקוד שלכם בוחר את הצעד הבא | המודל בוחר את הצעד הבא | |
|---|---|---|
| אדם צופה בכל תור | טופס עם מודל בתוכו: מסווגים, חילוץ, השלמה בתור יחיד | צ'אט עם כלים — הגדרה אחת אומרת agent, הגדרה שתיים אומרת לא |
| אף אחד לא צופה עד שזה נגמר | pipeline — הפתיחה של הגדרה שתיים אומרת agent, המשפט הרביעי שלה אומר לא | כולם מסכימים: agent |
כל הגדרה חולקת על תא אחר, ושני האחרים אינם במחלוקת כלל. לכן כשהתווית חשובה — בחוזה, בסקירת סיכונים, בפוסטמורטם — שני המשפטים שכדאי לכתוב אינם "האם זה agent" אלא מי בחר את הצעד הבא ו-מי צפה. על שניהם אפשר לענות מקריאת קוד, אף אחד מהם לא צריך את ההגדרה של מישהו, וביחד הם נושאים כל השלכה שהתווית אמורה הייתה לייצג.
שום דבר מזה אינו חדש. Wooldridge ו-Jennings סקרו את המשמעויות המתחרות של "agent" ב-1995;6 Franklin ו-Graesser שאלו את שאלת הפרק הזה ב-1996, אספו את ההגדרות שהסתובבו אז וגילו שהן לא מסכימות.7 סקר מ-2023 עדיין מגדיר agents מעקרונות ראשונים — "ישויות מלאכותיות שחשות את סביבתן, מקבלות החלטות ופועלות"8 — כי לא הייתה הסכמה מודרנית שאפשר לצטט, ו-CoALA מתאר חלקים במקום למתוח גבול בכלל.9 שלושים שנה של הימנעות מהסכמה אומרות שהמילה עושה יותר מעבודה אחת.
agent הוא N קריאות, לא אחת
קישור למקטע: agent הוא N קריאות, לא אחתעכשיו ההשלכה שמגיעה לפני הפילוסופיה, שהיא החשבון.
כל מדידה כאן היא באותה צורה. הקריאה היחידה עלתה 39 input tokens; אותה שאלה עם כלי אחד עלתה 420 על פני שתי קריאות; הלולאה שתנאי העצירה שלה הוסר עלתה 1,688 על פני שש. הגידול גרוע מלינארי, כי תור n נושא איתו כל תור קודם: עמודת ה-prompt של הרצת ששת התורים היא 187, 238, 261, 302, 327, 373. פרק 16 גזר שהסך הוא והתאים את העקומה לשיחה אמיתית. agent הופך כל משימה לשיחה הזו, בין שאדם רואה אותה ובין שלא.
אם ספירות ה-token המדודות האלה היו הולכות ל-endpoint מסחרי בתעריפים שפרק 16 קרא ב-6 בספטמבר 2026 — $2.00 למיליון input tokens ו-$12.00 למיליון output — ארבע ההרצות היו מתומחרות כך:
| הרצה | קריאות מודל | input tokens | output tokens | עלות |
|---|---|---|---|---|
| השאלה, בלי כלים | 1 | 39 | 8 | $0.000174 |
| אותה שאלה, כלי אחד בקטלוג | 2 | 420 | 38 | $0.001296 |
| שאלה שצריכה את הכלי | 2 | 425 | 33 | $0.001246 |
| אותו דבר, עם כלל העצירה שהוסר | 6 | 1,688 | 124 | $0.004864 |
שורה שתיים מול שורה אחת היא המספר שכדאי לזכור. פי שבעה וחצי מהעלות, עבור תשובה גרועה יותר לשאלה שהמודל כבר ידע. שום דבר לא הוגדר לא נכון: כלי היה קיים, אז המודל השתמש בו — והממצא של פרק 18, שהמחיר של קטלוג ולא הדיוק שלו הוא מה שכואב, מקבל כאן את ההדגמה הזולה ביותר שלו עם קטלוג של אחד.
וזו הסיבה שהחצי המועיל בשני המסמכים הוא החצי על לא לבנות את זה. Anthropic ישירה: מצאו את הפתרון הפשוט ביותר האפשרי והוסיפו מורכבות רק כשצריך, מה ש"עשוי לומר לא לבנות agentic systems בכלל", משום ש-agentic systems "מחליפות שיהוי ועלות בביצועי משימה טובים יותר" ו"עבור יישומים רבים, אופטימיזציה של קריאות LLM יחידות עם retrieval ודוגמאות in-context בדרך כלל מספיקה".4 המקרה שלה בעד agent צר: בעיות פתוחות שבהן אי אפשר לחזות את מספר הצעדים ואי אפשר לקודד מסלול hardcoded, בסביבה שאתם סומכים עליה, תוך קבלה של "עלויות גבוהות יותר, והפוטנציאל לשגיאות מצטברות".4 המסך של OpenAI הוא תמונת ראי — שיפוט מורכב, מערכי כללים שאי אפשר לתחזק, נתונים לא מובנים — ומסתיים באותו אופן: "אחרת, פתרון דטרמיניסטי עשוי להספיק".5
לכן, בטקסונומיה של הפרק הזה: מספר קבוע של צעדים בסדר קבוע הוא pipeline, ולקרוא לו agent לא יהפוך אותו למהיר יותר. אם מספר הצעדים תלוי במה שמוצאים בדרך, אתם רוצים לולאה — ואת הגמישות הזו קונים ב-N קריאות, תמליל ריבועי, ומערכת שיכולה לטעות N פעמים במקום פעם אחת.
לאן ממשיכים מכאן
קישור למקטע: לאן ממשיכים מכאןעכשיו יש לכם את הטקסונומיה, שתי ההגדרות המודרניות, שני הצירים שמיישבים ביניהן, ולולאה קצרה שעונה, קוראת ועוצרת.
ללולאה הזו יש דרך אחת להסתיים: המודל מפסיק לבקש כלים. פרק 23 שובר אותה בכוונה, שבע פעמים, וכל שבירה מוסיפה חלק. משימה בלתי אפשרית, והיא לעולם לא נגמרת — מכסת תורים. לילה של ריצה, והחשבון מגיע — תקציב בדולרים. כלי שנכשל — שגיאה שהמודל יכול לפעול לפיה. אותה קריאה פעמיים — מפתח idempotency. קובץ שלא היה אמור לגעת בו — אישור אנושי. הפעלה מחדש באמצע — התמדה של session. כלי שלוקח שלוש דקות בשקט — התקדמות וביטול. מה שיוצא הוא harness, הקובץ שעליו רץ שאר הקורס.
מה שמשאיר את השאלה שעליה האלכסון השנוי במחלוקת של הפרק הזה באמת דיבר. לולאה שמחליטה את הצעד הבא של עצמה צריכה להחליט מתי לעצור, ורק עכשיו ראינו מה קורה כשהיא לא יכולה: שישה תורים, פי ארבעה מהחשבון, ו-agent שחוקר את המשתמש על שאלה שכבר ענה עליה. עצירה אינה תנאי אחד. כמה יש, ואיזה מהם מופעל ראשון?
מקורות ושיטה
קישור למקטע: מקורות ושיטהLLM Powered Autonomous Agents של Lilian Weng (2023) הוא הפירוק המוכר ביותר של language agent לתכנון, זיכרון ושימוש בכלים, והוא הקריאה הבאה הנכונה לצד שני מסמכי הספקים; שלושת הרכיבים שלו הם פרקים 23, 24 ו-18 של הקורס הזה, בסדר הזה.
כל מספר בפרק הזה הופק על המכונה הזו ושום דבר לא הוערך. המסדרון, תוכנית הרצפה, ארבעת ה-agents שהולכים בה ושלוש מדיניות הסיור הם ה-TypeScript שלמעלה, רץ על Node 22; נתוני ה-agent האקראי הם ממוצעים על פני 2,000 הרצות seeded כל אחד, ונתוני הסיור הם הרצות seeded יחידות של 4,000 ticks. עקבות המודל מגיעים מ-Qwen2.5-0.5B-Instruct ב-float32 על CPU עם greedy decoding, שהוגש מעל loopback על ידי endpoint מקומי קטן ב-Python שטוען את המשקלים ומדבר בצורת OpenAI chat-completions — שוב התפר, עם הטנזורים בצד ה-Python והלולאה בצד ה-TypeScript — כך שספירות ה-token הן של ה-tokenizer של אותו מודל וה-latencies הן של אותה מכונה. הנתונים היחידים שנלקחו ממקום אחר הם שני המחירים בטבלת העלות, שהם התעריפים שפרק 16 קרא מדף התמחור של OpenAI ב-6 בספטמבר 2026, ומוחלים כאן על ספירות token שנמדדו מקומית כהמחשה ולא כחשבונית שנצפתה.
הפניות
קישור למקטע: הפניות-
Russell, S. ו-Norvig, P. Artificial Intelligence: A Modern Approach, מהדורה 4, פרק 2, Intelligent Agents. מקור עולם השואב, מפרט PEAS, הגדרת הרציונליות ביחס למדד ביצוע, שבע התכונות של סביבות משימה, חמשת סוגי ה-agent שבהם משתמשים כאן, וההבחנה שלפיה לולאות אינסופיות הן לעיתים קרובות בלתי נמנעות עבור simple reflex agents בסביבות נצפות חלקית. קוד המלווה של הספר הוא
aimacode/aima-pythonב-GitHub (8,806 כוכבים, דחיפה אחרונה ב-30 ביוני 2026, נקרא ב-7 בספטמבר 2026) — שווה לנקוב בשמו במדויק לפי מה שהוא. זה repository מלווה לספר, לא reference implementation שפרויקטים אחרים בונים עליו כפי ש-karpathy/micrograd(17,412) ו-karpathy/nanoGPT(62,852) הם. לכן הפרק הזה מצטט ומקשר אליו במקום לתרגם אותו, ולכן טיעון האקוסיסטם שהשאיר את פרק 5 ב-Python לא חל כאן: שום דבר בפרק הזה לא נוגע בטנזור, והלולאה שנכתבה למעלה היא האב הקדמון הישיר של זו שבפרק 23. ↩ ↩2 ↩3 ↩4 ↩5 -
Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. ו-Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022). השילוב לסירוגין של עקבות חשיבה ופעולות שאליו מתייחסת שורת ה-goal-based בטבלת המיפוי. ↩
-
Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. ו-Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). הסיכום של המאמר עצמו למנגנון הוא הסיבה שהוא ממופה ל-learning agent: הוא מחזק agents "לא באמצעות עדכון משקלים, אלא באמצעות משוב לשוני", עם agents ש"משקפים מילולית על אותות משוב מהמשימה, ואז שומרים את הטקסט הרפלקטיבי שלהם ב-episodic memory buffer כדי לעודד קבלת החלטות טובה יותר בניסויים הבאים". ↩ ↩2
-
Anthropic, Building effective agents, 19 בדצמבר 2024,
anthropic.com/engineering/building-effective-agents, נקרא ב-7 בספטמבר 2026. מקור ההבחנה workflow/agent שצוטטה לעיל, מונח המטרייה "agentic systems", תיאור agents כ"בדרך כלל פשוט LLMs שמשתמשים בכלים על בסיס משוב סביבתי בלולאה", ההנחיה למצוא את הפתרון הפשוט ביותר האפשרי ושזה "עשוי לומר לא לבנות agentic systems בכלל", והמקרה בעד ונגד agents, כולל "עלויות גבוהות יותר, והפוטנציאל לשגיאות מצטברות" וההמלצה על תנאי עצירה "כגון מספר איטרציות מרבי" כדי לשמור על שליטה. ↩ ↩2 ↩3 -
OpenAI, A practical guide to building agents, עמודים 4 עד 7, נקרא ב-7 בספטמבר 2026. מקור "Agents are systems that independently accomplish tasks on your behalf", החרגת "simple chatbots, single-turn LLMs, or sentiment classifiers", הגדרת workflow כ"רצף של צעדים שיש לבצע כדי להשיג את מטרת המשתמש", שני המאפיינים המרכזיים של agent, שלושת הרכיבים — מודל, כלים, הוראות — וקריטריוני הסינון למתי לבנות אחד, המסתיימים ב-"otherwise, a deterministic solution may suffice". ↩ ↩2 ↩3
-
Wooldridge, M. ו-Jennings, N. R. Intelligent Agents: Theory and Practice. The Knowledge Engineering Review, כרך 10, גיליון 2 (1995). הסקר שפיצל את שימושי התחום למובן חלש של agency — אוטונומיה, יכולת חברתית, תגובתיות, פרואקטיביות — ולמובנים חזקים יותר ששואלים אוצר מילים מנטלי. בקריאה כיום, זה תיעוד של אותו ויכוח ששני המסמכים של הפרק הזה עדיין מנהלים. ↩
-
Franklin, S. ו-Graesser, A. Is It an Agent, or Just a Program? A Taxonomy for Autonomous Agents. Proceedings of the Third International Workshop on Agent Theories, Architectures, and Languages, Springer (1996). מצוטט כאן לפי מה שהוא ולא עבור ציטוט: סקר שאסף את ההגדרות של "agent" שהיו אז בשימוש, גילה שהן אינן מסכימות, והציע טקסונומיה כדי להחליף את הוויכוח. שלושים שנה אחר כך הוויכוח נמצא בתיעוד מעוצב טוב יותר, וחוץ מזה לא השתנה. ↩
-
Xi, Z. et al. The Rise and Potential of Large Language Model Based Agents: A Survey. arXiv:2309.07864 (2023). צוטט לעיל עבור הגדרת הפתיחה שלו, "AI agents are artificial entities that sense their environment, make decisions, and take actions", שהיא הגדרת ספר הלימוד שנוסחה מחדש ב-2023 כי לא הייתה הגדרה מודרנית מוסכמת שאפשר לצטט. ↩
-
Sumers, T. R., Yao, S., Narasimhan, K. ו-Griffiths, T. L. Cognitive Architectures for Language Agents. arXiv:2309.02427 (2023). מארגן language agents כ"רכיבי זיכרון מודולריים, מרחב פעולה מובנה לאינטראקציה עם זיכרון פנימי וסביבות חיצוניות, ותהליך קבלת החלטות מוכלל לבחירת פעולות", וממקם אותם במפורש בהיסטוריה של AI סימבולי ומדע קוגניטיבי. טקסונומיית הזיכרון חוזרת בפרק 24, שבו טבלת שלושת המאגרים היא הצל המעשי שלה. ↩