arielshemesh1999@gmail.com · ישראל
← כל המאמרים

Headroom

שכבת דחיסה שיושבת בין הסוכן ל-LLM ודוחסת כל מה שהוא קורא - tool outputs, לוגים, קבצים, RAG chunks והיסטוריית שיחה - לפני שזה מגיע למודל. אותן תשובות, חלק קטן מהטוקנים: 60-95% פחות. רצה מקומית, הפיכה, ועובדת כספרייה, כ-proxy בלי שינוי קוד, או כשרת MCP.

מה זה

Headroom מתאר את עצמו בשורה אחת: "The context compression layer for AI agents." זו שכבה שדוחסת כל מה שהסוכן קורא - פלט של כלים, לוגים, RAG chunks, קבצים והיסטוריית שיחה - לפני שזה מגיע ל-LLM. אותן תשובות, חלק קטן מהטוקנים. הדוגמה החיה ב-README: לוג של 10,144 טוקנים נדחס ל-1,260, ואותו FATAL שחיפשת עדיין שם. הנקודה המרכזית היא לא "פחות טקסט" אלא "פחות טוקנים בלי לאבד את התשובה".

הריפו הוא github.com/chopratejas/headroom - רישיון Apache-2.0, כתוב בעיקר ב-Python עם ליבת Rust ו-SDK ל-TypeScript, הגרסה האחרונה היא v0.26.0 (יוני 2026), והפרויקט אסף מעל 41 אלף כוכבים (נכון ליוני 2026). מה שמייחד אותו לפי טבלת ההשוואה שלו: הוא רץ מקומית (הנתונים שלך לא עוזבים את המכונה), מכסה כל סוג תוכן ולא רק פלט CLI, מתחבר לכל framework מרכזי, והדחיסה שלו הפיכה - המקור נשמר וניתן לאחזור.

הבעיה - קונטקסט מנפח את החשבון

סוכן AI שעובד על משימה אמיתית קורא כמויות עצומות של קונטקסט: פלט של פקודות shell, סטאק-טרייסים, תוצאות חיפוש, קבצים שלמים, היסטוריית שיחה שמצטברת. כל טוקן שנכנס למודל עולה כסף ומוסיף latency, ורובו רעש - הזחה, מטא-דאטה חוזרת, מבני JSON שחוזרים על אותם מפתחות אלף פעם, קוד שכבר ראית. ככל שהמשימה ארוכה יותר, החלון מתמלא מהר יותר והעלות מטפסת. Headroom נכנס בדיוק לפער הזה: לדחוס את הרעש לפני המודל, בלי שהסוכן או הקוד שמסביבו יצטרכו לדעת שמשהו קרה.

הרעיון - שכבת דחיסה מקומית בנתיב

במקום לשלוח את הקונטקסט הגולמי היישר ל-LLM, Headroom יושב בנתיב כשכבת ביניים שרצה אצלך, ומריץ את התוכן דרך pipeline קצר:

הסוכן / האפליקציה  (Claude Code, Cursor, Codex, LangChain, הקוד שלך...)
        │  prompts · tool outputs · לוגים · תוצאות RAG · קבצים
        ▼
   Headroom  (רץ מקומית — הנתונים שלך נשארים כאן)
   CacheAligner → ContentRouter → CCR
                    ├─ SmartCrusher    (JSON)
                    ├─ CodeCompressor  (AST)
                    └─ Kompress-base   (טקסט, מודל HF)
        │  prompt דחוס  +  כלי אחזור
        ▼
   ספק ה-LLM  (Anthropic · OpenAI · Bedrock · ...)

הלב הוא ContentRouter: הוא מזהה איזה סוג תוכן הגיע - JSON, קוד, או פרוזה - ובוחר את הדוחס המתאים. ה-CacheAligner מייצב את ה-prefix של הבקשה כך ש-KV cache בצד הספק (Anthropic/OpenAI) באמת ייתפס במקום להישבר על כל בקשה. וה-CCR שומר את המקור מקומית, כך שאם המודל צריך את הגרסה המלאה הוא מבקש אותה בכלי ייעודי. כל זה רץ אצלך - אין שירות חיצוני שרואה את הנתונים.

ארבעה מצבי הפעלה

אותו מנוע, ארבע דרכים להכניס אותו לעבודה - וזו הסיבה שאפשר לאמץ אותו בלי לשכתב כלום:

  • ספרייהcompress(messages) ב-Python או ב-TypeScript, inline בתוך כל אפליקציה.
  • Proxyheadroom proxy --port 8787, אפס שינויי קוד, מכל שפה. כל לקוח תואם-OpenAI עובד דרכו.
  • עטיפת סוכןheadroom wrap claude|codex|cursor|aider|copilot בפקודה אחת.
  • שרת MCP — הכלים headroom_compress, headroom_retrieve, headroom_stats לכל לקוח MCP.

החלוקה הזו היא מה שהופך את האימוץ לזול: מי שכבר עובד עם Claude Code או Cursor מריץ headroom wrap ומסיים; מי שיש לו backend בכל שפה מצביע אותו ל-proxy המקומי ולא נוגע בקוד; ומי שבונה אפליקציה משלו קורא ל-compress() ישירות. מטריצת התאימות מסמנת ✅ ל-Claude Code, Codex, Cursor, Aider, Copilot CLI ו-OpenClaw.

מה בפנים - ששת המנגנונים

מתחת ל-ContentRouter יושבים כמה דוחסים מתמחים, כל אחד למשפחת תוכן אחרת:

  • SmartCrusher — דוחס JSON אוניברסלי: מערכים של dicts, אובייקטים מקוננים, טיפוסים מעורבים. במקום לחזור על אותם מפתחות בכל איבר, הוא מקפל את המבנה.
  • CodeCompressor — מודע ל-AST עבור Python, JavaScript, Go, Rust, Java ו-C++. הוא מבין מבנה קוד, לא רק טקסט, ולכן דוחס בלי לשבור משמעות.
  • Kompress-base — מודל HuggingFace ייעודי של הפרויקט (kompress-v2-base), שאומן על agentic traces - כלומר על הסוג האמיתי של פלט שסוכנים מייצרים - לדחיסת פרוזה כללית.
  • CacheAligner — מייצב prefixes כך ש-KV caches של הספק נתפסים בפועל. דחיסה בלי זה הייתה שוברת את ה-cache והופכת חיסכון אחד להפסד אחר.
  • דחיסת תמונות — 40-90% הקטנה דרך ML router מאומן.
  • CCR — דחיסה הפיכה: המקור נשמר מקומית והמודל מאחזר אותו לפי דרישה (ראו בהמשך).

נוסף עליהם זיכרון חוצה-סוכנים (cross-agent memory): מאגר משותף עם ייחוס לסוכן ו-dedup אוטומטי, כך ש-Claude, Codex ו-Gemini יכולים לחלוק קונטקסט בלי לשכפל אותו. זה הופך את Headroom מ"דוחס לבקשה בודדת" לשכבת זיכרון שמצטברת על פני סשנים וכלים.

CCR - דחיסה הפיכה

הסכנה הברורה בכל דחיסה היא אובדן: מה אם המודל דווקא צריך את השורה שנמחקה? התשובה של Headroom היא CCR (Reversible Compression) - המקור הלא-דחוס נשמר מקומית, והמודל יכול לקרוא ל-headroom_retrieve כדי לקבל אותו חזרה לפי דרישה, בתוך ה-TTL שהוגדר. כך הדחיסה היא ברירת מחדל אגרסיבית עם רשת ביטחון: רוב הזמן המודל עובד עם הגרסה הקצרה, ובמקרים הנדירים שהוא צריך את הפרטים המלאים הוא מבקש אותם, במקום שתשלח אותם מראש "ליתר ביטחון". זה גם ההבדל המרכזי מול רוב כלי הדחיסה האחרים בטבלת ההשוואה, שאצלם הדחיסה היא חד-כיוונית.

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

כל מה שעד כאן מקטין את ה-prompt ששולחים. אבל משלמים גם על כל טוקן שהמודל כותב בחזרה, ובמודלים מסדר Opus פלט עולה פי 5 מקלט. הרבה מהפלט הזה הוא בזבוז: פתיחים מסוג "מצוין, בוא ננסה...", הדפסה חוזרת של קוד שזה עתה הראית, ו"חשיבה" עמוקה על צעדים שגרתיים כמו קריאת קובץ. Headroom מצמצם גם את זה, מתוך ה-proxy ובלי שינוי קוד, בשני מנגנונים:

  • Verbosity steering — מוסיף בסוף ה-system prompt הערה קצרה ל"תהיה תמציתי, אל תחזור על הקונטקסט" (בסוף, כדי שה-prompt cache עדיין ייתפס).
  • Effort routing — כשתור הוא רק המודל שממשיך אחרי תוצאת כלי (קריאת קובץ, טסט שעבר), הוא מוריד את מאמץ ה"חשיבה". שאלות חדשות ושגיאות שומרות על מאמץ מלא.

מפעילים עם export HEADROOM_OUTPUT_SHAPER=1 (כבוי כברירת מחדל). נקודה הוגנת ששווה לציין: חיסכון בפלט הוא counterfactual - אי אפשר למדוד מה המודל היה כותב - ולכן Headroom מדווח הערכה כנה עם רווח סמך, למשל Reduction: 31.7% (95% CI 27.7%…35.7%) [estimated], ולא מספר מומצא. מי שרוצה מספר נמדד משאיר 10% מהשיחות בלי עיצוב כקבוצת ביקורת (HEADROOM_OUTPUT_HOLDOUT=0.1).

headroom learn - לומד מהכישלונות

פיצ'ר נפרד ומעניין: headroom learn כורה סשנים שנכשלו וכותב תיקונים אוטומטית לקבצי ההנחיות של הסוכן - CLAUDE.md, AGENTS.md, GEMINI.md. במקום שתחזור על אותה טעות בכל פעם ותתקן ידנית, הכלי מזהה דפוסי כשל ומעדכן את ההוראות כך שהסוכן לא ייפול בהם שוב. אותו רעיון מוחל גם על רמת התמציתיות: headroom learn --verbosity קורא את הסשנים הקודמים שלך ובוחר את רמת הקיצור המתאימה - כי אנשים לא אומרים כמה תמציתי הם רוצים, הם מראים את זה (קוטעים תשובות ארוכות, או עוברים הלאה לפני שסיימו לקרוא).

ההוכחות - בנצ'מארקים

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

עומס                          לפני     אחרי    חיסכון
חיפוש קוד (100 תוצאות)       17,765   1,408    92%
דיבוג תקלת SRE               65,694   5,118    92%
מיון GitHub issues           54,174  14,761    73%
חקירת codebase               78,502  41,254    47%

השנייה, והחשובה יותר, מראה שהדיוק נשמר - כי דחיסה ששוברת תשובות היא חסרת ערך:

בנצ'מארק     קטגוריה   N     Baseline  Headroom  דלתא
GSM8K        מתמטיקה   100    0.870     0.870     ±0.000
TruthfulQA   עובדתי    100    0.530     0.560     +0.030
SQuAD v2     QA        100      —       97%       19% דחיסה
BFCL         כלים      100      —       97%       32% דחיסה

השילוב הוא הסיפור: על GSM8K הדיוק זהה לחלוטין (±0.000) למרות הדחיסה, ועל TruthfulQA הוא אפילו עלה מעט (53%→56%) - סביר שדווקא קיצוץ הרעש עזר למודל להתמקד. את שתי הטבלאות אפשר לשחזר: python -m headroom.evals suite --tier 1.

התקנה והפעלה

שתי שורות מביאות אותך לאוויר:

pip install "headroom-ai[all]"     # Python, הכל
npm install headroom-ai            # TypeScript / Node
# אופציונלי: docker pull ghcr.io/chopratejas/headroom:latest

headroom wrap claude               # עוטף סוכן קוד
headroom proxy --port 8787         # proxy drop-in, אפס שינויי קוד
headroom perf                      # מראה את החיסכון

דרישת מערכת: Python 3.10+. יש extras גרנולריים ([proxy], [mcp], [ml], [code], [memory], [image] ועוד) למי שלא רוצה את הכל. על Apple Silicon אפשר להעביר את ה-embedder ל-GPU עם HEADROOM_EMBEDDER_RUNTIME=pytorch_mps. בסביבות עם SSL-inspection תאגידי כדאי להתקין Rust מראש כדי שה-build לא יתקע על הורדת rustup; ה-README מפרט את הנתיב המלא.

מגבלות והערכה כנה

הפרויקט עצמו מסמן מתי לא להשתמש בו, וזה מרענן. דלגו עליו אם אתם משתמשים רק ב-compaction הנייטיבי של ספק יחיד ולא צריכים זיכרון חוצה-סוכנים, או אם אתם בסביבת sandbox שבה תהליכים מקומיים לא יכולים לרוץ - כי Headroom רץ מקומית מעצם תכנונו. שתי הסתייגויות נוספות: ראשית, חיסכון הפלט הוא הערכה, לא מדידה ישירה, וה-README אומר זאת במפורש ומציע holdout למדידה אמיתית - שקיפות שלא מובנת מאליה. שנית, הוא מוסיף עוד רכיב נע לתשתית: מודל HF, ליבת Rust עם ONNX runtime, ושני assets שנמשכים דרך TLS (cdn.pyke.io ו-huggingface.co) - מי שעובד מאחורי proxy חוסם צריך לסדר אותם, אם כי הרצה כ-gateway טהור בלי דחיסה לא דורשת אף אחד מהם.

ראוי גם לציין שהמספרים תלויי-עומס מאוד: 47% על חקירת codebase מול 92% על חיפוש קוד או דיבוג SRE. הרווח הגדול מגיע מתוכן רועש וחזרתי (לוגים, תוצאות חיפוש, JSON) - שם יש הכי הרבה מה לדחוס - ולא מטקסט צפוף שכבר נקי.

למה זה חשוב בפועל

מצב ברירת המחדל של סוכן AI שעובד על משימה ארוכה הוא חלון שמתמלא: כל קריאת כלי, כל לוג, כל תוצאת חיפוש נדחפת לקונטקסט, העלות מטפסת וה-latency גדל. הערך המעשי של Headroom הוא שהוא חותך את הרעש הזה בלי לבקש ממך לשנות איך אתה עובד - headroom wrap על הסוכן שכבר יש לך, או proxy מקומי שה-backend מצביע אליו, וזהו.

שלוש הנקודות שמייחדות אותו מול חלופות פשוטות יותר: הוא מקומי (הנתונים לא עוזבים את המכונה - חשוב בקוד פרטי), הוא הפיך (CCR מחזיר את המקור אם המודל צריך אותו, אז אגרסיביות בדחיסה לא מסוכנת), והוא חוצה-סוכן (זיכרון משותף עם dedup). בעולם שבו מחיר הטוקנים הוא קו ישיר לחשבון בסוף החודש, שכבה שמורידה 60-95% מהקלט תוך שמירה על דיוק זהה היא לא אופטימיזציה שולית - היא משנה את הכלכלה של הרצת סוכנים בקנה מידה.

מקורות