Episodic Memory — כיצד סוכן לומד ממשימות קודמות

מאת צוות מדיה דיל · 12.08.2026 · Context Engineering · 5 דק׳

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

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

אפיזודי לעומת סמנטי: הבדל שקובע איך בונים

חשוב להבחין בין זיכרון אפיזודי לזיכרון סמנטי, כי הם נשמרים ונשלפים אחרת. זיכרון סמנטי הוא עובדות מנותקות מהקשר ("השרת רץ על פורט 8080") — זה בדיוק תחום ה-Structured Memory. זיכרון אפיזודי, לעומת זאת, שומר את הרצף: מה הייתה הבעיה, אילו צעדים ננקטו בסדר מסוים, מה עבד ומה לא עבד, ומה התוצאה הסופית. ההבדל הזה חשוב כי אפיזודה טובה לא רק אומרת "התשובה הייתה X" אלא "כשניסינו A זה נכשל בגלל B, אז עברנו ל-C וזה עבד" — בדיוק המידע שחוסך לסוכן עתידי לחזור על אותה טעות.

מבנה רשומת אפיזודה

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

{
  "episode_id": "ep_9931",
  "task_summary": "תקלת timeout בסנכרון בין שירות A ל-B",
  "steps": [
    {"action": "בדיקת לוגים", "outcome": "אין שגיאה מפורשת"},
    {"action": "בדיקת connection pool", "outcome": "נמצא exhaustion"}
  ],
  "resolution": "הגדלת pool size ל-50, הוספת timeout מפורש",
  "success": true,
  "task_embedding": [0.021, -0.14, ...]
}

שליפה: דמיון משימה, לא רק דמיון מילים

שליפת אפיזודה רלוונטית עובדת דרך דמיון סמנטי בין תיאור המשימה הנוכחית לתיאורי משימות שמורות — כלומר, embedding של המשימה החדשה מול embedding של ה-task_summary בכל אפיזודה, כפי שמפורט בהרחבה במאמר על embeddings. אבל דמיון טקסטואלי לבדו לא מספיק — שתי משימות יכולות להיראות דומות מילולית ולהיות שונות לגמרי במהות (אותה מילת מפתח, הקשר עסקי שונה לחלוטין), או להיפך. שיפור מעשי הוא לשלב סינון לפי מטא-דאטה מובנה (סוג מערכת, תגי תחום, טווח זמן) יחד עם החיפוש הסמנטי — בדיוק העיקרון שעומד מאחורי חיפוש היברידי, כדי לא לגרור אפיזודות שדומות טקסטואלית אבל לא רלוונטיות הלכה למעשה.

הסיכון: negative transfer וזיכרון מיושן

זיכרון אפיזודי לא תמיד עוזר — לפעמים הוא מזיק. אם אפיזודה ישנה מתייחסת לגרסת מערכת שכבר לא קיימת, או לפתרון שהיה נכון בזמנו אבל הפך למיושן, הסוכן עלול "ללמוד" מהניסיון הלא נכון ולחזור על פתרון שגוי בביטחון גבוה — תופעה שנקראת negative transfer. ההגנה המעשית היא תיוג אפיזודות עם timestamp ותוקף, בדיקה תקופתית (בדרך כלל כחלק מתהליך Memory Consolidation) שמסמנת או מוחקת אפיזודות שכבר לא רלוונטיות, ובמערכות רגישות — אפילו החלטה מפורשת שאפיזודות מעל גיל מסוים לא נשלפות אוטומטית אלא רק בבקשה מפורשת.

בידוד בין הקשרים

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

מה עושים עם אפיזודה שנכשלה

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

כמה אפיזודות לשלוף בכל פעם

פרמטר עיצוב שנראה טכני אך משפיע ישירות על איכות התוצאה הוא כמה אפיזודות דומות לשלוף ולהזין להקשר בכל משימה חדשה. שליפה של אפיזודה אחת בלבד חושפת את המערכת לסיכון שהאפיזודה הבודדת שנבחרה לא באמת מייצגת, גם אם היא הדומה ביותר סטטיסטית. שליפה של יותר מדי אפיזודות (עשר ומעלה) מציפה את ההקשר ומחזירה בעצם לבעיה שה-Just-in-Time Context נועד למנוע — עומס מידע שרובו לא רלוונטי. טווח שנוטה לעבוד טוב בפרודקשן הוא בין שלוש לחמש אפיזודות, עם דגש על גיוון ולא רק על דמיון: עדיף לשלוף כמה אפיזודות שמייצגות זוויות שונות של פתרון בעיה דומה, מאשר חמש אפיזודות כמעט זהות שכולן חוזרות על אותו מסלול פתרון בדיוק. טכניקות re-ranking שמאזנות בין דמיון לגיוון, בדומה לעקרונות שמופיעים במאמר על חיפוש היברידי, רלוונטיות גם כאן במלואן.

שדרוג הדרגתי: אין צורך להתחיל מ-vector store מלא

צוותים רבים דוחים בניית זיכרון אפיזודי מתוך תחושה שהוא דורש תשתית embeddings ו-vector database מלכתחילה. בפועל אפשר להתחיל הרבה יותר פשוט: שמירת אפיזודות כרשומות טקסט רגילות בטבלה, עם שליפה ראשונית מבוססת תגיות ידניות או קטגוריה גסה (סוג המשימה, השירות המעורב) במקום דמיון סמנטי. זה לא אופטימלי, אבל זה נותן ערך אמיתי כבר ביום הראשון בלי להשקיע בתשתית embeddings מראש. המעבר לשליפה מבוססת embedding, כשמגיע הזמן, הוא שדרוג נקודתי ולא פרויקט מחדש — מוסיפים שדה embedding לרשומות הקיימות, ומחליפים את לוגיקת השליפה מסינון תגיות לחיפוש דמיון, בלי לשנות את מבנה הנתונים הבסיסי. הגישה ההדרגתית הזו מתאימה גם לצוותים קטנים וגם כדרך לבדוק אם זיכרון אפיזודי בכלל מספק ערך למוצר הספציפי, לפני שמשקיעים בתשתית מלאה עבור יכולת שאולי לא תשתלם בסופו של דבר.

תגיות: Episodic Memory · Agent Learning · Embeddings · Hybrid Search · Task Retrieval

← חזרה לבלוג · צור קשר