<!-- GENERATED translation. Edit the English source or glossary.json, not this file. -->

वह इवैल्यूएशन रन जिसने इस दस्तावेज़ को शुरू किया था, पहली नज़र में स्वस्थ लग रहा था। मैं एक एंटरप्राइज प्रूफ-ऑफ-वैल्यू के लिए एक प्रोडक्शन-ग्रेड एजेंट के खिलाफ गोल्ड-सेट इवैल्यूएशन चला रहा था: कार्यों का एक क्यूरेटेड सेट, प्रत्येक में टूल कॉल का एक अपेक्षित क्रम था, जिसे एजेंट के खिलाफ रीप्ले किया गया और स्वचालित रूप से स्कोर किया गया। रीजनिंग ट्रेस वास्तव में अच्छे थे। मॉडल ने समस्याओं को सही ढंग से विघटित किया, समझदारी से योजना बनाई, और स्पष्ट अंतिम उत्तर लिखे। और यह उन टूल्स को छोड़ रहा था जिन्हें उसे 20 प्रतिशत से अधिक मामलों में कॉल करना आवश्यक था। कॉल विफल नहीं हो रहे थे। उन्हें गलत आर्गुमेंट्स के साथ कॉल नहीं किया जा रहा था। बस चुपचाप अपने मन से जवाब दे रहा था जैसे कि टूल मौजूद ही न हो।

मेरी पहली प्रवृत्ति सामान्य थी: मॉडल को बदलना, फिर सिस्टम प्रॉम्प्ट को फिर से लिखना। दोनों में से किसी ने भी संख्या को ज्यादा नहीं बदला। एक अधिक महंगे मॉडल ने 13 गुना लागत पर <dfn class="term" data-en="skip rate">स्किप दर</dfn> में कुछ अंक कम किए। प्रॉम्प्ट सर्जरी ("आपको उपलब्ध टूल्स का उपयोग करना ही होगा") ने विपरीत विफलता उत्पन्न की, एजेंट उन टूल्स को कॉल करने लगा जिनकी उसे आवश्यकता नहीं थी। जो अंततः ठीक हुआ वह उबाऊ था: मैंने टूल विवरणों को फिर से लिखा। मैंने बताया कि प्रत्येक टूल का उपयोग कब किया जाना चाहिए, कब नहीं, और वह क्या लौटाता है। मैंने बाधाओं को गद्य से हटाकर स्कीमा में डाल दिया। <dfn class="term" data-en="skip rate">स्किप दर</dfn> कम एकल अंकों में गिर गई। वही मॉडल, वही सिस्टम प्रॉम्प्ट, वही इवैल्यूएशन सेट।

वह परिणाम मेरे द्वारा बाद में मूल्यांकन किए गए हर एजेंट में दोहराया गया, और इसने टूल-कॉल विफलताओं के बारे में मेरी सोच बदल दी। प्रमुख कारण मॉडल की कमजोरी नहीं है। यह अधूरी निर्दिष्ट <dfn class="term" data-en="tool contract">टूल कॉन्ट्रैक्ट</dfn>्स हैं: अस्पष्ट विवरण, ओवरलैपिंग टूल्स, स्कीमा जो कचरा स्वीकार करते हैं, बाधाएं जो केवल डेवलपर के दिमाग में रहती हैं। टीमें उन डेवलपर्स के लिए टूल स्पेसिफिकेशन्स लिखती हैं जो स्रोत कोड पढ़ सकते हैं। वास्तविक पाठक एक संभाव्य मॉडल है जो ठीक वही JSON देखता है जिसे आपने रजिस्टर किया है और कुछ नहीं। यह गाइड वही है जो मैं अब इसके बारे में करता हूं, जिसमें वह नियतात्मक लिंटर भी शामिल है जिसे मैंने CI में इसे लागू करने योग्य बनाने के लिए बनाया है।

## टूल-कॉल विफलताओं का वर्गीकरण

जब मैं इवैल्यूएशन ट्रांसक्रिप्ट्स को स्कोर करता हूं, तो हर टूल-संबंधित विफलता पांच श्रेणियों में से एक में आती है। उपयोगी अनुशासन प्रत्येक श्रेणी को उस स्पेसिफिकेशन दोष तक वापस ट्रेस करना है जिसके कारण यह हुआ, क्योंकि यह आपको बताता है कि क्या ठीक करना है। 'मॉडल' को दोष देना आपको कोई कार्रवाई योग्य जानकारी नहीं देता है।

![एजेंट निर्णय बिंदु से शाखाबद्ध पांच टूल-कॉल विफलता मोड: स्किप, गलत टूल, गलत आर्गुमेंट्स, मनगढ़ंत आर्गुमेंट्स, और समय से पहले उत्तर, प्रत्येक को स्पेसिफिकेशन में उसके मूल कारण तक ट्रेस किया गया है](/diagrams/tool-failure-taxonomy.svg)

| विफलता मोड | ट्रांसक्रिप्ट में यह कैसा दिखता है | स्पेसिफिकेशन में मूल कारण | इवैल्यूएशन में इसका पता कैसे लगाएं |
| --- | --- | --- | --- |
| **स्किप** | कोई टूल कॉल नहीं जहां एक की आवश्यकता थी; एजेंट पैरामीट्रिक ज्ञान से या अनुमान लगाकर जवाब देता है | विवरण यह नहीं बताता कि टूल कब लागू होता है, या यह स्थापित नहीं करता कि इसका डेटा लाइव और आधिकारिक है | गोल्डन ट्रेस टूल X की अपेक्षा करता है; ट्रांसक्रिप्ट में X को कोई कॉल नहीं है। प्रति टूल स्किप रिपोर्ट करें, न कि केवल कुल मिलाकर |
| **गलत टूल** | एजेंट एक संभावित पड़ोसी को कॉल करता है: `search_documents` के बजाय `search_customer_accounts` | लगभग समान विवरण वाले ओवरलैपिंग टूल्स और कोई अस्पष्टता निवारण खंड नहीं | अपेक्षित टूल A, देखा गया टूल B। एक मैट्रिक्स में भ्रम को क्लस्टर करें; ओवरलैपिंग जोड़े तुरंत उजागर होते हैं |
| **गलत आर्गुमेंट्स** | कॉल स्कीमा सत्यापन में विफल रहता है या API 400 लौटाता है; एजेंट अंधाधुंध पुनः प्रयास करता है या हार मान लेता है | स्कीमा बहुत ढीला है: अनटाइप्ड पैरामीटर्स, कोई `required` ऐरे नहीं, फ्री-स्ट्रिंग फ़ील्ड जहां फॉर्मेट मौजूद हैं | ट्रेस में प्रति टूल स्कीमा-सत्यापन विफलताओं और 4xx प्रतिक्रियाओं की गणना करें |
| **मनगढ़ंत आर्गुमेंट्स** | आर्गुमेंट्स सिंटैक्टिक रूप से मान्य हैं लेकिन मनगढ़ंत हैं: एक अकाउंट ID जो बातचीत में कहीं भी दिखाई नहीं देता | स्पेसिफिकेशन में बाधाएं और उदाहरण गायब हैं, इसलिए मॉडल संभावित दिखने वाले मानों से अंतराल भरता है | बातचीत में या पिछले टूल परिणामों में वास्तव में मौजूद मानों के खिलाफ आर्गुमेंट मानों का अंतर करें |
| **समय से पहले उत्तर** | एजेंट उन टूल्स को कॉल किए बिना एक आत्मविश्वासपूर्ण अंतिम उत्तर देता है जो इसे आधार बनाते हैं | विवरण मॉडल को यह नहीं बताता कि उसका ज्ञान यहां पुराना है ('खाता डेटा दैनिक बदलता है; इसे कॉल करें भले ही आपको लगता है कि आप जानते हैं') | अंतिम उत्तर मौजूद, आवश्यक कॉल अनुपस्थित; जांचें कि क्या उत्तर के दावे टूल आउटपुट से ट्रेस किए जा सकते हैं |

इस तालिका के बारे में दो बातें दोहराव के माध्यम से अपनी जगह बना चुकी हैं। पहला, **स्किप सबसे आम विफलता है और सबसे कम दिखाई देने वाली है**। एक गलत कॉल एक त्रुटि फेंकता है जिस पर आप अलर्ट कर सकते हैं। एक स्किप एक धाराप्रवाह, आत्मविश्वासपूर्ण, गलत उत्तर उत्पन्न करता है, और आपके लॉग में कुछ भी इसे चिह्नित नहीं करता है। आप स्किप तभी देखते हैं जब आपके इवैल्यूएशन यह एन्कोड करते हैं कि कौन से टूल कॉल अपेक्षित थे। दूसरा, **पांच में से चार श्रेणियां स्पेसिफिकेशन दोष हैं**। वास्तव में अच्छी तरह से अलग किए गए टूलसेट के तहत केवल गलत-टूल चयन ही संभवतः एक मॉडल सीमा है, और वहां भी स्पेसिफिकेशन आमतौर पर एक साथी होता है।

> आपका टूल विवरण एक प्रॉम्प्ट है। इसे हर एक टर्न पर कॉन्टेक्स्ट विंडो में इंजेक्ट किया जाता है। अधिकांश टीमें सिस्टम प्रॉम्प्ट को दोहराने में हफ्तों खर्च करती हैं और उन पंद्रह प्रॉम्प्ट पर शून्य मिनट खर्च करती हैं जिन्हें उन्होंने इसके साथ शिप किया था।

## टूल कॉन्ट्रैक्ट वास्तव में क्या है

मैं जानबूझकर कॉन्ट्रैक्ट शब्द का उपयोग करता हूं। एक टूल दो बहुत अलग प्रणालियों के बीच की सीमा पर बैठता है: एक नियतात्मक कार्यान्वयन जो ठीक वही करता है जो उसका कोड कहता है, और एक संभाव्य कॉलर जो पूरी तरह से आपके द्वारा पंजीकृत टेक्स्ट और स्कीमा के आधार पर यह तय करता है कि इसे कब और कैसे इनवोक करना है। मॉडल आपका स्रोत कोड नहीं पढ़ सकता। यह किसी सहकर्मी से नहीं पूछ सकता। स्पेसिफिकेशन पूरा इंटरफ़ेस है, और इसके छह भाग हैं:

1.  **नाम।** टूल चयन के लिए सबसे मजबूत एकल संकेत। मॉडल विवरण का एक शब्द पढ़ने से पहले नामों पर पैटर्न-मैच करते हैं।
2.  **विवरण।** टूल का उपयोग कब करना है, कब नहीं, और यह क्या लौटाता है। यह वह दस्तावेज़ है जहां पाठक एक मॉडल है, जो लेखन नियमों को बदलता है।
3.  **स्कीमा।** इनपुट का मशीन-जांच योग्य आकार: प्रकार, आवश्यक फ़ील्ड, एनम्स, फॉर्मेट, रेंज।
4.  **बाधाएं।** वह सब कुछ जो स्कीमा संरचनात्मक रूप से व्यक्त नहीं कर सकता, स्पष्ट रूप से कहा गया है: ऑर्डरिंग निर्भरताएं ('`account_id` प्राप्त करने के लिए पहले `search_customer_accounts` को कॉल करें'), दर अपेक्षाएं, डेटा की ताजगी।
5.  **उदाहरण।** कम से कम एक ठोस, वैध इनवोकेशन। मॉडल अमूर्त विवरणों की तुलना में उदाहरणों से कहीं अधिक विश्वसनीय रूप से सामान्यीकरण करते हैं।
6.  **त्रुटि सिमेंटिक्स।** विफलता कैसी दिखती है और कॉलर को इसके बारे में क्या करना चाहिए। एक एजेंट जो जानता है कि `STATEMENT_NOT_READY` का अर्थ 'रुकें और उपयोगकर्ता को बताएं' है, वह स्टैक ट्रेस को घूरने वाले से अलग व्यवहार करता है।

![एक टूल कॉन्ट्रैक्ट की संरचना: एक अच्छी तरह से निर्दिष्ट टूल के नाम, विवरण, स्कीमा, त्रुटि सिमेंटिक्स और उदाहरण की ओर इशारा करते हुए कॉलआउट एनोटेशन](/diagrams/tool-contract-anatomy.svg)

सबसे अधिक लाभ उठाने वाली आदत **कार्यान्वयन विवरणों के बजाय व्यवहार-उन्मुख विवरण** लिखना है। एक कार्यान्वयन विवरण बताता है कि कोड क्या करता है: "अकाउंट्स सर्विस के माध्यम से ग्राहक डेटाबेस को क्वेरी करता है।" एक व्यवहार विवरण बताता है कि कॉलर को क्या करना चाहिए: "ग्राहक खातों को नाम, ईमेल या खाता संख्या से खोजता है। इसका उपयोग तब करें जब उपयोगकर्ता किसी विशिष्ट ग्राहक के बारे में पूछता है और आपके पास पहले से उसका खाता ID नहीं है।" पहला सटीक है और मॉडल के लिए बेकार है। दूसरा एक रूटिंग नियम जैसा लगता है, क्योंकि मॉडल इसे ठीक इसी तरह उपभोग करता है। मेरे द्वारा अब शिप किया गया हर विवरण शाब्दिक वाक्यांश 'इसका उपयोग तब करें जब' और, किसी भी टूल के लिए जिसके पास एक संभावित पड़ोसी है, 'इसके लिए इसका उपयोग न करें' शामिल करता है।

## वे नियम जो मापने योग्य रूप से मायने रखते हैं

ये वे नियम हैं जिन्हें मैं टूल स्पेसिफिकेशन्स की समीक्षा करते समय लागू करता हूं, मोटे तौर पर इस क्रम में कि प्रत्येक ने मेरे इवैल्यूएशन में स्किप और त्रुटि दरों को कितना बदला। इसमें से कुछ भी विदेशी नहीं है। यह सब नियमित रूप से प्रोडक्शन MCP सर्वर से अनुपस्थित रहता है।

#### प्रति टूल एक कार्य, और कोई ओवरलैपिंग पड़ोसी नहीं

यदि दो टूल्स एक ही अनुरोध को संभावित रूप से संभाल सकते हैं, तो मॉडल उनके बीच अपनी कॉल को विभाजित करेगा, और आपके इवैल्यूएशन एक साफ विफलता के बजाय एक धब्बादार भ्रम पैटर्न दिखाएंगे। सबसे खराब अपराधी जो मैं देखता हूं वे `get_customer` / `fetch_customer_details` / `lookup_client` जैसे जोड़े हैं जो विभिन्न टीमों से स्वाभाविक रूप से विकसित हुए हैं। उन्हें मर्ज करें, या प्रत्येक को एक स्पष्ट रूप से अलग सीमा दें और विवरण में नाम से दूसरे को क्रॉस-रेफरेंस करें ("लेनदेन इतिहास के लिए, इसके बजाय `list_account_transactions` का उपयोग करें")। टूल्स के बीच निर्णय लेने वाला एक मॉडल एक वर्गीकरण कार्य कर रहा है; आपका काम कक्षाओं को अलग करने योग्य बनाना है।

#### बताएं कि इसका उपयोग कब नहीं करना है

सकारात्मक विवरण एक अस्पष्ट क्षेत्र को परिभाषित करते हैं। नकारात्मक खंड इसके किनारों को परिभाषित करते हैं। मेरे शुरुआती उदाहरण में स्किप दरों को कम करने वाले विवरण ने केवल यह नहीं बताया कि टूल ने क्या किया; इसने कहा "इसका उपयोग तब भी करें जब आपको लगता है कि आप पहले से ही जवाब जानते हैं; होल्डिंग्स डेटा दैनिक बदलता है।" वह एक वाक्य सीधे स्किप और समय से पहले-उत्तर विफलताओं पर हमला करता है, क्योंकि मॉडल की डिफ़ॉल्ट धारणा यह है कि उसका पैरामीट्रिक ज्ञान पर्याप्त है। इसके विपरीत, "इसके लिए इसका उपयोग न करें" खंड गलत-टूल चयन पर हमला करते हैं। दोनों दिशाएं मायने रखती हैं।

#### बाधाओं को स्कीमा में डालें, गद्य में नहीं

गद्य बाधाएं सुझाव हैं। स्कीमा बाधाएं जांच योग्य हैं, और मॉडल उनका अधिक विश्वसनीय रूप से सम्मान करते हैं क्योंकि वे संरचनात्मक हैं। हर बार जब आप विवरण में "एक वैध तिथि होनी चाहिए" लिखते हैं, तो आप स्कीमा में `pattern` या `format` लिख सकते थे। यहां एक वास्तविक समीक्षा से पहले और बाद का उदाहरण है, सामान्यीकृत:

```json
{
  "name": "get_statement",
  "description": "Gets a statement. Date should be in the right format and not in the future.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "date": { "type": "string" },
      "acct": { "type": "string" }
    }
  }
}
```

यहां सब कुछ गलत है जब तक कि एक इवैल्यूएशन रन न हो: कोई आवश्यक ऐरे नहीं (इसलिए मॉडल दोनों फ़ील्ड को छोड़ सकता है), `date` के लिए कोई फॉर्मेट नहीं (मैंने ट्रेस में "पिछले महीने", "2026/05/01", और इपोक मिलिस देखा), और `acct` मॉडल को आधार बनाने के लिए कुछ भी नहीं देता है, जहां से मनगढ़ंत खाता ID आते हैं। पुनर्लेखन:

```json
{
  "name": "get_monthly_statement",
  "description": "Retrieves one closed monthly account statement as a PDF link. Use this after you have an account_id from search_customer_accounts. Do not use this for real-time balances; use get_account_balance. Returns error code STATEMENT_NOT_READY if the requested month is not yet closed; do not retry, tell the user when it will be available.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "account_id": {
        "type": "string",
        "pattern": "^ACC-[0-9]{8}$",
        "description": "Account identifier, e.g. ACC-00417233. Obtain via search_customer_accounts; never guess this value."
      },
      "month": {
        "type": "string",
        "pattern": "^[0-9]{4}-(0[1-9]|1[0-2])$",
        "description": "Statement month as YYYY-MM, e.g. 2026-05. Must be a fully closed month, not the current month."
      }
    },
    "required": ["account_id", "month"],
    "additionalProperties": false
  },
  "annotations": { "readOnlyHint": true }
}
```

एनम्स विशेष उल्लेख के हकदार हैं। कानूनी मानों के एक सीमित सेट वाला कोई भी पैरामीटर एक एनम होना चाहिए, पूर्ण विराम। विवरण में "इनमें से एक: सक्रिय, निष्क्रिय, बंद" के साथ एक फ्री स्ट्रिंग अंततः "निष्क्रिय" प्राप्त करेगी, और आपका बैकएंड उसके साथ जो भी करेगा वह करेगा।

#### आवश्यक बनाम वैकल्पिक के बारे में ईमानदार रहें

दो विफलता दिशाएं। वास्तव में आवश्यक फ़ील्ड को वैकल्पिक के रूप में चिह्नित करना उन कॉलों को आमंत्रित करता है जो इसे छोड़ देते हैं, और मॉडल फिर त्रुटि संदेश से सीखता है, एक टर्न बर्बाद करता है। एक वैकल्पिक फ़ील्ड को आवश्यक के रूप में चिह्नित करना मॉडल को एक मान का आविष्कार करने के लिए मजबूर करता है, जो एक मतिभ्रम है जिसे आपने फरमान द्वारा बनाया है। मैं दूसरे को लगातार उन स्पेसिफिकेशन्स में देखता हूं जो बैकएंड DTOs से उत्पन्न होते हैं जहां डेटाबेस के लिए हर फ़ील्ड आवश्यक था, कॉलर के लिए नहीं। नियम: `required` दर्शाता है कि टूल को उपयोगी काम करने के लिए क्या चाहिए, और हर वैकल्पिक फ़ील्ड का विवरण बताता है कि इसे छोड़े जाने पर क्या होता है ("सभी स्टेटस खोजने के लिए छोड़ दें")।

#### कोड के साथ विफल हों, गद्य के साथ नहीं

त्रुटि संदेश कॉन्ट्रैक्ट का हिस्सा हैं क्योंकि एजेंट उन्हें पढ़ता है और तय करता है कि आगे क्या करना है। एक कच्चा स्टैक ट्रेस या एक सामान्य "आंतरिक त्रुटि" मॉडल को दो विकल्प देता है: अंधाधुंध पुनः प्रयास करें या माफी मांगें। एक मशीन-कार्रवाई योग्य संकेत के साथ एक नियतात्मक त्रुटि कोड इसे लेने के लिए एक शाखा देता है। मैं जिस पैटर्न का उपयोग करता हूं: एक स्थिर `code` फ़ील्ड, एक-वाक्य मानव-पठनीय संदेश, और जहां लागू हो एक निर्देश (`retry_after_seconds`, "पहले एक वैध account_id प्राप्त करें")। इवैल्यूएशन में, यह डेड-एंड ट्रांसक्रिप्ट्स के एक वर्ग को रिकवरी में बदल देता है, और यह आपकी टेस्ट सूट में विफलता अभिकथन लिखना तुच्छ बना देता है।

#### कॉलर के लिए नाम दें, कोडबेस के लिए नहीं

क्रिया-वस्तु, snake_case, कोई आंतरिक शब्दजाल नहीं। `search_customer_accounts`, `queryCustDB`, `cst_lkp_v2`, और `CustomerAccountSearchServiceEndpoint` से बेहतर है। आंतरिक सिस्टम नाम विशेष रूप से महंगे होते हैं: मॉडल को कोई जानकारी नहीं है कि "Falcon" आपका मूल्य निर्धारण इंजन है, इसलिए `query_falcon` बिना लेबल के भी हो सकता है। नाम को शून्य संगठनात्मक संदर्भ वाले मॉडल को यह अनुमान लगाने देना चाहिए कि टूल क्या करता है। यह कॉस्मेटिक लगता है। ऐसा नहीं है; नाम टूल चयन में पहला-पास फ़िल्टर हैं, और भ्रम मैट्रिक्स में मैं खराब नाम वाले टूल्स को बेहतर नाम वाले पड़ोसियों को कॉल खोते हुए देख सकता हूं जो गलत काम करते हैं।

#### लंबाई बजट का सम्मान करें

विवरण की लंबाई का एक आदर्श बिंदु होता है। लगभग दस शब्दों से कम होने पर, टूल अधूरा निर्दिष्ट होता है और उसे छोड़ दिया जाता है या दुरुपयोग किया जाता है। कुछ सौ शब्दों से अधिक होने पर, संकेत डूब जाता है: 'कब उपयोग करें' खंड चौथे पैराग्राफ में दब जाता है और मॉडल के पास उसी कॉन्टेक्स्ट विंडो में ध्यान के लिए प्रतिस्पर्धा करने वाले पंद्रह अन्य टूल विवरण होते हैं। मेरी समीक्षाओं में, जो विवरण सबसे अच्छा प्रदर्शन करते हैं वे तीन से छह वाक्यों के होते हैं: यह क्या करता है, इसका उपयोग कब करना है, कब नहीं, यह क्या लौटाता है, त्रुटि व्यवहार। यदि आपको इससे अधिक की आवश्यकता है, तो टूल शायद बहुत सारे काम कर रहा है (नियम एक देखें) या अतिरिक्त सामग्री स्कीमा में होनी चाहिए।

## स्पेसिफिकेशन्स को नियतात्मक रूप से स्कोर करना

इन पर्याप्त समीक्षाओं के बाद, मैंने देखा कि मैं हर बार एक ही चेकलिस्ट लागू कर रहा था, और एक चेकलिस्ट जिसे आप हाथ से लागू करते हैं वह एक लिंटर है जिसे आपने अभी तक नहीं लिखा है। तो मैंने एक बनाया: **Tool Credit Score**, [Agent Contract Studio](https://github.com/letmereviewyourcode/agentic-contract-studio) का हिस्सा, ओपन सोर्स और [agentic-contract-studio.vercel.app](https://agentic-contract-studio.vercel.app/) पर लाइव चल रहा है। आप एक MCP टूल स्पेसिफिकेशन पेस्ट करते हैं (या इसे GitHub से आयात करते हैं, या एक चल रहे MCP सर्वर से खोजते हैं), और यह एक नियतात्मक रूब्रिक के खिलाफ हर टूल को 0 से 100 तक स्कोर करता है, फिर जो ठीक कर सकता है उसे स्वतः ठीक करता है।

रूब्रिक में पांच भारित श्रेणियां हैं, जो सीधे ऊपर की विफलता वर्गीकरण पर मैप करती हैं:

| श्रेणी | भार | यह क्या जांचता है | यह किस विफलता मोड को लक्षित करता है |
| --- | --- | --- | --- |
| विवरण | 25% | उपस्थित, 10+ शब्द, एक क्रिया क्रिया से शुरू होता है, 200 शब्दों से कम | स्किप, समय से पहले उत्तर |
| पैरामीटर्स | 25% | स्कीमा `type: object` है; हर पैरामीटर का एक प्रकार और विवरण है; एक `required` ऐरे मौजूद है और ईमानदार है | गलत और मनगढ़ंत आर्गुमेंट्स |
| सर्वोत्तम अभ्यास | 20% | MCP एनोटेशन (`readOnlyHint`, `destructiveHint`, `idempotentHint`); `additionalProperties: false`; विवरण में रिटर्न और त्रुटियों का उल्लेख है | गलत टूल, डेड-एंड त्रुटि हैंडलिंग |
| नामकरण | 15% | snake_case, क्रिया उपसर्ग, 64 वर्णों से कम | गलत टूल |
| उदाहरण | 15% | कम से कम एक वैध उदाहरण इनवोकेशन | गलत और मनगढ़ंत आर्गुमेंट्स |

स्कोर एक लेटर ग्रेड में बदल जाते हैं (90+ एक A है, 60 से कम एक F है), और ऑटो-फिक्सर यांत्रिक मरम्मत को नियतात्मक रूप से संभालता है: एक क्रिया उपसर्ग के साथ snake_case में नाम बदलना, लापता पैरामीटर प्रकार जोड़ना, उदाहरण और एनोटेशन को स्केफोल्ड करना। विवरण शब्दांकन के लिए एक वैकल्पिक LLM पॉलिश पास है, लेकिन यह ठीक वैसा ही है, वैकल्पिक, केवल स्थानीय, और यह कभी भी पैरामीटर नामों, प्रकारों या स्कीमा संरचना को नहीं छूता है। कोर पाइपलाइन को किसी मॉडल और किसी API कुंजी की आवश्यकता नहीं है।

वह अंतिम डिज़ाइन निर्णय ही मुख्य बात है, और इसका बचाव करना उचित है क्योंकि "बस एक LLM को स्पेसिफिकेशन की समीक्षा करने दें" स्पष्ट विकल्प है। मैंने CI के लिए नियतात्मक लिंटिंग को चार कारणों से चुना। यह **पुनरुत्पादनीय** है: हर रन में एक ही स्पेसिफिकेशन को एक ही स्कोर मिलता है, इसलिए एक पुल रिक्वेस्ट में स्कोर रिग्रेशन का मतलब है कि स्पेसिफिकेशन बदल गया, न कि जज का मूड। यह **तेज और मुफ्त** है, इसलिए आप इसे हर कमिट पर बिना टोकन बजट बातचीत के चला सकते हैं। यह **व्याख्या योग्य** है: हर काटे गए बिंदु का एक ठोस फिक्स के साथ एक नामित नियम से संबंध है, जो आप एक कोड समीक्षा टिप्पणी में चाहते हैं। और **इससे बहस नहीं की जा सकती**, जो जितना होना चाहिए उससे कहीं अधिक मायने रखता है; मैंने टीमों को एक LLM जज के फैसले पर एक घंटे तक फिर से बहस करते देखा है, और कोई भी रेगुलर एक्सप्रेशन से बहस नहीं करता।

ईमानदार चेतावनी: एक लिंटर फॉर्म की जांच करता है, अर्थ की नहीं। Tool Credit Score हर बार एक लापता `required` ऐरे को पकड़ेगा; यह आपको यह नहीं बता सकता कि आपके दो टूल्स सिमेंटिक रूप से ओवरलैप करते हैं, या कि आपका 'कब उपयोग करें' खंड आपके अपने सिस्टम के बारे में तथ्यात्मक रूप से गलत है। वे दोष केवल इवैल्यूएशन (मापी गई स्किप और भ्रम दरें) या एक मानवीय समीक्षा में सामने आते हैं। लिंटर का काम यह सुनिश्चित करना है कि सस्ते, यांत्रिक दोष कभी उस चरण तक न पहुंचें, ताकि महंगा समीक्षा प्रयास वहीं जाए जहां इसकी वास्तव में आवश्यकता है।

> 90+ Tool Credit Score यह गारंटी नहीं देता कि एजेंट आपके टूल्स का अच्छी तरह से उपयोग करेंगे। 60 से कम का स्कोर लगभग गारंटी देता है कि वे नहीं करेंगे। लिंटिंग एक फ्लोर है, छत नहीं।

## जहां MCP सर्वर इन विफलताओं को केंद्रित करते हैं

MCP ने टूल्स को पोर्टेबल बनाया, जो वास्तव में उपयोगी है, और इसने खराब स्पेसिफिकेशन्स को भी पोर्टेबल बनाया। तीन पैटर्न मेरे द्वारा समीक्षा किए गए अधिकांश कम-स्कोरिंग सर्वर के लिए जिम्मेदार हैं।

**ओपनएपीआई से उत्पन्न सर्वर।** एक कनवर्टर को एक OpenAPI दस्तावेज़ पर इंगित करें और आपको मिनटों में एक MCP सर्वर मिलता है: प्रति एंडपॉइंट एक टूल, पैरामीटर नाम सीधे बैकएंड से उठाए गए, विवरण जो API संदर्भ दस्तावेज़ पढ़ने वाले डेवलपर्स के लिए लिखे गए थे, यदि वे बिल्कुल भी लिखे गए थे। परिणाम एक स्पेसिफिकेशन सतह है जो आपके डेटाबेस के आकार की है, न कि आपके उपयोगकर्ताओं के कार्यों के आकार की। `post_v2_accounts_search`, `get_accounts_by_id`, और `get_accounts_search_legacy` का सामना करने वाला एक एजेंट ठीक वही भ्रम मैट्रिक्स उत्पन्न करेगा जिसकी आप भविष्यवाणी करेंगे। उत्पन्न सर्वर एक अच्छा शुरुआती बिंदु हैं; वे एक शिप करने योग्य कॉन्ट्रैक्ट नहीं हैं। एक क्यूरेशन पास का बजट बनाएं जो एंडपॉइंट-आकार के टूल्स को टास्क-आकार के टूल्स में मर्ज करता है।

**किचन-सिंक सर्वर।** एक सर्वर जो एक पूरे SaaS उत्पाद को लपेटता है और 80 टूल्स को उजागर करता है क्योंकि API में 80 क्षमताएं हैं। उनमें से प्रत्येक टूल परिभाषा को हर टर्न पर मॉडल के कॉन्टेक्स्ट में इंजेक्ट किया जाता है, इसलिए आप टोकन में पूरी सतह के लिए भुगतान करते हैं चाहे इस बातचीत को इसकी आवश्यकता हो या नहीं, और टूल चयन सटीकता कम हो जाती है क्योंकि उम्मीदवार सेट बढ़ता है, खासकर जब उम्मीदवार एक शब्दावली साझा करते हैं। मेरा कार्यशील बजट: किसी दिए गए कार्य के लिए एजेंट को वास्तव में उजागर किए गए टूल्स को लगभग 20 से कम रखें। वह संख्या मेरे इवैल्यूएशन से एक अवलोकन है, कानून नहीं, और बेहतर मॉडल इसे ऊपर की ओर धकेलते रहते हैं। प्रभाव की दिशा मेरे द्वारा परीक्षण किए गए हर मॉडल के लिए बनी हुई है।

**कोई प्रगतिशील प्रकटीकरण नहीं।** किचन सिंक का समाधान क्षमता को हटाना नहीं है, यह इसके एक्सपोजर को स्टेज करना है। सामान्य पथ के लिए एक छोटा कोर सेट उजागर करें। लॉन्ग-टेल क्षमता के लिए, एक खोज पैटर्न का उपयोग करें: एक `search_tools`-शैली का टूल जो मांग पर पूर्ण कॉन्ट्रैक्ट्स लौटाता है, विलंबित स्कीमा लोडिंग जहां आपका क्लाइंट इसका समर्थन करता है, या समर्पित सबएजेंट जो प्रत्येक टूलसेट के अपने हिस्से को ही देखते हैं। MCP का डिज़ाइन इसका समर्थन करता है: क्लाइंट चुनते हैं कि कौन से टूल्स को सतह पर लाना है, और टास्क कॉन्टेक्स्ट द्वारा सर्वर-साइड टूल फ़िल्टरिंग को लागू करना सीधा है। कॉन्ट्रैक्ट अनुशासन अभी भी हर परत पर लागू होता है; एक अस्पष्ट विवरण वाला खोजा गया टूल एक प्रीलोडेड टूल के समान ही विफल होता है, बस एक टर्न बाद।

MCP का `annotations` ब्लॉक (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) जितना उपयोग होता है उससे अधिक उपयोग का हकदार है। सुरक्षा मूल्य से परे, एनोटेशन एक क्लाइंट को विवरणों को पार्स किए बिना कंबल नीति (रीड-ओनली टूल्स को स्वतः-अनुमोदित करें, विनाशकारी लोगों को पुष्टि के पीछे गेट करें) लागू करने देते हैं, और वे लिंटर में सबसे सस्ते स्कोर सुधारों में से एक हैं।

## इवैल्यूएशन के साथ लूप को बंद करें

उपरोक्त कोई भी नियम राय के रूप में ज्यादा मायने नहीं रखता। वे मापे गए डेल्टा के रूप में बहुत मायने रखते हैं, और माप अनुशासन वही है जो मैंने [एजेंटिक सिस्टम का मूल्यांकन](/hi/guides/evaluating-agentic-systems/) में वर्णित किया है: अपेक्षित टूल-कॉल अनुक्रमों के साथ कार्यों का एक गोल्ड सेट, एजेंट के खिलाफ रीप्ले किया गया, स्वचालित रूप से स्कोर किया गया। <dfn class="term" data-en="tool contract">टूल कॉन्ट्रैक्ट</dfn>्स के लिए विशिष्ट लूप:

1.  **बेसलाइन।** वर्तमान स्पेसिफिकेशन्स के खिलाफ गोल्ड सेट चलाएं। प्रति-टूल स्किप दर, गलत-टूल भ्रम, और आर्गुमेंट सत्यापन विफलताओं को रिकॉर्ड करें। प्रति-टूल मायने रखता है: 8 प्रतिशत की कुल स्किप दर एक टूल को छिपा सकती है जिसे आधे समय स्किप किया जाता है।
2.  **स्पेसिफिकेशन्स को ठीक करें।** पहले लिंट करें (यांत्रिक दोष), फिर सिमेंटिक नियम लागू करें: सीमाएं, कब-उपयोग-न-करें खंड, स्कीमा बाधाएं।
3.  **वही गोल्ड सेट फिर से चलाएं।** मॉडल, प्रॉम्प्ट और कार्य नहीं बदले हैं, इसलिए डेल्टा स्पेसिफिकेशन के लिए जिम्मेदार है। यह सबसे साफ A/B है जो आपको एजेंट इंजीनियरिंग में कभी मिलेगा, और इसी तरह मुझे पता है कि विवरण पुनर्लेखन ने उस जुड़ाव में 20-प्लस प्रतिशत स्किप दर को कम एकल अंकों में काट दिया जिसने इस गाइड को शुरू किया।
4.  **इसे CI में गेट करें।** टूल स्पेसिफिकेशन्स कोड हैं। उन्हें संस्करणित करें, उनका अंतर करें, और एक विवरण परिवर्तन को एक व्यवहार परिवर्तन के रूप में मानें, क्योंकि यह एक है; यह एक प्रॉम्प्ट को संपादित करता है जो हर टर्न पर चलता है। मेरी पाइपलाइन एक पुल रिक्वेस्ट को विफल कर देती है यदि किसी टूल का Tool Credit Score थ्रेशोल्ड से नीचे गिर जाता है, और मर्ज से पहले एक इवैल्यूएशन री-रन के लिए किसी भी स्पेसिफिकेशन अंतर को चिह्नित करती है।

उसी धन-प्रबंधन जुड़ाव ने दूसरी संख्या उत्पन्न की जिसे मैं उद्धृत करता रहता हूं: एक बार जब टूल कॉन्ट्रैक्ट्स ठीक हो गए, तो एक मिड-टियर मॉडल ने हमारे गोल्ड सेट पर प्रीमियम मॉडल की सटीकता से लगभग 1/13वें लागत पर मेल खाया, जिसमें टूल-स्किप दरों को अनुमानित करने के बजाय मापा गया। खराब स्पेसिफिकेशन्स केवल विफलताएं ही नहीं पैदा करते। वे चुपचाप आपके मॉडल बिल को बढ़ाते हैं, क्योंकि महंगे मॉडल की अतिरिक्त क्षमता उन कॉन्ट्रैक्ट्स की भरपाई के लिए खर्च की जा रही थी जिन्हें सस्ते मॉडल ने ठीक से लिखे जाने पर निष्पादित किया होता।

मैं अभी भी क्या अलग करूंगा: मेरे गोल्ड सेट रीप्ले की गई बातचीत हैं, लाइव उपयोगकर्ता नहीं, और वास्तविक उपयोगकर्ता अनुरोधों को इस तरह से वाक्यांशित करते हैं जो क्यूरेटेड कार्यों की तुलना में टूल चयन को अधिक कठिन बनाता है। मेरे द्वारा शिप किए गए हर एजेंट के लिए प्रोडक्शन में स्किप दरें इवैल्यूएशन स्किप दरों से ऊपर रहती हैं। इवैल्यूएशन संख्या को एक निचली सीमा के रूप में मानें और उसी वर्गीकरण के खिलाफ प्रोडक्शन ट्रेस का नमूना लेते रहें।

## एक-पैराग्राफ संस्करण

प्रोडक्शन एजेंटों में अधिकांश टूल-कॉल विफलताएं स्पेसिफिकेशन दोष हैं, मॉडल दोष नहीं: स्किप, गलत-टूल चयन, गलत आर्गुमेंट्स, मनगढ़ंत आर्गुमेंट्स, और समय से पहले उत्तर सभी उन कॉन्ट्रैक्ट्स से जुड़े हैं जो डेवलपर्स के लिए लिखे गए थे, न कि उस मॉडल के लिए जो वास्तव में उन्हें पढ़ता है। कॉन्ट्रैक्ट को ठीक करें: प्रति टूल एक कार्य जिसमें कोई ओवरलैपिंग पड़ोसी न हो, स्पष्ट 'कब उपयोग करें' और 'कब उपयोग न करें' खंडों के साथ व्यवहार-उन्मुख विवरण, गद्य के बजाय स्कीमा में एनम्स, फॉर्मेट और रेंज के रूप में व्यक्त बाधाएं, एक ईमानदार `required` ऐरे, कम से कम एक उदाहरण, नियतात्मक त्रुटि कोड जिन पर एक एजेंट शाखा बना सकता है, और आंतरिक शब्दजाल से मुक्त क्रिया-वस्तु नाम। CI में उन सभी को नियतात्मक रूप से लिंट करें (मेरा ओपन-सोर्स Tool Credit Score इसे करता है, ऑटो-फिक्स के साथ 0 से 100 तक) क्योंकि पुनरुत्पादनीय स्कोर गेटिंग के लिए LLM-निर्णित समीक्षाओं से बेहतर होते हैं, फिर पहले और बाद में प्रति-टूल स्किप दरों को मापकर इवैल्यूएशन के साथ सिमेंटिक फिक्स को साबित करें। मेरे एंटरप्राइज इवैल्यूएशन कार्य में, उस लूप ने मॉडल या सिस्टम प्रॉम्प्ट को छुए बिना 20-प्लस प्रतिशत टूल-स्किप दर को कम एकल अंकों में काट दिया, और यही कारण है कि एक मिड-टियर मॉडल लगभग 1/13वें लागत पर एक प्रीमियम मॉडल से मेल खाया।

## संदर्भ

-   [मॉडल कॉन्टेक्स्ट प्रोटोकॉल स्पेसिफिकेशन](https://modelcontextprotocol.io/specification/latest), जिसमें टूल परिभाषाएं और एनोटेशन शामिल हैं
-   [एंथ्रोपिक: टूल उपयोग दस्तावेज़](https://docs.claude.com/en/docs/agents-and-tools/tool-use/overview), मॉडल टूल स्पेसिफिकेशन्स का उपभोग कैसे करते हैं, इसके लिए व्यावहारिक संदर्भ
-   [एंथ्रोपिक इंजीनियरिंग: एजेंटों के लिए प्रभावी टूल लिखना](https://www.anthropic.com/engineering/writing-tools-for-agents)
-   [एजेंट कॉन्ट्रैक्ट स्टूडियो (Tool Credit Score)](https://github.com/letmereviewyourcode/agentic-contract-studio), ऊपर वर्णित नियतात्मक MCP स्पेसिफिकेशन लिंटर, [agentic-contract-studio.vercel.app](https://agentic-contract-studio.vercel.app/) पर लाइव
-   [एजेंटिक सिस्टम का मूल्यांकन](/hi/guides/evaluating-agentic-systems/), इवैल्यूएशन हार्नेस के लिए मेरी फील्ड गाइड जिससे इस दस्तावेज़ के माप आते हैं