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

איך לבנות מערכת הערכות (Evals) עצמית לסוכני AI

למדו לבנות לולאת הערכה עצמית לסוכני AI בעזרת Python ו-SQLite. המדריך מפרט איך להפוך traces אמיתיים למקרי בוחן, להריץ בדיקות דטרמיניסטיות ולעקוב אחר שיעור ההצלחה בכל commit.

מהן הערכות (evals) עצמיות לסוכני AI

הערכות עצמיות (self-hosted evals) לסוכני AI הן ארבעה רכיבים שאתם שומרים במאגר הקוד שלכם: קובץ עם מקרי בוחן שמורים, סקריפט שמריץ את הסוכן מולם, סט בדיקות שמדרג כל תשובה, וטבלה של תוצאות שניתן לבצע עליה שאילתות. אף אחד מהרכיבים הללו אינו מחייב ספק חיצוני. כל הלולאה הזו מורכבת מכמה מאות שורות של Python וקובץ SQLite אחד.

הסוכן עבד בהדגמה כי בחרתם את חמשת הקלטים בעצמכם. הוא נשבר בשבוע השני כי שורת prompt השתנתה, או שהמודל השתנה, או שתיאור הכלי השתנה, ואף מדידה לא כיסתה זאת. לולאת הערכה הופכת תחושה של "זה מרגיש פחות טוב עכשיו" לנתון של "שיעור ההצלחה ירד מ-58 מתוך 60 ל-51 מתוך 60 ב-commit 4f1c9ab".

הלולאה מורכבת מארבעה שלבים, ומדריך זה מוקדש שלב אחד לכל סעיף: איסוף עקבות (traces) אמיתיים, קידום המקרים המעניינים למקרי בוחן, דירוג כל מקרה בכל שינוי, ושמירת שיעור ההצלחה לצד ה-commit שיצר אותו. אותה לולאה עובדת ללא קשר למה שעליו אתם מריצים את הסוכן, ו-מסגרות העבודה לסוכנים בהרצה עצמית ששווה להריץ נבדלות בעיקר בכמות העקבות שהן מספקות לכם בחינם.

מדוע הסוכן מפסיק לעבוד בשבוע השני

סוכן מורכב מ-prompt, מודל, קבוצת הגדרות של כלים, וכל הקשר (context) שנשלף בזמן הריצה. כל ארבעת המרכיבים הללו יכולים להשתנות מבלי שקוד היישום שלכם ישתנה, ולכן סקירת קוד רגילה לא תזהה שום בעיה.

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

הסיבה השנייה היא המודל. תעדו את מחרוזת המודל המדויקת ששלחתם בכל הרצה, claude-haiku-4-5-20251001 במקום להסתמך על קיצור שאתם זוכרים בראש, כיוון ששיעור הצלחה שיורד ביום שבו החלפתם מודלים ניתן לאבחון רק כאשר המודל מתועד בשורה המתאימה.

הסיבה השלישית היא כלים. ניסוח מחדש של תיאור כלי משנה את המועד שבו המודל מחליט לקרוא לו. אם הכלים שלכם מגיעים דרך שרתי MCP הרצים על גבי VPS, הסכימה נמצאת בתהליך אחר, ולכן היא יכולה להשתנות מבלי שיהיה שום הבדל (diff) במאגר הקוד שלכם. הסיבה הרביעית היא שליפה: אותה שאלה מגיעה לאינדקס שנבנה מחדש במהלך הלילה, והתשובה נגזרת מהמסמך החדש.

בניית סט הזהב מתוך עקבות (traces) שנאספו

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

ייצאו חלון זמן של תצפיות שורש (root observations) דרך ה-API הציבורי. הוא משתמש באימות בסיסי (basic authentication), כאשר המפתח הציבורי שלכם משמש כשם משתמש והמפתח הסודי כסיסמה.

export LF_HOST="https://langfuse.example.com"
curl -sS -u "$LF_PUBLIC_KEY:$LF_SECRET_KEY" \
  "$LF_HOST/api/public/v2/observations?limit=50&isRootObservation=true&fromStartTime=2026-07-01T00:00:00Z" \
  | jq '.data[0]'

קראו רשומה אחת לפני שאתם כותבים לוגיקת עיבוד (parsing). השורות חוזרות תחת data, אך שמות השדות המכילים את השאלה והתשובה תלויים באופן שבו הסוכן שלכם מבצע אינסטרומנטציה ל-spans שלו; לכן, בצעו מיפוי למה שאתם רואים בפועל במקום למה שציפיתם לראות. לאחר מכן, כתבו את המקרים ידנית, אובייקט JSON אחד לכל שורה, בתוך evals/cases.jsonl:

{"id": "refund-double-charge", "tags": ["smoke"], "input": "I was charged twice for order 41822.", "must_call": ["lookup_order", "create_refund"], "must_not_include": ["I cannot help"], "rubric": "The reply confirms exactly one refund for order 41822 and states the amount."}

חמישה כללים ישמרו על הסט ככלי עבודה יעיל:

  • 40 עד 80 מקרים הם כמות מספקת להתחלה. מתחת ל-20 מקרים, מקרה בודד שאינו יציב (flaky) מזיז את אחוז ההצלחה ב-5 נקודות, ומספר שקופץ ללא סיבה נראה לעין יזכה להתעלמות.
  • כל באג בייצור (production) שאתם מתקנים הופך למקרה בוחן ביום התיקון. הרגל זה הוא מה שגורם לסט לצמוח בכיוון הנכון.
  • התנהגות אחת לכל מקרה. מקרה בוחן שבודק בו-זמנית את סכום ההחזר ואת הטון של התשובה לא יספק לכם מידע מועיל כאשר הוא ייכשל.
  • ה-id לעולם אינו משתנה, כיוון שה-id הוא הדרך שבה ההרצה של היום מושוות לזו של החודש שעבר.
  • בצעו הסתרה (redaction) לפני ה-commit. קובץ זה נכנס ל-git, לכן הסירו שמות לקוחות וכל מספר הזמנה שאינו בבעלותכם.

בצעו הערכה עם בדיקות דטרמיניסטיות תחילה, כיוון שהן אינן כרוכות בעלות

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

פונקציה אחת בלבד מכירה את ה-agent שלכם. כל שאר המרכיבים ב-harness הם גנריים.

import json, os, urllib.request

def run_agent(case):
    req = urllib.request.Request(
        os.environ["AGENT_URL"],
        data=json.dumps({"input": case["input"]}).encode(),
        headers={"content-type": "application/json"},
    )
    with urllib.request.urlopen(req, timeout=120) as resp:
        return json.load(resp)


def deterministic(case, result):
    text = result.get("output", "")
    called = [c["name"] for c in result.get("tool_calls", [])]
    failures = []
    for tool in case.get("must_call", []):
        if tool not in called:
            failures.append(f"tool not called: {tool}")
    for phrase in case.get("must_not_include", []):
        if phrase.lower() in text.lower():
            failures.append(f"forbidden phrase: {phrase}")
    if len(called) > case.get("max_tool_calls", 12):
        failures.append(f"too many tool calls: {len(called)}")
    return failures

שמרו על תקציב השימוש בכלים בתוך הרשימה הזו. agent שפותר מקרה ב-3 קריאות היום וב-11 קריאות מחר עבר רגרסיה, גם אם התשובה הסופית נכונה, כיוון שאתם משלמים על כל קריאה שהוא מבצע.

שימוש ב-LLM כשופט, וארבע הדרכים שבהן זה משתבש

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

ארבעה כללים הופכים שופט לשימושי:

  • פסיקה בינארית, לעולם לא ציון מ-1 עד 10. סקאלה מחזירה 7 או 8 כמעט על הכל, לכן המספר לעולם לא משתנה ואתם לא לומדים ממנו דבר.
  • קריטריון אחד לכל קריאה. שאלו על סכום ההחזר, או על הטון, לא על שניהם בבת אחת.
  • ספקו לשופט את התשובה המצופה בכל מקרה שבו יש כזו. דירוג מול תשובת ייחוס הוא משימה קלה בהרבה מדירוג מופשט.
  • כפו את מבנה הפלט ונתחו אותו בקפדנות.
from anthropic import Anthropic

client = Anthropic()  # reads ANTHROPIC_API_KEY from the environment


def judge_prompt(case, output):
    return (
        "You grade one answer against one criterion.\n"
        "Reply with JSON only, in this exact shape:\n"
        '{"verdict": "pass", "confidence": "high", "reason": "one short sentence"}\n'
        f"Criterion: {case['rubric']}\n"
        f"Question: {case['input']}\n"
        f"Answer: {output}\n"
        "Length is not a criterion. Judge only the criterion above."
    )


def judge(case, output, model):
    msg = client.messages.create(
        model=model,
        max_tokens=200,
        messages=[{"role": "user", "content": judge_prompt(case, output)}],
    )
    return json.loads(msg.content[0].text)

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

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

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

הטיית מיקום. אם אתם משתמשים בשופט כדי להשוות בין שתי תשובות, A ו-B, החליפו את הסדר והריצו שוב. פסיקה שמשתנה בעקבות ההחלפה מעידה על כך שהשוואה זוגית אינה בטוחה עדיין עבור ה-rubric הזה.

זליגת ה-rubric. קריטריונים מעורפלים מייצרים שופטים נוחים מדי. "האם התשובה מועילה" מעביר כמעט הכל. "האם התשובה מציינת את סכום ההחזר בדולרים" מעביר רק את מה שהתכוונתם אליו. שכתבו כל קריטריון עד שהוא מציין במפורש את העובדה שנבדקת.

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

דירוג זול, הסלמה למודל מתקדם

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

ChartCost to judge 1,000 eval cases, list prices, August 2026
The data behind this chart
[
  {
    "label": "Haiku 4.5, Batch API",
    "usd_per_1000_judge_calls": "0.90"
  },
  {
    "label": "Haiku 4.5",
    "usd_per_1000_judge_calls": "1.80"
  },
  {
    "label": "Sonnet 5",
    "usd_per_1000_judge_calls": "3.60"
  },
  {
    "label": "Opus 5",
    "usd_per_1000_judge_calls": "9.00"
  }
]

נתונים אלו מניחים כ-1,200 טוקנים של קלט ו-120 טוקנים של פלט לכל קריאת מדרג, גודל ריאלי עבור שאלה אחת, תשובה אחת וקריטריון אחד. דירוג של 1,000 מקרים עולה 1.80 דולר ארה"ב ב-Claude Haiku 4.5 ו-9.00 ב-Claude Opus 5. הפער נראה זניח עד שמכפילים אותו. סט של 60 מקרים, שמדורג בכל commit, ב-40 commits בשבוע, מגיע ל-2,400 קריאות מדרג בשבוע עוד לפני שמישהו הריץ את ה-nightly job.

שתי הנחות חלות בצורה נקייה על עבודת eval, והן מצטברות. הרצות eval אינן אינטראקטיביות, לכן ה-Batch API מקצץ בחצי את מחירי הקלט והפלט בתמורה למסירה אסינכרונית, וזו השורה הראשונה בטבלה. ה-rubric וההנחיות זהים בייט-ל-בייט בכל קריאה, לכן prompt caching מתאים כאן: קריאת cache עולה עשירית ממחיר הקלט הבסיסי, וכתיבת cache של חמש דקות עולה פי 1.25 ממחיר הקלט הבסיסי, כך שה-cache מחזיר את עצמו לאחר פגיעה אחת. אלו מחירי המחירון של Anthropic נכון לאוגוסט 2026, ו-Sonnet 5 נמצא בתמחור היכרות עד ה-31 באוגוסט 2026, לכן העמודה השלישית תעלה לאחר תאריך זה.

הסולם, לפי הסדר:

  • בדיקות דטרמיניסטיות על כל מקרה. ללא עלות API כלל.
  • מודל מדרג קטן על המקרים שעברו את הבדיקות הללו.
  • מדרג מתקדם רק במקרים שבהם המדרג הקטן מדווח על כישלון, או על הצלחה בביטחון נמוך.
  • סקירה אנושית על מדגם קטן, פעם בשבוע.
CHEAP = "claude-haiku-4-5-20251001"
STRICT = "claude-opus-5"


def grade(case, result):
    hard = deterministic(case, result)
    if hard:
        return False, "deterministic", "; ".join(hard)
    first = judge(case, result["output"], CHEAP)
    if first["verdict"] == "pass" and first["confidence"] == "high":
        return True, CHEAP, first["reason"]
    second = judge(case, result["output"], STRICT)
    return second["verdict"] == "pass", STRICT, second["reason"]

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

מעקב אחר שיעור ההצלחה לאורך זמן במערכת שבבעלותך

שיעור הצלחה שלא ניתן לקשר ל-commit הוא רק תחושה. שמור שורה אחת לכל מקרה בוחן בכל הרצה, עם ה-commit והמודל בתוך השורה.

CREATE TABLE IF NOT EXISTS results (
  run_id      TEXT NOT NULL,
  ran_at      TEXT NOT NULL,
  git_sha     TEXT NOT NULL,
  agent_model TEXT NOT NULL,
  case_id     TEXT NOT NULL,
  passed      INTEGER NOT NULL,
  graded_by   TEXT NOT NULL,
  reason      TEXT
);
SELECT run_id, git_sha, agent_model,
       count(*) AS cases,
       round(100.0 * sum(passed) / count(*), 1) AS pass_pct
FROM results
GROUP BY run_id
ORDER BY ran_at DESC
LIMIT 10;

טען את הסכימה באמצעות sqlite3 evals/results.db < evals/schema.sql, ולאחר מכן קרא את המגמה בעזרת sqlite3 -box evals/results.db < evals/passrate.sql. שנה של הרצות יומיות על פני 60 מקרים מסתכמת בכ-22,000 שורות, כך שהאחסון לעולם לא יהפוך לפרויקט בפני עצמו. המדריך הרצת SQLite בסביבת production על גבי VPS מכסה את ההגדרות שמתחילות להיות משמעותיות אם הקובץ משותף בין מכונות.

המריץ (runner) מדפיס את אותו המידע עבור אדם:

run 2026-08-05T09:14:22Z  sha 4f1c9ab  model claude-sonnet-5  58/60 pass (96.7%)
FAIL refund-double-charge  deterministic: tool not called: create_refund
FAIL pto-policy-question   judge(opus): reply gives no dollar amount

הרץ את חבילת הבדיקות על שינויים שעלולים לשבור סוכן (agent), כלומר עריכות ב-prompt, שינויי מודל ושינויי כלים, ולא על כל commit בכל מקום במאגר. ה-hook הבא pre-push מכסה את תת-הקבוצה המהירה:

cat > .git/hooks/pre-push <<'EOF'
#!/bin/sh
python3 evals/run.py --set smoke || exit 1
EOF
chmod +x .git/hooks/pre-push

הרצות מלאות הן איטיות יותר ושייכות ללוח זמנים. שירות ו-timer של systemd ב-VPS לילי מריץ את כל הסט מול ה-prompt הפרוס, וזה מה שתופס שינויים שמגיעים מחוץ למאגר שלך, כגון כלי מאוחסן שהתנהגותו השתנתה.

סקירה אנושית, מבוססת דגימה ולא בדיקה ממצה

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

חמישה-עשר מקרים בשלוש דקות לכל אחד מסתכמים ב-45 דקות בשבוע, והם מניבים תיקונים למדריך הדירוג במקומות שבהם אתם והשופט אינכם מסכימים, בתוספת מקרים חדשים לסוגי כשלים שאף אחד לא העלה על דעתו. רשמו את הפסיקה האנושית באותה טבלה עם graded_by מוגדר ל-human, כך שהסכמה בין השופט לבין האדם תהפוך לשאילתה במקום לזיכרון.

מה משתבש במערך ה-eval עצמו

anthropic.RateLimitError בהרצה המלאה הראשונה. הרצה של שישים מקרים במקביל חורגת ממכסת הבקשות או ה-tokens של שכבת המנוי שלכם. הגבילו את ה-concurrency לארבעה עובדים (workers), והעבירו את ההרצה הלילית ל-Batch API.

json.JSONDecodeError: Expecting value: line 1 column 1 (char 0) מצד ה-judge. המודל השיב בטקסט חופשי, או עטף את ה-JSON בתוך code fence. בצעו ניסיון חוזר אחד, ולאחר מכן תעדו את המקרה כשגיאה. לעולם אל תתנו לכשל ב-parse להיחשב כהצלחה, כיוון שחבילת בדיקות שהופכת שגיאות להצלחות מתקרבת ל-100% בעוד שה-agent הופך גרוע יותר.

מקרים לא עקביים (Flaky cases). אותו קלט עובר בהרצה אחת ונכשל בבאה אחריה, כיוון שה-agent דוגם את הפלט שלו. הריצו את המקרה הלא עקבי שלוש פעמים ותעדו את השבר במקום למחוק את המקרה. מקרה שעובר שתי הרצות מתוך שלוש הוא באג אמיתי בחוסן המערכת, ולקוח ייתקל בו.

שחיקה של ה-golden set. מישהו עורך תשובה צפויה כדי להפוך את חבילת הבדיקות לירוקה. בחנו diffs ל-evals/cases.jsonl בקפידה רבה כמו diffs ל-agent, כיוון שהקובץ הזה הוא ההגדרה הכתובה שלכם למה שנכון.

חבילת בדיקות שלעולם לא נכשלת. שיעור הצלחה שעומד על 100% במשך חודש אומר שהסט הפסיק לעקוב אחרי המוצר. משכו עשרה עקבות (traces) אחרונים, מצאו את אלו שה-agent טיפל בהם בצורה גרועה, והוסיפו אותם. לאחר מכן, שברו משהו בכוונה וודאו שההרצה הופכת לאדומה; זו הבדיקה ש-mutation testing חל על חבילת בדיקות והדרך היחידה לדעת שלסט שלכם עדיין יש שיניים.

FAQ

כמה מקרים נדרשים עבור סט הערכה של סוכן AI?

התחילו עם 40 עד 80 מקרים והרחיבו את הסט בהתבסס על כשלים אמיתיים. מתחת ל-20 מקרים, תוצאה לא עקבית אחת משנה את אחוז ההצלחה ב-5 נקודות, ולכן הנתון מאבד מהמשמעות שלו. מעבר לכמה מאות מקרים, כל הרצה עולה כסף וזמן, בעוד שהתרומה השולית של כל מקרה נוסף לכיסוי הבדיקות נמוכה. המדד הקובע אינו הכמות, אלא שיעור סוגי הכשלים הידועים שלכם בסביבת הייצור שמופיעים בסט לפחות פעם אחת.

האם ניתן לסמוך על שופט LLM שיעריך את הסוכן שלי?

רק לאחר שמדדתם אותו מול התיוגים שלכם. שמרו 30 מקרים שתייגתם ידנית, ובדקו את השופט מולם בכל פעם שאתם משנים את מודל השופט או את ה-prompt שלו. שופטים נוטים להטיית אורך, שבה תשובות ארוכות ומנופחות עוברות לעיתים קרובות יותר, ולהטיית העדפה עצמית, שבה פלט ממשפחת המודלים שלהם מקבל ציון חיובי יותר. ניתן לבדוק את שתי התופעות: הוסיפו תוכן לתשובה שנכשלה ושפטו אותה מחדש, או העריכו את אותן תשובות באמצעות שופט ממשפחה אחרת. אם השופט חולק על התיוגים שלכם ביותר ממקרה אחד מתוך עשרה, הכללים (rubric) מעורפלים מדי לשימוש.

באיזה מודל כדאי להשתמש להערכת התוצאות?

העריכו בזול והסלימו לפי הצורך. בדיקות דטרמיניסטיות אינן עולות דבר, לכן הן ירוצו ראשונות על כל מקרה. מודל קטן יטפל במקרים הברורים של הצלחה. רק כשלים ופסיקות בעלות רמת ביטחון נמוכה יועברו למודל מתקדם (frontier model). לפי מחירון אוגוסט 2026, הערכת 1,000 מקרים עולה כ-1.80 דולר עם Claude Haiku 4.5 וכ-9.00 עם Claude Opus 5. מכיוון שהרצות הערכה הן אסינכרוניות, שימוש ב-Batch API יחצה את העלות הזו בחצי.

האם הערכות מחליפות ניטור בסביבת ייצור?

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