SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-08-31

איך להגביל עלויות של סוכן AI שרץ על VPS

סוכן AI שרץ ללא השגחה על שרת VPS עלול לצבור עלויות גבוהות בגלל לולאות אינסופיות. למדו כיצד להגדיר תקרות תקציב, להשתמש ב-prompt caching ולנטר שימוש ב-API למניעת חיובים חריגים.

כיצד למנוע מסוכן AI הפועל ללא הפסקה לצבור עלויות גבוהות

בקרת עלויות של סוכן AI על גבי VPS (שרת וירטואלי פרטי) מתבססת על תקרות שקובעים לפני הפעלת הסוכן, שכן איש אינו עוקב אחר המונה בזמן שהסוכן רץ. הגבילו כל תגובה באמצעות max_tokens, תַחמו את מספר האיטרציות של הלולאה בקוד שלכם, בצעו caching לחלק של ה-prompt שאינו משתנה, ותעדו את נתוני השימוש של כל תגובה כדי לזהות אילו משימות צורכות משאבים. דמי השכירות של השרת הם מחיר חודשי קבוע. ה-API של המודל מתומחר לפי token, ולולאה שרצה ללא השגחה עלולה לצבור עלויות גבוהות בשקט.

מדריך זה מניח שקיים כבר סוכן המבצע קריאות ל-Messages API משרת שבבעלותכם. המאמר בניית סוכן AI עם Claude על גבי VPS מכסה את התשתית הטכנית לכך.

מדוע סוכן אוטונומי (unattended) כרוך בעלות שונה

בסשן אינטראקטיבי מעורב אדם. כאשר המודל פונה לנתיב שגוי או קורא לוג באורך 40,000 שורות, המשתמש שעוקב אחריו עוצר אותו. לסוכן אוטונומי אין "בלם" כזה: הוא רץ עד לסיום הלולאה, ואז טיימר מפעיל אותו מחדש.

תדירות היא המכפיל שאנשים נוטים לפספס. משימה שמוגדרת לרוץ כל חמש דקות מתבצעת 288 פעמים ביום וכ-8,640 פעמים בחודש. העלות של הרצה בודדת היא המספר שעליך להכפיל. סוכנים רבים שמוגדרים כ-"always-on" אינם באמת צריכים להיות כאלה. הם רק צריכים להגיב בתוך מספר דקות, מה שמהווה למעשה לוח זמנים.

סוכן משלם גם על דברים שחלון צ'אט אינו משלם עליהם.

  • הגדרות כלים נלוות לכל בקשה. ה-prompt של מערכת השימוש בכלים עולה 290 טוקנים ב-Claude Opus 4.8 עם tool_choice של auto או none, ו-410 עם any או tool. הכלי bash מוסיף 325 טוקנים נוספים. כל שרת MCP שאתה מחבר מוסיף את הסכימות שלו למשקל הזה, כאשר MCP הוא ה-model context protocol.
  • תוצאות כלים הן טוקני קלט. פקודה שמדפיסה 8,000 שורות מכניסה 8,000 שורות לבקשה הבאה, ולכל בקשה שאחריה באותו סבב.
  • דפים שנטענו הם טוקני קלט. דף אינטרנט ממוצע של 10 kB הוא בערך 2,500 טוקנים, וקובץ PDF מחקרי של 500 kB הוא בערך 125,000. max_content_tokens מקצץ רק את תכני הטקסט, כיוון שהוא "חל על תוכן טקסטואלי, לא על תוכן בינארי כמו קובצי PDF". הגבל קובץ PDF באמצעות max_uses ו-allowed_domains במקום זאת.
  • חיפוש באינטרנט מתומחר לפי חיפוש, בעלות של 10$ ל-1,000 חיפושים, ללא קשר למספר התוצאות שחוזרות. חיפוש שנכשל אינו מחויב בתשלום.

אף אחד מהדברים הללו אינו יקר כשהוא קורה פעם אחת. כולם יקרים כשהם קורים 8,640 פעמים.

תקרות קשיחות ותקרות רכות פותרות בעיות שונות

max_tokens נאכף. זוהי תקרה קשיחה על סך הפלט של בקשה אחת, הכוללת את החשיבה ואת טקסט התגובה יחד. Claude לעולם לא יפיק פלט מעבר לה, והמודל אינו יכול לראות את המספר. הגעה לתקרה זו מניבה stop_reason: "max_tokens" ותשובה קטועה. המלכוד עבור סוכנים: כל בקשה בלולאת שימוש בכלים נושאת את ה-max_tokens שלה, לכן היא מגבילה תגובה אחת ולא את המשימה כולה. עשר קריאות לכלי ב-4,000 טוקנים מהוות תקרה של 40,000 טוקנים עבור הסבב.

תקציב משימה הוא בגדר המלצה. task_budget נמצא בתוך output_config ומורה למודל כמה טוקנים עומדים לרשותו עבור כל לולאת הסוכן, תוך ספירת החשיבה, הקריאות לכלים, תוצאות הכלים והפלט.

resp = client.beta.messages.create(
    model="claude-opus-4-8",
    max_tokens=4096,
    betas=["task-budgets-2026-03-13"],
    output_config={"task_budget": {"type": "tokens", "total": 64000}},
    messages=messages,
)

"תקציבי משימה הם רמז רך, לא תקרה קשיחה." Claude עשוי לחרוג מהם במהלך פעולה, והמגבלה הנאכפת על הפלט נותרת max_tokens. "הספירה לאחור גלויה למודל בלבד", ותגובות אינן נושאות שדה של תקציב שנותר. ה-task_budget.total המינימלי המקובל הוא 20,000 טוקנים, וערך נמוך מכך יחזיר שגיאת 400. תקציב קטן מדי עבור העבודה יגרום להתנהגות דמוית סירוב, כך שהמודל יצמצם את היקף המשימה או יעצור מוקדם.

פרט אחד עולה כסף במקום לחסוך אותו. אם הלקוח שלכם מפחית את task_budget.remaining בכל בקשת המשך, הערך המשתנה מבטל כל תחילית (prefix) שמורה המכילה אותו. הגדירו אותו פעם אחת, בבקשה הראשונה.

תקציבי משימה נמצאים בגרסת בטא ב-Claude Fable 5, ב-Claude Opus 4.8 וב-Claude Opus 4.7. המודלים Claude Sonnet 5 ו-Claude Haiku 4.5 מוגדרים כ-Not supported, ותקציבי משימה אינם חלים על Claude Code, לכן סשן Claude Code מנותק ב-tmux תלוי בהיגיינת סשנים במקום זאת.

התקרה השלישית נמצאת ב-Claude Console: העניקו לסוכן סביבת עבודה משלו, ולאחר מכן הגדירו בה מגבלת הוצאה חודשית ומגבלות קצב לדקה. "לא ניתן להגדיר מגבלות על סביבת העבודה המוגדרת כברירת מחדל" (Default Workspace), ו-"מגבלות ברמת הארגון חלות תמיד, גם אם סכום המגבלות של סביבות העבודה גבוה יותר". הוסיפו התראות הוצאה כדי שסף מסוים יתריע בפניכם לפני הגעה לתקרה.

בחירת מודל לכל משימה, ומה באמת משנה את רמת המאמץ

בחירת המודל היא החלטה שמתקבלת עבור כל משימה בנפרד. נכון ליולי 2026, המחיר למיליון טוקנים (קלט ולאחריו פלט) הוא: Claude Fable 5 ב-$10 ו-$50, Claude Opus 4.8 ו-Opus 4.7 ב-$5 ו-$25, Claude Sonnet 5 ב-$3 ו-$15, ו-Claude Haiku 4.5 ב-$1 ו-$5. המודל Sonnet 5 מתומחר כרגע מתחת למחיר הרשמי שלו, כיוון ש"תמחור היכרות של $2/$10 למיליון טוקני קלט/פלט בתוקף עד ה-31 באוגוסט 2026". שלב שמבצע סיווג של שורות לוג בלבד אינו זקוק ל-Opus. אין גם מכסה חינמית שתספוג עומס עבודה, כיוון ש-ל-Claude API אין מסלול חינמי מעבר לקרדיט הקטן שניתן בעת ההרשמה.

רמת המאמץ (effort) היא המנוף השני. output_config.effort מקבל את low, medium, high, xhigh ו-max, כאשר ברירת המחדל היא high; לכן, הגדרה מפורשת של high זהה להשמטתו. רמת מאמץ נמוכה יותר חוסכת יותר מאשר רק קיצור אורך החשיבה: התיעוד מציין שהיא גורמת ל-Claude לבצע פחות קריאות לכלים (tool calls) ולשלב פעולות לכדי פעולה אחת. בסוכן (agent), זהו החיסכון המשמעותי יותר, כיוון שקריאה לכלים שנמנעה היא בקשה שלמה שלעולם לא מתרחשת.

המלכודת היא שרמת המאמץ מתנגשת עם ה-cache. שינוי הערך בין בקשות מבטל את ה-prompt caching. בדוגמה המתועדת, בקשה 2 דיווחה על cache_read_input_tokens: 3546; בקשה 3, עם שינוי רמת המאמץ מ-high ל-medium, דיווחה על cache_creation_input_tokens מתוך 3546 ו-cache_read_input_tokens מתוך 0. לכן, יש לשנות את רמת המאמץ בין עומסי עבודה שונים, ולעולם לא בתוך שיחה אחת שנשמרה ב-cache. כדי לכוון את עומק החשיבה מבלי לשבור את ה-cache, יש לעשות זאת ב-prompt: שורה כמו "ענה ישירות ללא התלבטות" בהודעת המשתמש האחרונה מותירה את נקודות העצירה הקודמות ללא פגע.

טוקני חשיבה מחויבים לפי תעריפי פלט ונספרים כחלק מ-max_tokens, וזו הסיבה שתשובה קטועה מעידה לעיתים קרובות על כך שהחשיבה כילתה את התקציב. קראו את usage.output_tokens_details.thinking_tokens עבור המספר. מה באמת מרכיב את חשבון הטוקנים של Claude מפרק את המונה לגורמים.

שמירה במטמון של ה-prefix היציב, ומניעת פגיעה בו בטעות

כתיבה למטמון עולה פי 1.25 ממחיר הקלט הבסיסי עבור מטמון של חמש דקות, ופי 2 עבור מטמון של שעה. קריאה מהמטמון עולה פי 0.1, לכן "השימוש במטמון משתלם כבר לאחר קריאה אחת עבור משך של 5 דקות (כתיבה של 1.25x), או לאחר שתי קריאות עבור משך של שעה (כתיבה של 2x)".

שורה אחת מסבירה מדוע זה מתאים לסוכן (agent) שפועל ללא הפסקה: "המטמון מתרענן ללא עלות נוספת בכל פעם שהתוכן השמור בשימוש". משימה שמופעלת כל שתי דקות מול מטמון של חמש דקות שומרת על ה-prefix שלה חם לאורך כל היום בעלות של כתיבה אחת בלבד.

שלוש דרכים לאבד את המטמון מבלי להבחין בכך.

prefix שמשתנה. "ה-prefixes של המטמון נוצרים בסדר הבא: tools, system, ולאחר מכן messages." כל שינוי בבתים (bytes) המופיעים מוקדם יותר בסדר זה מבטל את כל מה שבא אחריו, ועריכת הגדרות של כלים מבטלת את המטמון כולו. הטעות הנפוצה ביותר היא הכללת חותמת זמן או מזהה הרצה (run id) בתוך ה-system prompt: כל בקשה נושאת אז prefix שונה, כותבת רשומה חדשה בעלות של 1.25x, ולא קוראת דבר בחזרה. הסימן לכך הוא usage.cache_read_input_tokens בערך 0 בקריאות שנראות זהות. העבירו את הטקסט המשתנה להודעת המשתמש האחרונה.

prefix קצר מדי. לכל מודל יש אורך מינימלי שניתן לשמירה במטמון; מתחת לאורך זה, הבקשה מעובדת ללא שימוש במטמון ו"לא מוחזרת שגיאה". הנתונים כוללים 1,024 טוקנים ב-Claude Opus 4.8 וב-Claude Sonnet 5, ו-4,096 ב-Claude Haiku 4.5, לכן העברת משימה מ-Sonnet ל-Haiku עלולה להשבית את השימוש במטמון בשקט.

שיחה שחורגת מחלון הסריקה (lookback). "חלון הסריקה הוא 20 בלוקים." המערכת בודקת לכל היותר 20 מיקומים לכל נקודת עצירה (breakpoint), ואז עוצרת. בדוגמה המתועדת, תור (turn) המכיל 35 בלוקים עם נקודת עצירה בבלוק 35 בודק את בלוקים 35 עד 16, והרשומה של התור הקודם בבלוק 15 נופלת מחוץ לחלון, לכן אין התאמה (hit). סוכן שמוסיף כמה בלוקים של שימוש בכלים ותוצאות כלים בכל תור חוצה את רף ה-20 תוך שניים או שלושה תורים. עומדות לרשותכם ארבע נקודות עצירה לכל בקשה, לכן הקצו אחת מהן להודעות האחרונות.

שלחו כל משימה שיכולה להמתין ל-Batches API

"כל השימוש מחויב ב-50% ממחירי ה-API הסטנדרטיים", הן עבור קלט והן עבור פלט. עיבוד אצווה (Batch processing) הוא אסינכרוני, "כאשר רוב האצוות מסתיימות בפחות מ-1 שעה", והתוצאות זמינות לאחר שכל בקשה הסתיימה או לאחר 24 שעות, המוקדם מביניהם. זהו המצב האופייני, אך הוא אינו מובטח.

בצעו polling ל-processing_status עד שהסטטוס יהיה ended. בקשות שמחזירות errored, canceled או expired אינן מחויבות בתשלום. סייג אחד אם אתם מסתמכים על מגבלת הוצאות: "אצוות עשויות לחרוג מעט ממגבלת ההוצאות שהוגדרה עבור ה-Workspace שלכם".

ההנחות מצטברות, ומכיוון שאצווה עשויה להימשך יותר מחמש דקות, התיעוד ממליץ על מטמון של שעה עבור אצוות שחולקות הקשר (context). לכן, פצלו את העבודה: כל מה שאדם או webhook ממתינים לו נשאר בנתיב החי (live path), בעוד סיכום לילי או סיווג לוגים מאתמול עוברים לאצווה בחצי מחיר.

תיעוד שדות השימוש של כל תגובה במאגר נתונים מקומי

לא ניתן לייחס הוצאות שלא תועדו. כל תגובה מציינת את העלות שלה.

u = resp.usage
row = {
    "job": job_name,
    "model": resp.model,
    "uncached_input": u.input_tokens,
    "cache_write": u.cache_creation_input_tokens,
    "cache_read": u.cache_read_input_tokens,
    "output": u.output_tokens,
    "stop_reason": resp.stop_reason,
}

הוסיפו שורה אחת לכל קריאת API לקובץ JSON-lines, מתויגת לפי שם המשימה שלכם. לאחר שבוע תוכלו לדעת איזו משימה צורכת משאבים ואיזו רק נראית עמוסה. עקבו אחר cache_read: עמודה של אפסים היא באג העלות הנפוץ ביותר בסוכן (agent) המתארח באופן עצמאי.

שדה אחד עלול להטעות בקריאה. input_tokens סופר רק את הטוקנים שאחרי נקודת ה-cache האחרונה, לכן גודל ה-prompt האמיתי הוא total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens. סוכן שמדווח על input_tokens: 400 ב-prompt גדול אינו זול: השאר הגיע מה-cache.

בצעו ספירה לפני השליחה. ספירת טוקנים היא פעולה חינמית ומגבלות הקצב שלה נפרדות מיצירת הודעות, לכן השתמשו ב-count_tokens כדי לסרב לקובץ מצורף גדול מדי במקום לשלם כדי לגלות זאת. התוצאה היא הערכה בלבד, לכן בצעו מדידה מחדש עבור כל מודל ולעולם אל תעשו שימוש חוזר בספירה של tokenizer מספק אחר. Claude Opus 4.7 ומודלי Opus מאוחרים יותר, Claude Fable 5 ו-Claude Sonnet 5 משתמשים ב-tokenizer חדש ש"מייצר כ-30% יותר טוקנים עבור אותו טקסט". Claude Sonnet 4.6 וגרסאות מוקדמות יותר, ביניהן Claude Haiku 4.5, משתמשים בגרסה הקודמת.

לקבלת תמונה מהימנה, ה-Admin API מדווח על שימוש ב-https://api.anthropic.com/v1/organizations/usage_report/messages ועל עלות ב-https://api.anthropic.com/v1/organizations/cost_report. שניהם דורשים מפתח ניהול (sk-ant-admin01-...) כ-x-api-key: $ANTHROPIC_ADMIN_KEY עם anthropic-version: 2023-06-01, ומקבלים את bucket_width=1d, group_by[]=model ו-api_key_ids[]=. מגבלה אחת: "ה-Admin API אינו זמין עבור חשבונות אישיים".

הפרמטר האחרון הוא טריק זול לייחוס עלויות: תנו לכל משימה מפתח API משלה, סננו בעזרת api_key_ids[], ופצלו את הדוח לפי מפתח בעזרת group_by[]=api_key_id. המסנן הוא ברבים, בעוד ממד הקיבוץ הוא ביחיד. שמרו את המפתחות בסביבת העבודה (environment) ולא בקוד, כפי שמתואר ב-יישום Claude API ראשון על שרת VPS.

הגבלת הלולאה, כי שום דבר אחר לא יעשה זאת

ספירת איטרציות מוגבלת אינה בגדר רשות כאן. הלולאה היא שלך, ולכן המונה הוא שלך:

for step in range(MAX_STEPS):          # MAX_STEPS = 12, never "while True"
    resp = client.messages.create(...)
    if resp.stop_reason != "tool_use":
        break
else:
    log.warning("job %s hit MAX_STEPS=%d, giving up", job_name, MAX_STEPS)

אף תקרה שצוינה לעיל לא תעשה זאת עבורך: max_tokens מגביל תגובה אחת בלבד, והמודל רק מקבל הנחיה לגבי תקציב המשימה. מוצר מאוחסן היה עוצר אותך כאן, בדומה לאופן שבו המגבלה של Claude על קריאות לכלי בתוך סבב יחיד עוצרת סשן שביצע יותר מדי קריאות כאלו, אך לולאה שכתבת בעצמך מגיעה ללא מנגנון הגנה כזה עד שתוסיף אחד.

התקן בלם שני מחוץ לתהליך. הרץ את המשימה מתוך systemd timer במקום כתהליך קבוע, והגדר RuntimeMaxSec= ביחידת השירות שלו. בעזרת RuntimeMaxSec=600, הרצה שתקועה תסתיים לאחר עשר דקות במקום להמשיך לרוץ עד שתבחין בכך. הרצת תוכנית כשירות וטיימר ב-systemd מכסה את קובצי היחידה עצמם. בדוק מה ביצעה הרצה מסוימת בעזרת journalctl -u triage-agent.service --since "1 hour ago".

הגבל גם ניסיונות חוזרים (retries), כיוון שטיפול שמנסה שוב ושוב יחייב אותך על כל ניסיון. שגיאת 429 או 500 מצדיקה מספר ניסיונות עם backoff. שגיאת 400 אינה מצדיקה אף ניסיון, כיוון שאותה בקשה תיכשל באותו אופן.

בקרת עלויות של סוכן AI מתחילה בקריאת הנתונים שלכם

אף אחד לא יכול לומר לכם מה העלות של סוכן שפועל ללא הפסקה, כיוון שהעלות היא מספר ה-tokens לכל הרצה כפול מספר ההרצות ביום, ושני המשתנים הללו שייכים לכם. הריצו את הסוכן פעם אחת, קראו את שורת השימוש שתיעדתם, והכפילו בלוח הזמנים שלכם. בדקו את דוח העלויות יומיים לאחר מכן מול החישוב הזה. כאשר השניים אינם תואמים, הפער הוא כמעט תמיד מטמון (cache) פגום או לולאה שרצה זמן רב יותר ממה שהנחתם.

הנחה זו מבוססת על שימוש ב-API key, כיוון שהסוכן הוא תוכנית שלכם הקוראת ל-Messages API. עבור עבודה אינטראקטיבית שלכם, איזו תוכנית Claude מתאימה לאופן העבודה שלכם מכסה את הצד של המנוי. כל מחיר ומגבלה כאן נבדקו מול התיעוד של Anthropic ביולי 2026, לכן קראו שוב את דף התמחור לפני שאתם בונים תקציב.

FAQ

כמה עולה להריץ סוכן AI פעיל תמיד על גבי VPS?

קיימות שתי חשבוניות, ורק אחת מהן ניתנת לחיזוי. השרת הוא בעלות חודשית קבועה. ה־API של המודל מתומחר לפי טוקנים, לכן העלות היא תוצר של צריכת הרצה בודדת כפול תדירות ההרצה. Anthropic לא מפרסמת נתונים עבור סוכן עצמאי שרץ תמיד, לכן יש להתייחס לכל מספר שמוצג כהערכה בלבד. בצעו לוג ל־usage מהרצה אחת אמיתית והכפילו לפי לוח הזמנים שלכם.

מה ההבדל בין max_tokens לבין תקציב משימה?

הערך max_tokens נאכף ואינו גלוי למודל. הוא מגביל את הפלט של בקשה בודדת, כולל תהליך החשיבה, וחריגה ממנו מניבה stop_reason: "max_tokens". תקציב משימה הוא ההפך: המודל מקבל את המספר ומנהל את לולאת הסוכן לפיו, אך "תקציבי משימה הם רמז רך, לא מגבלה קשיחה" והמגבלה הנאכפת היא עדיין max_tokens.

מדוע cache_read_input_tokens תמיד אפס עבור הסוכן שלי?

מכיוון שהתחילית משתנה בין קריאות, או שהיא קצרה מכדי לעבור שמירה בזיכרון מטמון (cache). הסיבה הנפוצה היא חותמת זמן או מזהה הרצה (run id) שמוכנסים לתוך ה-system prompt: המטמון מבוסס על התחילית, לכן כל שינוי בבייט בודד מבטל את כל מה שאחריו. שינוי בהגדרות הכלים או בערך ה-effort גורם לאותה תוצאה. סיבה נוספת היא גודל, שכן הנחיות קצרות אינן נשמרות במטמון ולא מתקבלת שגיאה על כך.

איך עוצרים סוכן AI מלהיכנס ללולאה אינסופית?

ספרו את מספר האיטרציות בקוד הלולאה שלכם ועצרו במספר מקסימלי קבוע, כיוון ש-max_tokens מגביל תגובה בודדת בעוד סוכן מבצע פעולות רבות. הוסיפו מגבלת זמן חיצונית לתהליך: הפעילו את המשימה מתוך systemd timer עם הגדרת RuntimeMaxSec=, כך שהרצה תקועה תסתיים לפי לוח זמנים. הגבילו גם ניסיונות חוזרים (retries), שכן לולאת ניסיונות חוזרים מחייבת על כל ניסיון.

האם ניתן להגדיר מגבלת הוצאות על מפתח API בודד של Claude?

מגבלת ההוצאות המתועדת היא ברמת ה-workspace ולא ברמת המפתח, לכן הקצו לסוכן workspace משלו והגבילו את ההוצאה החודשית שם. "לא ניתן להגדיר מגבלות על ה-Default Workspace". הוסיפו התראות הוצאה כך שסף מסוים יתריע בפניכם מראש. לצורך שיוך עלויות, הנפיקו לכל משימה מפתח משלה, ולאחר מכן קבצו את דוח השימוש באמצעות group_by[]=api_key_id.