דלג לתוכן
25/30פרק 25 מתוך 30

תזמור Multi-Agent: חמישה דפוסים, ומתי אחד מנצח

אותה חשבונית נפתרה בארבע דרכים ותומחרה בטבלה אחת: ה-orchestrator עלה פי 1.66 מ-agent יחיד והגיע לאותה הכרעה.

בעמוד הזה

פרק 24 הסתיים בשאלה שהוא הרוויח ביושר: כש-sub-agent טועה, על מה בדיוק ההורה יכול להסתכל?

הפרק הזה עונה עליה עם חשבון. משימה אחת — לקוח מערער על חשבונית ורוצה תשובה — נפתרה בארבע דרכים, כולן מריצות את ה-harness של פרק 23 מול אותו ספק מתוסרט, כולן סופרות את אותם tokens עם אותו encoder, כולן מתומחרות לפי התעריפים שפרק 16 קרא ב-6 בספטמבר 2026.

סידורקריאות modelinput tokensoutputעלותזמן שעוןהכרעה
prompt chaining4900165$0.0037801,648 msשגויה
agent אחד, ארבעה כלים52,697179$0.0075422,224 msנכונה
מקטעים מקבילים92,910324$0.0097082,165 msנכונה
orchestrator-workers123,628438$0.0125125,090 msנכונה, והוא לא יכול להוכיח זאת

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

השורה שאיש אינו מכניס לטבלאות האלה היא השנייה: agent אחד עם ארבעת הכלים הגיע לאותה הכרעה כמו ה-orchestrator תמורת 60 % מהכסף ו-44 % מזמן השעון. זו אינה העדפה לפשטות. זו מדידה, ושאר הפרק עוסק בשאלה מתי היא מפסיקה להיות נכונה.

הצגת פרטים

מה הפרק הזה צריך מהקודמים.

  • פרק 18 עבור חוזה הכלי: schema שה-model רואה, endpoint שהוא לעולם לא רואה. agent שלם נכנס מאחורי הממשק הזה, וזה כל עניין ה-multi-agent.
  • פרק 22 עבור שתי ההגדרות שפורסמו ל-agent ואינן מסכימות זו עם זו, ועבור האריתמטיקה שלפיה שרשרת prompts היא N קריאות.
  • פרק 23 עבור הלולאה, חמש הדרכים לצאת, מצב הריצה וה-trace. כל סידור למטה הוא הקובץ ההוא, שנקרא אחרת.
  • פרק 24 עבור מה שחלון עולה ומה נופל ממנו. sub-agent הוא הרביעי מבין ארבע האסטרטגיות שלו, והיחיד שהוא agent שני ולא מדיניות.

בלי tensors. הכול כאן TypeScript, חוץ משתי מדידות שנלקחו מול model מקומי אמיתי.

חברה פורטוגלית כותבת לגבי חשבונית FT-2026-0918. האימייל אומר שהמע״מ נראה שגוי, ומצרף את החשבונית: נטו EUR 248.00, מע״מ שנגבה בשיעור 21 %, EUR 52.08, סך הכול EUR 300.08.

העובדות הדרושות לתשובה נמצאות בשלושה מקומות, ורק אחד מהם נמצא באימייל:

איפהמה כתוב שם
החשבונית המצורפתהמוכר בספרד, מע״מ הוחל ב-21 %, EUR 52.08
רשומת ההזמנההקונה רשום בפורטוגל, עם מזהה מע״מ תקף, עסק לעסק
טבלת המסשיעור מקומי בספרד 21 %; עסקה תוך-אירופית עסק לעסק עם מזהה תקף, reverse charge, 0 %

מחברים את השלושה והחשבונית שגויה: חל reverse charge, המע״מ היה צריך להיות אפס, ויש להוציא זיכוי על EUR 52.08. מסתכלים רק על החשבונית והיא מושלמת אריתמטית — 248.00 ועוד 52.08 הם 300.08 — וכך גם תגידו.

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

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

תשובה רשאית להשתמש רק בעובדה שנמצאת ב-prompt שלה.

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

חמשת הדפוסים, בכארבעים שורות

קישור למקטע: חמשת הדפוסים, בכארבעים שורות

חמשת השמות שלמטה הם של Anthropic, מתוך Building effective agents, ושם אוצר המילים הזה התייצב.1 אף אחד מחמשת הרעיונות אינו חדש, ולהגיד מי נתן איזה שם — ואיזה רעיון ותיק יותר — הוא חצי מהערך שבידיעתם.

patterns.tsTS
/* 1. Prompt chaining: a fixed pipeline. The control flow is yours. */
export async function chain(steps: Step[], first: string) {
  let carry = first, all = first;
  for (const s of steps) {
    const r = await step(s.role, s.system, s.accumulate ? all : carry);   
    carry = r.text;
    all = `${all}\n${r.text}`;
  }
  return carry;
}

/* 2. Routing: one cheap call picks the branch. The fallback is not a model. */
export async function route<T>(input: string, classify: Classifier,
                               routes: Record<string, Branch<T>>, fallback: Branch<T>) {
  let label: string | undefined;
  try { label = await classify(input); } catch { label = undefined; }
  return ((label && routes[label]) || fallback)(input);                    
}

/* 3. Parallelisation. The pattern IS this line. */
export const parallel = <T>(workers: Branch<T>[], input: string) =>
  Promise.all(workers.map((w) => w(input)));                              

/* 4. Orchestrator-workers: an agent behind a tool. Chapter 18's interface, unchanged. */
export function agentTool(o: WorkerSpec): Tool {
  return {
    name: o.name, description: o.description, readOnly: true,
    parameters: { type: "object", properties: { question: { type: "string" } } },
    async run(args: { question: string }) {
      const child = newRun(o.system, args.question);          // its own window
      await runTracked(child, o.tools, o.usage);              // its own limits
      const conclusion = child.output ?? "no result";
      if (!o.carryFindings) return conclusion;                             
      return `${conclusion}\nFINDINGS ${evidence(child)}`;                 
    },
  };
}

/* 5. Evaluator-optimiser: make, judge, remake. Rounds are calls. */
export async function refine(make: Make, judge: Judge, maxRounds: number) {
  let draft = "", feedback: string | undefined;
  for (let r = 1; r <= maxRounds; r++) {
    draft = (await make(feedback)).text;
    const j = await judge(draft);
    if (j.ok) return { draft, rounds: r };
    feedback = j.note;
  }
  return { draft, rounds: maxRounds };
}

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

Chaining, וההחלטה שהוא מקבל בשבילכם

קישור למקטע: Chaining, וההחלטה שהוא מקבל בשבילכם

Prompt chaining ״מפרק משימה לרצף של צעדים, שבו כל קריאת LLM מעבדת את הפלט של הקודמת״.1 הרעיון קודם למודלי שפה: זו pipeline, עם עסקת החליפין של pipeline — בהירות תמורת control flow שנקבע לפני שהנתונים מגיעים.

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

TEXT
--- relay: each step sees only the previous step's output
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 vat_amount=52.08 ...
check:   ARITHMETIC ok 248.00+52.08=300.08
decide:  VERDICT=unknown reason=no_invoice_in_context
draft:   "we are looking into invoice FT-2026-0918 and will come back to you."

--- accumulating: each step sees the email and everything produced so far
extract: FIELDS invoice_id=FT-2026-0918 net=248.00 vat_rate_applied=21 ...
check:   ARITHMETIC ok 248.00+52.08=300.08
decide:  VERDICT=invoice_correct reason=net_248.00_plus_21pct_vat_52.08_equals_300.08
draft:   "we have checked FT-2026-0918 and it is correct... Nothing is owed back."

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

השרשרת המצטברת — השורה בטבלת הפתיחה — עלתה $0.003780, כלומר 95 % יותר עבור ארבע קריאות זהות, כי עכשיו כל צעד נושא את כל מה שהיה לפניו. היא הפיקה את הפלט המסוכן. שוטף, מצטט את האריתמטיקה שלו, נכון בכל מספר שהוא מזכיר, ואומר ללקוח שלא מגיע דבר כאשר מגיעים EUR 52.08.

ההבדל בין השתיים הוא ternary אחד. שרשרת שנושאת פחות מפיקה תשובות שחסרות באופן ברור; שרשרת שנושאת הכול מפיקה תשובות שגויות בביטחון — ורק הסוג השני נשלח.

אף אחד מהם אינו הכשל האמיתי. הכשל האמיתי הוא שה-pipeline החליט, לפני שקרא משהו, שהמשימה הזו היא ארבעה צעדים על תוכן של אימייל. בשום מקום במבנה הזה אין מקום לומר ״מדינת הרישום אינה באימייל הזה; לכו הביאו אותה״. Chaining נכון כשהפירוק ידוע מראש ויציב. כאן זו הייתה השערה, וההשערה נשלחה.

Routing, הוותיק ביותר, ותוכנית ב׳ שאיש לא כותב

קישור למקטע: Routing, הוותיק ביותר, ותוכנית ב׳ שאיש לא כותב

Routing ״מסווג קלט ומפנה אותו למשימת המשך מתמחה״.1 השם חדש; המנגנון הוא dispatcher, ותיק יותר כמעט מכל דבר אחר בספר הזה. מה שחדש הוא שהמסווג יכול להיות model — וזה מה שגורם לו להיכשל בדרכים ש-switch מעולם לא הכיר.

route.tsTS
const answer = await route(email,
  (q) => classifyWithSmallModel(q),          // cheap model, one call
  { billing: billingAgent, tax: taxAgent, dunning: dunningAgent },
  taxAgent,                                  // deterministic, chosen in advance
);

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

הדבר השני הוא שגם ה-prompt של ה-router אינו בחינם. כדי לבחור model, router צריך קטלוג של models לבחור מתוכו, וכל רשומה בו היא input שה-router משלם עליו לפני שהוא קרא את השאלה של המשתמש. בקצב ה-input שהקורס הזה מתמחר לפיו, קטלוג של כ-3,800 tokens כבר עולה כמו כל ריצת ה-agent בת חמש הקריאות בטבלת הפתיחה. בפועל קריאת ה-routing רצה על model זול, וזו כל הסיבה ש-routing מחזיר את ההשקעה; אבל כדאי לעשות את האריתמטיקה בכיוון הזה במקום להניח. Routing שגוי בדיוק כשהמשימה המנותבת זולה יותר מהחלטת הניתוב.

Parallelisation: מקטעים, והצבעה, שהיא self-consistency

קישור למקטע: Parallelisation: מקטעים, והצבעה, שהיא self-consistency

Anthropic מחלקת את זה לשניים: sectioning — ״פירוק משימה לתת-משימות עצמאיות שרצות במקביל״ — ו-voting — ״הרצת אותה משימה כמה פעמים כדי לקבל outputs מגוונים״.1 הם חולקים תרשים וכמעט שום דבר אחר.

Sectioning הוא הרווח הזול, והוא השורה מ-patterns.ts: שלושה מומחים — חיוב, מס, מדיניות — כל אחד עם חלון וכלים משלו, על אותו אימייל, וקריאת סינתזה אחת בסוף. אותה עבודה, מסודרת בשתי דרכים:

קריאות modelinputoutputעלותזמן שעון
שלושת העובדים, אחד אחרי השני92,910324$0.0097083,894 ms
אותם שלושה, Promise.all92,910324$0.0097082,165 ms

אותו token אחר token, מהיר פי 1.8. לכן הדפוס זוכה לשם משלו: הוא היחיד מבין החמישה שמשפר משהו בלי לעלות שום דבר. המלכוד הוא שהמקטעים חייבים להיות עצמאיים באמת — תנו למקטע B עובדה שמקטע A מפיק ו-Promise.all מריץ את שניהם מול מצב שעדיין אינו קיים. לולאת for הסתירה את הבאג; השורה האחת חושפת אותו.

Voting הוא חיה אחרת שלובשת את אותה תמונה. להריץ את אותה שאלה k פעמים ולקחת את הרוב הוא self-consistency, שפורסם בידי Wang ואחרים במרץ 2022 כאסטרטגיית decoding, כמעט שלוש שנים לפני שמישהו קרא לו דפוס orchestration. התקציר שלו מדויק לגבי המנגנון — ״קודם דוגם קבוצה מגוונת של נתיבי הסקה במקום לקחת רק את הנתיב החמדני, ואז בוחר את התשובה העקבית ביותר באמצעות marginalizing out של נתיבי ההסקה שנדגמו״ — ולגבי הרווח: +17.9 נקודות ב-GSM8K.2

מכאן נובעים שני דברים שהתמונה מסתירה. ראשית, voting דורש את הדגימה של פרק 17: בטמפרטורה אפס כל k הדגימות הן אותה דגימה, והרוב הוא תשובה אחת ששולמה k פעמים. שנית, זה עובד רק במקום שבו לרוב יש משמעות — בתשובת החשבונית למעלה אין מה לספור, כי חמש טיוטות הן חמישה משפטים שונים. Voting מיועד למשימות עם תשובה קצרה וניתנת להשוואה, שזה בדיוק ה-benchmarks של Wang וכמעט שום דבר ש-agent מול לקוחות עושה.

נמדד כאן על 20 בעיות מילוליות בשלושה צעדים שתשובותיהן מחושבות ולא נשפטות, עם ה-model המקומי של פרק 23 חושב צעד אחר צעד:

קריאות modelinputoutputעלות עבור ה-20נכוןרווח בר-סמך 95 %
שרשרת greedy אחת201,3302,649$0.0344489/2026–66 %
רוב של 5, טמפרטורה 0.81006,65013,245$0.1722409/2026–66 %

פי חמישה קריאות, פי חמישה tokens, בדיוק פי חמישה חשבון, ולא תשובה נכונה נוספת אחת. Voting הוא הימור, לא שיפור, ובריצה הזו הוא הפסיד.

שתי הסתייגויות, לפני שמישהו מצטט זאת כהפרכה של Wang. עשרים ניסויים אינם יכולים להבחין בין 45 % ל-60 % — הרווח הוא ברוחב הטענה, וזו המשמעת של פרק 4 מופנית אל התוצאה שלי. והרווחים שפורסמו מגיעים מ-models גדולים בסדרי גודל, שבהם נתיבי ההסקה המגוונים שעליהם voting עושה marginalize באמת מגוונים. מה שעובר אינו המספר: אלא שהמכפיל מדויק וידוע מראש, בעוד שהרווח לא.

Orchestrator-workers, ומה סיכום איננו

קישור למקטע: Orchestrator-workers, ומה סיכום איננו

בזרימת העבודה orchestrator-workers ״LLM מרכזי מפרק משימות באופן דינמי, מאציל אותן ל-worker LLMs, ומסנתז את התוצאות שלהם״, וההבדל מ-sectioning הוא ש״תת-המשימות אינן מוגדרות מראש, אלא נקבעות בידי ה-orchestrator״.1 המקור כאן אינו מודלי שפה כלל: זה master-worker, והגרסה שבה עובדים כותבים ממצאים למרחב משותף שבקר קורא היא ארכיטקטורת blackboard, ממחקר זיהוי דיבור בשנות ה-70. מה שחדש ב-2026 הוא שהבקר הוא model ולכן אפשר להחליט את הפירוק לפי הקלט — הגמישות והעלות במשפט אחד.

זה עלה 12 קריאות model לעומת 5 של agent יחיד, והגיע לאותה הכרעה. ואז הוא עשה משהו ששווה להתבונן בו מקרוב:

TEXT
orchestrator final: VERDICT=credit_note_due amount=52.08 source=worker_unverified
                  | PO_MISMATCH=yes source=worker_unverified
single agent:       VERDICT=credit_note_due amount=52.08 reason=reverse_charge_should_have_applied
                  | PO_MISMATCH=yes invoice_says=PO-4417 order_says=PO-4471

שניהם נכונים. רק אחד יודע למה. ל-tax worker היו החשבונית, ההזמנה וטבלת המס בחלון שלו, הוא הגיע למסקנה, וגם שם לב — איש לא ביקש — שמספר הזמנת הרכש בחשבונית אינו תואם לזה שבהזמנה. ואז הוא החזיר סיכום. ה-orchestrator יכול לחזור על שתי האמירות ולא לבדוק אף אחת, כי הראיות נשארו בחלון שהוא מעולם לא ראה. זו שאלת הסיום של פרק 24, עם תשובה: ההורה יכול להסתכל על כל מה שהילד בחר לכתוב.

התיקון הוא דגל, ויש לו מחיר:

מה העובד מחזירinput tokens של ה-orchestratorעלותמה ההורה יכול לעשות
המסקנה שלו3,628$0.012512לחזור עליה
המסקנה שלו והראיות שלו4,065$0.013554לגזור אותה שוב, ולא להסכים

שנים-עשר אחוז יותר input tokens, 8.3 % יותר כסף, והביטוי source=worker_unverified נעלם מהתשובה. זו העסקה בכל multi-agent system והיא כמעט אף פעם לא נאמרת: החלון הנקי של הילד שווה שיהיה, יכולת הביקורת של ההורה שווה תשלום, ואי אפשר לקבל את שניהם בחינם.

אז מתי orchestrator-workers שגוי? כאן, במשימה הזו. הוא קנה תשובה נכונה ש-agent אחד עם אותם ארבעה כלים גם הגיע אליה, תמורת פי 1.66 עלות ופי 2.3 זמן שעון, והפך את התשובה הזו לקשה יותר להגנה. ההנחיה של Anthropic עצמה אומרת זאת לפני שהדפוסים מתחילים: למצוא ״את הפתרון הפשוט ביותר האפשרי, ולהגדיל מורכבות רק כשצריך״, כי ״agentic systems לעיתים קרובות מחליפים latency ועלות בביצועי משימה טובים יותר״.1 הטבלאות למעלה הן המשפט הזה עם מספרים מתחתיו.

Evaluator-optimiser, והשופט שכתב את הבחינה

קישור למקטע: Evaluator-optimiser, והשופט שכתב את הבחינה

קריאה אחת מייצרת, אחרת מעריכה, והלולאה חוזרת עד שההערכה עוברת.1 האבות שפורסמו הם Self-Refine — אותו model כ-״generator, refiner, and feedback provider״, שמדווח על כ-20 נקודות שיפור מוחלט בממוצע על פני שבע משימות3 — ו-Reflexion, ששומרת את הביקורת ב-buffer אפיזודי בין ניסיונות ומדווחת על 91 % pass@1 ב-HumanEval כשה-baseline הגיע ל-80 %.4

מודל העלות הוא הפשוט ביותר מבין החמישה: שתי קריאות לסיבוב, ומספר הסיבובים אינו שלכם. שלושה סיבובי refinement על משימה שלקחה קריאה אחת הם שש קריאות, ולכן הרצפה של הדפוס היא 6× והתקרה שלו היא כל cap שתגדירו — מה שהופך את יציאת התקציב של פרק 23 לחובה ולא לסדר אסתטי.

התקרה עדינה יותר, ואפשר למדוד אותה. על אותן 20 בעיות ה-model המקומי ענה נכון על 9. אחר כך הראו לו כל אחת מהתשובות האלה ושאלו אם היא נכונה — בלי לומר לו שהתשובה שלו עצמו, מה שמסיר את הטיית החנופה ומשאיר את שאלת היכולת:

התשובה של ה-model עצמוהוא אמר ״כן״הוא אמר ״לא״
ה-9 שהיו נכונות90
ה-11 שהיו שגויות38

זה שופט טוב יותר מכפי שכותרת הסעיף מרמזת, ולומר זאת זו הנקודה של מדידה במקום קביעה: הוא לא חסם שום דבר נכון ותפס 8 מתוך 11 טעויות. כמסנן, הוא שווה את הקריאות שלו.

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

מכאן הכלל: evaluator מרוויח את הקריאות שלו רק כשיש לו משהו שאין ל-generator. קומפיילר, חבילת בדיקות, schema validator, model אחר, אדם. התוצאות של Self-Refine עצמה נמדדות מול העדפת אדם ומדדי משימה, לעולם לא מול דעתו של ה-model על עצמו. אם היתרון היחיד של ה-evaluator שלכם הוא prompt אחר, אתם משלמים כפול על הסכמה. פרק 29 בונה את הגרסה עם יתרון אמיתי: golden set שהתשובות שלו כתובות מראש.

החמישה שלמעלה הם צורות עבור הקוד שלכם. מתחתיהם יושבת משפחה שנייה שלעיתים קרובות רשומה לצידם ולא צריכה להיות: ReAct, Reflexion, plan-and-execute ו-tree of thoughts הן לולאות הסקה, והעלות שלהן היא בבקשות.

פרק 12 עסק בהסקה בתוך ה-model, שעליה אתם משלמים ב-output tokens בקריאה אחת. זה הסוג השני. ההבדל חשוב כשהחשבון מגיע: chain of thought ארוך יותר מייקר קריאה אחת, ולולאת הסקה הופכת משימה אחת לקריאות רבות, שכל אחת מהן שולחת מחדש את כל מה שקדם לה — הריבועיות שפרק 23 מדד בטבלת ההשתוללות שלו.

לולאהקריאות, לכל משימהמה הקריאות הנוספות קונות
ReActאחת לכל צעד, עד שהוא עוצרה-model מגיב למה שהכלים החזירו5
plan-and-executeאחת לתכנון, ואז אחת לכל צעדהתוכנית קבועה לפני שהצעד הראשון רץ6
Reflexionניסיונות × (פעולה + reflection)הביקורת שורדת לניסיון הבא4
tree of thoughtsbranching factor × depth, ועוד evaluation אחד לכל nodeחיפוש, עם backtracking7

מאמר tree-of-thoughts מפרסם טבלת עלויות משלו, וזה נדיר מכפי שראוי. ב-Game of 24 עם GPT-4: input/output prompting best-of-100 פתר 33 % ב-$0.13 למקרה, chain of thought best-of-100 פתר 49 % ב-$0.47, ו-tree of thoughts פתר 74 % ב-$0.74, כשהמחברים מציינים שהוא ״could require 5-100 times more generated tokens than CoT״.7

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

הקורס הזה אינו מממש אותן מחדש. לכל הארבע יש מימושי reference של המחברים שלהן, ב-Python, והערך שלהן הוא להיות המקור ולא תרגום: ysymyth/ReAct, noahshinn/reflexion, princeton-nlp/tree-of-thought-llm ו-AGI-Edgerunners/Plan-and-Solve-Prompting. קראו את ה-prompts במאגרים האלה; ה-prompts הם המאמרים.

שתי טופולוגיות, ואחת מהן לא חוזרת

קישור למקטע: שתי טופולוגיות, ואחת מהן לא חוזרת

עכשיו multi-agent ממש, המקום שבו רוב הבלבול חי. יש שתי דרכים שבהן agent אחד מערב agent אחר, הן אינן וריאנטים, וההבדל הוא מי נשאר אחראי אחר כך.

Agent ככלי. ההורה קורא לו, מקבל תשובה, וממשיך. זה ממשק הכלי של פרק 18 עם agent שלם מאחוריו, וההורה לעולם לא מאבד שליטה. זה מה שה-orchestrator למעלה עושה.

Handoff. ההורה מעביר את השיחה ואינו מקבל אותה בחזרה. המדריך של OpenAI הוא ההצהרה שפורסמה בצורה הברורה ביותר: handoffs הם ״a one way transfer that allow an agent to delegate to another agent... If an agent calls a handoff function, we immediately start execution on that new agent that was handed off to while also transferring the latest conversation state.״8

אזהרת אוצר מילים, כי זה מפיל אנשים שוב ושוב: ״handoff״ היא מילה של SDK אחד, לא תקן. זו טרמינולוגיה מ-OpenAI Agents SDK ומהמדריך הזה, שגם קורא לשני הסידורים ״manager״ ו-״decentralized״ ומציין שבדפוס manager ״edges represent tool calls whereas in the decentralized pattern, edges represent handoffs״.8 יש כן תקן פתוח במרחב הזה — A2A, בגרסה 1.0.0, תחת זכויות היוצרים של Linux Foundation, עם היסטוריית גרסאות מתועדת ורשימת breaking changes מתועדת, שהעיקרון המוצהר שלו הוא opaque execution: agents ״collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations״.9 זה לא handoff, וההשוואה שייכת לפרק 26. מה שחשוב כאן הוא שאחת משתי המילים היא API של ספרייה והשנייה היא specification עם ממשל.

ההבחנה היא מבנה נתונים, לא תרשים:

graph.tsTS
export type EdgeKind = "tool" | "handoff";
export interface AgentEdge { from: string; to: string; kind: EdgeKind }
export interface AgentGraph { root: string; agents: Record<string, AgentSpec>; edges: AgentEdge[] }

/** One agent may not be both a tool of X and a handoff target of X. */
export function conflicts(g: AgentGraph): AgentEdge[] {
  const seen = new Map<string, EdgeKind>();
  const bad: AgentEdge[] = [];
  for (const e of g.edges) {
    const key = `${e.from}->${e.to}`;
    const other = seen.get(key);
    if (other && other !== e.kind) bad.push(e);                            
    else seen.set(key, e.kind);
  }
  return bad;
}

/** Every agent reachable from the root, and at what depth. */
export function reachable(g: AgentGraph): Map<string, number> {
  const depth = new Map([[g.root, 0]]);
  const queue = [g.root];
  while (queue.length) {
    const id = queue.shift()!;
    for (const e of g.edges.filter((x) => x.from === id)) {
      if (depth.has(e.to)) continue;
      depth.set(e.to, depth.get(id)! + 1);
      queue.push(e.to);
    }
  }
  return depth;
}

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

TEXT
reachable: lead@0 billing@1 tax@1 dunning@1
orphans:   ghost
conflicts: lead->tax

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

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

מה הועברpayload ממוצעהאילוץ היה בוהמומחה זכר אותורווח בר-סמך 95 %
כל השיחה173 tokens24/2420/24 — 83 %64–93 %
סיכום שכתב ה-agent השולח62 tokens1/240/24 — 0 %0–14 %
רק הודעת המשתמש האחרונה61 tokens0/240/24 — 0 %0–14 %
רשומה typed69 tokens24/2424/24 — 100 %86–100 %

השורה השלישית היא control ומתנהגת כמו אחת: העובדה אינה שם, ולכן אי אפשר להיזכר בה. שלוש האחרות הן הממצא.

התמליל המלא הוא 173 tokens ועובד 83 % מהזמן, כשארבעת הכשלונות שלו הם הנושא של פרק 24 ולא של זה. הרשומה ה-typed היא 69 tokens — שבעה יותר מהסיכום — ועובדת בכל פעם, כי האילוץ יושב בשדה בעל שם במקום במשפט.

והסיכום הוא השורה שצריך לבהות בה. הוא נכשל 24 פעמים מתוך 24, והסיבה אינה שהקורא פספס אותו. האילוץ הופיע רק ב-1 מתוך 24 הסיכומים בכלל. ה-agent המקבל לא היה רשלן; הוא קיבל טקסט שלא הכיל את התשובה. סיכום הוא דחיסה שלא אתם כתבתם, שמיוצרת בידי model שאת חלונו אינכם יכולים לראות, וממוטבת להיקרא כמו סיכום — ו-״הלקוח אומר שברשומות שלנו המדינה שגויה״ הוא בדיוק סוג הפסוקית ש-summariser משמיט כרעש פרוצדורלי.

גבול ישר על המספר הזה: ה-summariser הוא model של חצי מיליארד פרמטרים, וגדול יותר היה שומר יותר. מה שאינו משתפר עם הגודל הוא צורת הסיכון — ה-agent השולח מחליט, בכל handoff, בכל ניסוח, באופן בלתי נצפה, אילו עובדות שורדות. הרשומה ה-typed אינה תלויה בשיפוט הזה כלל, ולכן היא מנצחת מכוח הבנייה ולא מכוח אינטליגנציה. כל מה שחייב לשרוד העברה צריך להיות שדה, לא משפט.

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

שלוש עובדות סיום, כולן מהטבלאות למעלה.

multi-agent system מכפילה קריאות, וקריאות הן ריבועיות ב-context. ה-orchestrator עשה 12 קריאות model במקום שבו agent אחד עשה 5, וכל אחת נושאת transcript הולך וגדל משלה — 3,628 input tokens מול 2,697, פער שמתרחב עם אורך המשימה.

כל גבול הוא ערוץ מאבד. שני agents פירושם סיכום אחד. ארבעה agents בשרשרת פירושם שלושה, מורכבים, שכל אחד נכתב בידי model שממטב למשהו שאינו ההחלטה שלכם.

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

כל זה אינו טיעון נגד ה-multi-agent frameworks שפורסמו, ושווה לקרוא אותם כמקורות ראשוניים ולא דרך מדריכים.10 זה טיעון לכך שה-agent השני צריך להצדיק את מקומו.

לכן, מבחן ולא העדפה. הוסיפו agent שני כשאחד לפחות מאלה נכון: תת-המשימה צריכה חלון נקי שההורה לא חייב לרשת (פרק 24); תת-המשימות באמת עצמאיות וזמן השעון חשוב, שזה ה-1.8× למעלה; תת-המשימה צריכה הרשאות שונות או model אחר, מה שפרק 30 הופך לטיעון אבטחה; או שתת-המשימה בבעלות מישהו אחר, המקום שבו protocol אמיתי מתחיל להיות חשוב. אם התשובה היא ״כדי שלכל agent יהיה prompt ברור יותר״, תנו ל-agent האחד prompt ברור יותר. זה בחינם.

עכשיו אתם יכולים לנקוב בשמות חמשת הדפוסים, לתמחר אותם זה מול זה על משימה אחת, להבדיל orchestrator מ-sectioner ו-tool call מ-handoff, ולהגן על agent יחיד באמצעות טבלה במקום העדפה.

כל סידור כאן חלק נוחות אחת שלא תשרוד מגע עם שום דבר אמיתי: כל הכלים היו שלנו. חשבונית, הזמנה, טבלת מס, העובדים מאחורי ה-orchestrator — אותו repository, אותו deploy, אותם types, אותם אנשים.

עכשיו שימו אחד מהם מעבר לגבול חברה. טבלת המס שייכת לספק חשבונאות, רשומת ההזמנה למערכת מחסן, ואף אחד מהם לא קרא את ממשק Tool שלכם. אתם צריכים דרך עבור model שלא כתבתם לגלות, לתאר ולקרוא ליכולת שמישהו אחר מפעיל — עם authentication (שהוא החצי של פרק 27), versioning, והבטחה ששרת אינו יכול לקרוא את שאר השיחה שלכם. זו בעיית protocol, יש לה specification עם schema נורמטיבי, וכמעט כל מה שמאונדקס עליה מתאר גרסה שכבר לא קיימת.

פרק 26 קורא את ה-specification הזה במקום לסכם אותו, ומתחיל בהקלדת JSON-RPC בטרמינל ביד.


כל עלות וספירת token למעלה הגיעו מהספק המתוסרט שתואר בסעיף השני, על Node 22 מעל loopback interface, בספירה עם encoding של o200k_base ובתמחור לפי התעריפים שפרק 16 קרא ב-6 בספטמבר 2026 — $2.00 למיליון input tokens ו-$12.00 למיליון output. נתוני זמן השעון הם מאותן ריצות כשה-latency של הספק נקבע ל-400 ms לקריאה וכלים ל-50 ms, כך שהם מודדים את הסידור ולא ספק כלשהו. שתי מדידות ה-model האמיתי — טבלת ה-handoff וטבלת ה-voting-and-judging — השתמשו ב-Qwen/Qwen2.5-0.5B-Instruct ב-float32 על ה-CPU מאחורי endpoint באותה צורה, greedy למעט כשמצוינת טמפרטורה, עם רווחים שחושבו בשיטת Wilson מפרק 4. שום בקשה בפרק הזה לא נשלחה ל-endpoint בתשלום, ושום מספר בו לא הוערך.

  1. Anthropic, Building effective agents, 19 בדצמבר 2024, anthropic.com/engineering/building-effective-agents, נקרא ב-7 בספטמבר 2026. מקור חמשת שמות ה-workflow שנעשה בהם שימוש למעלה וכל ביטוי שצוטט מהם — prompt chaining, routing, parallelisation עם וריאנטי sectioning ו-voting שלו, orchestrator-workers, evaluator-optimiser — וכן ההמלצה למצוא ״the simplest solution possible, and only increasing complexity when needed״ וההבחנה ש-״agentic systems often trade latency and cost for better task performance״. פרקים 22 ו-23 מצטטים את ההגדרה שלו ל-agent. 2 3 4 5 6 7

  2. Wang, X., Wei, J., Schuurmans, D., Le, Q., Chi, E., Narang, S., Chowdhery, A. and Zhou, D. Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171 (מרץ 2022). מקור דפוס voting, המתואר שם כאסטרטגיית decoding ולא כארכיטקטורה: דגימת נתיבי הסקה מגוונים, ואז ״select the most consistent answer by marginalizing out the sampled reasoning paths״, עם רווחים מדווחים של +17.9 ב-GSM8K, +11.0 ב-SVAMP, +12.2 ב-AQuA, +6.4 ב-StrategyQA ו-+3.9 ב-ARC-challenge.

  3. Madaan, A. et al. Self-Refine: Iterative Refinement with Self-Feedback. arXiv:2303.17651 (2023). לולאת evaluator-optimiser עם model אחד בכל שלושת התפקידים — ״generator, refiner, and feedback provider״ — שמשפרת ״by ~20% absolute on average in task performance״ על פני שבע משימות, כפי שנמדד לפי העדפת אדם ומדדים אוטומטיים ולא לפי verdict של ה-model עצמו.

  4. Shinn, N., Cassano, F., Berman, E., Gopinath, A., Narasimhan, K. and Yao, S. Reflexion: Language Agents with Verbal Reinforcement Learning. arXiv:2303.11366 (2023). מוסיף זיכרון אפיזודי של self-critiques בין ניסיונות — ״reinforce language agents not by updating weights, but through linguistic feedback״ — ומדווח על 91 % pass@1 ב-HumanEval מול 80 % עבור baseline של GPT-4. שימו לב לדרישה שהתוצאות שלו תלויות בה: אות אמיתי מהסביבה, כגון בדיקה נכשלת, ולא דעתו של ה-model על עצמו. 2

  5. Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K. and Cao, Y. ReAct: Synergizing Reasoning and Acting in Language Models. arXiv:2210.03629 (2022). עקבות הסקה ופעולות משולבים; פרק 23 בנה את הלולאה הזו. מצוטט כאן בשל צורת העלות שלו ולא בשל תוצאותיו: קריאת model אחת לכל צעד, כשה-transcript כולו נשלח מחדש בכל פעם.

  6. Wang, L., Xu, W., Lan, Y., Hu, Z., Lan, Y., Lee, R. K.-W. and Lim, E.-P. Plan-and-Solve Prompting: Improving Zero-Shot Chain-of-Thought Reasoning by Large Language Models. arXiv:2305.04091 (2023). ״First, devising a plan to divide the entire task into smaller subtasks, and then carrying out the subtasks according to the plan״ — צורת plan-then-execute, ומקור העסקה שהפרק הזה מתעניין בה: התוכנית קבועה לפני שהתצפית הראשונה מגיעה, כלומר prompt chaining עם פירוק שנכתב בידי model במקום בידיכם.

  7. Yao, S., Yu, D., Zhao, J., Shafran, I., Griffiths, T. L., Cao, Y. and Narasimhan, K. Tree of Thoughts: Deliberate Problem Solving with Large Language Models. arXiv:2305.10601 (2023). חיפוש על ״thoughts״ ביניים עם self-evaluation ו-backtracking; 74 % ב-Game of 24 מול 4 % עבור chain-of-thought prompting. נתוני העלות שצוטטו למעלה הם של המאמר עצמו, מנספח B.3, טבלה 7: לכל מקרה, input/output prompting best-of-100 ב-$0.13 עבור 33 %, chain of thought best-of-100 ב-$0.47 עבור 49 %, ו-tree of thoughts ב-$0.74 עבור 74 %, עם הערת המחברים ש-ToT ״could require 5-100 times more generated tokens than CoT״. 2

  8. OpenAI, A practical guide to building agents (PDF), נקרא ב-7 בספטמבר 2026. הפיצול manager מול decentralised, מסגור הגרף שצוטט למעלה (״in the manager pattern, edges represent tool calls whereas in the decentralized pattern, edges represent handoffs״), וההגדרה של handoff כ-״a one way transfer... we immediately start execution on that new agent that was handed off to while also transferring the latest conversation state״. שימו לב מה הסעיף האחרון הזה קובע: ב-SDK הזה מצב השיחה אכן עובר, וזו החלטת תכנון של הספרייה הזו ולא תכונה של handoffs בכלל. 2

  9. Agent2Agent (A2A) Protocol Specification, הגרסה המשוחררת האחרונה 1.0.0, a2a-protocol.org/latest/specification/, נקרא ב-7 בספטמבר 2026; זכויות יוצרים Linux Foundation, Apache-2.0. צוטט למעלה: ״open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems״, ועקרון opaque execution — agents ״collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations״. הדף כולל היסטוריית גרסאות (0.1.0, 0.2.6, 0.3.0, 1.0.0), נספח breaking changes, ונספח על היחס שלו ל-MCP. פרק 26 עושה את ההשוואה הזו.

  10. ה-multi-agent frameworks שהפרק הזה אינו מלמד, לקורא שרוצה את המקורות הראשוניים ולא מדריך: Wu, Q. et al., AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation, arXiv:2308.08155 (2023), שבו agents הם ״customizable, conversable״ והשיחה עצמה היא מודל התכנות; Hong, S. et al., MetaGPT: Meta Programming for a Multi-Agent Collaborative Framework, arXiv:2308.00352 (2023), שמקודד נהלי עבודה סטנדרטיים ל-role prompts ומציין במפורש ש-״solutions to more complex tasks are complicated through logic inconsistencies due to cascading hallucinations caused by naively chaining LLMs״ — השרשרת הבטוחה-אך-שגויה שנמדדה בראש הפרק הזה, בשם בתקציר; ו-Park, J. S. et al., Generative Agents: Interactive Simulacra of Human Behavior, arXiv:2304.03442 (2023), עשרים וחמישה agents עם זיכרון, reflection ותכנון, שהיא התשובה הגדולה ביותר שפורסמה לשאלה ״מה קורה אם ממשיכים להוסיף agents״.


נוצר על ידי

David Vicente Campos

מייסד NeuraLIA Labs ושותף-מייסד MyRealFood

אני מהנדס מחשבים, בוגר אוניברסיטת לאון. הייתי שותף בהקמת MyRealFood, שם, כסמנכ״ל טכנולוגיות, בניתי את האפליקציה שמיליוני אנשים השתמשו בה כדי לאכול בריא יותר, והקמתי את NeuraLIA Labs, שם אני בונה מוצרי בינה מלאכותית. כאן אני כותב על מה שהייתי צריך להבין לאורך הדרך, כפי שהייתי רוצה שמישהו היה מסביר לי בזמנו.

עוד על המחבר

פורסם על ידי NeuraLIA Labs.

פוסטים חדשים ישירות לתיבת הדואר

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

תוכן הקורס

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev10 דקות קריאה

מודל ה-AI Jev נבנה להחלטות, לא לפרוזה

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

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering10 דקות קריאה

הנדסת הקשר לסוכני AI ארוכי־טווח

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

מוכנים לתת ל-LIA לבחור?

בנו עם כל מודלי ה-AI במקום אחד — התחילו בחינם עוד היום.