Skip to main content
एक एजेंट के लिए जिसे आपने स्वयं लिखा है, या एक फ्रेमवर्क जिसके लिए Failproof AI के पास कोई एडेप्टर नहीं है। इंस्ट्रूमेंट करने के लिए कुछ नहीं है: आप ईवेंट उत्सर्जित करते हैं। यह वही API है जिसे चारों फ्रेमवर्क एडेप्टर अंदर से कॉल करते हैं। वे इसके ऊपर अनुवाद तालिकाएं हैं।

इंस्टॉल करें

कोई अतिरिक्त नहीं, और कोई निर्भरता नहीं।

इंस्ट्रूमेंट करें

इसे ऊपर से नीचे पढ़ें और यह कहता है कि इसका मतलब क्या है: और प्रत्येक वास्तव में क्या उत्सर्जित करता है: अंदर सब कुछ session_id और agent_id को छोड़ सकता है। स्कोप संदर्भ चर पर पहचान बांधते हैं और हर ईवेंट कॉल इसे वापस पढ़ता है, इसलिए आप अपने फ़ंक्शन के माध्यम से कभी id का धागा नहीं डालते। तीनों async with और with दोनों के तहत काम करते हैं। एजेंट को नेस्ट करने से पेड़ बनता है। parent_id और गहराई को स्टैक से गणना की जाती है:

एक स्कोप कैसे बंद होता है

agent() आपके लिए अपवाद संभालता है: त्रुटि agent_end से पहले उत्सर्जित होती है, क्योंकि डैशबोर्ड agent_end पर स्पान को बंद करता है और इसके बाद कुछ भी कुछ भी में जिम्मेदार नहीं है। एक रद्दीकरण एक विफलता नहीं है, इसलिए रद्द किए गए रन त्रुटि सतह को प्रदूषित नहीं करते। अपवाद हमेशा फिर से उठाया जाता है: एक स्कोप कभी निगल नहीं लेता।

ईवेंट विधियां

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

उदाहरण

OpenAI API के विरुद्ध एक टूल-कॉलिंग लूप, कोई एजेंट फ्रेमवर्क के बिना:
यह छह ईवेंट प्रकार का उत्पादन करता है जो एक एडेप्टर आपको देगा। पूर्ण चलने योग्य संस्करण, टूल परिभाषाओं के साथ, SDK रिपोजिटरी में docs/manual/examples/ के तहत शिप होता है।

थ्रेड्स और async

संदर्भ चर asyncio कार्यों में स्वचालित रूप से प्रसारित होते हैं। वे नए थ्रेड में प्रसारित नहीं होते, क्योंकि एक थ्रेड एक खाली संदर्भ के साथ शुरू होता है।
propagate() के बिना, वर्कर की ईवेंट एक TypeError उठाती हैं जो सुधार का नाम देते हैं बजाय किसी सेशन पर उतरने के। यह जानबूझकर है: कोई सेशन के साथ एक ईवेंट को ingest द्वारा छोड़ दिया जाता है और 200 उत्तर दिया जाता है, जो मूक विफलता है जिसे पहचान परत रोकने के लिए मौजूद है।

एडेप्टर के बिना एक फ्रेमवर्क इंस्ट्रूमेंट करें

हर एजेंट फ्रेमवर्क आपको एक ही तीन सीम देता है। उन्हें मैप करें और आपके पास एक पूर्ण ट्रेस है — चारों शिप किए गए एडेप्टर इससे अधिक कुछ नहीं करते।
1

रन को ब्रैकेट करें

2

प्रत्येक टूल को ब्रैकेट करें

जो कुछ भी फ्रेमवर्क एक टूल रैपर या मिडलवेयर कहता है उसमें।
3

प्रत्येक मॉडल कॉल को जोड़ी करें

एक नोड, स्टेप या मिडलवेयर सीमा देखने योग्य है? इसे एक हुक जोड़ी में लपेटें — hook_triggered / hook_completed — एक नेस्ट किए गए agent() में नहीं। agent_id कम-कार्डिनलिटी पहलू है, और प्रति नोड एक प्रविष्टि इसे डुबो देती है। हुक स्पान एक ही तरह से प्रस्तुत होते हैं और आपको प्रति-नोड विलंबता देते हैं।
मैनुअल और स्वचालित मिश्रित होते हैं। एक एडेप्टर एक हाथ से लिखे गए स्कोप के अंदर चल रहा है उस सेशन से जुड़ता है और उस एजेंट का माता-पिता बनता है, इसलिए आपको एक पेड़ मिलता है दो के बजाय — उपयोगी जब आप एक फ्रेमवर्क को स्वयं एक समर्थित के साथ इंस्ट्रूमेंट करते हैं।
दो कारण, और ऊपर दिए गए तीन सीम दोनों का उत्तर हैं:
  • autogen-core सितंबर 2025 के बाद से अरक्षित है।
  • AG2 अन्य फ्रेमवर्क के हुक के समकक्ष कोई प्रक्रिया-व्यापी पंजीकरण बिंदु नहीं उजागर करता है, इसलिए इसे इंस्ट्रूमेंट करने का अर्थ हर निर्माण साइट पर हर एजेंट को लपेटना है।
सीम को हाथ से मैप करना एक ही ईवेंट को एक ही निष्ठा पर रिकॉर्ड करता है जो एक शिप किया गया एडेप्टर होगा।

गहराई में जाना

रिकॉर्डिंग वास्तव में कैसे काम करती है। शुरुआत करने के लिए इसमें से कोई भी आवश्यक नहीं है।
हर रिकॉर्डिंग का एक ही आकार है: एक स्पान खुलता है, काम इसके अंदर नेस्ट होता है, और हर ओपनिंग ईवेंट को एक क्लोजिंग ईवेंट मिलता है।जोड़ी यूनिट है। प्रत्येक क्लोजिंग ईवेंट एक अवधि ले जाता है जो SDK इसके ओपनिंग वाले से मापता है।नीचे एक वास्तविक रन प्रति फ्रेमवर्क है — SDK के साथ शिप किए गए उदाहरणों से कैप्चर किया गया, मॉडल नाम सामान्यीकृत। ध्यान दें कि एक एकल कॉल से कितना वापस आता है।
14 ईवेंट
नोड्स हुक जोड़ी बन जाते हैं, इसलिए आप प्रति-नोड विलंबता प्राप्त करते हैं बिना उन्हें एजेंट सूची में भीड़ किए।
कोई सेशन-अंत ईवेंट नहीं है। एक सेशन कुछ ऐसा नहीं है जिसे आप बंद करते हैं — यह एक session_id साझा करने वाली ईवेंट का एक समूह है।स्थिति ट्रेस के आकार से प्राप्त की जाती है:तो एक सेशन तब समाप्त होता है जब हर जोड़ी बंद हो जाती है। एडेप्टर आपके लिए agent_end उत्सर्जित करते हैं, और टियरडाउन पर वे कुछ भी अभी भी खुला बंद करते हैं और इसे अधूरा चिह्नित करते हैं — एक क्रैश किया गया रन done बैठता है एक दृश्यमान अंतराल के साथ बजाय हैंगिंग के।
यह है कि एक सेशन दो कॉल पर फैल सकता है। एक LangGraph interrupt() रन को रोकता है, रूट स्पान जानबूझकर खुला रहता है, और पुनरारंभ करने वाली कॉल इसे बंद करती है। दोनों कॉल एक सेशन हैं।
session_id और agent_id हर ईवेंट विधि पर वैकल्पिक हैं। छोड़ा गया, वे एनक्लोजिंग स्कोप से समाधान करते हैं:
उन्हें स्पष्ट रूप से पास करने से अभी भी काम करता है और प्राथमिकता लेता है। कुछ भी बांधा नहीं और कुछ भी पारित नहीं, कॉल एक TypeError उठाता है जो सुधार का नाम देता है बजाय कोई सेशन के साथ एक ईवेंट उत्सर्जित करने के, जिसे ingest 200 का उत्तर देते हुए छोड़ देगा।स्कोप संदर्भ चर पर पहचान बांधते हैं। वे asyncio कार्यों में स्वचालित रूप से प्रसारित होते हैं लेकिन नए थ्रेड में नहीं — failproofai_sdk.propagate() में एक वर्कर लपेटें।

कौन कौन सी id बनाता है

एडेप्टर session_id कैसे समाधान करते हैं

पहला मैच जीता:
  1. एक स्पष्ट session_id विकल्प
  2. प्रति-कॉल मेटाडेटा
  3. एनक्लोजिंग session() स्कोप
  4. फ्रेमवर्क मेटाडेटा
  5. फ्रेमवर्क का अपना रन id
इसे कभी आविष्कार नहीं किया जाता है जबकि इनमें से एक मौजूद है — एक संश्लेषित id एक रन को कई सेशन में विभाजित करेगा।

agent_id को कम कार्डिनलिटी रखें

यह हर डैशबोर्ड सतह पर प्राथमिक पहलू है, और एक LowCardinality(String) कॉलम। एक प्रति-रन मान कॉलम को खराब करता है और फ़िल्टर ड्रॉपडाउन को प्रति रन एक प्रविष्टि से भरता है।एडेप्टर उस कॉलम की रक्षा करते हैं:असली id fw_agent_id / fw_run_id पर रखा जाता है, जहां यह एक पहलू बने बिना पूछताछ योग्य रहता है।
यह गार्ड केवल फ्रेमवर्क द्वारा चुने गए लेबल को छूता है। एक agent_id जिसे आप स्वयं पास करते हैं — event.*, या failproofai_sdk.agent(...) के लिए — ठीक जैसे दिया गया रिकॉर्ड किया जाता है। एक स्पष्ट तर्क को मूक रूप से फिर से लिखना उस कार्डिनलिटी से बदतर होगा जिसे यह रोकता है, इसलिए अपने स्वयं के स्पान का नाम तदनुसार रखें।
कौन सा फ्रेमवर्क क्या रिकॉर्ड करता है, ऊपर से रन से मापा गया:एक डैश का मतलब फ्रेमवर्क के पास कोई ऐसी अवधारणा नहीं है। human_pause और human_interrupt एक व्यक्ति द्वारा एजेंट पर कार्य करने का वर्णन करते हैं, जिसका कोई फ्रेमवर्क संकेत नहीं देता — स्वयं उत्सर्जन करें।
एक ईवेंट कभी अकेले नहीं आता। एक स्पान खुलता है, एक बंद होता है, और क्लोजिंग ईवेंट एक अवधि ले जाता है जो SDK इसके ओपनिंग वाले से मापता है।
कोई क्लोजिंग के साथ एक ओपनिंग ईवेंट कभी खत्म नहीं होने वाला एक स्पान है। सेशन हमेशा चल रहे के रूप में प्रस्तुत होता है, हमेशा के लिए, और इसकी सक्रिय अवधि बढ़ती रहती है। यह वह विफलता मोड है जिसे हाथ से इंस्ट्रूमेंट करते समय देखने के लिए है।

सहसंबंध नियम

  • मिलान पूर्णता ईवेंट के लिए एक ही tool_call_id, hook_id, pause_id, या input_id का पुनः उपयोग करें।
  • SDK tool_result, hook_completed, agent_resume, और human_input के लिए duration_ms की गणना करता है। इसे उन विधियों में पास करने से ValueError उठता है।
  • duration_ms स्वीकार किया जाता है model_response पर, क्योंकि केवल कॉलर असली प्रदाता विलंबता जानता है। यह एक पूर्णांक होना चाहिए — एक फ्लोट कॉल साइट पर ValueError उठाता है, क्योंकि सर्वर कॉलम को एक अहस्ताक्षरित 32-बिट पूर्णांक के रूप में पढ़ता है और कुछ और के लिए NULL संग्रहीत करेगा।
  • सहसंबंध कुंजियां तरह और सेशन द्वारा स्कोप की जाती हैं, इसलिए एक टूल कॉल और एक हुक सुरक्षित रूप से एक id साझा कर सकते हैं, और दो समवर्ती सेशन टकराए बिना समान id का पुनः उपयोग कर सकते हैं। वे एजेंट द्वारा स्कोप नहीं किए जाते हैं: एक जोड़ी एक एजेंट के तहत खुली और दूसरे के तहत बंद अभी भी सहसंबंधित होती है, जो बहु-एजेंट फ्रेमवर्क में सामान्य मामला है।
  • request_id model_request को model_response के साथ जोड़ी करता है। इसके बिना, मॉडल ईवेंट प्रति एजेंट क्रम में जोड़ी होती हैं, इसलिए समवर्ती कॉल गलत जोड़ी बनाती हैं।
  • प्रक्रियाओं में विभाजित एक जोड़ी अभी भी डाउनस्ट्रीम में सहसंबंधित होती है, लेकिन SDK इसकी प्रक्रिया में-अवधि की गणना नहीं कर सकता है।
  • लंबित मानचित्र अधिकतम 10,000 स्टार्ट पकड़ता है और पूर्ण होने पर सबसे पुरानी प्रविष्टि को निष्कासित करता है।
failproofai-sdk इंस्टॉल करने से सब कुछ इंस्टॉल होता है, सभी चार एडेप्टर शामिल हैं। अतिरिक्त एडेप्टर नहीं, फ्रेमवर्क खींचते हैं।
import failproofai_sdk अनुबंध शून्य-निर्भरता है, एक परीक्षण द्वारा प्रवर्तित जो निर्मित व्हील को --no-deps के साथ इंस्टॉल करता है और एक और जो साबित करता है कि कोई फ्रेमवर्क sys.modules तक नहीं पहुंचता है।
कोई failproofai_sdk.crewai विशेषता नहीं है। एडेप्टर जानबूझकर शीर्ष-स्तरीय पैकेज पर प्रदर्शित नहीं होते हैं: एक को छूना एक विशेषता पहुंच के दुष्प्रभाव के रूप में फ्रेमवर्क आयात करेगा, शून्य-निर्भरता प्रतिश्रुति को तोड़ते हुए। instrument() का उपयोग करें।
ऑटो-डिटेक्शन sys.modules को पढ़ता है, न कि इंस्टॉल किए गए पैकेज सूची को, इसलिए एक फ्रेमवर्क जिसे आपने इंस्टॉल किया है लेकिन कभी आयात नहीं किया वह इंस्ट्रूमेंट नहीं है और आपकी ओर से कभी आयात नहीं किया जाता है। यह देखने के लिए कि क्या वायर्ड है:
बिना CrewAI वाली मशीन पर instrument("crewai") नहीं उठाता। यह एक चेतावनी लॉग करता है और () लौटाता है, इसलिए एक लापता फ्रेमवर्क कभी एक प्रक्रिया को नीचे नहीं लाता है जो अन्य को भी इंस्ट्रूमेंट करता है।चेतावनी अंतर्निहित ImportError ले जाती है, और वह संदेश सटीक install कमांड का नाम देता है — इसलिए सुधार आपके लॉग में है, छिपा नहीं।
इसके बजाय उठाने के लिए FAILPROOFAI_SDK_STRICT=1 सेट करें। वह झंडा एक बार पढ़ा जाता है और कैश किया जाता है, इसलिए मध्य-रन सेट करने के बजाय अपनी प्रक्रिया शुरू होने से पहले निर्यात करें।
instrument() आपके फ्रेमवर्क आयात के बाद आना चाहिए। ऑटो-डिटेक्शन sys.modules को पढ़ता है, इसलिए आयात के ऊपर एक नंगा कॉल कुछ भी नहीं खोजता है, कुछ भी इंस्टॉल नहीं करता है, और () लौटाता है।
यह गलत प्राप्त करें और प्रक्रिया SDK आयातित, एडेप्टर स्पष्ट रूप से इंस्टॉल, और कोई भी ईवेंट उत्सर्जित नहीं के साथ चलता है। यह एक चेतावनी लॉग करता है जो बिल्कुल ऐसा कहता है — इसलिए एक रन रिकॉर्ड नहीं करते समय पहले अपने लॉग जांचें।
स्पूल वह है जो इसे सुरक्षित बनाता है: आपका एजेंट कभी नेटवर्क पर ब्लॉक नहीं होता है, और एक क्लाउड आउटेज एक बढ़ती डायरेक्टरी का मतलब है खोई हुई ईवेंट के बजाय।प्रत्येक फ्लश एक बैच फाइल लिखता है, पहले .tmp, फिर fsync, फिर एक परमाणु नाम बदलना:
डेमन केवल .jsonl उठाता है, इसलिए यह कभी आधी-लिखी गई फाइल नहीं पढ़ सकता। स्टेम एक टाइमस्टैम्प, प्रक्रिया id और अनुक्रम संख्या ले जाता है, इसलिए दो प्रक्रियाएं एक ही मिलीसेकंड में फ्लश करना संघर्ष नहीं कर सकती हैं। कतार 10,000 ईवेंट पर capped है; इसके बाद यह सबसे पुरानी को बंद करता है और लॉग करता है।
collector.redact आपकी SDK ईवेंट पर लागू नहीं होता है। यह कभी उन्हें नहीं देखता है।
डेमन आपकी बैच भेजता है। वह उन्हें खोलता या फिर से लिखता नहीं है।संपादन जहां डेमन अपनी स्वयं की ईवेंट लिखता है — जहां बैच भेजे जाते हैं नहीं। इसलिए एक प्रॉम्प्ट या एक टूल तर्क जिसमें एक API कुंजी होती है अभी भी आगमन पर रखती है।यह जानबूझकर है। ये आपके स्वयं के इंस्ट्रूमेंटेशन कॉल हैं, और पारगमन में उन्हें फिर से लिखने का अर्थ होगा कि आप जो ईवेंट प्राप्त करते हैं वे ईवेंट नहीं हैं जो आपने उत्सर्जित किए हैं।
आप स्रोत पर पेलोड को नियंत्रित करते हैं, दो जगहों में:
  • एडेप्टर पर सामग्री कैप्चर बंद करें। विकल्प नाम भिन्न होता है, और एक एडेप्टर के पास कोई नहीं है — यह एक एकल सार्वभौमिक स्विच नहीं है:
    • LangChain / LangGraph, Pydantic AI — capture_content=False
    • LlamaIndex — capture_messages=False
    • CrewAI — कोई सामग्री स्विच नहीं; session_id एकमात्र विकल्प है यह पढ़ता है, इसलिए प्रॉम्प्ट और पूर्ति हमेशा रिकॉर्ड किए जाते हैं।
    instrument() एडेप्टर द्वारा पढ़ी जाने वाली विकल्प को छोड़ता है, इसलिए गलत नाम पास करने से कुछ नहीं उठाया जाता है और कुछ भी नहीं बदलता है।
  • पहली जगह में रहस्य को input= को हाथ न सौंपें।
collector.redact किसी के लिए विकल्प नहीं है।
एक खाली स्पूल डायरेक्टरी स्वस्थ स्थिति है। इसे डिलीवरी की जांच करने के लिए न बनाएं।
डेमन इसे भेजने के मिलीसेकंड के भीतर प्रत्येक बैच को हटा देता है, इसलिए एक ls रेस एकत्रकर्ता और आपने जो उत्सर्जित किया उसका एक अंश दिखाता है — एक SDK से अप्रभेद्य जो कुछ भी रिकॉर्ड नहीं करता है।ईवेंट वास्तव में उतरे हैं यह पुष्टि करने के लिए, डैशबोर्ड की जांच करें। स्पूल को भरते हुए देखने के लिए, पहले डेमन को रोकें।
हर कॉलबैक एक रैपर के अंदर चलता है जिसका एकमात्र काम पुनः उठाना है, इसलिए आपकी कॉल ठीक एक try में बैठता है और सब कुछ SDK करता है इसके बाहर होता है।डिफ़ॉल्ट उत्पादन में सही है और डीबग करते समय गलत है, क्योंकि यह केवल यह साबित कर सकता है कि यह क्रैश नहीं हुआ। डीबग करते समय इसे जोर देने के लिए FAILPROOFAI_SDK_STRICT=1 सेट करें।

सामान्य समस्याएं

एक ओपनिंग ईवेंट का कोई क्लोजिंग नहीं है: एक model_request के बिना model_response, या एक tool_use के बिना tool_result। स्कोप का उपयोग करें, जो शरीर उठाए जाने पर भी जोड़ी की गारंटी देते हैं। यदि आप ईवेंट विधियों को सीधे कॉल करते हैं, तो try और finally का उपयोग करें।
यह मिलान ओपनिंग ईवेंट से मापा जाता है, इसलिए यह tool_result, hook_completed, agent_resume, और human_input पर अस्वीकार किया जाता है। यह model_response पर स्वीकार किया जाता है, क्योंकि केवल आप असली प्रदाता विलंबता जानते हैं, और यह एक पूर्णांक होना चाहिए।
थ्रेड ने कभी संदर्भ को विरासत में नहीं दिया। कॉलेबल को failproofai_sdk.propagate() में लपेटें। थ्रेड्स और async देखें।
अतिरिक्त फील्ड आखिरी में मर्ज होते हैं, इसलिए model या outcome जैसे वास्तविक फील्ड का नाम इसे अधिलेखित करेगा और एक संग्रहीत कॉलम बदल देगा। अपना नामस्थान; एडेप्टर एक fw_ उपसर्ग का उपयोग करते हैं।
agent_id कम-कार्डिनलिटी पहलू है और आपने एक रन id में डाल दिया। एक भूमिका या नोड नाम का उपयोग करें और असली id को एक पेलोड फील्ड में डालें।

अगला

यह कैसे काम करता है

जोड़ी, id, सेशन जीवनचक्र, और डिलीवरी।

एक ट्रेस पढ़ें

आपके द्वारा अभी कैप्चर किए गए सेशन के माध्यम से कारणात्मकता का पालन करें।

फ्रेमवर्क एडेप्टर

LangGraph, CrewAI, LlamaIndex, और Pydantic AI।