Context Window Fragmentation — ניהול הקשר מפוצל בין כלים שונים
מאת צוות מדיה דיל · 12.08.2026 · Context Engineering · 5 דק׳
כשמשימה זורמת בין כמה כלים וסוכנים, כל אחד עם חלון הקשר משלו, קל מאוד לאבד תמונה מלאה — איך בונים שכבת תיאום שמונעת את זה.
תהליך אוטומטי שהיה אמור לטפל בפנייה של לקוח — לזהות את הבעיה, לחפש בבסיס הידע, לעדכן טיקט, ולשלוח תשובה — עבר בפועל דרך ארבעה כלים ושני סוכני משנה שונים, וכל אחד מהם ראה רק פרוסה צרה של התמונה. הסוכן ששלח את התשובה הסופית לא ידע שסוכן החיפוש כבר בדק וגילה שהבעיה חוזרת אצל הלקוח בפעם השלישית החודש, כי העובדה הזו נשארה קבורה בהקשר של הכלי שגילה אותה ולא עברה הלאה. זו Context Window Fragmentation: מצב שבו הידע הרלוונטי למשימה קיים במערכת, אבל מפוזר בין כמה חלונות הקשר נפרדים שאף אחד מהם לא רואה את כולם.
למה זה קורה כמעט בכל מערכת multi-tool
כל כלי, API, ותת-סוכן פועל עם חלון הקשר משלו — זו לא בעיה, זו בדיוק הסיבה שמערכות multi-agent מתפקדות (כל רכיב מטפל בפרוסה שהוא מתמחה בה, בלי להיחנק בפרטים לא רלוונטיים, תופעה שנדונה בהרחבה תחת השם Context Rot). הבעיה מתחילה כשאין מנגנון מפורש להעברת מידע רלוונטי בין החלונות האלה. עקרונות היסוד של תחום זה מפורטים במאמר הכללי על Context Engineering. במערכת שבנויה נאיבית, כל כלי "יורה ושוכח" — מחזיר תוצאה, וההקשר הפנימי שלו (למה הגיע לתוצאה הזו, מה עוד גילה בדרך) נעלם ברגע שהתשובה נשלחת הלאה. זה שונה מ-Context Isolation, שמונע זליגה בין ישויות שלא אמורות לראות זו את זו בכוונה — כאן הבעיה הפוכה: מידע שכן צריך לזרום בין רכיבים, אבל בפועל לא זורם, בגלל היעדר תשתית להעברה.
שני דפוסי כשל אופייניים
הראשון הוא אובדן קונטקסט בדרך — סוכן A מגלה עובדה חשובה, מעביר לסוכן B רק תקציר דחוס מדי, ו-B מקבל החלטות בלי הפרט שהיה קריטי. השני הוא סתירות בין כלים — כלי אחד מדווח מצב אחד (למשל "המלאי זמין"), כלי אחר, שרץ באותו זמן בערך, מדווח מצב אחר ("המלאי אזל"), ואין אף גורם מרכזי שמזהה את הסתירה לפני שהיא מגיעה למשתמש. שני הדפוסים חמורים יותר ככל שיש יותר שלבים בשרשרת, כי ההסתברות לאובדן מידע או סתירה מצטברת בכל hop נוסף.
הפתרון: מצב קנוני, לא רק העברת הודעות
הגישה שעובדת בפרודקשן היא הפרדה בין "מה שכל כלי רואה" לבין "מצב המשימה הקנוני" — אובייקט מרכזי אחד, מחוץ לחלון ההקשר של כל כלי בודד, שמייצג את מה שידוע בוודאות על המשימה בכל רגע נתון. כל כלי או תת-סוכן, כשהוא מסיים, לא רק מחזיר תשובה לקורא הישיר שלו — הוא כותב עדכון למצב הקנוני, בפורמט מובנה בסגנון שמתואר במאמר על ארכיטקטורת זיכרון סוכנים. כל רכיב שממשיך לפעול על אותה משימה קורא מהמצב הקנוני, לא רק מהתשובה הישירה שקיבל מהשלב הקודם.
const taskState = {
task_id: "t_552",
findings: [],
updateFinding(source, fact) {
this.findings.push({ source, fact, ts: Date.now() });
}
};
// כל כלי כותב הנה, לא רק מחזיר תשובה לקורא הישיר
searchTool.onResult(r => taskState.updateFinding("search", r.summary));
המצב הקנוני הזה הוא בפועל שכבת ה-Working Memory של המשימה כולה, לא רק של שיחה בודדת — הוא חי מעל לכלים הבודדים ומשרת את כולם.
אורקסטרטור: מי אחראי על התמונה המלאה
מצב קנוני בלי מישהו שאחראי עליו נוטה להתפורר בחזרה לפרגמנטציה. דפוס נפוץ ויעיל הוא רכיב אורקסטרציה ייעודי — לא בהכרח מודל, לפעמים פשוט קוד דטרמיניסטי — שאחראי במפורש לקרוא את המצב הקנוני לפני כל שלב, לזהות סתירות בין ממצאים ממקורות שונים, ולהחליט מה עובר לשלב הבא ומה לא. זה מפחית את הנטל מכל כלי בודד להיות "מודע" לכל שאר המערכת, ומרכז את האחריות על עקביות במקום אחד שאפשר לבדוק ולדבג. הדפוס הזה משתלב ישירות עם עקרונות Just-in-Time Context — האורקסטרטור מחליט מה מהמצב הקנוני רלוונטי לשלב הבא, ומעביר רק את זה, לא את הכל.
מתי הפרגמנטציה לא באמת בעיה
לא כל משימה multi-tool זקוקה למצב קנוני מלא — כשהשרשרת קצרה (שני שלבים, קלט-פלט פשוט) ואין תלות אמיתית בין ממצאי כלים שונים, התשתית הנוספת היא עלות מיותרת. הסימן שמצדיק השקעה הוא כשמתגלים בפועל מקרים שבהם מידע "אבד בדרך" בין כלים — או כשמורכבות השרשרת עולה מעבר לכמה שלבים ליניאריים פשוטים לגרף תלויות אמיתי, שם אינטואיציה בלבד כבר לא מספיקה כדי לעקוב אחרי מה כל רכיב יודע.
דיבוג פרגמנטציה: לוג מאוחד לעומת לוגים נפרדים
כשמשהו משתבש במערכת multi-tool מפורקת, הצעד הראשון בדיבוג הוא כמעט תמיד לנסות להבין "מה כל רכיב ראה באותו הרגע" — ובלי תשתית מתאימה, זו משימה כואבת של איסוף ידני מלוגים נפרדים של כל כלי, כל אחד בפורמט שונה, כל אחד עם timestamp שלא בהכרח מסונכרן עם השאר. הפתרון המעשי הוא לוג מאוחד עם trace_id יחיד שמלווה את המשימה מתחילתה ועד סופה, כשכל רכיב — כלי, תת-סוכן, קריאת API — כותב אליו אירוע עם אותו מזהה. כך אפשר, בזמן דיבוג, לשלוף בפקודה אחת את כל מה שקרה סביב משימה ספציפית, בסדר הכרונולוגי הנכון, ולראות בדיוק היכן פרט מסוים "נעלם" — האם הוא מעולם לא נכתב למצב הקנוני, נכתב אך לא נקרא בשלב הבא, או נקרא אך לא הובא בחשבון בהחלטה הסופית. ההשקעה בתשתית trace_id אחידה נראית משנית בשלבי הפיתוח המוקדמים, אבל היא בדיוק מה שהופך שעת דיבוג לחמש דקות ברגע שהמערכת כבר רצה בפרודקשן עם עומס אמיתי.
גרסאות של המצב הקנוני
כשכמה כלים כותבים למצב הקנוני במקביל, ולא תמיד באותו סדר, עולה שאלה נוספת: מה קורה כששני עדכונים מגיעים כמעט בו-זמנית ומתייחסים לאותו שדה? פתרון נאיבי — "האחרון מנצח" (last write wins) — עלול לגרום לכך שממצא חשוב שהתקבל מוקדם יותר יידרס בטעות על ידי עדכון מאוחר פחות רלוונטי, רק כי הוא הגיע שני. גישה עמידה יותר משתמשת בגרסאות (versioning) על כל שדה במצב הקנוני — כל עדכון נרשם עם timestamp ומקור, ובמקום דריסה מוחלטת, המצב הקנוני שומר את כל הגרסאות ומאפשר לרכיב שקורא אותו להחליט אם הוא רוצה את הגרסה האחרונה, את הגרסה בעלת רמת הביטחון הגבוהה ביותר, או את כל הגרסאות יחד לצורך השוואה. זה מוסיף מורכבות, אבל במערכות שבהן סתירות בין כלים הן תופעה שכיחה ולא חריגה, זו כמעט תמיד השקעה משתלמת — כי היא הופכת סתירה מבעיה שקטה ומוסתרת לעובדה גלויה שהאורקסטרטור יכול להתמודד איתה במפורש.
תגיות: Context Fragmentation · Multi-Agent Systems · Orchestration · Agent Memory · Tool Use