נכתב על ידי פרית'ווי רג'אסקרן (Prithvi Rajasekaran), חבר בצוות ה-Labs שלנו.
במהלך החודשים האחרונים עבדתי על שתי בעיות קשורות: לגרום ל-Claude לייצר עיצובי פרונטאנד (Frontend) באיכות גבוהה, ולגרום לו לבנות יישומים שלמים ללא התערבות אנושית. עבודה זו החלה ממאמצים מוקדמים סביב יכולת עיצוב הפרונטאנד של Claude Code ו-ארכיטקטורת הריסון (harness) לסוכני קידוד ארוכי טווח, שם עמיתיי ואני הצלחנו לשפר את ביצועי Claude הרבה מעבר לבסיס באמצעות הנדסת פרומפטים ועיצוב ארכיטקטורת הריסון – אך שתי הגישות הגיעו בסופו של דבר לתקרה.
כדי לפרוץ את המגבלה, חיפשתי גישות חדשניות בהנדסת AI שיעבדו על פני שני תחומים שונים למדי: האחד מוגדר על ידי טעם סובייקטיבי, והשני על ידי נכונות ושימושיות ניתנות לאימות. בהשראת רשתות יריבות יוצרות (GANs), עיצבתי מבנה מרובה סוכנים עם סוכן יוצר (generator) וסוכן מעריך (evaluator). בניית מעריך שידרג תוצאות באופן אמין – ועם 'טעם' – דרשה תחילה פיתוח סט קריטריונים שיכול להפוך שיפוטים סובייקטיביים כמו 'האם העיצוב הזה טוב?' למונחים קונקרטיים וניתנים לדירוג.
לאחר מכן, יישמתי טכניקות אלה על קידוד אוטונומי ארוך טווח, ולקחתי שתי תובנות מעבודת הריסון המוקדמת שלנו: פירוק הבנייה לנתחים ניתנים לטיפול, ושימוש ב-Artifacts מובנים להעברת הקשר בין סשנים. התוצאה הסופית הייתה ארכיטקטורת שלושה סוכנים – מתכנן, יוצר ומעריך – שיצרה יישומי Full-Stack עשירים על פני סשנים של קידוד אוטונומי שנמשכו מספר שעות.
מדוע יישומים נאיביים לא מספיקים
הראינו בעבר כי לעיצוב ארכיטקטורת ריסון יש השפעה מהותית על האפקטיביות של קידוד סוכני ארוך טווח. בניסוי מוקדם יותר, השתמשנו בסוכן אתחול כדי לפרק מפרט מוצר לרשימת משימות, ובסוכן קידוד שיישם את המשימות תכונה אחת בכל פעם לפני שהעביר Artifacts כדי לשמר הקשר בין סשנים. קהילת המפתחים הרחבה יותר הגיעה לתובנות דומות, עם גישות כמו שיטת "Ralph Wiggum" המשתמשת ב-hooks או סקריפטים כדי לשמור סוכנים במחזורי איטרציה רציפים.
אך חלק מהבעיות נותרו עקביות. במשימות מורכבות יותר, הסוכן עדיין נוטה לסטות מהמסלול לאורך זמן. בעת פירוק הבעיה, הבחנו בשני מצבי כשל נפוצים אצל סוכנים המבצעים סוגים אלה של משימות.
הראשונה היא שמודלים נוטים לאבד קוהרנטיות במשימות ארוכות ככל שחלון ההקשר מתמלא (ראו את הפוסט שלנו על הנדסת הקשר). חלק מהמודלים מציגים גם "חרדת הקשר", שבה הם מתחילים לסיים עבודה בטרם עת כשהם מתקרבים למה שהם מאמינים שהוא מגבלת ההקשר שלהם. איפוס הקשרים – ניקוי חלון ההקשר לחלוטין והפעלת סוכן חדש, בשילוב עם העברה מובנית שנושאת את מצב הסוכן הקודם והצעדים הבאים – מטפל בשתי הבעיות הללו.
זה שונה מ'דחיסה' (compaction), שבה חלקים קודמים של השיחה מסוכמים במקום כך שאותו סוכן יכול להמשיך לעבוד על היסטוריה מקוצרת. בעוד שדחיסה שומרת על המשכיות, היא לא מספקת לסוכן דף נקי, מה שאומר שחרדת הקשר עדיין יכולה להתמיד. איפוס מספק דף נקי, במחיר של צורך ב-Artifact העברה עם מספיק מידע כדי שהסוכן הבא יוכל להמשיך את העבודה בצורה נקייה. בבדיקות המוקדמות שלנו, מצאנו ש-Claude Sonnet 4.5 הציג חרדת הקשר בעוצמה מספקת עד כדי כך שדחיסה לבדה לא הספיקה כדי לאפשר ביצועי משימות ארוכות חזקים, ולכן איפוס הקשרים הפך חיוני לעיצוב הריסון. זה פותר את בעיית הליבה, אך מוסיף מורכבות תזמור, תקורה של טוקנים וזמן אחזור לכל הרצת ריסון.
בעיה שנייה, שטרם התמודדנו איתה, היא הערכה עצמית. כאשר מתבקשים להעריך עבודה שהפיקו, סוכנים נוטים להגיב בשבחים בוטחים לעבודה – גם כאשר, למתבונן אנושי, האיכות בינונית בעליל. בעיה זו בולטת במיוחד במשימות סובייקטיביות כמו עיצוב, שבהן אין בדיקה בינארית המקבילה לבדיקת תוכנה ניתנת לאימות. האם פריסה (layout) מרגישה מלוטשת או גנרית זו שאלה של שיקול דעת, וסוכנים נוטים באופן אמין לכיוון החיובי בעת דירוג עבודתם שלהם.
עם זאת, גם במשימות שיש להן תוצאות ניתנות לאימות, סוכנים עדיין מפגינים לעיתים שיקול דעת לקוי המעכב את ביצועיהם בעת השלמת המשימה. הפרדת הסוכן המבצע את העבודה מהסוכן השופט אותה מתגלה כמנוף חזק לטיפול בבעיה זו. ההפרדה אינה מבטלת מיד את הסלחנות הזו בפני עצמה; המעריך הוא עדיין LLM הנוטה להיות נדיב כלפי פלטים שנוצרו על ידי LLM. אבל כוונון עדין של מעריך עצמאי להיות סקפטי מתברר כניתן לטיפול הרבה יותר מאשר לגרום ליוצר להיות ביקורתי כלפי עבודתו שלו, וברגע שקיים משוב חיצוני כזה, ליוצר יש משהו קונקרטי להתבסס עליו לצורך איטרציה.
עיצוב פרונטאנד: הפיכת איכות סובייקטיבית לניתנת לדירוג
התחלתי בניסויים על עיצוב פרונטאנד, שם בעיית ההערכה העצמית הייתה הבולטת ביותר. בהיעדר כל התערבות, Claude נוטה בדרך כלל לפריסות בטוחות וצפויות שהן פונקציונליות מבחינה טכנית אך לא בולטות חזותית.
שתי תובנות עיצבו את ארכיטקטורת הריסון שבניתי לעיצוב פרונטאנד. ראשית, בעוד שאסתטיקה אינה ניתנת לצמצום מלא לציון – וטעמים אישיים תמיד ישתנו – ניתן לשפר אותה באמצעות קריטריוני דירוג המקודדים עקרונות והעדפות עיצוביות. קשה לענות באופן עקבי על השאלה "האם העיצוב הזה יפה?", אך "האם זה תואם את העקרונות שלנו לעיצוב טוב?" נותן ל-Claude משהו קונקרטי לדרג לפיו. שנית, על ידי הפרדת יצירת הפרונטאנד מדירוג הפרונטאנד, אנו יכולים ליצור לולאת משוב שמניעה את היוצר לכיוון פלטים חזקים יותר.
עם זאת בחשבון, כתבתי ארבעה קריטריוני דירוג שנתתי גם לסוכני היוצר והמעריך בפרומפטים שלהם:
- איכות עיצוב: האם העיצוב מרגיש כיחידה קוהרנטית שלמה ולא כאוסף חלקים? עבודה חזקה כאן משמעותה שהצבעים, הטיפוגרפיה, הפריסה, התמונות ופרטים אחרים משתלבים ליצירת מצב רוח וזהות ייחודיים.
- מקוריות: האם יש עדות להחלטות מותאמות אישית, או שמדובר בפריסות תבניות, ברירות מחדל של ספריות ודפוסים שנוצרו על ידי AI? מעצב אנושי אמור לזהות בחירות יצירתיות מכוונות. רכיבי מלאי שלא שונו – או סימנים מובהקים של יצירת AI כמו מעברי צבע סגולים על כרטיסים לבנים – נכשלים כאן.
- אומנות: ביצוע טכני: היררכיית טיפוגרפיה, עקביות ריווח, הרמוניית צבעים, יחסי ניגודיות. זו בדיקת יכולת ולא בדיקת יצירתיות. רוב היישומים הסבירים עושים כאן עבודה טובה כברירת מחדל; כישלון משמעו יסודות שבורים.
- פונקציונליות: שימושיות בלתי תלויה באסתטיקה. האם משתמשים יכולים להבין מה הממשק עושה, למצוא פעולות עיקריות ולהשלים משימות ללא ניחושים?
הדגשתי איכות עיצוב ומקוריות על פני אומנות ופונקציונליות. Claude כבר קיבל ציונים טובים על אומנות ופונקציונליות כברירת מחדל, שכן היכולת הטכנית הנדרשת נטתה להגיע באופן טבעי למודל. אבל בעיצוב ובמקוריות, Claude לעיתים קרובות הפיק פלטים שהיו עדינים במקרה הטוב. הקריטריונים הענישו במפורש דפוסי "AI slop" גנריים במיוחד, ועל ידי מתן משקל רב יותר לעיצוב ומקוריות, זה דחף את המודל לכיוון לקיחת סיכונים אסתטיים יותר.
כיליתי את המעריך באמצעות דוגמאות בשיטת Few-shot עם פירוט ציונים מפורט. זה הבטיח ששיקול הדעת של המעריך תאם את העדפותיי, והפחית את סחיפת הציונים על פני איטרציות.
בניתי את הלולאה על ה- Claude Agent SDK, מה ששמר על התזמור פשוט. סוכן יוצר יצר תחילה פרונטאנד HTML/CSS/JS בהתבסס על פרומפט של משתמש. נתתי למעריך את ה-Playwright MCP, שאפשר לו לקיים אינטראקציה ישירה עם העמוד החי לפני דירוג כל קריטריון וכתיבת ביקורת מפורטת. בפועל, המעריך ניווט בעמוד בעצמו, צילם מסכים ולימד בקפידה את היישום לפני שהפיק את הערכתו. משוב זה זרם בחזרה ליוצר כקלט לאיטרציה הבאה. הרצתי 5 עד 15 איטרציות לכל יצירה, כאשר כל איטרציה דחפה בדרך כלל את היוצר לכיוון ייחודי יותר כשהוא הגיב לביקורת המעריך. מכיוון שהמעריך ניווט באופן פעיל בעמוד במקום לדרג צילום מסך סטטי, כל מחזור ארך זמן שעון קיר אמיתי. הרצות מלאות נמשכו עד ארבע שעות. כמו כן, הנחיתי את היוצר לקבל החלטה אסטרטגית לאחר כל הערכה: לחדד את הכיוון הנוכחי אם הציונים היו במגמת עלייה, או לעבור לאסתטיקה שונה לחלוטין אם הגישה לא עבדה.
בכל ההרצות, הערכות המעריך השתפרו על פני איטרציות לפני שהגיעו לרמה קבועה, עם מקום לשיפורים נוספים. חלק מהיצירות שוכללו באופן הדרגתי. אחרות עברו תפניות אסתטיות חדות בין איטרציות.
ניסוח הקריטריונים כיוון את היוצר בדרכים שלא ציפיתי להן באופן מלא. הכללת ביטויים כמו "העיצובים הטובים ביותר הם באיכות מוזיאונית" דחפה עיצובים להתכנסות ויזואלית מסוימת, מה שמצביע על כך שהפרומפטים הקשורים לקריטריונים עיצבו ישירות את אופי הפלט.
בעוד שהציונים השתפרו בדרך כלל על פני איטרציות, התבנית לא תמיד הייתה לינארית באופן נקי. יישומים מאוחרים יותר נטו להיות טובים יותר כשלם, אך ראיתי בקביעות מקרים שבהם העדפתי איטרציה אמצעית על פני האחרונה. מורכבות היישום נטתה גם היא לעלות לאורך סבבים, כאשר היוצר הגיע לפתרונות שאפתניים יותר בתגובה למשוב המעריך. גם באיטרציה הראשונה, הפלטים היו טובים באופן ניכר מנקודת בסיס ללא כל פרומפט, מה שמצביע על כך שהקריטריונים והשפה הקשורה אליהם כיוונו את המודל הרחק מברירות מחדל גנריות לפני שכל משוב מעריך הוביל לחידוד נוסף.
בדוגמה בולטת אחת, הנחיתי את המודל ליצור אתר אינטרנט למוזיאון אמנות הולנדי. באיטרציה התשיעית, הוא יצר דף נחיתה נקי, כהה-תמה, למוזיאון בדיוני. העמוד היה מלוטש ויזואלית אך במידה רבה תאם את ציפיותיי. לאחר מכן, במחזור העשירי, הוא ביטל לחלוטין את הגישה ודמיין מחדש את האתר כחוויה מרחבית: חדר תלת-ממדי עם רצפה משובצת שרונדרה בפרספקטיבת CSS, יצירות אמנות תלויות על הקירות במיקומים חופשיים, וניווט מבוסס פתחים בין חדרי גלריה במקום גלילה או לחיצה. זו הייתה קפיצה יצירתית שטרם ראיתי מיצירה חד-מעברית.
סקיילינג לקידוד Full-Stack
עם ממצאים אלה ביד, יישמתי את התבנית בהשראת GAN על פיתוח Full-Stack. לולאת היוצר-מעריך ממפה באופן טבעי למחזור חיי פיתוח התוכנה, שבו ביקורת קוד ובדיקות QA ממלאות את אותו תפקיד מבני כמו מעריך העיצוב.
הארכיטקטורה
בארכיטקטורת הריסון ארוכת הטווח הקודמת שלנו, פתרנו את נושא הקידוד הקוהרנטי מרובה הסשנים באמצעות סוכן אתחול, סוכן קידוד שעבד תכונה אחת בכל פעם, ואיפוס הקשרים בין סשנים. איפוס הקשרים היה צעד מרכזי: הריסון השתמש ב-Sonnet 4.5, שהציג את הנטייה ל"חרדת הקשר" שהוזכרה קודם לכן. יצירת ריסון שעבד היטב על פני איפוס הקשרים הייתה המפתח לשמירה על המודל במשימה. Opus 4.5 הסיר במידה רבה את ההתנהגות הזו בעצמו, ולכן יכולתי להשמיט לחלוטין את איפוס הקשרים מהריסון הזה. הסוכנים הופעלו כסשן רציף אחד על פני כל הבנייה, כאשר הדחיסה האוטומטית של ה-Claude Agent SDK טיפלה בגדילת ההקשר לאורך הדרך.
בעבודה זו בניתי על הבסיס מהריסון המקורי עם מערכת תלת-סוכנית, כאשר כל סוכן מטפל בפער ספציפי שצפיתי בהרצות קודמות. המערכת כללה את פרסונות הסוכנים הבאות:
מתכנן: ריסון ארוך הטווח הקודם שלנו דרש מהמשתמש לספק מפרט מפורט מראש. רציתי להפוך את השלב הזה לאוטומטי, ולכן יצרתי סוכן מתכנן שלקח פרומפט פשוט של 1-4 משפטים והרחיב אותו למפרט מוצר מלא. הנחיתי אותו להיות שאפתני לגבי היקף ולהישאר ממוקד בהקשר המוצר ובתכנון טכני ברמה גבוהה יותר, ולא ביישום טכני מפורט. דגש זה נבע מהחשש שאם המתכנן ינסה לציין פרטים טכניים גרעיניים מראש ויטעה במשהו, השגיאות במפרט יתגלגלו ליישום בהמשך. נראה היה חכם יותר להגביל את הסוכנים על התוצרים שיופקו ולתת להם להבין את הדרך תוך כדי עבודה. ביקשתי מהמתכנן גם למצוא הזדמנויות לשלב תכונות AI במפרטי המוצר. (ראו דוגמה בנספח למטה.)
יוצר: גישת ה"תכונה-אחת-בכל-פעם" מהריסון המוקדם יותר עבדה היטב לניהול היקף. יישמתי מודל דומה כאן, והנחיתי את היוצר לעבוד בספרינטים, לקחת תכונה אחת בכל פעם מהמפרט. כל ספרינט יישם את האפליקציה עם ערימת React, Vite, FastAPI ו-SQLite (מאוחר יותר PostgreSQL), והיוצר הונחה להעריך את עבודתו בעצמו בסיום כל ספרינט לפני העברה ל-QA. היה לו גם Git לבקרת גרסאות.
מעריך: יישומים מריסונים מוקדמים יותר נראו לעיתים קרובות מרשימים אך עדיין הכילו באגים אמיתיים כשניסית להשתמש בהם בפועל. כדי לתפוס אותם, המעריך השתמש ב-Playwright MCP כדי ללחוץ על היישום הפועל כפי שמשתמש היה עושה, לבדוק תכונות UI, נקודות קצה של API ומצבי בסיס נתונים. לאחר מכן, הוא דירג כל ספרינט הן מול הבאגים שמצא והן מול סט קריטריונים שדגם את ניסוי הפרונטאנד, מותאם כאן לכיסוי עומק מוצר, פונקציונליות, עיצוב ויזואלי ואיכות קוד. לכל קריטריון הייתה סף קשיח, ואם אחד מהם ירד מתחתיו, הספרינט נכשל והיוצר קיבל משוב מפורט על מה השתבש.
לפני כל ספרינט, היוצר והמעריך ניהלו משא ומתן על חוזה ספרינט: הסכימו על איך נראית "עבודה גמורה" עבור נתח העבודה הזה לפני כתיבת קוד כלשהו. זה היה קיים מכיוון שמפרט המוצר היה ברמה גבוהה במכוון, ורציתי שלב שיגשר על הפער בין סיפורי משתמשים ליישום שניתן לבדוק. היוצר הציע מה יבנה וכיצד יאומת ההצלחה, והמעריך סקר את ההצעה כדי לוודא שהיוצר בונה את הדבר הנכון. השניים עשו איטרציות עד שהסכימו.





