צוות פיתוח בינוני העלה יותר ממאה סטוריז ל-Jira בתוך שבוע. AI כתב את כולם. אף אחד לא קרא אותם.
הסטוריז נראו בסדר גמור. אורך נכון, כותרות נכונות, ולכל אחד מהם היה מקטע של acceptance criteria. ואז QA פתח את הטיקט הראשון ולא הצליח לגזור ממנו בדיקה. גרומינג הפך לחדר שלם של אנשים שקוראים מסך בשקט. הטיקטים לא היו שגויים בדיוק. הם היו כאלה שאי אפשר להפריך, וזה גרוע יותר, כי שגוי מישהו תופס.
מה שחסר שם לא היה פרומפט טוב יותר. מה שחסר היה קורא. משהו שפותח את הטיוטה, מעמיד אותה מול סטנדרט שמישהו טרח לכתוב, ומחזיר אותה עם הסיבה כשהיא לא עומדת בו.
לצורה הזו יש שלושה חלקים, וכל השלושה נמצאים היום ב-Routines: בדיקה שיושבת על החיבור בין שני שלבים, ניסיון חוזר שנושא את הערת הביקורת בחזרה לתוך הפרומפט, ו-trace שבו אפשר לקרוא כל ניסיון שהסוכן עשה בדרך.
שני שלבים וחיבור אחד. התווית על החיבור היא הסטנדרט שהטיוטה צריכה לעבור, והתג שמתחתיה הוא מספר הניסיונות החוזרים שהכותב מקבל.
הבדיקה יושבת על החיבור, לא בתוך הפרומפט
על קנבס ה-Flows, כל חיבור בין שני שלבים יכול לשאת בדיקה כתובה בשפה חופשית. האפליקציה ממסגרת אותה כ-״Only continue when...״, וה-flow שלמעלה משתמש באמת המידה הזו:
Only if the story has testable acceptance criteria, names its dependencies and bounds its scope
שלושה דברים ראויים לתשומת לב במקום שבו המשפט הזה יושב.
הוא נשפט בקריאה נפרדת למודל ולא באותה קריאה שכתבה את הטיוטה, והקריאה הזו מחזירה פסיקה משלה והערת ביקורת כתובה משלה. ההפרדה הזו היא כל העניין. מודל שמתבקש לכתוב סטורי ואז לתת ציון לסטורי שהוא בדיוק כתב הוא לא קורא עצמאי. קריאה שנייה, ששופטת את הטיוטה הגמורה מול סטנדרט שמישהו התחייב אליו מראש, קרובה הרבה יותר לכזה.
הוא קורא את הטיוטה, לא תקציר שלה. העורך כותב את המגבלה באותה נשימה: ״The check reads the first ~12,000 characters of the previous step's result. When it can't tell, the setting below decides.״
והוא שומר על החיבור. מעבר זורם הלאה לשלב הבא. נפילה לא. השלב של Jira לא רואה לעולם סטורי שאמת המידה פסלה.
כל מה שנוגע ללולאה נמצא בחלונית אחת: הסטנדרט, מה קורה בנפילה, מה קורה בפסיקה לא ברורה, וכמה ניסיונות חוזרים השלב מקבל.
מה בדיוק חוזר לכותב בניסיון החוזר
״ניסיון חוזר עם משוב״ הייתה הבטחה חלשה אם המשוב היה מעורפל. הוא לא מעורפל, ואפשר לקרוא אותו.
כשהבדיקה נופלת נפילה ברורה והחיבור מוגדר ל-״Retry the step with feedback״, שלב הכתיבה רץ שוב כשהערת הביקורת נכנסת לפרומפט שלו תחת כותרת קבועה, ### Reviewer feedback from the previous attempt, ואחריה הוראה להתייחס למשוב ולבצע את המשימה מחדש, ואז טקסט הבדיקה והערת הביקורת עצמה.
כך זה נראה בניסיון השני של ההרצה שלמעלה, מצוטט מתוך תמונת הפרומפט שה-trace שמר:
Your previous attempt did not pass the automated check. Address this feedback, then redo the task:
- Check: Only if the story has testable acceptance criteria, names its dependencies and bounds its scope Feedback: The acceptance criteria are not testable: "works well on mobile" cannot be checked. Name the breakpoints and the expected behaviour at each.
זו הערת code review לכל דבר. היא מצביעה על השורה הבעייתית, אומרת למה היא בעייתית, ואומרת מה כן היה פותר אותה. הניסיון השני חזר טוב יותר ועדיין לא עבר, כי הוא לא ציין את התלות במיגרציה של ה-API של החיוב וה-scope שלו עדיין כיסה שני מסכים. הניסיון השלישי ציין את שניהם ועבר.
הפרומפט שהניסיון השני קיבל, נשמר יחד עם ההרצה: הערת הביקורת תחת כותרת אחת, הבקשה של ההרצה תחת הכותרת שאחריה. לא תיאור של מה שהניסיון החוזר עשה, אלא הפרומפט עצמו.
היכולת לקרוא את הפרומפט הזה היא ההבדל בין סוכן שאתם מפקחים עליו לבין סוכן שאתם מקווים לגביו. כשלולאה מוציאה משהו מוזר, השאלה תמיד היא איזה ניסיון סטה ומה בדיוק אמרו לו. ה-trace עונה על זה בלי לנחש.
התקציב, ומה קורה כשהוא נגמר
לכל חיבור יש תקציב ניסיונות חוזרים משלו, שנקבע במונה ״How many retries״, והאפליקציה מקבלת בין אחד לחמישה. כל ניסיון חוזר הוא הרצה מלאה של השלב מחדש, וזה בדיוק מה שהעורך אומר ממש מתחת למונה: כל ניסיון מריץ את השלב מחדש ומוציא טוקנים.
כשהתקציב נגמר, הענף נעצר, וכדאי לזהות ב-trace בדיוק איך זה נראה. שלב הכתיבה עצמו מסיים כרגיל. מה שנעצר הוא החיבור: השלב הבא מסומן ״התנאי לא התקיים״ ונושא את הסיבה כשמספר הניסיונות מופיע לפניה, בצורה ״Stopped after 4 attempts:״ ואחריה הערת הביקורת שפסלה את הטיוטה האחרונה. המספר הזה סופר ניסיונות ולא ניסיונות חוזרים, ולכן תקציב של שלושה ניסיונות חוזרים מוצג כארבעה. שום דבר לא ממשיך הלאה, וסיכום ההרצה סופר את השלב הזה כשלב שדולג ולא כשלב שנכשל. זו ההתנהגות שרוצים משער. לולאה שהייתה מוותרת ומעבירה בכל זאת את הטיוטה האחרונה הייתה גרועה יותר מאפס בדיקות, כי הייתה לכם הרצה ירוקה וטיקט גרוע.
מקרה אחד במכוון לא מנסה שוב. אם הבדיקה חוזרת לא ברורה, לא קריאה או עם שגיאה, ההגדרה הנפרדת באותה חלונית מכריעה, תיבת הסימון ״If the check can't decide, stop here״. רק נפילה ברורה מוציאה ניסיון חוזר מהתקציב. פסיקה מעורפלת שהייתה נכנסת ללולאה הייתה מרוקנת את כל התקציב בלי לומר לכם דבר.
כותב אחד, בקשה אחרת בכל הרצה
flow עם בדיקות הוא עדיין flow קבוע. אם צריך לערוך את ההוראה של שלב הכתיבה לפני כל טיקט, רק העברתם את העבודה למקום אחר במקום להיפטר ממנה.
לכן הבקשה נוסעת עם ההרצה. לכל flow יש מתג ״Ask for input when I run this״ ורמז ״What to ask for״, והוא כבוי עד שמדליקים אותו. כשהוא דלוק, לחיצה על Run פותחת חלון בשם ״Input for this run״, שבו כותבים את הבקשה של אותה הרצה ולוחצים Run.
מדליקים את השאלה, וכותבים את הטקסט שהחלון יציג לכם.
flow כותב אחד וגנרי, בקשה אחרת בכל פעם. אף אחד לא עורך את ה-flow כדי לכתוב טיקט אחר.
האפליקציה מסבירה לאן הטקסט הולך: ״This goes to the steps that start the flow, and it is saved with the run so you can see it later.״ הוא נמסר לשלבים שאין להם חיבור נכנס, נכתב כמרקדאון מתויג מעל ההוראה שלהם עצמם, ונשמר על ההרצה עצמה, כך שהרצה שתפתחו בעוד שלושה שבועות עדיין מראה מה ביקשו ממנה.
הרצות מתוזמנות נמצאות במכוון מחוץ למנגנון הזה. בלשון האפליקציה: ״Scheduled runs never ask, and they never reuse an earlier answer.״ תזמון שהיה פותח חלון ב-8 בבוקר וממתין הוא תזמון שבור, ותזמון ששולף בשקט את הבקשה של יום שלישי שעבר גרוע ממנו.
שתי היכולות מתחברות זו לזו. כששלב עם בדיקה מנסה שוב, האפליקציה מרכיבה את פרומפט הניסיון החוזר משני החלקים: הערת הביקורת תחת כותרת משלה, אחריה הבקשה של ההרצה תחת כותרת משלה, ואחריהן ההוראה הבסיסית של השלב. תמונת הפרומפט שהופיעה קודם במאמר מציגה את שני הראשונים בדיוק בסדר הזה, כותרת הביקורת ואחריה כותרת ה-Run input. הניסיון השלישי עדיין כותב על הדבר שביקשתם בניסיון הראשון.
כל ניסיון נשאר מתועד
ה-trace הוא המקום שבו מייסד באמת מרוויח מהמנגנון הזה, כי הוא הופך את ״ה-AI כתב את זה״ למשהו שאפשר לבקר בדיעבד.
פותחים הרצה שהסתיימה, וה-trace מציג את הכותרת של ההרצה, את הבקשה שהיא קיבלה, וכל שלב עם הסטטוס שלו. שלב שנכנס ללולאה נושא תג ניסיונות, והחלונית מקבצת את העבודה לפי ניסיון: ״Attempt 1 of 3״, ״Attempt 2 of 3״, כשלכל אחד מהם הפרומפט המורכב מאחורי ״Show the prompt״, התוצאה מאחורי ״Show result״, והפסיקה והערת הביקורת שהבדיקה החזירה.
הרצה אחרת מזו שבחלון שלמעלה, שמורה בשלמותה: הבקשה שקיבלה, שני הניסיונות שנפלו, והערת הביקורת שהולידה כל כתיבה מחדש.
השלב האחרון מספר לכם את החצי השני. השלב של Jira מתעד שהוא עבד מהתוצאה של שלב הכתיבה, מציג את התנאי שהיה צריך לעבור בדרך פנימה יחד עם הפסיקה שאישרה אותו, ואז את התוצאה שהוא הפיק.
הטיקט שנוצר, והפסיקה שהקנתה לו את הזכות להיווצר. ל-Routines יש connector ל-Jira, ולכן השלב האחרון הוא טיקט אמיתי ולא טיוטה בקובץ טקסט.
טיקט בבורד שיש מאחוריו הרצה הוא אובייקט אחר מטיקט שמישהו ייצר והדביק. אם סטורי מתגלה כזבל אחרי שבועיים, אמת המידה שהעבירה אותו מתועדת, ומכאן שאפשר לתקן את אמת המידה. זו הלולאה שבאמת מצטברת.
כמה זה עולה, ואיפה זה רץ
בדיקות אינן חינם והאפליקציה לא מעמידה פנים אחרת. כל ניסיון הוא קריאה למודל, וכך גם כל בדיקה. ה-trace מתמחר את הבדיקות בשורה נפרדת, ברמת ההרצה וברמת כל שלב, ובהרצה בת שני השלבים שלמעלה, עם שלושה ניסיונות בשלב הכתיבה, השורה הזו מציגה $0.0027.
מי משלם על הטוקנים האלה הוא הגדרה עם שני מצבים, שמופיעה באפליקציה תחת ״מאיפה מגיעה הבינה״. במצב ״המפתח שלי״ הטיוטות והבדיקות עוברות ישירות מה-Mac שלכם אל השירות שחיברתם, ו-Routines לא גובה עליהן דבר. החיבור הזה יכול להיות מנוי ChatGPT או Claude שהתחברתם אליו, Claude Code, או מפתח API של Anthropic או OpenRouter. במצב ״הבינה של Routines״, ברירת המחדל לחשבון שאין לו מפתח משלו, הן עוברות במקום זאת דרך השרתים של Routines, וכל ניסיון וכל בדיקה משולמים מהיתרה שלכם ב-Routines.
כדאי לדייק איפה כל חלק יושב. ה-flow עצמו לא מסונכרן לשום מקום, בלשון האפליקציה עצמה בכותרת התחתונה של הקנבס: ״Flows run on this Mac only. They are not synced to your other devices.״ הגרף, התזמון ושורות ההרצה נשארים על המכונה הזו. לא מעט בכל זאת נוסע, וה-flow הזה הוא דוגמה טובה לכך. כל ניסיון כתיבה וכל בדיקה הם בקשה לספק שחיברתם, ולכן טיוטות והערות ביקורת מגיעות לספק הזה בדיוק כמו כל פרומפט שאתם מקלידים, והשלב האחרון קיים בדיוק כדי לשלוח את הסטורי הגמור ל-Atlassian. Cloud Sync and Backup כבוי כברירת מחדל; אם תדליקו אותו, כל תוצאה של רוטינה, כולל הטיוטה של כל ניסיון, מועתקת לחשבון Routines שלכם כדי שהמכשירים שלכם יחלקו אותה.
אם כבר בניתם אוטומציה של טיקטים בכלי אורקסטרציה, ההשוואה בין Routines ל-n8n עוברת על המקומות שבהם גרף נודים בדפדפן הוא התשובה הנכונה, ועל אלה שבהם אפליקציית Mac שכבר מחזיקה את החשבונות שלכם היא הנכונה.
איך מקימים אחד כזה
הגרסה הקטנה והשימושית ביותר היא שני שלבים וחיבור אחד.
- הוסיפו את הרוטינה שכותבת את הסטורי כשלב ראשון, ואת הרוטינה שדוחפת ל-Jira כשלב שני. את השני מטפל ה-connector של Jira. הדליקו בהגדרות שלו את ״Allow writes (create & update issues)״, כי חיבור Jira טרי הוא לקריאה בלבד עד שתעשו זאת.
- לחצו על החיבור ביניהם וכתבו את הסטנדרט תחת ״Only continue when...״. כתבו אותו כמו שהייתם מתדרכים מבקר קפדן. אמת המידה שבמאמר הזה היא משפט אחד עם שלוש דרישות, ומשפט אחד מספיק כדי להתחיל.
- הגדירו את ההתנהגות בנפילה ל-״Retry the step with feedback״ ואת מספר הניסיונות לשניים או שלושה. השאירו את ״If the check can't decide, stop here״ מסומן.
- הדליקו את ״Ask for input when I run this״ וכתבו את הרמז שאתם בעצמכם תקראו בעוד חודש, משהו כמו ״Describe the story to write״.
- הריצו פעם אחת ופתחו את ה-trace. קראו את הניסיון הראשון ואת הערת הביקורת שהוא חטף. אם הערת הביקורת שגויה, אמת המידה שגויה, וזה תיקון של שורה אחת.
אם אתם רוצים גם את הכיוון ההפוך, לקרוא מתוך Jira ולא לכתוב אליו, מתכון סיכום Jira היומי הוא רוטינה מוכנה שמדווחת מה זז אתמול.
Routines היא הורדה חינמית ל-macOS עם תקופת ניסיון של שבעה ימים, ולולאות הביקורת שוחררו בגרסה v0.94.0.
שאלות נפוצות
האם סוכן AI יכול לבדוק את הטיקטים שהוא עצמו כתב לפני שהם נוצרים ב-Jira?
כן, בתנאי שהבדיקה היא שלב נפרד ולא עוד שורה באותו פרומפט. ב-Routines כל חיבור בין שני שלבים על קנבס ה-Flows יכול לשאת בדיקה כתובה בשפה חופשית, שהאפליקציה ממסגרת כ-״Only continue when...״. הבדיקה היא קריאה נפרדת למודל, עם פסיקה משלה והערת ביקורת כתובה משלה, והתוצאה של השלב הקודם מגיעה לשלב הבא רק כשהבדיקה עוברת. ב-flow שבמאמר הזה, החיבור בין ״Draft Jira Story״ ל-״Push to Jira״ נושא את אמת המידה ״Only if the story has testable acceptance criteria, names its dependencies and bounds its scope״. טיוטה שנופלת בה לא מגיעה בכלל לשלב של Jira.
מה הבדיקה באמת קוראת?
את התוצאה של השלב שהיא תלויה בו. האפליקציה כותבת את המגבלה בעורך הבדיקה עצמו: ״The check reads the first ~12,000 characters of the previous step's result. When it can't tell, the setting below decides.״ כלומר אמת המידה נשפטת מול הטיוטה עצמה ולא מול תקציר שלה, ותוצאה ארוכה במיוחד נשפטת לפי הפתיחה שלה ולא לפי הסוף.
כמה פעמים הוא ינסה שוב שלב שנפל?
אתם קובעים את זה לכל חיבור בנפרד במונה ״How many retries״, והאפליקציה מקבלת בין ניסיון חוזר אחד לחמישה. כשהבדיקה נופלת נפילה ברורה והחיבור מוגדר ל-״Retry the step with feedback״, שלב המקור רץ שוב כשהערת הביקורת נוספת לפרומפט שלו. כשתקציב הניסיונות נגמר הענף נעצר, אבל לא בכך שהשלב שנכנס ללולאה מסומן כנכשל. השלב הזה מסיים, ומה שנעצר הוא החיבור: השלב הבא מסומן ״התנאי לא התקיים״ ונושא את הסיבה כשמספר הניסיונות לפניה, למשל ״Stopped after 4 attempts״, שהם הניסיון הראשון ועוד תקציב של שלושה ניסיונות חוזרים. התוצאה שלא אושרה לא מגיעה לשלב הבא, וסיכום ההרצה סופר את השלב הזה כשלב שדולג ולא כשלב שנכשל.
מה קורה אם הבדיקה לא מצליחה להכריע?
היא לא מנסה שוב. פסיקה שהאפליקציה לא מצליחה לקרוא כמעבר ברור או כנפילה ברורה מטופלת על ידי הגדרה נפרדת באותו עורך, תיבת הסימון ״If the check can't decide, stop here״. רק נפילה ברורה מוציאה ניסיון חוזר מהתקציב. ההפרדה הזו חשובה בעיקר בגלל העלות, כי בדיקה מעורפלת שהייתה נכנסת ללולאה הייתה שורפת את כל התקציב על כלום.
אפשר לתת לאותו flow בקשה אחרת בכל הרצה?
כן. לכל flow יש מתג ״Ask for input when I run this״ ולצידו רמז ״What to ask for״, והוא כבוי עד שמדליקים אותו. כשהוא דלוק, לחיצה על Run פותחת חלון ״Input for this run״ שבו כותבים את הבקשה של אותה הרצה. האפליקציה מסבירה לאן זה הולך: ״This goes to the steps that start the flow, and it is saved with the run so you can see it later.״ flow כותב אחד ויחיד יכול לשרת כל בקשת טיקט, כי הבקשה נוסעת עם ההרצה במקום להיערך לתוך ה-flow. הרצות מתוזמנות מוחרגות בכוונה, בלשון האפליקציה: ״Scheduled runs never ask, and they never reuse an earlier answer.״
כמה עולה להריץ flow עם בדיקות?
יותר מ-flow בלי בדיקות, והאפליקציה אומרת את זה בדיוק במקום שבו מגדירים את הלולאה: כל ניסיון מריץ את השלב מחדש ומוציא טוקנים. כל ניסיון הוא קריאה אמיתית למודל, וכך גם כל בדיקה. ה-trace מתמחר את הבדיקות בשורה נפרדת, ברמת ההרצה וברמת כל שלב. בהרצה בת שני השלבים שמופיעה במאמר, עם שלושה ניסיונות בשלב הכתיבה, השורה הזו מציגה $0.0027. מי משלם אותה תלוי באיזה משני המצבים תחת ״מאיפה מגיעה הבינה״ אתם נמצאים. במצב ״המפתח שלי״ הניסיונות והבדיקות עוברים ישירות מה-Mac שלכם אל השירות שחיברתם, מנוי ChatGPT או Claude, Claude Code, או מפתח API של Anthropic או OpenRouter, ו-Routines לא גובה עליהם דבר. במצב ״הבינה של Routines״, ברירת המחדל לחשבון שאין לו מפתח משלו, הם עוברים במקום זאת דרך השרתים של Routines, וכל ניסיון וכל בדיקה משולמים מהיתרה שלכם ב-Routines.
ה-flow רץ על ה-Mac שלי?
ה-flow כן, והוא לא מסונכרן. האפליקציה מפורשת בכותרת התחתונה של הקנבס: ״Flows run on this Mac only. They are not synced to your other devices.״ הגרף, התזמון ושורות ההרצה נשארים על המכונה הזו. עבודה כן יוצאת ממנה. כל ניסיון כתיבה וכל בדיקה הם בקשה לספק ה-AI שחיברתם, ולכן הטיוטות והערות הביקורת מגיעות לספק הזה בדיוק כמו כל פרומפט אחר שאתם שולחים אליו, ושלב שתפקידו למסור משהו החוצה, למשל יצירת הטיקט ב-Jira בסוף ה-flow הזה, מגיע גם הוא לשירות הזה. Cloud Sync and Backup כבוי כברירת מחדל; אם תדליקו אותו, כל תוצאה של רוטינה, כולל הטיוטה של כל ניסיון, מועתקת לחשבון Routines שלכם כדי שהמכשירים שלכם יחלקו אותה.