מה זה Loop engineering? הגדרה ומשמעות
הנדסת לולאות היא המעבר מכתיבת פרומפטים בודדים לתכנון מערכת בקרה לסוכני AI. למדו כיצד להגדיר טריגרים, גבולות גזרה, מנגנוני אימות ותקציב במקום להסתמך על הוראות טקסט.
מה המשמעות של הנדסת לולאות (Loop engineering)
הנדסת לולאות היא הפרקטיקה של תכנון המחזור החוזר שבו פועל סוכן AI: מה מעיר אותו, באילו משאבים הוא יכול לגעת, כיצד נבדק הפלט שלו, ומה עוצר אותו. הנדסת פרומפטים (Prompt engineering) מעצבת הודעה בודדת עבור מודל. הנדסת לולאות מעצבת את התהליך ששולח אלפי הודעות בזמן שאתם ישנים. יחידת העבודה עוברת מהפרומפט אל הלולאה.
הגרסה המקוצרת: אתם מפסיקים לכתוב הוראות ומתחילים לכתוב מערכת בקרה. הסוכן עדיין זקוק להוראות טובות, אך הן הופכות לרכיב אחד בתוך מחזור שרץ לפי לוח זמנים, עובד בתוך עותק מבודד של הקוד שלכם, מוכיח את התוצאה של עצמו באמצעות בדיקה, ומוותר כאשר התקציב נגמר.
מדוע המונח הופיע בשנת 2026
השם מתקבע בציבור ממש עכשיו. מאגר ה-GitHub cobusgreyling/loop-engineering עבר את רף 9,600 הכוכבים בתוך חודשיים מהופעתו הראשונה (נכון ליולי 2026) והציג כ-11,600 כוכבים ב-2026-10-27, תחת השורה "הפסק לתת הנחיות. תכנן את הלולאה. קבל ציון." ביולי 2026, קובץ ה-README שלו קיבץ את השינוי לשישה אבני בניין: תזמון, worktrees, מיומנויות, תוספים ומחברים, סוכני-משנה, וזיכרון עמיד שנשמר מחוץ לשיחה. ה-README הנוכחי כבר לא מכיל את הרשימה הזו (נבדק ב-2026-10-27), אך הוא עדיין שומר את מצב הלולאה בקובץ מחוץ לשיחה.
המאגר נותן קרדיט ל-Boris Cherny, המוביל את Claude Code ב-Anthropic, כאחד ממקורות ההשראה שלו. הציטוט המפורסם שלו הוא:
אני כבר לא נותן הנחיות (prompt) ל-Claude. יש לי לולאות שרצות ומנחות את Claude.
מאגר שני, AI-Builder-Club/skills, עומד על כ-1,300 כוכבים (נכון ל-2026-10-27) ומגדיר את שני התפקידים באופן ישיר: "codebase harness" שהופך מאגר לבטוח עבור סוכן להרצת בדיקות ופריסות, ו-"loop engineer" שבונה תהליכי עבודה שמתעוררים לפי טריגר, מבצעים את העבודה, וכותבים את מה שלמדו לקובץ משותף כדי שהלולאה הבאה תוכל לקרוא אותו.
אף אחד מהמאגרים לא המציא את הפרקטיקה הזו. כל מי שהריץ nightly build, כלי linter ב-continuous integration, או cron job שפותח כרטיס, כבר מכיר את המבנה. מה שחדש הוא שהעובד בתוך הלולאה הוא כעת לא-דטרמיניסטי, מה שמשנה את מה שהמערכת העוטפת צריכה לעשות.
ארבעת החלקים של לולאה
לכל לולאה תקינה יש ארבעה חלקים אלו, ולולאה שמדלגת על אחד מהם היא הלולאה שתעיר אתכם ב-3 לפנות בוקר.
- טריגר (Trigger). האירוע שמתחיל הרצה: טיימר, webhook, בקשת pull request חדשה, או התראה.
- גבולות (Boundary). הקבצים, פרטי הגישה (credentials) והרשת שהסוכן רשאי להגיע אליהם במהלך אותה הרצה.
- אימות (Verification). בדיקה עם קוד יציאה (exit code) הקובעת אם לשמור את פלט ההרצה או להשליך אותו.
- תקציב (Budget). מגבלת ה-token, הזמן והכסף שמסיימת הרצה, בין אם הצליחה ובין אם לא.
קראו את ארבעת הסעיפים הללו כשאילתות, ותקבלו סקירת תכנון עבור כל סוכן שאתם עומדים להשאיר רץ.
טריגר: מה מעיר את הסוכן
טיימר הוא הטריגר הפשוט ביותר, ובשרת Linux טיימר של systemd עדיף על cron למטרה זו, כיוון שהוא מתעד לוגים, מאפשר הגדרת מדיניות ניסיונות חוזרים, ואינו מפעיל עותק נוסף של יחידה שעדיין רצה. תכונה אחרונה זו מונעת את באג החפיפה הנפוץ ביותר בלולאות של סוכנים: שתי ריצות שעורכות את אותו ענף בו-זמנית.
תחילה, הקצו לסוכן משתמש ייעודי משלו. משתמש זה הוא חלק ממעטפת האבטחה, לכן הוא הבעלים של /srv/agent ותו לא:
sudo useradd --system --home-dir /srv/agent --shell /usr/sbin/nologin agent
sudo chown -R agent:agent /srv/agentלאחר מכן, צרו את יחידת השירות ב-/etc/systemd/system/agent-loop.service:
[Unit]
Description=Agent loop: triage open issues
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
User=agent
WorkingDirectory=/srv/agent/repo
ExecStart=/srv/agent/bin/loop.sh
TimeoutStartSec=1800ואת הטיימר ב-/etc/systemd/system/agent-loop.timer:
[Unit]
Description=Run the triage loop every 30 minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=30min
Unit=agent-loop.service
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable --now agent-loop.timer
systemctl list-timers agent-loop.timerהפקודה systemctl list-timers אמורה להציג עמודת NEXT עם זמן עתידי ועמודת LEFT המציגה ספירה לאחור. תוצאה ריקה משמעותה שהטיימר אינו מופעל, כיוון ש-enable ללא --now מתזמן אותו להפעלה הבאה בלבד. TimeoutStartSec=1800 חשוב יותר ממה שנראה לעין. שירות מסוג Type=oneshot נחשב כ"מתחיל" עד שהסקריפט שלו מסיים לרוץ, ו-systemd מבטל כברירת מחדל את מגבלת הזמן (timeout) עבור יחידות מסוג oneshot. ללא שורה זו, סוכן שנתקע בהמתנה לקלט יישאר במצב הפעלה (activating) לנצח, וכל פעימת טיימר עתידית תמצא אותו עדיין רץ ולא תפעיל דבר. עם השורה הזו, systemd מסיים את הריצה לאחר 30 דקות ומסמן אותה כנכשלה. אם תשנו בעתיד את היחידה ל-Type=simple כברירת מחדל, TimeoutStartSec לא יכסה יותר את הריצה עצמה, ו-RuntimeMaxSec= היא ההגדרה שתגביל אותה. קראו לוג של ריצה באמצעות journalctl -u agent-loop.service -n 50.
אם אתם מפעילים את הלולאה מתוך cron במקום זאת, הוסיפו מנגנון הגנה מפני חפיפה, כיוון ש-cron יפעיל בשמחה עותק שני:
*/30 * * * * /usr/bin/flock -n /tmp/agent-loop.lock /srv/agent/bin/loop.shהפקודה flock -n מסתיימת מיד עם סטטוס 1 כאשר ה-lock מוחזק, כך שהריצה השנייה נעלמת בשקט במקום להתחרות בראשונה. אותו מערך של systemd service ו-timer תקף לכל משימה ארוכת טווח בשרת, בין אם מדובר בסוכן ובין אם לא.
גבולות: הענקת עותק נפרד לכל הרצה
סוכן שעורך את עץ העבודה שלך הוא סוכן שעלול לאבד עבודה שלא בוצע לה commit. השימוש ב-Git worktrees פותר זאת בעלות נמוכה: כל הרצה מקבלת ספרייה משלה וענף (branch) משלה, תוך שיתוף מאגר אובייקטים יחיד.
cd /srv/agent/repo
git worktree add -b loop/triage-01 /srv/agent/work/triage-01 origin/main
git worktree listgit worktree list מדפיס שורה אחת לכל עץ עם הנתיב, ה-commit והענף שלו. בסיום ההרצה, git worktree remove /srv/agent/work/triage-01 מסיר את ה-worktree, אך רק אם הוא נקי. אם בעץ יש קבצים שלא נמצאים במעקב, קבצים במעקב שעברו שינוי, או submodules, Git יסרב לפעולה עד שתוסיף את --force. זו הסיבה שסקריפט ה-gate להלן כופה הסרה רק על הנתיב שבו ההרצה מסתיימת. git worktree prune מנקה רשומות שהספרייה שלהן נעלמה. לולאות מקביליות הופכות לבטוחות בשלב זה, כיוון ששני סוכנים על שני ענפים בשתי ספריות שונות אינם יכולים לדרוס זה את זה.
הגבול נוגע גם לפרטי הזדהות (credentials). לולאה שרצה ללא השגחה מחזיקה אסימונים (tokens) ארוכי טווח, וכל הרצה היא הזדמנות לדליפת אסימון לתוך לוג, commit או הקשר של מודל. הגבל את האסימון למאגר (repository) היחיד שהלולאה נוגעת בו, הרחק אותו מהסביבה שה-shell של הסוכן רואה במידת האפשר, וקרא את כיצד לשמור סודות מחוץ לסוכני AI לפני שאתה מעניק ללולאה גישת production. לקבלת חומת הגנה חזקה יותר, הרץ את כל הלולאה על מכונה וירטואלית זמנית שניתן להשמיד לאחר כל הרצה. הכלי שבו אתה משתמש קובע גם הוא חלק מהגבול עוד לפני כתיבת הקוד, לכן כדאי לקרוא את השוואה בין ה-sandbox המנוהל של Cowork לבין Claude Code על המכונה שלך לפני שתחליט כמה בידוד עליך לבנות בעצמך.
אימות: השער שהופך את הלולאה לבטוחה
זהו החלק שמבדיל בין לולאה לבין משימת cron שמקלידה פקודות. הפלט של הסוכן הוא הצעה בלבד. השער הוא שמחליט.
#!/usr/bin/env bash
set -euo pipefail
repo=/srv/agent/repo
branch="loop/$(date -u +%Y%m%dT%H%M%SZ)"
tree="/srv/agent/work/$(basename "$branch")"
cd "$repo"
git fetch --quiet origin
git worktree add -b "$branch" "$tree" origin/main
cd "$tree"
# the agent's own command runs here, in non-interactive mode
if ! npm test; then
echo "gate failed: discarding $branch" >&2
cd "$repo"
git worktree remove --force "$tree"
exit 1
fi
git push origin "$branch"
cd "$repo"
git worktree remove "$tree"set -euo pipefail מבצע עבודה ממשית בתוך הסקריפט הזה. ללא -e, כשל ב-git fetch יתעלם מהשגיאה וההרצה תמשיך מול origin/main מיושן. ללא -u, שגיאת הקלדה בשם של משתנה תתרחב למחרוזת ריקה, ופעולת הניקוי תרוץ על הנתיב הלא נכון במקום להיכשל באופן ברור. בשורה האחרונה אין --force בכוונה: אם ההרצה השאירה קבצים לא מתועדים או לא שמורים ב-tree, git יסרב למחוק אותו, ו--e יסיים את ההרצה עם שגיאה לאחר ה-push במקום למחוק בשקט עבודה שאף אחד לא שמר.
בלוק ה-if ! npm test הוא לב העניין. קוד היציאה של בדיקה שאתם כבר סומכים עליה, חבילת הבדיקות שלכם או בודק הטיפוסים, הוא שמחליט אם ה-branch יידחף (pushed) או יושמד. לולאה ללא שער מייצרת עבודה שאף אחד לא יספיק לעבור עליה, וזה גרוע יותר מחוסר עבודה. לולאה עם שער מייצרת branch שכבר עבר את אותו רף שכל branch של תורם אנושי חייב לעבור. שער ירוק לא מעיד על כמות הקוד שהסוכן שינה כדי להגיע לשם, לכן כדאי לשלב את הבדיקה עם הנחיה קבועה כמו הכלל שגורם לסוכן לבצע את השינוי הקטן ביותר שעובד, ששומרת על ה-diff קטן מספיק כדי שהסקירה שלו תישאר זולה.
בחרו שער שנכשל בכנות. חבילת בדיקות שעוברת על diff ריק מלמדת את הלולאה שאי-עשייה היא הצלחה. מאגרים עם בדיקות חלשות מקבלים לולאות חלשות, וזו הסיבה שהמאגרים המובילים מציבים את "הכנת בסיס הקוד לסוכנים" לפני "כתיבת הלולאה". אם אתם רוצים לדעת האם החבילה שלכם באמת תתפוס רגרסיה ולא רק תריץ את השורות, mutation testing היא הבדיקה שתענה על כך, ו-סוכן שמחזיר דוח עדות שניתן להרצה חוזרת במקום לבקש מכם לקרוא את ה-diff שלו הופך את התשובה הזו למשהו שתוכלו לאמת בעצמכם.
תקציב: מה עוצר הרצה
סוכן שמבצע ניסיונות חוזרים ללא הגבלה הוא סוכן שיוצר חשבונית ללא הגבלה. הגדירו לכל לולאה תקרה של זמן אמת, הנאכפת על ידי TimeoutStartSec לעיל; הגדירו מונה ניסיונות חוזרים בתוך הסקריפט שלכם; והגדירו תקרת הוצאות הנאכפת ברמת חשבון ספק הענן. לאחר מכן, תעדו את העלות של כל הרצה, כדי שתוכלו לזהות זליגה בלולאה לפני שהיא מופיעה בחשבונית. המדריך בקרת עלויות עבור VPS של סוכן הפועל ללא הפסקה מכסה את הצד החשבונאי, והמדריך ניהול ההקשר שסוכן נושא בין תורות מכסה את הגורם המשמעותי ביותר לעלות לכל הרצה, שכן לולאה שקוראת מחדש את אותו מאגר (repository) בכל 30 דקות משלמת על כך בכל 30 דקות.
עלות היא הסיבה לכך שלולאות בדרך כלל עדיפות על פני סשן אחד ארוך. הרצה שמתחילה מחדש, מבצעת משימה אחת ממוקדת ומסתיימת, שומרת על הקשר מצומצם. סשן שנותר פתוח במשך שמונה שעות נושא עמו כל טעות קודמת בהיסטוריה שלו, ומשלם על כל התמליל בכל תור.
התבניות שמאגרי הטרנדים מקודדים
מאגר ה-loop-engineering מפרט שמונה תבניות ייצור (נכון ל-2026-10-27), וכדאי לקרוא אותן כתפריט ולא כמניפסט. מיון יומי. לולאה דקה שרצה כ-GitHub Action ולא שומרת קובץ מצב. "בייביסיטר" ל-pull-request שעוקב אחר הערות סקירה ועונה עליהן. סורק continuous-integration שאוסף build-ים שנכשלו. סורק תלויות. מנסח changelog. ניקוי לאחר merge. מיון נושאים.
מה שמשותף להן הוא משימה צרה עם שער ברור. ל-"תקן את ה-build שנכשל" יש תנאי הצלחה שהמכונה יכולה לקרוא. ל-"שפר את בסיס הקוד" אין, ולכן הוא לעולם לא הופך ללולאה. הוא הופך לבלגן עם לוח זמנים.
הן גם חולקות תיעוד כתוב. שני המאגרים מוציאים את המצב מחוץ לשיחה לתוך קבצים במאגר: מה רץ, מה נמצא, מה הוחלט. הקובץ הזה הוא הזיכרון של הלולאה, וזו הסיבה שלולאה שנייה יכולה להתבסס על העבודה של הראשונה במקום לגלות אותה מחדש. זו גם הדרך לבצע ביקורת על סוכן בדיעבד, שכן ההקשר (context) של המודל נעלם ברגע שההרצה מסתיימת. תיאום בזמן אמת הוא ערוץ נפרד, ו-סשן Claude Code אחד יכול להעביר עבודה לאחר על אותה מכונה בזמן ששניהם עדיין רצים, אך שום דבר בחילופי המידע האלה לא שורד את הסשן, לכן הקובץ נשאר החלק שקוראים מאוחר יותר.
היכן לולאות נכשלות
הכשלים הם משעממים, והם חוזרים על עצמם בצוותים שונים.
- היעדר בקרה. הפלט מצטבר, איש אינו בוחן אותו, האמון מתערער, והלולאה מושבתת.
- חפיפה. שתי הרצות על אותו branch, או שני סוכנים באותו working tree, יוצרים התנגשויות שהסוכן מנסה לפתור בעצמו.
- סטייה שקטה. הלולאה ממשיכה לעבור בהצלחה כיוון שהבדיקה חלשה מכדי להיכשל.
- היקף בלתי מוגבל. טריגר שמופעל בכל commit במאגר עמוס הופך לבעיית עלויות בתוך יום אחד.
לכל אחד מהם יש פתרון זהה: צמצמו את המשימה, הדקו את הבדיקה, ונהלו לוג של ההרצה. אם אינכם יכולים לתאר את תנאי המעבר במשפט אחד, המשימה אינה מוכנה לאוטומציה.
תחילת עבודה ללא תשתית מורכבת
אין צורך ב־framework. שרת Linux קטן שפועל תמיד, מאגר git שחבילת הבדיקות שלו נכשלת כאשר היא אמורה להיכשל, טיימר אחד של systemd וסקריפט shell המכיל if יוצרים לולאה שלמה. זהו המקום שבו רוב האנשים צריכים להתחיל, כיוון ששאלות התכנון מקבלות מענה תוך כדי הרצת המערכת ולא על ידי בחירת כלי מורכב. ברגע שלולאה אחת יציבה, הרצת לולאה שנייה היא בעיקר עניין של טיימר נוסף ו־worktree נוסף. עיינו ב-איך להריץ סוכן AI לכתיבת קוד על גבי VPS עבור הגדרת הבסיס, וב-אפשרויות נוכחיות לסוכני AI באירוח עצמי אם ברצונכם להריץ את הסוכן עצמו על חומרה שבשליטתכם.
FAQ
האם הנדסת לולאות (loop engineering) שונה מהנדסת פרומפטים (prompt engineering)?
הנדסת פרומפטים מבצעת אופטימיזציה להודעה בודדת: ניסוח, דוגמאות ופורמט פלט. הנדסת לולאות מבצעת אופטימיזציה למחזור שסביב ההודעה: הטריגר שמפעיל את הריצה, ה-sandbox שבו היא פועלת, הבדיקה שמאשרת או דוחה את הפלט, והתקציב שמסיים אותה. עדיין נדרש פרומפט איכותי בתוך הלולאה. הפרומפט מפסיק להיות הדבר שאתם מכווננים מדי יום, כיוון שלשער (gate) ולטריגר יש השפעה גדולה יותר על התוצאה.
האם אני צריך framework כדי לבנות לולאת סוכן (agent loop)?
לא. טיימר של systemd, עץ עבודה (worktree) של git לכל ריצה, סקריפט shell שמסתיים בפקודת בדיקה, ומכסת הוצאות בחשבון הספק מכסים כל חלק בהגדרה. Frameworks מוסיפים ממשקי תזמון, פורמטים של זיכרון משותף וניתוב מרובה-סוכנים, שהם שימושיים ברגע שמריצים כמה לולאות. הם אינם תנאי סף עבור הלולאה הראשונה.
מהו harness של בסיס קוד (codebase harness)?
זהו אוסף הדברים המאפשרים לסוכן לעבוד במאגר (repository) ללא נוכחות אדם: הגדרה בפקודה אחת, בדיקות שרצות ללא אינטראקציה ונכשלות בקול רעש, linter, ודרך לפרוס או להציג שינוי בתצוגה מקדימה. המונח מגיע מאותו גל של מאגרים משנת 2026 כמו הנדסת לולאות. המבחן המעשי פשוט: אם תורם אנושי חדש לא יכול לעבור מ-clone לבדיקות ירוקות בפקודה אחת, גם סוכן לא יוכל.
איך אני מונע מלולאת סוכן לצבור חשבון גדול?
הגבילו אותה בשלושה מקומות. הגדירו TimeoutStartSec ביחידת systemd מסוג Type=oneshot כמו זו שלעיל, כך שריצה תקועה תסתיים (בשירות Type=simple המקבילה היא RuntimeMaxSec). הגבילו ניסיונות חוזרים בתוך הסקריפט במקום לבצע לולאה עד להצלחה. הגדירו מגבלת הוצאה קשיחה בחשבון ה-API, שכן זו התקרה היחידה שהסוכן לא יכול לעקוף באמצעות שכנוע. לאחר מכן, תעדו את העלות לכל ריצה, כיוון שלולאה שהעלות שלה מוכפלת היא בדרך כלל לולאה שהיקף העבודה שלה התרחב בשקט.
אילו משימות כדאי להפוך ללולאה תחילה?
בחרו משימה עם תנאי הצלחה שניתן לקריאה על ידי מכונה ורדיוס פגיעה קטן. תיקון build אדום, עדכון תלות ויצירה מחדש של changelog מתאימים כולם, כיוון שחבילת בדיקות או diff יכולים להוכיח את התוצאה. עבודה פתוחה כמו refactoring או עיצוב עדיין לא מתאימה, כיוון שאין שום דבר שהשער יכול לבדוק, ולולאה ללא שער היא דרך יקרה לייצר חוב סקירה (review debt).