למה "זה עבד" ו"זה נכשל" לא מספיקים
תוכנה רגילה שנכשלת בדרך כלל מודיעה על כך: היא נעצרת ומדפיסה הודעת-שגיאה שמצביעה על המקום שבו נשברה. סוכן-AI נכשל אחרת. הוא ממשיך לרוץ, מקבל בכל צעד החלטה שנראית סבירה, ומגיע לתוצאה שנראית מסודרת — אבל בדרך הוא חיפש במקום הלא נכון, פירש לא נכון תשובה של כלי חיצוני, או חזר שלוש פעמים על אותה פעולה בלי להתקדם. מי שרואה רק את הפלט הסופי אינו יכול להבחין בין השניים.
"נצפוּת" (Observability) הוא מונח שהגיע לתחום ה-AI מעולם התוכנה הרגיל. תיעוד OpenTelemetry — פרויקט קוד-פתוח שמגדיר מוסכמות אחידות לנתוני-טלמטריה, ושפלטפורמות מסחריות בונות עליהן (ראו בהמשך) — מגדיר אותה כיכולת ש"מאפשרת להבין מערכת מבחוץ, בכך שהיא מאפשרת לשאול שאלות על המערכת בלי להכיר את פעולתה הפנימית". הדגש על "שאלות" אינו מקרי: המבחן המעשי אינו אם יש גרפים על המסך, אלא אם אפשר לענות על שאלה חדשה שאיש לא חשב עליה מראש. אותו תיעוד קורא לזה "לא-ידועים לא-ידועים" — התקלות שלא נצפו, ולכן איש לא הכין להן מדד ייעודי.
זה לא מגיע בחינם: "כדי לשאול שאלות כאלה על המערכת, היישום חייב לכלול מכשור מתאים" — כלומר הקוד עצמו חייב לפלוט את הנתונים. אותו תיעוד גם נותן מבחן פשוט לשאלה כמה מכשור מספיק: יישום שהמכשור שלו מתאים הוא כזה שבו "מפתחים אינם צריכים להוסיף עוד מכשור כדי לאתר תקלה, מפני שיש להם כבר את כל המידע הדרוש". בסוכנים המבחן הזה נכשל לעיתים קרובות, כי מה שרוצים לדעת בדיעבד אינו מה שנראה חשוב מראש.
שלושה סוגי-נתונים: יומן, מדד ועקבה
הנתונים שמערכת פולטת נקראים "טלמטריה" (Telemetry), ולפי אותו תיעוד הם "נתונים הנפלטים ממערכת ומהתנהגותה". הם מגיעים בשלוש צורות.
"יומן" (Log) הוא "הודעה עם חותמת-זמן שנפלטת משירותים או מרכיבים אחרים" — שורת-טקסט שאומרת מה קרה ומתי. זה הכלי הוותיק והפשוט ביותר, והבעיה איתו בסוכן היא נפח: אלפי שורות בלי מבנה שמקשר ביניהן.
"מדד" (Metric) הוא "צבירה על פני פרק-זמן של נתונים מספריים על התשתית או על היישום" — כמה משימות רצו היום, מה זמן-התגובה הממוצע, כמה טוקנים נצרכו. מדד טוב לענות על "האם משהו השתנה", ופחות על "מה קרה במקרה הבודד הזה".
"עקבה" (Trace) היא, בהגדרת אותו תיעוד, "הדרך שעברה בקשה בודדת — שנשלחה על ידי יישום או משתמש-קצה — כשהיא נעה דרך כמה שירותים בארכיטקטורה". המילים "כמה שירותים" הן כל העניין: עקבה נועדה לחבר יחד צעדים שהתרחשו במקומות שונים, לא לתעד רכיב בודד. זו הצורה הקריטית לסוכנים, ולה מוקדש הסעיף הבא.
שלושתן יחד הן מה שמאפשר לענות על השאלה שאותו תיעוד מציב כמבחן-האמינות של מערכת: "האם השירות עושה את מה שהמשתמשים מצפים שיעשה".
עקבה: המבנה שמראה מה קרה בכל צעד
עקבה בנויה מיחידות שנקראות "מקטעים" (Spans). מקטע "מייצג יחידת-עבודה או פעולה", והמקטעים הם "אבני-הבניין של עקבות". לכל מקטע יש התחלה, סוף, סטטוס — "לא-נקבע", "שגיאה" או "תקין" — ו"תכונות" (Attributes), שהן "זוגות מפתח-ערך המכילים מטא-נתונים... הנושאים מידע על הפעולה שהמקטע עוקב אחריה". אפשר גם לתלות על מקטע "אירועים", שהם למעשה "הודעת-יומן מובנית... המשמשת לציון נקודת-זמן משמעותית ויחידה במהלך המקטע".
החלק החשוב הוא הקינון. מקטע יכול להכיל מקטעי-בן, ו"מקטעי-בן מייצגים תת-פעולות"; המקטע העליון, זה שאין לו אב, "מייצג את ההתחלה והסוף של הפעולה כולה". כל המקטעים באותה עקבה חולקים מזהה אחד, "מזהה-עקבה", ולכן אפשר לחבר יחד מקטעים שהגיעו "מתהליכים שונים, שירותים שונים, מכונות וירטואליות ומרכזי-נתונים שונים" לכדי "מבט מקצה-לקצה על כל מערכת".
בתרגום לשפת-הסוכן: המשימה כולה היא המקטע העליון; כל קריאה למודל-השפה וכל הפעלה של כלי חיצוני היא מקטע-בן; והלולאה שבה הסוכן חזר על עצמו מופיעה כשלושה מקטעי-אחים כמעט זהים בזה אחר זה. זה בדיוק המידע שאי-אפשר לשחזר מהפלט הסופי.
שווה לשים לב לפרט קטן בסטטוס: ברירת-המחדל היא "לא-נקבע", ולפי התיעוד היא "מייצגת מקטע שהסתיים בלי שגיאה". כלומר, היעדר סימון-שגיאה אינו עדות לכך שמישהו בדק שהצעד הצליח — הוא רק אומר שהצעד לא התפוצץ. בסוכן, שבו רוב הכשלים אינם התרסקויות אלא החלטות גרועות, ההבדל הזה הוא כל ההבדל.
התקן שנכתב בדיוק לסוכנים
כדי שכלי-ניטור אחד יוכל להציג ריצה של סוכן בלי להכיר כל מסגרת-פיתוח בנפרד, צריך שכל המסגרות יקראו לאותם דברים באותם שמות. הסכמה כזו נקראת בעולם התוכנה "מוסכמות סמנטיות" (Semantic Conventions).
ב-OpenTelemetry נפתח לשם כך מאגר-קוד ייעודי לתחום ה-AI היוצר, שמגדיר לפי תיאורו "מוסכמות סמנטיות ל-Generative AI, כולל מקטעים, מדדים ואירועים ללקוחות GenAI, ל-MCP, ומוסכמות ספציפיות-לספק". המסמך שעוסק בסוכנים מגדיר חמישה סוגי-מקטע, ואלה הם: create_agent (יצירת סוכן), invoke_agent בשתי צורות — אחת לקריאה מבחוץ ואחת לפעולה פנימית — invoke_workflow (הפעלת תהליך-עבודה שלם), ו-plan (שלב-התכנון). חמשת הסוגים מסומנים במסמך בסטטוס Development, כלומר עדיין בפיתוח ולא סופיים.
המוסכמות האלה אינן נשארות על הנייר: ספקים מסחריים בונים עליהן בפועל. מיקרוסופט מתארת את שכבת-העקיבה של פלטפורמת Foundry שלה כ"בנויה על תקני OpenTelemetry ומשולבת ב-Azure Monitor Application Insights", ומציינת שהיא תומכת בעקיבה עבור מסגרות נפוצות ובהן LangChain, LangGraph, ה-OpenAI Agents SDK ומסגרת-הסוכנים של מיקרוסופט עצמה — ארבע מסגרות שונות, שכולן מנוטרות דרך אותה שכבה. אותה חברה גם מגדירה את המונח בהקשר ה-AI בצורה רחבה יותר מ-OpenTelemetry: "היכולת לנטר, להבין ולאתר תקלות במערכות AI לאורך כל מחזור-החיים שלהן" — הגדרה שכוללת אצלה במפורש גם את שלב-ההערכה, ולא רק את איסוף-הנתונים.
אותו מאגר אינו עוצר בסוכן עצמו: לפי תיאורו הוא מכסה גם את MCP, הפרוטוקול שדרכו סוכנים מתחברים לכלים חיצוניים, וגם מוסכמות ספציפיות לספקים מסחריים. זה חשוב מעשית, כי שכבת-הכלים היא בדיוק המקום שבו סוכן נכשל בשקט — כלי שהחזיר תשובה ריקה או שגיאה שהסוכן התעלם ממנה.
עצם קיומה של רשימה כזו הוא אמירה על מצב התחום: שלב-התכנון של סוכן — הרגע שבו הוא מחליט מה הצעד הבא — נחשב היום ליחידה מדידה בפני עצמה, ולא לקופסה שחורה שרק התוצאה שלה נראית.
מה נרשם בפועל, ומה לא חייב להירשם
מוסכמות-השמות מפרטות גם אילו נתונים נלווים לכל מקטע, ולכל נתון יש "רמת-דרישה" משלו. חלקם נדרשים תמיד: שם-הפעולה — gen_ai.operation.name — מסומן Required בכל חמשת סוגי-המקטע. שם-הספק, gen_ai.provider.name, מסומן Required רק בשניים מהם, אלה שהמסמך מגדיר כמקטעי-לקוח (CLIENT) — יצירת-סוכן והפעלת-סוכן מבחוץ — ואינו מופיע כלל בשלושת המקטעים הפנימיים. אחרים נדרשים רק בתנאי, כמו סוג-השגיאה (error.type) כשמשהו נכשל.
מעניין לא פחות מה יושב ברמה הנמוכה ביותר, Opt-In — נתון שנרשם רק אם מפעילים אותו במפורש. שלוש תכונות מסומנות כך, וכולן תוכן: ההודעות עצמן (gen_ai.input.messages ו-gen_ai.output.messages), הנחיות-המערכת (gen_ai.system_instructions) והגדרות-הכלים (gen_ai.tool.definitions). כלומר, התקן אינו מחייב לרשום את תוכן השיחה. זו הבחנה מעשית וחשובה. מצד אחד, בלי ההודעות קשה מאוד להבין למה הסוכן החליט מה שהחליט. מצד שני, ההודעות הן בדיוק המקום שבו יושבים נתוני-הלקוח — שם, כתובת, מסמך שהועלה — ורישום גורף שלהן מעביר מידע רגיש למערכת נוספת. ארגון שמפעיל סוכן מול קהל נדרש להכריע בשאלה הזו במפורש, לא בברירת-מחדל.
השימוש בטוקנים, לעומת זאת, יושב ברמה גבוהה יותר: gen_ai.usage.input_tokens ו-gen_ai.usage.output_tokens מסומנים Recommended, כלומר מומלצים ולא Opt-In. ההפרש הזה מחזק את הנקודה ולא מחליש אותה, כי זה בדיוק הנתון שמתרגם ישירות לכסף. סוכן שנכנס ללולאה חוזרת אינו מודיע על כך בשום מקום, אבל הוא בהחלט מופיע בספירת-הטוקנים — ולעיתים זו הדרך הראשונה שבה מישהו מבחין בבעיה.
הגבול: לראות זה לא לשפוט
נצפוּת עונה על השאלה "מה קרה". היא אינה עונה על "האם זה היה נכון". עקבה מפורטת יכולה להראות בבירור שהסוכן הפעיל שלושה כלים והחזיר תשובה תוך אחת-עשרה שניות, ולא לרמוז בכלל שהתשובה שגויה. השיפוט הזה הוא נושא נפרד — הערכת סוכנים — שמשתמש בנתוני-הנצפוּת כחומר-גלם, אבל מוסיף עליהם קריטריון-הצלחה מוגדר.
באותה מידה, נצפוּת אינה עמידות. היומן שנשמר לצורך ביצוע עמיד והעקבה שנשמרת לצורך נצפוּת מתעדים את אותה ריצה ונראים דומים, אבל נכתבו לשני קוראים שונים: הראשון נקרא על ידי המערכת עצמה, כדי לשחזר את מצבה אחרי קריסה, והשני נקרא על ידי אדם, כדי להבין מה קרה. מערכת יכולה להחזיק אחד בלי השני, ורבות אכן מחזיקות.
ולבסוף, מגבלה שאין לה פתרון טכני: עקבה מראה מה הסוכן עשה, לא למה. השדה שנראה כמו "הסיבה" הוא הטקסט שהמודל עצמו כתב לפני הפעולה — תיאור שהמודל הפיק, לא הצצה למנגנון שקיבל את ההחלטה. זו הבחנה שקל לשכוח דווקא כשקוראים עקבה שנראית כמו יומן-מחשבות מסודר ומשכנע.