Context Engineering: למה ה-agent שלך נעשה פחות חכם בתור 40
הזזת עובדה שלוש שורות למטה ב-prompt שתופס 2.6% מה-window מפילה retrieval מ-84% ל-19%. ה-window לא היה הבעיה.
בעמוד הזה
הנה prompt אחד שנשלח 288 פעמים לאותו מודל עם greedy decoding. אורכו 853 tokens. הוא מכיל מרשם של עשרים וחמישה כרטיסי תמיכה — עיר, תור, עדיפות, בעלים, שלוחה — ושאלה אחת: מרטה פריירה צריכה שיחזרו אליה לגבי הכרטיס שלה. מהי שלוחת הקו הישיר של הכרטיס הזה?
המרשם זהה בכל פעם. המודל זהה בכל פעם. הדבר היחיד שמשתנה הוא איזו מתוך עשרים וחמש השורות מחזיקה את התשובה.
| מיקום התשובה | פגיעות | שיעור retrieval | מרווח 95 % |
|---|---|---|---|
| 1 מתוך 25 | 27/32 | 84 % | 68–93 % |
| 4 מתוך 25 | 6/32 | 19 % | 9–35 % |
| 7 מתוך 25 | 6/32 | 19 % | 9–35 % |
| 10 מתוך 25 | 9/32 | 28 % | 16–45 % |
| 13 מתוך 25 | 8/32 | 25 % | 13–42 % |
| 16 מתוך 25 | 6/32 | 19 % | 9–35 % |
| 19 מתוך 25 | 6/32 | 19 % | 9–35 % |
| 22 מתוך 25 | 3/32 | 9 % | 3–24 % |
| 25 מתוך 25 | 7/32 | 22 % | 11–39 % |
שלושים ושניים ניסויים בכל שורה, כרטיס אחר בכל ניסוי, מרווחי Wilson מ-פרק 4, כי שבעה-עשר מתוך עשרים לא באמת מבדילים דבר מדבר.
מיקום ראשון נענה נכון ב-84 % מהמקרים. כל מיקום אחר נמצא בין 9 % ל-28 %, וכל שמונת המרווחים האלה חופפים, ולכן הקריאה ההוגנת היא קודם הראשון, ואז כל השאר. Liu ואחרים מצאו U — גבוה בשני הקצוות, נמוך באמצע — וזרוע ה-recency לא מופיעה כאן בבירור: 22 % במיקום האחרון נמצא בתוך הפיזור של האמצעיים. מה שלא נמצא בתוך שום דבר הוא הנפילה ממיקום 1 למיקום 4. שלוש שורות.
ה-context window של המודל הזה הוא 32,768 tokens. ה-prompt משתמש ב-853 מהם, 2.6 %. שום דבר לא גלש, שום דבר לא נחתך, לא הגענו לשום מגבלה, לא הופיעה שום אזהרה. המודל הפסיק למצוא שורה שנמסרה לו, מפני שהשורה זזה שלושה מקומות למטה ברשימה של עשרים וחמש.
פרק 16 תמחר את ה-context window וסיים באזהרה ש-להחזיק מיליון tokens אינו אומר להשתמש בהם, והפנה לכאן. זה כאן.
הצגת פרטים
מה הפרק הזה צריך מהקודמים.
- פרק 9 גזר self-attention ואת עלות שלו. כל token עושה attention לכל token אחר, ולכן מספר היחסים הזוגיים גדל עם ריבוע האורך. העובדה הזו משמשת בהמשך, ולא נגזרת מחדש.
- פרק 16 ספר את חמשת דליי ה-token לחיוב והראה שהחשבון של שיחה גדל ריבועית. הפרק הזה עוסק במה שעושים לגבי זה בלי לשבור את ה-agent.
- פרק 18 בנה את קטלוג הכלים ומדד שעשרים כלים לא פגעו בבחירה אבל הכפילו את ה-prompt פי שישה. הנה החשבון שלהם.
- פרק 19 בנה retrieval. ה-just-in-time retrieval בהמשך הוא אותו פרק כשהוא מיושם על ההיסטוריה של ה-agent עצמו; chunking לא מוסבר מחדש.
- פרק 23 בנה את ה-harness. כל מה שבפרק הזה הוא policy שרצה בתוך הלולאה שלו, ולכן זה TypeScript: התוצר הוא שירות ארוך-חיים שמחזיק state, לא notebook שמחזיק tensors.
שתי עבודות עם שמות דומים
קישור למקטע: שתי עבודות עם שמות דומיםAnthropic שרטטה את הקו בספטמבר 2025, ושני המשפטים צריכים לעמוד זה לצד זה. Prompt engineering הוא ״שיטות לכתיבה ולארגון של הוראות LLM לתוצאות מיטביות״. Context engineering הוא ״מערך האסטרטגיות לאצירה ולתחזוקה של קבוצת ה-tokens (מידע) המיטבית בזמן LLM inference, כולל כל המידע האחר שעשוי לנחות שם מחוץ ל-prompts״.1
ההבדל התפעולי הוא מתי, ו-על ידי מי. prompt נכתב פעם אחת, בידי אדם, ונבדק. context מורכב בכל קריאה, בידי קוד שאף אחד לא מסתכל עליו, מחומרים שאף אחד לא כתב ידנית: ארבעים תורים של היסטוריה, שש תוצאות כלים, ארבעה קטעים שנשלפו ב-retrieval, פרופיל משתמש, שנים-עשר JSON schemas. פרק 15 מדד מה הוראות טובות יותר קונות. הפרק הזה עוסק בתשעים האחוזים האחרים של ה-tokens, שמגיעים מעצמם.
אותו מסמך מציין את המשאב שכולם מוציאים: למודלים ״יש 'תקציב attention' שהם מושכים ממנו כשהם מנתחים נפחים גדולים של context. כל token חדש שמוכנס מרוקן חלק כלשהו מהתקציב הזה״. והוא מציין את הסימפטום: ״ככל שמספר ה-tokens ב-context window גדל, היכולת של המודל לזכור מידע מתוך אותו context במדויק יורדת״ — context rot.1
המשפט האחרון הוא טענה על התנהגות, כלומר אפשר לבדוק אותו, והטבלה בראש הדף הזה היא הבדיקה.
איך הטבלה הזו נוצרה
קישור למקטע: איך הטבלה הזו נוצרהארבעים שורות מול ה-endpoint המקומי מ-פרק 22 — שרת Python קטן שמחזיק את Qwen2.5-0.5B-Instruct על ה-CPU ומדבר במבנה chat-completions, כך שהלולאה נשארת TypeScript וה-tensors נשארים בצד השני של ה-port.
const DEPTHS = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1];
for (const d of DEPTHS) {
const slot = Math.round(d * (N - 1));
let hits = 0, other = 0;
for (let t = 0; t < TRIALS; t++) {
const recs = buildRecords(N, 1000 + t); // 25 unique tickets
const gold = recs[Math.floor(rng(7 + t)() * N)]; // a different one each trial
const rest = recs.filter((x) => x.ticket !== gold.ticket).slice(0, N - 1);
const lines = [...rest.slice(0, slot).map((x) => x.line),
gold.line,
...rest.slice(slot).map((x) => x.line)];
const r = await complete(prompt(lines, ask(gold.owner)), { maxTokens: 12 });
const said = /\d{4}/.exec(r.text)?.[0];
if (said === String(gold.ext)) hits++;
else if (said && recs.some((x) => String(x.ext) === said)) other++;
}
}מונה other הוא מה שהופך תוצאה מאכזבת לתוצאה שימושית: כשהמודל טועה, האם הוא אבוד או בטוח בעצמו?
התשובה היא בטוח בעצמו. על פני שמונת המיקומים שאינם ראשונים, 136 מתוך 205 התשובות השגויות היו שלוחה של כרטיס אחר — מספר אמיתי בן ארבע ספרות, בפורמט נכון, שנקרא מהשורה הלא נכונה. במיקום 1 רק אחת מחמש ההחמצות הייתה כזו; במיקום 7, עשרים ואחת מתוך עשרים ושש היו.
ההבחנה הזו היא מה שחשוב בפרודקשן. מודל שאומר אני לא מוצא את זה הוא באג ששמים לב אליו; מודל שמחזיר את המספר של שורה שכנה הוא באג שמשחררים, כי על המסך השניים נראים זהים. זה הכשל שפרק 19 בנה נגדו ציטוטים ניתנים לאימות, כשהוא מגיע מתוך ה-prompt במקום מתוך ה-index.
זה לא רק איפה. זה גם כמה.
קישור למקטע: זה לא רק איפה. זה גם כמה.מיקום הוא ציר אחד. אורך הוא הציר השני, וקל יותר לבדוק אותו: להשאיר את התשובה באמצע ולהגדיל את הרשימה.
| רשומות | prompt tokens | פגיעות | שיעור | מרווח 95 % | שורה שגויה | אף אחד |
|---|---|---|---|---|---|---|
| 1 | 97 | 18/20 | 90 % | 70–97 % | 0 | 2 |
| 3 | 159 | 11/20 | 55 % | 34–74 % | 9 | 0 |
| 8 | 315 | 3/20 | 15 % | 5–36 % | 17 | 0 |
| 20 | 695 | 2/20 | 10 % | 3–30 % | 16 | 2 |
| 40 | 1,324 | 3/20 | 15 % | 5–36 % | 15 | 2 |
| 80 | 2,587 | 1/20 | 5 % | 1–24 % | 18 | 1 |
| 140 | 4,477 | 2/20 | 10 % | 3–30 % | 18 | 0 |
רשומה אחת ו-97 tokens: 90 %. שלוש רשומות ו-159 tokens: 55 %. שמונה רשומות ו-315 tokens: 15 %, ומשם שטוח ונמוך עד 140 רשומות ו-4,477 tokens. כל הקריסה מתרחשת בין השורה הראשונה לשורה השמינית של רשימה.
העמודה האחרונה היא כל מה שאינו השלוחה הנכונה ואינו שלוחה של רשומה אחרת, וכשיש רשומה אחת בלבד בדף, זה המקום היחיד שבו תשובה שגויה יכולה לנחות. שתי ההחמצות ב-רשומה אחת שוות דיווח במקום לעגל אותן החוצה, כי אף אחת מהן לא הייתה סירוב: אחת ענתה 5806 למרשם שהשורה היחידה בו אומרת 5805. ב-97 tokens עם מועמד יחיד, המודל הזה עדיין מעתיק ספרה לא נכון פעמיים מתוך עשרים, וזה הרצפה שמולה כל השאר נמדד.
מכאן נובעים שני דברים. context גדול יותר קונה את הזכות לשלוח יותר, לא את הוודאות שזה ייקרא: למודל הזה יש window של 32,768 tokens וטווח עבודה, במשימה הזו, של כמה מאות tokens. ואין סף, אין מצוק, אין מצב ״context מלא״ — ההידרדרות כבר בדרך ברשומה השלישית ומושלמת בשמינית, באחוז אחד מה-window. מה שלא יהיה context limit, הוא לא מה ששולט בזה.
בדרך כלל מציעים שני מנגנונים. הראשון הוא האריתמטיקה מפרק 9, ש-Anthropic מנסחת באותם מונחים של הקורס הזה: מודלים ״מבוססים על ארכיטקטורת transformer, שמאפשרת לכל token לעשות attention לכל token אחר בכל ה-context. התוצאה היא n² יחסים זוגיים עבור n tokens״.1 Attention על רצף ארוך יותר אינו אותה פעולה שמיושמת על יותר חומר; זהו תקציב קבוע אחד של מסת הסתברות שמתפזר על פני יותר מתחרים. השני הוא אימון: מודלים רואים הרבה יותר רצפים קצרים מארוכים, ולכן תבניות מיקום ארוכות-טווח הן החלק הכי פחות מתורגל ברשת. זה טיעון, לא מדידה, והפרק הזה לא יכול להכריע אותו.
מה שכן מוכרע הוא הצורה, והיא מוכרת מאז 2023. Liu ואחרים בדקו מענה לשאלות מרובות-מסמכים ו-key-value retrieval על פני משפחות וגדלים של מודלים, ומצאו ש-״הביצועים לרוב גבוהים ביותר כאשר המידע הרלוונטי מופיע בתחילת ה-input context או בסופו, ויורדים משמעותית כאשר מודלים צריכים לגשת למידע רלוונטי באמצע contexts ארוכים, אפילו במודלים שמוגדרים במפורש כ-long-context״.2 פרק 15 לקח מהמאמר הזה את כלל המיקום שלו; פרק 19 לקח ממנו את הסיבה לכך שעשרים chunks שנשלפו ב-retrieval יכולים לקבל ציון גרוע מארבעה. הצורה הפרקטית של העובדה היא המשפט היחיד כאן שעליו כדאי לפעול: למדוד את זה על המודל שלך עם הנתונים שלך לוקח חמש דקות, ושום עקומה שפורסמה לא מחליפה את שלך.
אף אחד לא יודע מה נמצא ב-window שלו
קישור למקטע: אף אחד לא יודע מה נמצא ב-window שלושאלו צוות מה ממלא את ה-context של ה-agent שלו ותקבלו הערכה, כי שום API לא מחזיר את התשובה: התגובה נותנת את prompt_tokens, מספר אחד לכל זה.
אפשר לשחזר את הפירוק עם ארבע ספירות ושלוש החסרות — ה-prompt המרונדר כולו, אותו דבר בלי הגדרות כלים, הודעת ה-system לבדה עם ובלעדיהן, והכול כשהוסרו תוצאות הכלים:
async function buckets(messages: Msg[]) {
const sys = messages.slice(0, 1);
const withoutResults = messages.filter((m) => m.role !== "tool");
const [total, sysWithTools, sysNoTools, noResults] = await Promise.all([
countPrompt(messages, CATALOGUE), // everything
countPrompt(sys, CATALOGUE), // system + scaffolding + schemas
countPrompt(sys), // system + scaffolding
countPrompt(withoutResults, CATALOGUE), // everything but tool output
]);
return {
system: sysNoTools,
tools: sysWithTools - sysNoTools,
toolResults: total - noResults,
conversation: total - sysWithTools - (total - noResults),
total,
};
}countPrompt מחיל את תבנית הצ׳אט של המודל עצמו לפני tokenizing, וזה חשוב יותר ממה שנדמה: הטקסט שלך הוא לא מה שנספר. סמני תפקידים, הקדמת ה-tool calling והרינדור של ה-schema הם כולם tokens שאתה משלם עליהם ומעולם לא הקלדת. פרק 7 בנה tokenizer ופרק 16 ספר עם js-tiktoken; כאן הספירה מגיעה מאותו מודל שיקרא את ה-prompt, וזו הספירה היחידה שנכונה בדיוק.
עכשיו הריצו agent אמיתי דרך זה: ארבעים תורים של חקירת אירוע, שנים-עשר כלים, סביבת תפעול מזויפת שמחזירה dumps של לוגים וסדרות מדדים ריאליסטיים.
| תור | system | הגדרות כלים | שיחה | תוצאות כלים | prompt כולל | input שחויב בתור הזה |
|---|---|---|---|---|---|---|
| 1 | 85 | 1,817 | 155 | 490 | 2,547 | 4,370 |
| 2 | 85 | 1,817 | 282 | 529 | 2,713 | 5,275 |
| 5 | 85 | 1,817 | 647 | 1,870 | 4,419 | 8,093 |
| 10 | 85 | 1,817 | 946 | 2,141 | 4,989 | 4,951 |
| 20 | 85 | 1,817 | 1,500 | 2,943 | 6,345 | 6,316 |
| 30 | 85 | 1,817 | 2,187 | 4,000 | 8,089 | 8,059 |
| 40 | 85 | 1,817 | 3,053 | 5,677 | 10,632 | 21,090 |
קראו את השורה הראשונה מול האחרונה.
ב-תור 1 ה-prompt הוא 2,547 tokens ו-71 % ממנו הם הגדרות כלים. ה-system prompt הוא 3 %. מה שהמשתמש הקליד הוא 6 %. ה-agent עוד לא עשה כלום וכבר נושא 1,817 tokens של JSON schema.
עד תור 40 ה-prompt הוא 10,632 tokens והחלקים התהפכו: הגדרות 17 %, שיחה 29 %, תוצאות כלים 53 %. פלט הכלים עקף את ההגדרות בתור 5; השיחה לא עקפה אותן עד תור 25, כך שבשישים האחוזים הראשונים של הסשן קטלוג הכלים היה גדול יותר מכל מה שנאמר.
ואז הסך הכול. על פני 57 קריאות מודל, ההרצה חויבה ב-370,291 input tokens עבור context סופי של 10,632 — ה-prompt האחרון שולם בערך שלושים וחמש פעמים, שזה הריבועי של פרק 16 עם מכפיל של agent מעליו. מתוך אותם 370,291, 103,569, או 28 % מכל מה שחויב, היו שנים-עשר הגדרות הכלים, שנשלחו מחדש byte-identical בכל קריאה.
כמה עולה הגדרת כלי
קישור למקטע: כמה עולה הגדרת כליקטלוג הכלים הוא העלות הקבועה הגדולה ביותר ב-agent והוא בלתי נראה, כי לעולם לא רואים אותו: מעבירים מערך של אובייקטים והספק מרנדר אותו לתוך ה-prompt עבורך. במדידה, על אותם שנים-עשר כלים:
system prompt + chat scaffolding, no tools: 85 tokens
all twelve definitions: 1,817 tokens
of which fixed tool-calling scaffolding: 126 tokens
three tools instead of twelve: 605 tokens
same twelve, one-sentence descriptions,
no parameter prose: 1,291 tokens (-29 %)לכל כלי, העלות השולית נעה מ-80 tokens עבור get_current_time, שמקבל string אחד, עד 263 עבור search_tickets, שמקבל ארבעה פרמטרים עם enum ומשפט הנחיה לכל אחד. זה שער החליפין מאחורי העצה המרכזית של פרק 18 ש-התיאור הוא ה-API: תיאור טוב עולה בערך מאה tokens בכל בקשה לשארית חייו של ה-agent. שלוש השלכות.
כלי שאינך משתמש בו עדיין מחויב. ה-agent קרא לשבעה מתוך השנים-עשר. חמשת האחרים עלו 697 tokens בכל אחת מ-57 הבקשות — 39,729 בסך הכול, יותר מעשירית מכל מה שההרצה חויבה עליו, עבור יכולות שלא נגע בהן. אחד מהחמישה נושא את הפרט החד ביותר ב-trace: המודל ניסה שלוש פעמים לקרוא ל-read_log, שלא קיים. הכלי שהוא רצה היה search_logs, ההגדרה השנייה הכי יקרה בקטלוג ב-237 tokens. הוא שילם על ההגדרה הזו 57 פעמים, מעולם לא השתמש בה, ומעולם לא מצא את שמה.
קיצוץ פרוזה הוא האופטימיזציה הזולה ביותר הזמינה, והוא trade. קיצור תיאורים למשפט אחד והסרת תיעוד פרמטרים חסכו 526 tokens לקריאה, 29 אחוזים, בלי לגעת בשורת לוגיקה — וגרמו למודל לקרוא לכלים פחות טוב, וזה מה שפרק 18 מדד. הנקודה היא ששני הצדדים של ה-trade הזה נמצאים עכשיו באותה יחידה.
בקנה מידה מסוים, שליחת הגדרות בכלל מפסיקה להיות הגיונית. Anthropic נתנה לזה מספר בנובמבר 2025: סט גדול של שרתים מחוברים פירושו עיבוד ״מאות אלפי tokens״ של הגדרות לפני שהבקשה נקראת, והחלפה של זה ב-code execution — ה-agent מגלה וטוען רק את ההגדרות שהוא צריך — ״מפחיתה את השימוש ב-token מ-150,000 tokens ל-2,000 tokens, חיסכון של 98.7% בזמן ובעלות״.3 אותו רעיון כמו שאר הפרק, מיושם על schemas במקום על היסטוריה: שמרו את ה-index, פתרו את הערך לפי דרישה.
לשבור את זה בכוונה
קישור למקטע: לשבור את זה בכוונהשני דברים נשתלו בתמליל בן ארבעים התורים. ב-תור 2, לפני כל עבודה אמיתית, המשתמש מציין כלל קבוע: כל כרטיס שאתה פותח חייב להיות מתויק תחת מספר העובד שלי, 4417. ב-תור 19, באמצע האירוע, עובדה: ה-shard המושפע הוא pay-shard-7, אושר על ידי צוות התשלומים. בתור 40 המשתמש מבקש מה-agent לפתוח את כרטיס האירוע, שצריך את שניהם. כל probe נשאל בשישה ניסוחים שונים ומקבל ציון מתוך שש — greedy decoding הוא דטרמיניסטי, ולכן קריאה אחת נותנת כן או לא שאי אפשר לשחזר כשיעור, ושש נותנות שיעור.
לאחר מכן התמליל משוחזר תחת שבע policies של context. משוחזר ולא מורץ מחדש, בכוונה: ההודעות, קריאות הכלים ותוצאות הכלים זהות byte-identical בכל השבע, כך שהמשתנה היחיד הוא מה כל policy בחרה לשמור. פרק 16 הראה למה sliding window הוא מהלך כלכלי גרוע, כי הוא הורס את ה-prefix שניתן ל-cache. הנה מה שהוא עושה להתנהגות:
| context policy | input tokens על פני 40 התורים | prompt בתור 40 | כלל מתור 2 | עובדה מתור 19 |
|---|---|---|---|---|
| היסטוריה מלאה | 370,291 | 10,632 | 6/6 | 5/6 |
| sliding window, 12 ההודעות האחרונות | 157,578 | 2,922 | 5/6 | 0/6 |
| השמטת תוצאות כלים מעל 4 תורים | 243,445 | 6,311 | 6/6 | 3/6 |
| compaction כל 6 תורים | 195,515 | 3,220 | 6/6 | 0/6 |
| compaction ועוד הערות שנכתבו על ידי מודל | 200,849 | 3,286 | 6/6 | 0/6 |
| להצמיד את תורי המשתמש עצמו, בחזית | 168,550 | 3,559 | 6/6 | 5/6 |
| להצמיד את תורי המשתמש עצמו, בסוף | 168,835 | 3,564 | 6/6 | 6/6 |
| בקרה: שני התורים ושום דבר אחר | — | 1,981 | 6/6 | 6/6 |
שורות ה-compaction כוללות את עלות הדחיסה: 18,581 input tokens עבור שבעה סיכומים ועוד 3,392 עבור רושם ההערות. שורת הבקרה שם כדי שאפשר יהיה לקרוא אפס כאפס — עם שתי ההודעות לבדן ב-prompt של 1,981 tokens, המודל עונה על שני ה-probes באופן מושלם, כך שאף שורה אינה מצב שבו המשימה קשה מדי.
היסטוריה מלאה זוכרת, והיא הדבר היקר ביותר בטבלה: 370,291 input tokens עבור סשן שהתוכן העמיד שלו הוא שני משפטים.
זה עונה על שאלה שהפתיחה השאירה פתוחה. למה תמליל של 10,632 tokens מחזיק עובדה שמרשם של 853 tokens מאבד? כי אורך הוא המשתנה הלא נכון. המרשם מחזיק עשרים וחמש שלוחות בנות ארבע ספרות בעשרים וחמישה משפטים זהים — עשרים וארבעה decoys כמעט מושלמים לדבר שרוצים. התמליל מחזיק בדיוק מספר עובד אחד ושם shard אחד. Context rot הוא interference לפני שהוא volume, ולכן 136 מתוך 205 התשובות השגויות למעלה היו ערך של שכן. השאלה המועילה לגבי window היא לא כמה הוא ארוך; אלא כמה דברים בו נראים כמו התשובה.
ה-sliding window זול יותר ב-57 % ואיבד את האירוע. מספר העובד שורד רק כי ה-agent חזר עליו בתורים האחרונים. ה-shard, שנאמר פעם אחת בתור 19, אינו ב-12 ההודעות האחרונות — והמודל לא אומר זאת. כשנשאל שש פעמים הוא ענה ״the affected payment shard is shard 4417״, כשהוא מושיט יד למספר העובד, המזהה האחר היחיד שנותר ב-window שלו, ופעמיים ״pool״, שנשלף מתוך המחרוזת pool_exhausted בשורת לוג.
Compaction זולה ואיבדה את אותה עובדה. שבעה סיכומים, שנכתבו על ידי המודל תחת הוראה מפורשת לשמור מזהים, מספרים, הוראות קבועות ושאלות פתוחות, ו-pay-shard-7 לא נמצא באף אחד מהסיכומים החשובים; שש הניחושים היו shard 1, pay_shard_1 ו-pool. Compaction לא נכשלת בקול. היא מייצרת סשן שוטף, סביר וקצר בהרבה, שהשמיט בשקט שורה אחת.
שלוש שורות קיבלו 0/6 על העובדה מתור 19 — ה-sliding window, compaction, ו-compaction עם הערות. שמונה-עשרה תשובות שגויות ביניהן, ו-אף אחת מהן לא הייתה ״אני לא יודע.״
ואז השורה שאמורה להביך. שמירה מילולית של ארבעים הודעות המשתמש עצמו, יחד עם ארבעת התורים האחרונים במלואם ושום דבר אחר, עולה 168,550 tokens — 54 % פחות מהיסטוריה מלאה — ועונה על שני ה-probes טוב כמו היסטוריה מלאה או טוב יותר. בלי summariser, בלי note-taker, בלי מודל שני: פילטר על role === "user". המילים של המשתמש הן ה-tokens הזולים והיקרים ביותר לערך ב-window של agent, ורוב העיצובים זורקים אותן יחד עם כל השאר.
שתי השורות האחרונות הן שוב טבלת הפתיחה, בתוך ה-agent. אותו בלוק מוצמד, מוזז מהודעת ה-system לסוף ה-prompt: 5/6 הופך ל-6/6. בשישה ניסויים זה לא הבדל מובהק ולא מוצג ככזה — הוא מוצג כתזכורת ש-איפה הוא פרמטר שאתה מגדיר, בין שאתה יודע זאת ובין שלא.
ארבע דרכים להוציא פחות window
קישור למקטע: ארבע דרכים להוציא פחות windowארבע האסטרטגיות שלהלן הן של Anthropic, בסדר שלה, אף שרק שלוש האחרונות הן רשימת long-horizon שלה.1 כל הארבע הן וריאציות על הוראה אחת: אל תישא את מה שאתה יכול לשלוף, ואל תישא גולמי את מה שאתה יכול לשאת דחוס.
Just-in-time retrieval
קישור למקטע: Just-in-time retrievalאל תטענו תוכן מראש. שמרו מזהים — נתיב קובץ, שאילתה, מספר כרטיס, שם כלי והארגומנטים שלו — ופתרו אותם כשצריך. הדלי הגדול ביותר ב-agent למעלה הוא פלט כלי שנקרא פעם אחת, שימש פעם אחת, ואז נישא עוד שלושים תורים. החלפת כל תוצאה שגילה מעל ארבעה תורים ב-stub שאומר מה היא הייתה ואיך להחזיר אותה היא שש שורות:
const elide: Policy = (h) => [SYSTEM, ...h.flatMap((turn, ti) =>
turn.map((m) => (ti < h.length - 4 && m.role === "tool"
? { role: "tool", name: m.name,
content: `[${m.name} result from turn ${ti + 1}, ${m.content.length} chars, ` +
`elided; call ${m.name} again with the same arguments to re-read it]` }
: m)))];זה פרק 19 כשה-corpus מוחלף בעבר של ה-agent עצמו. מנגנון ה-retrieval כבר שם — הוא קטלוג הכלים.
Compaction
קישור למקטע: Compactionכשהתמליל עובר סף, החליפו את החלק הישן ביותר שלו בסיכום שכתב מודל והמשיכו. ה-prompt שכותב את הסיכום הוא כל העיצוב, ושם compaction מנצחת או מפסידה: שמרו מזהים, מספרים, הוראות קבועות ושאלות פתוחות; זרקו נימוסים ופלט כלי שאפשר לשלוף מחדש.
Compaction היא lossy מעצם בנייתה, מה שהיא מאבדת נבחר על ידי מודל בשמך, ושום דבר לא זורק שגיאה כשהוא בוחר לא נכון. היא גם לא חינמית: כל compaction היא קריאה נוספת שה-input שלה הוא הדבר שנדחס.
Structured note-taking
קישור למקטע: Structured note-takingשמרו חנות קטנה מחוץ ל-context והזריקו אותה מחדש בשלמותה בכל תור. בניגוד לסיכום היא append-only וניתנת ל-addressing: כלל שנכתב בתור 2 עדיין שם מילה במילה בתור 400. הגרסה שנמדדה כאן שואלת את המודל, אחרי כל הודעת משתמש, האם היא מכילה משהו עמיד:
const r = await complete([
{ role: "system", content:
"You keep a durable note file for a support session. Given one user message, " +
"output one short note ONLY if it states a standing rule, an identifier or a fact " +
"that must survive the rest of the session. Otherwise output exactly NONE." },
{ role: "user", content: `Turn ${i + 1}: ${user}` },
], { maxTokens: 40 });
if (!/^none\b/i.test(r.text.trim())) notes.push(`turn ${i + 1}: ${r.text.trim()}`);זו האסטרטגיה עם התקרה הגבוהה ביותר כאן, והיא זו שנכשלה במדידה. על פני ארבעים הודעות משתמש, ה-note-taker שמר שלוש הערות ואף אחת מהשתיים החשובות: שורת עצה מ-runbook, הודעה שהסשן מסתיים, ו-Europe/Madrid is currently 13:45 — זמן שהוא המציא, כי הכלי שהוא ניסח מחדש החזיר 09:52 UTC. ה-note-taker הוא מודל, וכל מה שבפרק הזה חל גם עליו.
Sub-agents
קישור למקטע: Sub-agentsתנו למשימה ממוקדת window משלה — system prompt משלה, קטלוג קטן משלה, בלי היסטוריית ההורה — והחזירו תשובה קצרה במקום תמליל. פרק 23 שם אחד מאחורי tool schema והשאיר את החשבון לכאן; החשבון הוא שהתשובה של הילד היא החלק היחיד ב-window של הילד שההורה משלם עליו אי פעם.
ה-sub-agent לא מופיע בטבלה למעלה כי הוא לא רץ ארבעים תורים: הוא רץ פעם אחת, ב-window שמישהו הגדיר עבורו scope. בהינתן ה-system prompt, תורים 17 עד 19 ושום דבר אחר — 2,737 tokens — הוא ענה על probe ה-shard 6/6, טוב יותר מכל policy בטבלה, ועל probe העובד 0/6, כי המספר הזה לא נמצא בשלושת התורים שנמסרו לו.
זה sub-agents בשני מספרים: window נקי אינו אינטליגנציה, הוא scope, וה-scoping נעשה מראש על ידי קוד שכבר חייב לדעת אילו תורים חשובים. עוד דבר אחד בתשובות האלה שווה לשמור. זו הייתה ה-policy היחידה שענתה ״None available״ במקום להמציא משהו. מודל עם context קטן וקוהרנטי יודע מה חסר לו; מודל עם context גדול ורועש לא.
שלושת הזיכרונות
קישור למקטע: שלושת הזיכרונותכמעט כל שיחה מבולבלת על זיכרון של agent היא שלושה מנגנונים שלובשים מילה אחת. יש להם משכי חיים, בעלים ואופני כשל שונים, ולמערכת ששומרת אותם באותו מקום יש בעיה שהיא עוד לא הבחינה בה.
| היסטוריית שיחה | retrieval | זיכרון משתמש מתמשך | |
|---|---|---|---|
| מחזיק | מה שנאמר בסשן הזה | מסמכים שבבעלותך | עובדות על אדם |
| חי | סשן אחד | עד אינדוקס מחדש | על פני כל הסשנים, לנצח |
| נכתב על ידי | הלולאה, אוטומטית | pipeline של ingestion | המודל, בכוונה |
| נכנס ל-prompt | במלואו, בכל קריאה | ארבעה קטעים, כששאילתה מתאימה | במלואו, בכל קריאה |
| נכשל על ידי | גדילה עד שהוא נרקב | retrieval של ה-chunk הלא נכון | זכירת משהו שגוי עליך |
| נבנה ב | פרק 23 | פרק 19 | הפרק הזה |
המסגרת האקדמית היא של CoALA, שמארגנת language agents סביב ״רכיבי זיכרון מודולריים״ ומפרידה working memory ממאגרים episodic, semantic ו-procedural.4 MemGPT לוקח את אותו רעיון מילולית, בהשאלה של זיכרון וירטואלי ממערכות הפעלה: שכבה מהירה בתוך ה-window, שכבה איטית מחוצה לו, והמודל עצמו מזיז נתונים ביניהן באמצעות function calls.5 שניהם מאלצים את השאלה שמוצר צריך לענות עליה בכל מקרה — לא כמה אפשר לשמור, אלא לאיזה מאגר זה שייך, ומתי זה פג.
המבחן הפרקטי הוא שאלה אחת לכל עובדה: מה עדיין צריך להיות נכון מחר? תוצאת כלי מתור 12, כלום. סיכום של הסשן, עד שהסשן מסתיים. העובדה שמספר העובד של המשתמש הוא 4417, עד שהוא מחליף עבודה. שלוש תשובות, שלושה מאגרים.
לאן זה הולך עכשיו
קישור למקטע: לאן זה הולך עכשיועכשיו אפשר למדוד מה נמצא ב-window, להחליט מה נשאר בו, ולהבדיל בין agent ששכח משהו לבין אחד שנשא אותו ולא הסתכל.
האחרונה מבין ארבע האסטרטגיות היא זו שלא מתאימה לכאן. sub-agent אינו context policy, הוא agent שני, וברגע שיש שניים צריך להחליט מה עובר ביניהם ומי אחראי. פרק 25 הוא זה: חמש תבניות ה-orchestration ומאיפה כל אחד מהשמות שלהן באמת מגיע, שתי הטופולוגיות שמתבלבלות זו עם זו — לשאול sub-agent ולקבל תשובה בחזרה, מול למסור לו את השיחה ולא לקבל אותה בחזרה — והממצא המדוד שבמשימה שהוא מתמחר, הסידור הפשוט יותר מנצח — ואחריו הבדיקה למתי הוא מפסיק לנצח.
הוא גם יורש בדיוק את מה שהפרק הזה כרגע מדד. sub-agent מחזיר סיכום. סיכום הוא compaction שלא כתבת, שמיוצר על ידי מודל שאת ה-window שלו אינך יכול לראות, ולהורה אין דרך להבדיל בין סיכום טוב לבין סיכום שגוי ובטוח בעצמו — אותה הבחנה שהפרידה בין 84 % ל-19 % בראש הדף הזה, והפכה שמונה-עשרה עובדות חסרות לשמונה-עשרה עובדות מומצאות. אז: כשה-sub-agent טועה, על מה בדיוק ההורה יכול להסתכל?
מקורות ושיטה
קישור למקטע: מקורות ושיטהכל מספר כאן הופק על המכונה הזו ושום דבר לא הוערך. המודל הוא Qwen2.5-0.5B-Instruct ב-float32 על ה-CPU עם greedy decoding, מוגש מעל loopback באמצעות endpoint קטן ב-Python שמדבר במבנה chat-completions וחושף נתיב ספירת token — שוב התפר של פרק 14, tensors בצד ה-Python והלולאה בצד ה-TypeScript — כך שכל ספירה היא tokenizer של אותו מודל עצמו שמוחל על תבנית הצ׳אט שלו עצמו. טבלת המיקום היא 288 קריאות, תשעה מיקומים כפול שלושים ושניים ניסויים עם כרטיס שונה בכל ניסוי; טבלת האורך היא 140 קריאות; הרצת ה-agent היא 57 קריאות מודל על פני 43 דקות שעון; טבלת ה-policy היא אותו תמליל אחד ששוחזר תחת שבע policies. המרווחים הם של Wilson, מפרק 4. לא נקרא שום API בתשלום, ולכן גם אין בפרק אפילו מחיר אחד: ספירות ה-token מדויקות, והתעריפים שהייתם מכפילים בהם הם של פרק 16.
הפניות
קישור למקטע: הפניות-
Anthropic, Effective context engineering for AI agents, 29 בספטמבר 2025,
anthropic.com/engineering/effective-context-engineering-for-ai-agents, נקרא ב-7 בספטמבר 2026. מקור שתי ההגדרות שצוטטו למעלה, של ״attention budget״ והקביעה שכל token חדש מרוקן אותו, של תיאור context rot, של מסגור היחסים הזוגיים n², ושל האסטרטגיות ששימשו כעמוד השדרה של הפרק הזה. שלוש מהן הן רשימת ה-long-horizon שלו — compaction, structured note-taking וארכיטקטורות multi-agent; just-in-time retrieval מופיע מוקדם יותר באותו מאמר, תחת context retrieval ו-agentic search, ומקובץ איתן כאן. ↩ ↩2 ↩3 ↩4 -
Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F. and Liang, P. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (v1 יולי 2023, v3 נובמבר 2023). צוטט בפרקים 15, 16 ו-19 ונמדד כאן. המשפט המצוטט הוא מה-abstract; שתי המשימות של המאמר הן מענה לשאלות מרובות-מסמכים ו-key-value retrieval, והממצא שהאפקט נמשך גם במודלים explicitly long-context הוא החלק שחשוב להחלטת מוצר. ↩
-
Anthropic, Code execution with MCP: building more efficient agents, 4 בנובמבר 2025,
anthropic.com/engineering/code-execution-with-mcp, נקרא ב-7 בספטמבר 2026. מקור הירידה מ-150,000 ל-2,000 tokens והנתון 98.7 %, ושל התצפית שהגדרות כלים שנטענות מראש תופסות context לפני שהבקשה נקראת. ↩ -
Sumers, T. R., Yao, S., Narasimhan, K. and Griffiths, T. L. Cognitive Architectures for Language Agents. arXiv:2309.02427 (2023). מארגן language agents סביב ״רכיבי זיכרון מודולריים, מרחב פעולה מובנה לאינטראקציה עם זיכרון פנימי וסביבות חיצוניות, ותהליך קבלת החלטות מוכלל לבחירת פעולות״, ומפצל זיכרון ל-working, episodic, semantic ו-procedural. פרק 22 השתמש בטקסונומיה שלו עבור ה-learning agent; טבלת שלושת המאגרים למעלה היא הצל הפרקטי שלה. ↩
-
Packer, C., Wooders, S., Lin, K., Fang, V., Patil, S. G., Stoica, I. and Gonzalez, J. E. MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560 (אוקטובר 2023). מציע ״virtual context management, טכניקה השואבת השראה ממערכות זיכרון היררכיות במערכות הפעלה מסורתיות״, כשהמודל עצמו מזיז נתונים בין שכבה מהירה בתוך ה-window לשכבה איטית מחוצה לו. האמירה הברורה ביותר בכל מקום לגבי למה ה-window הוא cache ולא זיכרון. ↩