איך לעדכן את AGENTS.md באופן אוטומטי בעזרת dox
קובץ AGENTS.md מיושן גורם לסוכני בינה מלאכותית לבצע פעולות שגויות על בסיס מידע לא רלוונטי. השתמשו בכלי dox כדי להפיק את התיעוד מתוך הקוד ולמנוע שגיאות קריטיות ב-build.
מדוע קובץ AGENTS.md שלכם הופך לשגוי לאחר שלושה שבועות
קובץ AGENTS.md מתיישן מכיוון שאין שום דבר שמקשר בינו לבין הקוד. אתם כותבים אותו פעם אחת, ידנית, ביום שבו המאגר נראה בצורה מסוימת. לאחר מכן מריץ הבדיקות משתנה, חבילה עוברת מיתוג מחדש, שירות נמחק, והקובץ עדיין מתאר את המצב של יוני. שום דבר לא נכשל, כי אף שלב ב-build לא קורא אותו.
הסוכן (agent) קורא את הקובץ ומאמין לו. זה החלק שעולה לכם ביוקר. מאגר ללא AGENTS.md גורם לסוכן תכנות לבחון את השטח לפני שהוא פועל. מאגר עם AGENTS.md שגוי גורם לו להפסיק לבדוק, כי כבר יש לו תשובה. הוא מריץ את הפקודה שציינתם בקובץ, ה-shell עונה Missing script: "test", וכעת הסוכן מתחיל לנחש. לעיתים קרובות הוא עורך את package.json כדי להוסיף את הסקריפט שהתיעוד שלכם הבטיח. הקובץ המיושן לא נכשל בשקט. הוא גרם לעריכה שלא רציתם.
dox הוא פתרון אחד לכך. זהו סט חוקים, שנכתב עבור הסוכן, שהופך את עדכון התיעוד לחלק מסיום העבודה, כך שהקובץ משתנה באותו commit שבו השתנה הקוד שהפך אותו לשגוי.
מהו dox ומה הוא אינו
dox הוא קובץ Markdown יחיד. המאגר נמצא ב-agent0ai/dox, הוא מופץ תחת רישיון MIT, ונכון ל-11 באוגוסט 2026, הפרויקט כולו הוא AGENTS.md בגודל 3906 בתים, הכולל קובץ README, קובץ LICENSE ושתי תמונות. אין חבילה להתקנה ואין סביבת זמן ריצה (runtime).
זה משמעותי, כיוון שהמילה "מחולל" (generator) מרמזת על תוכנית שמנתחת את הקוד שלכם. שום דבר לא מנתח את הקוד שלכם. dox הוא חוזה שסוכן הקידוד שלכם קורא: הסוכן שלכם הוא המחולל, ו-dox הוא סט ההוראות שמורה לו מתי לקרוא את התיעוד, מתי לשכתב אותו, ומהו המבנה של כל מסמך.
הקובץ מכיל עשרה סעיפים ושניים מהם מבצעים את העבודה. "קרא לפני עריכה" (Read Before Editing) מורה לסוכן לסרוק משורש המאגר ועד לכל נתיב שהוא מתכנן לשנות, ולקרוא כל קובץ AGENTS.md לאורך כל נתיב, בסשן הנוכחי, מבלי להסתמך על זיכרון. "עדכן לאחר עריכה" (Update After Editing) מורה לו שכל שינוי משמעותי מחייב מעבר DOX, כלומר שלב עדכון תיעוד שמתבצע לפני שהמשימה נחשבת כהושלמה. המעבר מעדכן את המסמך הקרוב ביותר שבבעלותו כאשר המטרה, המבנה, תהליך העבודה, ההרשאות או העדפות המשתמש השתנו.
שאר הקובץ עוסק במבנה. לקובץ AGENTS.md צאצא יש סדר סעיפים ברירת מחדל: מטרה, בעלות, חוזים מקומיים, הנחיות עבודה, אימות, ואינדקס DOX צאצאים. קובץ השורש מכיל חוקים כלל-פרויקטיים בתוספת אינדקס DOX צאצאים ברמה העליונה, וזו הדרך שבה סוכן מגלה את מסמכי הצאצאים. "סגירה" (Closeout) היא רשימת התיוג שהסוכן מריץ בסוף משימה: בדיקה חוזרת של הנתיבים ששונו מול השרשרת, עדכון המסמכים הקרובים ביותר שבבעלותו, רענון כל אינדקס מושפע, מחיקת סתירות, הרצת אימות קיים, ודיווח על אילו מסמכים הוא השאיר ללא שינוי במכוון.
קיבוע התיעוד (dox) ל-commit ספציפי, לא ל-main
במאגר אין תגיות או גרסאות (releases), לכן אין מספר גרסה שאפשר לקבע. במקום זאת, קבעו את ה-commit. הקובץ AGENTS.md הנוכחי הוא ב-commit מספר f34ec7ad1055d3393887e5a2670e8cb7320c9165, מתאריך 1 באוגוסט 2026.
mkdir -p .agent
curl -fsSL -o .agent/dox-f34ec7a.md \
https://raw.githubusercontent.com/agent0ai/dox/f34ec7ad1055d3393887e5a2670e8cb7320c9165/AGENTS.md
wc -c .agent/dox-f34ec7a.mdהפקודה wc -c אמורה להדפיס 3906. מספר שונה מעיד על כך שלא משכתם את הקובץ המתואר במדריך זה, לכן קראו אותו לפני שתסתמכו עליו. אם תזינו בטעות hash שגוי של commit, הדגל -f יגרום ל-curl לעצור עם curl: (22) The requested URL returned error: 404 ולא לכתוב תוכן, ו-wc -c ידפיס לאחר מכן 0. קובץ קטוע גרוע יותר מקובץ חסר, כיוון שהסוכן יפעל לפי חצי חוזה מבלי לדעת זאת.
cp .agent/dox-f34ec7a.md AGENTS.md
git add AGENTS.md .agent/dox-f34ec7a.md
git commit -m "Add DOX rules (agent0ai/dox @ f34ec7a)"הפקודה cp מיועדת למאגר שעדיין אין בו AGENTS.md. אם כבר קיים אצלכם קובץ כזה, אל תדרסו אותו. הציבו את מקטעי התיעוד מעל התוכן הקיים שלכם, שמרו על הכללים שלכם מתחת, וקראו את התוצאה פעם אחת מההתחלה ועד הסוף. שני מסמכים שסותרים זה את זה יגרמו לסוכן לפעול לפי השורה האחרונה שקרא.
לאחר מכן, בתוך המאגר, בקשו מהסוכן לבצע את הסבב הראשון. ה-README מספק את הניסוח המדויק:
Initialize DOX tree for this project now.הפקודה יוצרת את קובצי ה-AGENTS.md המשניים ואת האינדקסים שמפנים אליהם. בדקו מה היא ביצעה לפני שתסתמכו על התוצאות:
git status --short
find . -name AGENTS.md -not -path './.git/*' | sortכל קובץ שמופיע בפלט של find חייב להופיע באינדקס תיעוד משני (Child DOX Index) כלשהו מעליו. מסמך משני שאף אינדקס לא מציין הוא מסמך שהסוכן עלול להחמיץ, כיוון שהאינדקס הוא הדרך שלו למצוא מסמכים שאינם נמצאים ישירות בנתיב שבו הוא סורק.
מה dox יכול לראות, ומה הוא אינו יכול לדעת
הסוכן שבונה את העץ שלך קורא את ה-repository, לכן כל מה שנמצא ב-repository יכול להיכנס למלאי: מבנה הספריות, ה-manifests של החבילות וקובצי ה-lock, הסקריפטים ב-package.json או ב-Makefile או ב-pyproject.toml, קובצי ה-workflow של ה-CI, ה-Dockerfiles, נקודות הכניסה, ו-CODEOWNERS אם קיים כזה. מלאי שנבנה מתוך אלו הוא באמת בעל תחזוקה עצמית. כאשר חבילה עוברת מיקום, הסבב הבא מעדכן את השורה שמתארת אותה.
כל מה שמופיע להלן נתון להחלטתך, כיוון שהוא לא נמצא ב-repository כדי שניתן יהיה לקרוא אותו:
- מדוע כלל מסוים קיים; זה מה שמונע מסוכן להסיר אותו בטענה שמדובר במורכבות מיותרת.
- איזה מבין שני נתיבי עבודה נתמך, ואיזה מהם ממתין למחיקה.
- כל דבר שנמצא מחוץ ל-repository, כגון סביבת ה-staging או הסיבה לכך שתלות מסוימת נעולה על גרסה מלפני שתי גרסאות.
- מה התוכניות שלך לשבוע הבא; זהו ההבדל בין קובץ עדכני לבין קובץ שימושי.
dox יודע זאת על עצמו. הכללים שלו קובעים ש-Work Guidance חייב לשקף את הסטנדרטים הנוכחיים של הפרויקט או את ההנחיות של המשתמש, ואם עדיין אין כאלו, עליך להשאיר את הסעיף ריק. ה-Verification חייב לשקף בדיקה קיימת, לכן ללא תשתית בדיקות ב-repo, הסעיף הזה יישאר ריק עד שתהיה אחת כזו. קובץ שנוצר באופן אוטומטי וממציא סטנדרט גרוע יותר מסעיף ריק, כיוון שהסוכן יאכוף לאחר מכן את ההמצאה הזו.
הפרדת הכוונה האנושית מהמלאי המיוצר אוטומטית
זהו הכשל שגורם לאנשים לוותר על תיעוד שנוצר אוטומטית. אתם כותבים פסקה שמסבירה שתור המשימות חייב להישאר עם צרכן יחיד. שלושה שבועות לאחר מכן, תהליך אוטומטי משכתב את הקובץ והפסקה שלכם נעלמת בתוך diff של ארבעים שורות, שרובן בסך הכל שינוי סדר של שמות קבצים, ואף אחד לא מבחין בכך.
ישנם שני מנגנונים, ואתם זקוקים לשניהם.
ראשית, העבירו כוונה (intent) בעלת אופי קבוע לקובץ נפרד. החלטות תכנון והנימוקים מאחוריהן שייכים ל-קובץ DESIGN.md שנכתב עבור הסוכן, והערות המיועדות לבני אדם שייכות למקום שבו אתם מפרידים את HUMAN.md מתוך AGENTS.md. הקובץ AGENTS.md מכיל אז את המלאי ואת החוזים המקומיים, וזה בדיוק החלק שאמור להשתנות כאשר הקוד משתנה.
שנית, גדרו את הכוונה שחייבת להישאר בתוך AGENTS.md. עטפו אותה בסימנים והתייחסו לבלוק כאל תוכן בבעלות אנושית:
## User Preferences
<!-- dox:keep start -->
The jobs queue stays single consumer. Ordering is the reason this service exists.
Deploys ship on Tuesday. A Friday deploy is a human decision, not an agent decision.
<!-- dox:keep end -->הערות Markdown אינן מוצגות בדף, אך הסוכן עדיין קורא אותן. כעת, הפכו את הישרדות הבלוק לניתנת לבדיקה, כך שתהליך שמוחק אותו ייכשל בצורה רועשת. הריצו זאת ב-CI (אינטגרציה רציפה) בכל pull request:
git fetch -q origin main
sed -n '/dox:keep start/,/dox:keep end/p' AGENTS.md > /tmp/keep.head
git show origin/main:AGENTS.md | sed -n '/dox:keep start/,/dox:keep end/p' > /tmp/keep.base
diff -u /tmp/keep.base /tmp/keep.headdiff לא מדפיס דבר ומחזיר 0 כאשר הבלוק לא שונה. כל פלט מצביע על כך שהתהליך שכתב מחדש טקסט בבעלות אנושית, ולכן אדם צריך לאשר זאת או לבצע revert. הבדיקה נשמרת מבלי שאיש יצטרך לזכור זאת.
רענון בתוך ה-pull request, לא לפי טיימר
הרגע הטוב ביותר לרענן מסמך הוא בעת ה-commit שהופך אותו ללא מעודכן. כללו את פעולת ה-DOX באותו ה-pull request שבו בוצע השינוי המבני; כך ה-diff נשאר קטן מספיק כדי שיהיה אפשר לקרוא אותו באמת.
בדיקה חוסמת שמבצעת אכיפה:
#!/usr/bin/env bash
set -euo pipefail
git fetch -q origin main
base=$(git merge-base origin/main HEAD)
changed=$(git diff --name-only "$base" HEAD)
if grep -qE '^(src|apps|packages)/' <<<"$changed" && ! grep -q 'AGENTS\.md$' <<<"$changed"; then
echo "Code changed but no AGENTS.md was touched. Run a DOX pass, or say why not."
exit 1
fiהתאימו את הנתיבים למאגר שלכם. הערך המוסף הוא שהבדיקה נכשלת בענף (branch), שם התיקון זול, והיא נכשלת מסיבה שסוקר יכול לפעול לפיה.
לוח זמנים הוא גיבוי, לא מנגנון עבודה. משימה שבועית תופסת את מה שאף אחד לא הבחין בו בענף: קבצים שהוזזו ב-rebase, חבילה שנמחקה ב-merge, או מסמך שמפנה לספרייה שכבר לא קיימת. הריצו זאת על שרת קטן, אותו אחד שבו אתם עשויים להשתמש כדי להריץ סוכן תכנות על גבי VPS, והגדירו לו לפתוח pull request במקום לבצע push ישירות ל-main.
#!/usr/bin/env bash
set -euo pipefail
cd /srv/src/myapp
git fetch -q origin
git switch -c "dox/refresh-$(date +%Y%m%d)" origin/main
# Your agent CLI goes on the next line, in whatever non-interactive mode it offers.
# Prompt: "Run a DOX pass over this repository. Change AGENTS.md files only."
git add '*AGENTS.md'
git commit -m "dox: refresh AGENTS.md tree" || { echo "nothing to refresh"; exit 0; }
git push -q -u origin HEAD
gh pr create --fillההערה הזו היא מציין מיקום מכוון. לכל סוכן יש ממשק שורת פקודה (CLI) משלו ודגל (flag) ייעודי להרצה לא אינטראקטיבית. פקודה שמועתקת מדף אינטרנט ואינה תואמת לגרסה שלכם תיכשל בתוך cron, שם אף אחד לא יראה את השגיאה. מלאו את הפרטים והריצו את הסקריפט ידנית פעם אחת לפני שאתם מתזמנים אותו. ה-|| exit 0 חשוב גם הוא: git commit מסיים הרצה עם קוד שגיאה שאינו אפס באמצעות nothing to commit, working tree clean כאשר העץ כבר מעודכן, ותחת set -e זה ידווח על הרצה תקינה כעל כשל.
כל הרצה עולה ב-tokens, כיוון ש-"Read Before Editing" גורם לסוכן לקרוא את כל השרשרת בכל משימה. זהו מחיר העסקה, וכדאי לעקוב אחריו אם אתם כבר מחשבים את העלות של הרצות הסוכן שלכם.
Monorepos: חוזים רבים, אינדקס אחד
קובץ AGENTS.md שורשי יחיד במאגר המכיל ארבעים חבילות מייצר diff של יצירה מחדש שאף אחד לא קורא, ומסמך שרובו אינו רלוונטי למה שהסוכן מבצע כרגע. הפתרון של dox הוא Child DOX Index: השורש מכיל כללים החלים על כל המאגר ומפנה לצאצאיו, וכל גבול בר-קיימא מחזיק בקובץ משלו. כיצד להגדיר את מבנה העץ הזה, ואילו כלים קוראים קבצים מקוננים, מוסבר ב-קבצי AGENTS.md מקוננים עבור monorepos.
מה ש־dox משנה הוא שטח הפנים של הסקירה. בקשת pull הנוגעת ב-packages/api צריכה להפיק diff של תיעוד בתוך packages/api ולא בשום מקום אחר:
git diff --stat -- '*AGENTS.md'אם פקודה זו מציגה שישה קבצים עבור שינוי בחבילה אחת, העץ שגוי. או שהגבולות גסים מדי, או שכלל השייך לשורש הועתק לכל צאצא. dox מציין את התיקון ישירות: כללים רחבים נכנסים למסמכי ההורה, פרטים קונקרטיים נכנסים למסמכי הצאצא. כללים כפולים הם הגורם לכך ששינוי שגרתי גורם לכתיבה מחדש של הכל. אם אותם כללים חלים באמת על פני מאגרים נפרדים, זו בעיה אחרת, ו-שיתוף כישורי סוכנים בין מאגרים הוא הכלי המתאים יותר לכך.
סקירת ה-diff כקוד
קל לאשר diff של תיעוד שנוצר אוטומטית מבלי לקרוא אותו, וכך משתחרר קובץ שגוי. קראו אותו בחשדנות שבה הייתם בוחנים קוד שנוצר אוטומטית, וחפשו ארבעה דברים:
- פקודה שהקובץ מציין כעת, שעליכם להריץ בעצמכם לפני המיזוג. הוראות בנייה מומצאות הן הכשל הנפוץ ביותר.
- שורה שנמחקה והכילה כוונה מסוימת. הוספות הן זולות. מחיקות הן המקום שבו אובדן מידע מתרחש.
- נתיב אבסולוטי, שם מארח (hostname), כתובת URL פנימית, או כל דבר שנראה כמו פרטי הזדהות.
- רשומה במלאי עבור משהו שכבר אינו קיים, עניין ש-
lsמסדיר בשנייה.
לאחר מכן, בדקו את הגודל באמצעות wc -l AGENTS.md. קובץ root שעובר מאתיים שורות הוא סימן לכך שיש לפצל אותו, כיוון שכל הערך של השרשרת טמון בכך שהסוכן קורא את החלק הרלוונטי הקטן במקום את הכל.
כאשר מתרחשת תקלה
המעבר מחק את בלוק הכוונה שלך. הבדיקה diff לעיל מדפיסה את השורות שהוסרו. שחזר את הקובץ מנקודת ה-branch באמצעות git restore --source=origin/main AGENTS.md, ולאחר מכן הרץ שוב את המעבר עם הוראה מצומצמת יותר המציינת את הסעיפים שניתן לשנות.
שני ענפים עברו יצירה מחדש. אתה מקבל CONFLICT (content): Merge conflict in AGENTS.md וסימני התנגשות <<<<<<< HEAD בתוך הקובץ. אל תערוך את הסימנים ידנית. הקובץ נוצר באופן אוטומטי, לכן הפתרון הנכון הוא הרצה מחדש של המעבר על העץ הממוזג.
הסוכן מתעלם מהקובץ לחלוטין. בדוק איזה שם קובץ הכלי שלך קורא בפועל. אם הוא קורא קובץ אחר, הפנה אותו לאותו תוכן באמצעות ln -s AGENTS.md CLAUDE.md ובצע commit לקישור הסימבולי (symlink), כך שתשמור על מקור אחד במקום על שני מסמכים שמתרחקים זה מזה. אם שם הקובץ נכון והכללים עדיין נדלגים, הרץ את האבחון עבור מדוע סוכני קידוד מתעלמים מההוראות שלך לפני שתכתוב את המסמך מחדש.
העץ הצמיח ילדים שאף אחד לא אינדקס. השווה את הפלט של find . -name AGENTS.md מול ערכי האינדקס במסמכי האב. ילד שאף אינדקס לא מציין הוא ילד שהסוכן יכול לעבור על פניו מבלי להתייחס אליו.
מתי מחולל (generator) הוא מיותר
חבילה אחת, פקודת בדיקה אחת, ושני אנשים שמכירים את ה-repository: כתבו את עשרים השורות ידנית. קובץ AGENTS.md באורך עשרים שורות לא מתיישן מספיק מהר כדי להצדיק עץ, אינדקס, בדיקת CI ומשימה שבועית. קראו אותו מחדש בכל פעם שאתם משנים את ה-build. זוהי כל עלות התחזוקה, והיא קטנה מעלות המנגנון שסביבו.
השימוש ב-dox כדאי כאשר ב-repository יש גבולות שאף אדם לא מחזיק בראשו: כמה חבילות עם חוקים שונים, או תורמים שמגיעים ללא הרקע הנדרש. הערך אינו הטקסט שמחולל. הערך הוא שהתיעוד הופך למשהו ש-pull request יכול להיכשל בגללו, וזו הסיבה היחידה לכך שקובץ כלשהו ב-repository נשאר מעודכן.
FAQ
האם עליי להתקין משהו כדי להשתמש ב-dox?
לא. dox הוא קובץ Markdown יחיד, תחת רישיון MIT, ונכון ל-11 באוגוסט 2026 המאגר אינו מפיץ חבילות או releases. עליך להעתיק את תוכנו לקובץ ה-AGENTS.md בפרויקט שלך, וסוכן הקידוד שלך יפעל לפי הכללים המפורטים בו. קבע (pin) את ה-commit שהעתקת, f34ec7ad1055d3393887e5a2670e8cb7320c9165 בעת כתיבת שורות אלו, וציין אותו בהודעת ה-commit שלך כדי שתוכל לדעת בהמשך לפי איזו גרסה של הכללים נבנה העץ שלך.
כיצד אוכל למנוע מתהליך יצירה מחדש למחוק את הכללים שכתבתי בעצמי?
הפרד בין כוונות לבין מלאי. הנמקה עמידה צריכה להיכתב במסמך נפרד, וכל מה שחייב להישאר בתוך AGENTS.md צריך להיות בתוך בלוק מסומן. לאחר מכן, בצע בדיקה של הבלוק ב-CI: חלץ אותו מה-branch ומה-origin/main באמצעות sed, השווה בין השניים בעזרת diff, והכשיל את ה-build בכל מקרה של הבדל. אדם יאשר או יבטל את השינוי, במקום שהוא יעבור ללא הבחנה בתוך diff גדול.
באיזו תדירות עליי ליצור מחדש את AGENTS.md?
בכל פעם שמתבצע pull request שגורם לו להיות שגוי. שינוי מבני והתיעוד שלו שייכים לאותו diff, כיוון שזהו הרגע היחיד שבו למישהו יש את ההקשר הנדרש כדי לבחון את שניהם. מעבר מתוזמן שבועי משמש כגיבוי לסטייה שחמקה מ-branch, ועליו לפתוח pull request במקום לבצע commit ישירות ל-main.
האם פקודות build צריכות להימצא ב-AGENTS.md שבשורש או בזה של תת-ספרייה?
במסמך הקרוב ביותר שאחראי עליהן. כללים החלים על כל המאגר ואינדקס הילדים נמצאים בשורש. פקודה החלה על חבילה אחת נמצאת ב-AGENTS.md של אותה חבילה. dox פותר קונפליקטים לפי מרחק: המסמך הקרוב יותר שולט בפרטים המקומיים, ואף מסמך ילד אינו רשאי להחליש כלל של הורה. העתקת אותה פקודה לכל חבילת ילד היא מה שגורם למעבר שגרתי לשכתב את כל העץ.
האם dox כדאי עבור מאגר קטן?
בדרך כלל לא. חבילה אחת עם פקודת בדיקה אחת וקובץ AGENTS.md של עשרים שורות מתדרדרת לאט, ותוכל לתקן זאת בדקה שלאחר שתבחין בכך. dox מצדיק את עלותו כאשר במאגר יש כמה גבולות עם כללים שונים, או תורמים שחסרים את הרקע הנדרש, כיוון שאז שרשרת המסמכים מבצעת עבודה שאף אדם בודד אינו עושה.