ג'וזי לאתר ג'וזי ←
הבלוג של ג'וזי · הנדסה
מהשטח · חלק שלישי

רגע, זה לא מסתדר לי. מה נשאר לבן אדם לעשות

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

י״ר
ישראל רוטCTO ומייסד־שותף, ג'וזי · 15 באוגוסט 2026
יד רובוטית לבנה ויד אנושית מצביעות זו לעבר זו, על רקע צהוב
כן, אני יודע — עוד קלישאה. שתי האצבעות שנוגעות. שמתי אותה כאן בכוונה, כי הפוסט הזה עוסק בדיוק ברגע ההפוך: לא זה שבו בן האדם מוסר את העבודה, אלא זה שבו הוא מצביע חזרה ואומר "רגע, זה לא מסתדר".

Image by Tumisu from Pixabay

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

אז השאלה המעניינת היא לא אם הם טובים. השאלה היא מה נשאר לי.

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

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

101 מתוך פי כמעט מאה

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

ואז הוא עשה משהו גרוע יותר מלפספס באג. הוא בנה טיעון על גבי המספר:

הסוכן

זה לא "101 בעמוד הראשון" — זה כל משתמש חי שעוקב אחרי מישהו בכלל. כלומר גרף העוקבים הוא ליבה קטנה וצפופה של משתמשים פעילים, וכנראה רוב דומם גדול בלי אף עוקב.

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

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

אני

אני לא מאמין שיש לנו רק 101 משתמשים שעוקבים אחרי מישהו. זה לא מסתדר לי.

ORIGINAL
I don't believe we have only 101 users who follow someone. This makes no sense to me

הסוכן

האינטואיציה שלך נכונה, ואני חושב שאני יודע למה. 101 הוא גודל האצווה הראשונה שמונגו מחזירה כברירת מחדל לפקודת find — זה לא צירוף מקרים.

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

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

הסוכן

ההרצה היבשה לא דיווחה על גרף קטן — היא דיווחה על קריאה קטנה. הסקריפטים מעבדים בשקט את ~101 המסמכים הראשונים ועוצרים, ואז מדפיסים סיכום שנקרא כמו ריצה מלאה ומוצלחת. ההרצה שלך על פרודקשן הייתה משאירה את הקולקשן ריק ב־98 אחוז, בלי שגיאה בשום מקום.

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

שש־עשרה שניות של שום דבר מסוים

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

אני

16 שניות לא מסתדרות לי. מה יכול להסביר ביצועים כאלה?

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

The take bounds the result, not the work — which is the part that makes this look deceptively cheap in code review.

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

אני

רגע, אבל השאילתה על המשתמשים היא זו שלקחה 16 שניות — זה עוד לפני ההרחבה לרשומות המקושרות, לא?

הסוכן

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

[…] טוב שלחצת — והתשובה מתהפכת.

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

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

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

שלושה דברים ששום ריפוזיטורי לא יודע

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

אני

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

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

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

אני

רגע, ההגבלה היא הבעיה. רוב המסכים בשוק המרכזי שלנו הם 1280 פיקסלים ומעלה.

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

אני

רגע, נראה לי שמתחילים להיות לנו יותר מדי אירועים לנהל. אנחנו באמת צריכים את כולם?

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

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

רדיוס הנזק

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

אני

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

הסוכן

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

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

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

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

ועכשיו איפה הסקירה שלי נכשלה

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

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

ואז הסוכן אמר את הדבר שמטריד אותי מאז:

הסוכן

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

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

אז למה לא תפסתי?

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

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

לתת למכונה את החצי של המכונה

הבדיקה שהייתה תופסת את זה מכנית עד כדי מבוכה:

הפרומפט שהיה חוסך שישה שבועות

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

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

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

וגם אני טועה, ובקביעות

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

אני

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

הסוכן אבחן סיבה סבירה תוך דקות, אישר חזרה לאחור כדי לשחרר אותי, ולקח אחריות בכתב. ואז:

אני

רגע, התיאור שלי היה שגוי. תן לי לבדוק שוב.

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

הסוכן

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

העבודה שבאמת נשארה לי

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

מה שאני מביא

ולא נמצא בשום ריפוזיטורי

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

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

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