ניתוב מודלים בסוכני תכנות: מתי זה משתלם?
ניתוב דינמי בין מודלים פוגע ב-prompt cache ומייקר את עלויות סוכני התכנות. גלו מתי כדאי להשתמש בניתוב, מתי עדיף לקבע מודל, ומה החישוב הכלכלי מאחורי החלטות אלו.
השפעת ניתוב רב-מודלים על סוכן תכנות
ניתוב רב-מודלים (multi-model routing) שולח כל בקשה למודל הזול ביותר שמסוגל לטפל בה. בתעבורת צ'אט זה עובד היטב. בסוכן תכנות (coding agent), זה בדרך כלל עולה יותר ממה שזה חוסך, כיוון שהחשבון של סוכן מושפע בעיקר מקידומת ה-prompt שנשמרת ב-cache עבור כל מודל, ומעבר בין מודלים מוחק את ה-cache הזה.
הכלל שפוסט זה מציע הוא: נתבו בין ספקים לצורך זמינות, נתבו בין שכבות (tiers) לצורך עלות רק בגבולות של משימות, וקבעו מודל אחד לכל סשן עבור כל פעולה סוכנית. כל מה שמופיע להלן הוא הנימוק לכך.
ארבעה מונחים, מוגדרים פעם אחת. נתב (router) בוחר מודל עבור כל בקשה. שער (gateway) הוא ה-proxy שדרכו עוברת הבקשה, שעשוי או לא עשוי לבצע ניתוב בעצמו. מטמון prompt (prompt cache) הוא הספק ששומר את הקידומת המעובדת של ה-prompt שלכם, כך שבקשה מאוחרת יותר שחוזרת על אותה קידומת מחויבת בשבריר ממחיר הקלט. מטמון KV (KV cache) הוא אותו רעיון בתוך שרת שאתם מריצים בעצמכם.
מדוע תעבורת צ'אט מנותבת היטב בעוד שתעבורת סוכנים אינה כזו
בקשת צ'אט היא תור בודד. היא מגיעה, מסווגת, עוברת למודל וחוזרת. שום דבר לא עובר לבקשה הבאה. נתב יכול לשלוח שאלה זו למודל קטן ואת הבאה למודל גדול, ואף אחת מהבקשות לא "יודעת" שהשנייה התרחשה. זהו עומס העבודה שכמעט כל מדד ביצועים (benchmark) לניתוב מודד, ונתבים טובים אכן מצטיינים בכך.
תור של סוכן (agent) אינו בקשה אחת. הוראה אחת כמו "fix the failing test" הופכת לעשרים עד שישים קריאות API. כל קריאה שולחת מחדש את כל השיחה: ה-system prompt, כל הגדרת כלי, כל קובץ שהסוכן קרא, וכל פלט של פקודה שהוא ראה. ההקשר (context) רק גדל. עד הקריאה השלושים, התחילית החוזרת על עצמה יכולה להגיע לעשרות אלפי tokens, בעוד שהתוכן החדש באמת בכל קריאה הוא כמה מאות בלבד.
המבנה הזה משנה את המשמעות של המילה "יקר". בצ'אט, העלות היא בערך מחיר המודל כפול הבקשה. בלולאת סוכן, העלות היא התחילית, שמחויבת מחדש בכל קריאה בודדת. המשך פוסט זה נובע מעובדה אחת זו בלבד.
מטמון ה-prompt הוא לפי מודל, והסוכן נמצא בתוכו
Anthropic מתמחרת קריאה מהמטמון ב-0.1 ממחיר הקלט הבסיסי, וכתיבה למטמון לחמש דקות ב-1.25 ממנו. אלו הם מחירי המחירון הרשמיים, נכון לאוגוסט 2026.
The data behind this chart
[
{
"label": "Opus 5",
"uncached_input_usd": "5.00",
"cache_read_usd": "0.50"
},
{
"label": "Sonnet 5",
"uncached_input_usd": "2.00",
"cache_read_usd": "0.20"
},
{
"label": "Haiku 4.5",
"uncached_input_usd": "1.00",
"cache_read_usd": "0.10"
}
]קראו את הסדרה השנייה מול הראשונה, לאורך השורות ולא במורדן. קריאה מהמטמון ב-Opus 5 עולה 0.50 דולרים למיליון טוקנים. קלט ללא מטמון ב-Haiku 4.5, המודל הזול ביותר ברשימה, עולה 1.00 דולרים. מכאן שקריאה חוזרת של תחילית (prefix) חמה במודל היקר ביותר עולה פחות לטוקן קלט מאשר קריאה של אותה תחילית במצב קר במודל הזול ביותר.
השוואה בודדת זו משבשת את רוב תוכניות הניתוב. נתב שמעביר עבודה "למטה" בדרגות המודלים משווה מחירי מחירון. אולם סוכן באמצע סשן אינו משלם מחיר מחירון על המודל שבו הוא כבר משתמש. הוא משלם את מחיר הקריאה מהמטמון, שנמצא כבר מתחת לתעריף ללא-מטמון של המודל הזול.
המטמונים מבוססים על hash של תחילית ה-prompt, והם ספציפיים לכל מודל. בקשה למודל אחר מבצעת hash מול מאגר שמעולם לא ראה אותה, לכן היא לא מוצאת דבר ומשלמת מחיר מלא. המטמון הוא גם היררכי: תחילה כלים (tools), לאחר מכן מערכת (system), ולבסוף הודעות. שינוי בכל רמה מבטל את אותה רמה ואת כל מה שאחריה, מה שאומר שעריכת הגדרת כלי אחד משליכה את מטמון ה-system prompt שמאחוריו. סוכנים שרושמים כלים בזמן ריצה (runtime) נתקלים בבעיה זו גם ללא מעורבות של נתב.
העלות האמיתית של החלפת מודל באמצע סשן
קחו סשן עם prefix יציב של 40,000 tokens, גודל רגיל לאחר שסוכן קרא מספר קבצים. להלן עלות ה-prefix של תור (turn) בודד, המחושבת לפי המחירון לעיל.
The data behind this chart
[
{
"label": "Opus 5, cache warm",
"prefix_cost_usd": "0.020"
},
{
"label": "Sonnet 5, turn after switch",
"prefix_cost_usd": "0.100"
},
{
"label": "Opus 5, cache re-warmed",
"prefix_cost_usd": "0.250"
}
]הישארות על Opus 5 עם cache חם עולה 0.020 דולרים עבור ה-prefix של אותו תור. התור הראשון לאחר ניתוב (routing) ל-Sonnet 5 עולה 0.100 דולרים, כיוון של-Sonnet אין רשומה עבור ה-prefix הזה ועליה לכתוב אחת. חזרה ל-Opus 5 עולה 0.250 דולרים, כיוון שהרשומה המקורית פגה בזמן שהסשן לא היה פעיל במודל זה.
לפיכך, הלוך-חזור משלם על שתי כתיבות ל-cache כדי להימנע משתי קריאות מה-cache. כנגד זאת, ההחלפה קנתה תור אחד של פלט במחיר הפלט של Sonnet במקום זה של Opus. בלוק הפרטים מפרט את כל התהליך: החיסכון מסתכם בשברירי סנט, בעוד שקנס ה-cache מסתכם בעשרות סנטים. הקנס גדול ביותר מסדר גודל אחד, והוא גדל ככל שאורך ה-prefix גדל, בעוד שהחיסכון אינו גדל.
כיצד מחושבים הנתונים הללו
כל מספר כאן הוא חישוב אריתמטי המבוסס על המחירון הרשמי בטבלה הראשונה. זהו מודל עלות ולא מדד ביצועים (benchmark), ולא נשלחו בקשות כדי להפיק אותו. שנו את גודל ה-prefix והיחס ישתנה בהתאם.
Prefix: 40,000 tokens, נשמר קבוע לאורך התור.
Opus 5, warm read 40,000 x $0.50 / 1e6 = $0.020
Sonnet 5, cache write 40,000 x $2.50 / 1e6 = $0.100 (1.25 x $2 base)
Opus 5, cache write 40,000 x $6.25 / 1e6 = $0.250 (1.25 x $5 base)הלוך-חזור: $0.100 + $0.250 = $0.350. שני תורי ה-Opus החמים שהוחלפו: $0.040. עלות נוספת של הסטייה: $0.310.
החיסכון, בתור אחד של 800 tokens של פלט, הוא פער מחיר הפלט בין Opus 5 ב-$25 למיליון לבין Sonnet 5 ב-$10 למיליון:
800 x ($25 - $10) / 1e6 = $0.012הוצאה של $0.310 כדי לחסוך $0.012 היא הפסד של פי עשרים וחמישה בערך. החיסכון גדל בהתאם ל-tokens של הפלט, שהם קטנים וקבועים בערך בכל תור. הקנס גדל בהתאם לגודל ה-prefix, שגדל לאורך כל הסשן. סשנים ארוכים יותר מחמירים את המצב, לעולם לא משפרים אותו.
פורמטים של קריאות לכלים אינם זהים בין ספקים
סוכן (agent) הוא לולאת קריאה לכלים, לכן הפורמט של הקריאה לכלים משמעותי באופן שאינו קיים בצ'אט רגיל. ה-Messages API של Anthropic מחזיר בלוק תוכן מסוג tool_use ומצפה לקבל בחזרה בלוק מסוג tool_result. ממשקי API התואמים ל-OpenAI מחזירים מערך tool_calls שבו function.arguments הוא מחרוזת מקודדת ב-JSON ולא אובייקט מקונן. שער (gateway) מבצע תרגום בין השניים, ועבור קריאות רגילות התרגום מתבצע בצורה נקייה.
הבעיות מופיעות בקצוות. קריאות כלים מקביליות, שבהן המודל מנפיק כמה קריאות בתגובה אחת, מיוצגות בצורה שונה ואינן נתמכות באופן זהה בכל מקום. אכיפת סכימה קפדנית היא תכונה התלויה בספק, לכן מודל שמבטיח ארגומנטים תקינים לפי סכימה בנקודת קצה אחת, נוטה רק לקירוב של ארגומנטים תקינים בנקודה אחרת. הסוכן רואה את ההבדל כתוצאת כלי המכילה שגיאת ניתוח (parse error), שאותה הוא מנסה לתקן באמצעות סבב נוסף. סבבי תיקון אלו מחויבים במחיר המלא של ה-prefix, כך שאי-התאמה בפורמט באה לידי ביטוי בחשבונית וגם בתמליל.
נקודות קצה באירוח עצמי דורשות הגדרה מפורשת של נושא זה. השרת התואם ל-OpenAI של vLLM דורש --enable-auto-tool-choice יחד עם --tool-call-parser המותאם למשפחת המודלים (hermes, mistral, llama3_json ואחרים), בתוספת תבנית צ'אט (chat template) המטפלת בהודעות עם תפקיד כלי. התיעוד של vLLM מציג בבירור את מגבלות הנתיב הזה: עם tool_choice="auto" וללא אכיפת סכימה קפדנית, vLLM מחלץ קריאות לכלים מתוך טקסט גולמי, ולכן הארגומנטים עלולים לעיתים להיות פגומים או להפר את סכימת הפרמטרים של הפונקציה. בחירת מנתח (parser) שגוי עבור המודל שלכם היא שגיאת תצורה שמתבטאת בסוכן שאינו מסוגל להפעיל כלים; כדאי לדעת זאת לפני שמנתבים אליו תעבורה. ה-ההבדל בין Ollama לבין vLLM להגשת מודלים באופן עצמאי משמעותי כאן, כיוון ששניהם חושפים יכולות קריאה לכלים בתנאים שונים.
שינוי התנהגות עקב מנגנון fallback במהלך משימה ללא שגיאה
ניתוב fallback הוא התכונה בעלת הסבירות הגבוהה ביותר להפעלה בשוגג. שער (gateway) מוגדר לבצע ניסיון חוזר במודל אחר כאשר הראשון מחזיר שגיאת rate limit או שגיאת 5xx, ולאחר מכן מעביר את המודל שנכשל למצב המתנה (cooldown) למשך מספר שניות. בתעבורת צ'אט זהו פתרון תקין לחלוטין. בתוך משימת סוכן (agent) ארוכה, המשמעות היא שהחצי השני של המשימה התבצע במודל שלא בחרת בו.
דבר אינו מדווח על כך. המשימה אינה נכשלת, הסוכן אינו מזהיר, וסטטוס היציאה הוא הצלחה. התוצאה היא משימה שבה התוכנית נכתבה על ידי מודל אחד, בעוד העריכות בוצעו על ידי מודל אחר, עם טון והרגלי עבודה שמשתנים באמצע התהליך. הסימן האמין היחיד הוא השדה model בלוג הבקשות של ה-gateway או במטא-דאטה של התגובה. לכן, אם אתם מפעילים מנגנוני fallback, תעדו את השדה הזה עבור כל בקשה וקראו אותו כאשר התוצאה מפתיעה אתכם. ניפוי שגיאות בהתנהגות מבלי לדעת איזה מודל הפיק אותה מבזבז יותר זמן ממה שה-fallback חסך.
אותו מלכוד קיים גם בדחיסת הקשר (context compression). סוכנים רבים מסכמים היסטוריה ארוכה על ידי קריאה למודל קטן. אם קריאה זו נושאת מודל שונה או system prompt שונה, היא כותבת רשומת cache משל עצמה ואינה מרעננת את זו של הסשן הראשי, כך שהפנייה המלאה הבאה משלמת את מחיר ה-cold prefix. הדחיסה חסכה טוקנים אך איבדה את ה-cache.
התקורה של הניתוב אכן קיימת, אך השיהוי אינו הגורם המכריע
נתבים אכן מוסיפים עבודה לכל בקשה, וכדאי לדייק לגבי היקפה. חברת DigitalOcean מדווחת כי מודל ה-Arch-Router שלהם פותר את כוונת הניתוב בכ-51 מילי-שניות, עם דיוק ניתוב של 93.17% לפי הערכותיהם. אלו הנתונים שלהם, המבוססים על המדידות וה-benchmark שלהם, ולא תוצאה אוניברסלית. אם מקבלים אותם כפשוטם, המסקנה מעודדת: 51 מילי-שניות על פני ארבעים קריאות סוכן מסתכמות בתוספת של כשתי שניות למשימה שנמשכת מספר דקות.
שתי שניות אינן הגורם שהופך את הניתוב ליקר במקרה זה. התקורה המכאיבה באמת היא נתב שמבצע סיווג באמצעות קריאה למודל מלא, שכן מדובר בהסקה (inference) נוספת על כל בקשה, אשר מתומחרת ומתווספת לתור כמו כל פעולה אחרת. מתחת לשניהם נמצאת אריתמטיקת ה-cache שהוזכרה לעיל, שאינה מהווה תקורה כלל. זהו המחיר של הדבר שהניתוב נועד לייעל.
בשרת שאתם מנהלים בעצמכם, אותו כלל חל עם פחות מרחב תמרון. המקבילה המקומית ל-prompt cache היא prefix caching בתוך ה-KV cache, השוכן בזיכרון ה-GPU. אירוח של שני מודלים על GPU אחד מחלק את הזיכרון ביניהם, כך שכל אחד מהם מחזיק KV cache קטן יותר ומפנה קידומות מוקדם יותר. ניתוב בין שני מודלים מקומיים עלול לכן להפחית את שיעור ה-cache hit עבור שניהם בו-זמנית. אם אתם מתכננים את החומרה לכך, הזיכרון וה-CPU שסוכן קידוד באמת צריך על גבי VPS הם נקודת התחלה מועילה יותר מאשר נתב.
כללי ההחלטה
- ניתוב בין ספקים לטובת זמינות. כאשר החלופה היא בקשה שנכשלה, כל עלות היא עלות מוצדקת. קבעו את מנגנון ה-fallback למודל בעל פורמט קריאות כלי (tool call) זהה, כדי שלולאת ה-agent תמשיך לעבוד, ותעדו איזה מודל שירת כל קריאה.
- ניתוב בין שכבות (tiers) לטובת עלות רק בגבולות המשימה. בחירה ב-Haiku עבור שינוי שם וב-Opus עבור ביצוע refactor היא החלטה טובה שמתקבלת פעם אחת, לפני תחילת הסשן. זו החלטה גרועה אם היא מתקבלת בתור ה-30 של אותו סשן.
- קיבוע מודל אחד לכל סשן עבור כל פעולה סוכנית (agentic). הערך של סשן טמון ב-cache החם שלו. התייחסו להחלפת מודלים כפי שהייתם מתייחסים לניקוי ה-cache, כיוון שזה בדיוק מה שקורה בפועל.
- ניתוב חופשי של סוכני משנה (subagents). סוכן משנה שמתחיל עם הקשר (context) טרי וקטן אינו מאבד cache חם, ולכן הוא יכול לרוץ על כל מודל שמתאים למשימתו. זהו המקום היחיד בתוך ה-agent שבו הניתוב הוא כמעט ללא עלות.
כדי לבנות זאת, ה-gateway מבצע את העבודה: כינויי מודלים (model aliases) ורשימות fallback מפורשות. תצורה מינימלית של LiteLLM proxy נראית כך.
model_list:
- model_name: agent-primary
litellm_params:
model: anthropic/claude-opus-5
api_key: os.environ/ANTHROPIC_API_KEY
- model_name: agent-standby
litellm_params:
model: anthropic/claude-sonnet-5
api_key: os.environ/ANTHROPIC_API_KEY
router_settings:
fallbacks: [{"agent-primary": ["agent-standby"]}]
num_retries: 2
cooldown_time: 30כוונו את ה-agent אל agent-primary והוא יישאר על מודל אחד עד שאותו מודל לא יהיה זמין. שני הערכים יושבים אצל אותו ספק, כך שפורמט קריאות הכלי אינו משתנה כאשר ה-fallback מופעל. אתם עדיין מקבלים שינוי שכבה באותו רגע, וזו פשרה ששווה לעשות רק כי החלופה היא בקשה שנכשלה. זהו ניתוב זמינות ללא ניתוב עלות נלווה, וזהו השילוב שרוב ה-agents לכתיבת קוד מחפשים. הבנייה המלאה, כולל מפתחות ותקציבים, מכוסה במדריך הרצת LiteLLM gateway בניהול עצמי על ה-VPS שלכם, ופוסט זה נמנע במכוון מחזרה על כך.
כאשר מודל אחד שנבחר היטב עדיף על כל נתב
ניתוב (routing) הוא פתרון לשונות בקושי של בקשות. לסוכן תכנות יש פחות שונות כזו ממה שנראה לעין, כיוון שהחלק היקר בכל קריאה הוא אותו prefix, ללא קשר למה שהקריאה מבקשת. ברגע שה־prefix דומיננטי, ההפרש בין השכבה הזולה לשכבה היקרה מצטמצם לכדי ההפרש במחירי הפלט שלהן, והפלט מהווה חלק קטן מהטוקנים של סוכן.
לכן, ברירת המחדל הכנה היא מודל אחד, שנבחר פעם אחת, עם caching מופעל ו־TTL (זמן חיים) ארוך מספיק כדי לכסות את ההפסקות שבהן אתם עוצרים לקרוא diff. חברת Anthropic מציעה כתיבת cache לשעה במחיר של פי 2 מקלט בסיסי, מה שמחזיר את ההשקעה לאחר שתי קריאות, וזה לרוב מנוף טוב יותר מכל נתב. בחרו את השכבה באופן מושכל באמצעות השוואה ישירה בין Opus, Sonnet ו-Haiku, ואם החשבון עדיין מהווה בעיה, צמצמו אותו באמצעות תקציבים והקשרים (contexts) קטנים יותר כפי שמתואר ב-שליטה בעלויות סוכן AI על גבי VPS, במקום באמצעות החלפת מודלים באמצע סשן.
נתבו בקשות כאשר הן עצמאיות וקצרות, או כאשר סוכני משנה מתחילים עם הקשרים חדשים. קבעו מודל אחד (pin) כאשר יש לכם סשן ארוך שמבצע משימה אחת. רוב העבודה של סוכני תכנות היא מהסוג השני, וזו הסיבה שהנתב שחוסך כסף במוצר צ'אט שלכם יעלה לכם כסף בשקט כאן. אם טרם החלטתם על הסוכן עצמו, ההשוואה בין Claude Code לבין Cursor, Codex ו-Copilot מכסה כיצד כל אחד מהם מטפל בבחירת מודל, וחלקם מקבלים את ההחלטה הזו עבורכם.
FAQ
האם החלפת מודלים באמצע סשן באמת גורמת לאובדן ה-prompt cache?
כן. ה-prompt caches מבוססים על hash של תחילית ה-prompt ונשמרים ברמת המודל, לכן בקשה שנשלחת למודל אחר מבצעת hash מול מאגר שמעולם לא ראה את התחילית הזו. המערכת לא מוצאת דבר וגובה את מלוא המחיר על קלט ללא cache, ולאחר מכן גובה תשלום על כתיבה ל-cache אם האפשרות מופעלת. חזרה למודל הקודם לא משחזרת את הרשומה המקורית, כיוון שזמן החיים המוגדר כברירת מחדל של חמש דקות בדרך כלל פג עד אז. בדקו את השדות cache_read_input_tokens ו-cache_creation_input_tokens באובייקט ה-usage של התגובה: סבב שקורא אפס tokens מה-cache בסשן ארוך הוא הסימפטום לכך.
האם ניתוב למודל זול יותר הוא אי פעם משתלם עבור סוכן (agent)?
רק כאשר אין cache חם שעלול ללכת לאיבוד. קריאה מה-cache ב-Anthropic עולה פי 0.1 ממחיר קלט בסיסי, מה שהופך קריאה חמה ב-Opus 5 לזולה יותר ממחיר קלט ללא cache ב-Haiku 4.5. ברגע שלסשן יש תחילית גדולה ב-cache, המודל הנוכחי הוא כבר האופציה הזולה ביותר מבחינת קלט. הניתוב משתלם כשההקשר (context) טרי וקטן: בתחילת משימה, או בסוכן משנה (subagent) שנושא רק את ההקשר הדרוש לו.
מדוע הסוכן שלי התנהג אחרת באמצע משימה?
בדקו אם הופעל מנגנון fallback ב-gateway. מגבלת קצב (rate limit) או שגיאת 5xx במודל הראשי גורמים ל-gateway לנסות שוב מול מודל הגיבוי ולהעביר את המודל הראשי למצב קירור (cooldown) למשך מספר שניות, כך ששארית המשימה רצה במקום אחר. פעולה זו אינה מייצרת שגיאה או אזהרה, והמשימה מדווחת כהצלחה. השדה model בלוג הבקשות של ה-gateway או במטא-דאטה של התגובה הוא התיעוד האמין היחיד, לכן תעדו אותו לכל בקשה אם אתם מפעילים fallbacks.
האם קריאות לכלים (tool calls) עובדות אותו דבר בכל ספק?
לא בדיוק. ה-Messages API של Anthropic משתמש בבלוקים של תוכן מסוג tool_use ו-tool_result, בעוד ש-APIs תואמי OpenAI משתמשים במערך tool_calls שבו ה-function.arguments הוא מחרוזת מקודדת ב-JSON. ה-gateway מתרגם היטב את המקרים הנפוצים, אך קריאות כלים מקביליות ואכיפת סכימה קפדנית משתנות בין ספק לספק. ב-vLLM בהתקנה עצמית עליכם להגדיר --enable-auto-tool-choice ו---tool-call-parser התואמים למשפחת המודלים שלכם. תיעוד ה-vLLM מציין שללא אילוץ סכימה קפדני, השרת מחלץ קריאות כלים מתוך טקסט גולמי, ולכן ארגומנטים עלולים לעיתים להיות שגויים במבנה שלהם.
לכמה זמן כדאי להגדיר את ה-cache TTL עבור סשן תכנות?
השתמשו בזמן החיים המוגדר כברירת מחדל של חמש דקות לעבודה רציפה, ובאופציה של שעה אחת כאשר אדם קורא diffs בין סבבים. Anthropic מתמחרת כתיבה של חמש דקות פי 1.25 מקלט בסיסי, וכתיבה של שעה פי 2, לעומת קריאה שעולה פי 0.1. עלות הכתיבה של חמש דקות מכוסה על ידי קריאה אחת, ועלות הכתיבה של שעה על ידי שתיים. לכן, בכל סשן שבו אתם מצפים לחזור ולהמשיך, זמן חיים ארוך יותר בדרך כלל עולה פחות מאשר תשלום על תחילית קרה.