Orkas Orkas
डाउनलोड GitHub
मुखपृष्ठ ब्लॉग आर्किटेक्चर
आर्किटेक्चर

एजेंट की नींव फिर से लिखना: Orkas की बुनियाद से कोड पुनर्संरचना

Orkas ने 1.0 रिलीज़ शृंखला में अपने एजेंट की नींव कैसे दोबारा बनाई: प्रक्रिया के भीतर चलने वाला रनटाइम, प्रदाताओं का क्रमिक बदलाव, गतिशील समूह-चैट समन्वय, खुली होस्टिंग, स्मृति और स्व-विकास।

जब कोई AI एजेंट उत्पाद परिपक्व होता है, तो सबसे महँगी चीज़ फ़ीचर नहीं — उसकी नींव होती है। यह लेख Orkas की 1.0 रिलीज़ शृंखला में किए गए बुनियादी रीफ़ैक्टर का विवरण देता है — मॉडल कॉलिंग, एजेंट लूप, बहु-एजेंट समन्वय और टूल इकोसिस्टम का पूरा पुनर्गठन — और हर निर्णय के पीछे किए गए समझौतों को समझाता है।

संक्षिप्त विवरण दोबारा लिखने का उद्देश्य इसका परिणाम वह ऐप है जिसे आप आज इंस्टॉल कर सकते हैं: MIT के तहत ओपन सोर्स, स्थानीय-प्रथम और चाहें तो अपनी प्रदाता कुंजियों पर चलने वाला।
Orkas डाउनलोड करें — मुफ़्त

नींव में बदलाव क्यों करें

Orkas एक स्थानीय-प्रथम डेस्कटॉप AI एजेंट कार्यक्षेत्र है: एजेंट का सारा काम उपयोगकर्ता की अपनी मशीन की एक प्रक्रिया में चलता है, डेटा स्थानीय रूप से रहता है और शुरू से अंत तक क्लाउड सिंक माँग पर होता है। शुरुआती संस्करणों में फ़ीचर तेज़ी से जुड़ते गए — स्किल लाइब्रेरी, नॉलेज बेस, कनेक्टर, ग्रुप चैट जैसा बहु-एजेंट तंत्र — लेकिन आगे बढ़ने पर यह और स्पष्ट हुआ: असली रुकावट कोई एक फ़ीचर नहीं, बल्कि "नींव के स्तर" की तीन चीज़ें थीं।

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

  2. समन्वय "स्थिर योजना" पर आधारित था। शुरुआती संस्करण एक योजना/DAG इंजन था: पहले मॉडल से कार्य को योजना ग्राफ़ में बाँटवाना, फिर निष्पादक से ग्राफ़ के अनुसार काम भेजना। यह व्यवस्थित लगता है, लेकिन एजेंट की वास्तविकता बहुत गतिशील होती है — एक फ़ाइल पढ़ने से पता चलता है कि दिशा बदलनी है, और एक उपकार्य का परिणाम तय करता है कि अगला कदम किसे सौंपना है। पहले से बने ग्राफ़ में निर्णय स्थिर कर देने का मतलब है कि हर बार "योजना वास्तविकता के साथ नहीं चल पा रही" वाली समस्या को निष्पादक के भीतर सुधारना पड़ेगा।

  3. इकोसिस्टम एक बंद कैटलॉग था। स्किल केवल आधिकारिक मार्केटप्लेस से आ सकती थीं, कनेक्टर हार्ड-कोडेड कैटलॉग थे और उपयोगकर्ता की मशीन पर पहले से मौजूद बाहरी एजेंट टूल Orkas के लिए पूरी तरह अपारदर्शी थे। कोई उपयोगकर्ता तृतीय-पक्ष प्रोजेक्ट या अपना MCP सर्वर जोड़ना चाहे, या मशीन पर पहले से मौजूद एजेंट से Orkas की स्किल और नॉलेज बेस का उपयोग करवाना चाहे — आर्किटेक्चर के स्तर पर इनमें से कुछ भी संभव नहीं था।

इस रीफ़ैक्टर का मूल विचार सरल है: एजेंट की नींव का नियंत्रण फिर अपने हाथों में लेना। ठोस रूप में यह चार परस्पर जुड़े पहलुओं में सामने आता है — स्वयं बनाया गया इन-प्रोसेस रनटाइम, प्रदाता से स्वतंत्र मॉडल परत, गतिशील ग्रुप चैट समन्वय और बंद कैटलॉग से खुले होस्ट की ओर बदलाव। आइए इन्हें एक-एक करके देखें।

1. कोडिंग एजेंट की पूरी क्षमताएँ डेस्कटॉप पर लाना

डेस्कटॉप एजेंट का अपना मैदान है — यहाँ वास्तविक फ़ाइल सिस्टम, वास्तविक शेल और वास्तविक स्थानीय टूलचेन है। केवल चैट कर सकने वाला सहायक इस परिवेश की क्षमता बर्बाद कर रहा है; डेस्कटॉप का वास्तविक लाभ उठाता है कोडिंग एजेंट की क्षमताओं का पूरा समूह: अक्षर-सीमा तक फ़ाइलें पढ़ना और लिखना, कई फ़ाइलों में खोज, bash और सिस्टम टूल चलाना, कई वर्कर समानांतर शुरू करना और जटिल कार्य सचमुच पूरा होने तक दर्जनों टर्न चलाते रहने के लिए लंबे समय तक समस्या हल करना।

रीफ़ैक्टर का मुख्य परिणाम इसी क्षमता समूह को लाने के लिए है मूल रूप से Orkas की अपनी प्रक्रिया के भीतर — एक स्वतंत्र, गतिशील रूप से लोड होने वाला, इन-प्रोसेस एजेंट रनटाइम (जिसे कोड में core-agent कहा जाता है)। यह एक और चैट रैपर नहीं है; यह ऐसा एजेंट इंजन है जिसका नियंत्रण Orkas खुद रखता है।

मुख्य आर्किटेक्चरल निर्णय था इसे दो परतों में बाँटना:

  • इंजन परत (स्वतंत्र पैकेज): सिर्फ़ एजेंट का तंत्र — टूल कॉलिंग लूप, स्ट्रीमिंग इवेंट, कॉन्टेक्स्ट संपीड़न, त्रुटि वर्गीकरण और पुनः प्रयास, प्रदाता एब्स्ट्रैक्शन, सैंडबॉक्स, स्किल स्कैनिंग, मेमोरी, स्व-विकास। यह कुछ भी नहीं जानती Orkas के किसी व्यावसायिक तर्क के बारे में: यह व्यावसायिक डेटा डायरेक्टरी नहीं पढ़ती, बातचीत की फ़ाइल का फ़ॉर्मैट नहीं समझती और कभी IPC को नहीं छूती।
  • अडैप्टर परत (मुख्य प्रक्रिया के भीतर): इंजन को Orkas से जोड़ती है — सत्र को स्थायी रूप से सहेजना, प्रदाता बदलना, टूल अनुमतियाँ, स्किल रजिस्ट्री, कनेक्टर, नॉलेज बेस और विभिन्न जनरेशन टूल। यह इंजन के मूल इवेंट को Orkas के अपने इवेंट स्वरूप में बदलती है, ताकि व्यावसायिक परत को हमेशा स्थिर इंटरफ़ेस ही दिखे।

इंजन और अडैप्टर की यह सीमा आगे मिलने वाले पूरे लचीलेपन की जड़ है। इंजन को स्वतंत्र रूप से जाँचा और विकसित किया जा सकता है; अडैप्टर परत इंजन को दूषित किए बिना Orkas-विशिष्ट जटिलता (रोटेशन, कूलडाउन, सैंडबॉक्स, अनुमतियाँ) सुरक्षित रूप से संभाल सकती है। टीम की आर्किटेक्चर समीक्षा ने इसे एक पंक्ति में समेटा: यह सार्थक जटिलता है — इसे मिलाकर एक मत कर देना।

क्षमता समूह वास्तव में क्या है

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

  • सूक्ष्म स्तर के फ़ाइल कार्य और स्थानीय खोज। read_file अक्षर-सीमा के अनुसार पढ़ने का समर्थन करता है और PDF / Office दस्तावेज़ों से अपने आप टेक्स्ट निकालता है; edit_file सटीक "पुरानी स्ट्रिंग → नई स्ट्रिंग" प्रतिस्थापन करता है और किसी भी लेखन से पहले पढ़ना अनिवार्य करता है; write_file तैयार सामग्री को सहेजता है और उसका रिकॉर्ड रखता है; stat_file आकार जाँचता है; search_files नाम/ग्लॉब से खोजता है, grep_files कई फ़ाइलों की सामग्री में खोज करता है। यह समूह एजेंट को इंजीनियर की तरह वास्तविक कार्यक्षेत्र में "कोड खँगालने, फ़ाइलें बदलने" देता है, केवल पूरे ब्लॉक पढ़ने और निकालने तक सीमित नहीं रखता।
  • Bash और सिस्टम टूल। सैंडबॉक्स में चलने वाला शेल निष्पादक, जिसमें पृष्ठभूमि निष्पादन मोड (लंबे कार्य मौजूदा टर्न से अलग हो जाते हैं, लॉग फ़ाइल में जाते हैं) और खतरनाक कार्रवाइयों के लिए जोखिम के स्तर के अनुसार नियंत्रण है। डेस्कटॉप एजेंट की उपयोगिता का बड़ा हिस्सा सिस्टम टूलचेन को सीधे कमांड दे सकने से ही आता है।
  • कई वर्कर समानांतर। एक ही टर्न के भीतर स्वतंत्र, केवल पढ़ने वाले टूल एक साथ चलते हैं; कार्य स्तर पर कमांडर स्वतंत्र उपकार्यों को कई वर्कर में समानांतर बाँट भी सकता है (खंड 3 देखें)। जहाँ सुरक्षित हो वहाँ समानांतर चलाना "लंबे कार्यों" के वास्तविक बीते समय को स्वीकार्य सीमा में लाने की कुंजी है।
  • दीर्घकालिक तर्क और कार्य समाधान। ऐसा लूप जो लगातार दर्जनों टर्न चला सके, अपना कॉन्टेक्स्ट संभाल सके, त्रुटियों से उबर सके और कभी एक ही जगह घूमते हुए न अटके — यही "जटिल काम पूरा करने" और "प्रश्न का उत्तर देने" के बीच की विभाजक रेखा है।

इंजीनियरिंग के स्तर पर इसे वास्तविक उपयोग के योग्य कैसे बनाया गया

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

  • वास्तविक कॉन्टेक्स्ट विंडो + केवल 80% पर संपीड़न। इंजन हर मॉडल की वास्तविक कॉन्टेक्स्ट विंडो पढ़ता है (दस लाख टोकन वाली विंडो के मॉडल सहित) और उपयोग 80% पर पहुँचने पर ही संपीड़न शुरू करता है — सावधानी के नाम पर 60% से शुरू करके उपयोगी कॉन्टेक्स्ट का 40% फेंकने के बजाय। एक "लाभहीन संपीड़न" सुरक्षा जाँच भी है: यदि बचाकर रखा गया आखिरी हिस्सा पहले से ही विंडो भर देता है (मान लें, आखिरी हिस्से में बहुत बड़ी फ़ाइल पढ़ने का परिणाम है), तो संपीड़न कुछ खाली नहीं कर सकता; इसलिए यह सिर्फ़ चेतावनी लॉग करके छोड़ देता है, व्यर्थ सारांश कॉल कभी नहीं चलाता। लंबे कार्य में "पहले क्या हुआ याद रहना" इसी पर निर्भर करता है।

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

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

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

  • लूप की पहचान। जब वही टूल कॉल लगातार दोहराई जाती है, तो इंजन पहले संकेत देता है (तीसरी बार) और फिर पूरी तरह रोकता है (पाँचवीं बार); कोई भी अलग सिग्नेचर गिनती फिर से शुरू कर देता है — पेजिनेशन/पोलिंग जैसे वैध बदलावों पर गलती से रोक नहीं लगेगी। मॉडल अटकने पर अब चुपचाप टोकन खर्च नहीं करता रहता।

  • मुख्य टर्न के आउटपुट की कठोर सीमा हटाना। मुख्य टर्न का आउटपुट अब बहुत छोटी सीमा से बँधा नहीं है, इसलिए लंबी रिपोर्ट और बड़े संपादन चुपचाप कट नहीं जाते; सहायक कॉल (संपीड़न, चिंतन) अब भी सावधानीपूर्वक छोटी सीमा इस्तेमाल करती हैं।

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

ये सुधार मिलकर इस प्रश्न का उत्तर देते हैं कि "तैयार SDK ही क्यों न इस्तेमाल करें": क्योंकि डेस्कटॉप एजेंट की सबसे मज़बूत क्षमताएँ ठीक उसी परत में होती हैं जिसे SDK उपलब्ध नहीं कराता; उन्हें वास्तविक उपयोग के योग्य बनाने के लिए लूप अपने नियंत्रण में होना चाहिए।

2. मॉडल को हमेशा ऑनलाइन रखना: बहु-परतीय प्रदाता रैपर

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

सबसे महत्त्वपूर्ण डिज़ाइन यह है कि रोटेटर रनर के नीचे रहता है। इंजन किसी प्रदाता को कॉल करने से पहले ही उपयोगकर्ता का संदेश स्थायी सत्र में लिख देता है; यदि पुनः प्रयास/रोटेशन इंजन के स्तर पर किया जाए, तो या तो उपयोगकर्ता का संदेश दोबारा भेजना होगा या पूरे सत्र को पिछली स्थिति में लौटाने का तंत्र लिखना होगा। रोटेटर को इंजन के नीचे रखने से उपयोगकर्ता का संदेश ठीक एक बार लिखा जाता है, और "दूसरे विकल्प से फिर कोशिश करना" सत्र की स्थिति को बिल्कुल प्रभावित नहीं करता।

रोटेटर का निर्णय भी सीमित है और इस सीमा पर केंद्रित है: पहला कंटेंट इवेंट:

  • विफलता होने पर पहले कि मॉडल कोई सार्थक सामग्री (टेक्स्ट/टूल कॉल) निकाले — अगले विकल्प पर जाना सुरक्षित है;
  • पहला कंटेंट इवेंट निकलते ही — रोटेशन रोक दें और त्रुटि को ऊपर जाने दें, क्योंकि मॉडल पूरा टर्न पहले ही चला चुका हो सकता है और उसे दोहराने से वास्तविक प्रभाव वाली कार्रवाइयाँ फिर हो जाएँगी।

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

प्रदाता "सूची" की ओर, रीफ़ैक्टर तीन प्रकार के स्रोतों को एक साझा एब्स्ट्रैक्शन में समेटता है:

  • Orkas-प्रबंधित LLM: सर्वर पर चलने वाला प्रॉक्सी, साइन इन करते ही इस्तेमाल के लिए तैयार, जहाँ सर्वर टेक्स्ट/इमेज मॉडल के बीच रूटिंग करता है;
  • अपनी कुंजी लाएँ: सामान्य मुख्यधारा के बड़े मॉडल प्रदाता;
  • बाहरी सीधे कनेक्शन वाले अडैप्टर: ऐसे मॉडलों का समूह जिन्हें सीधे कनेक्शन की ज़रूरत है या जिनकी अपनी बिलिंग है, जिन्हें हाथ से उसी प्रदाता इंटरफ़ेस के अनुरूप ढाला गया है।

ऊपर की परतों को यह सब केवल एक स्थिर (provider, model) जोड़ी के रूप में दिखता है — रोटेशन, कूलडाउन और बाहरी अनुकूलन सब अडैप्टर परत के भीतर छिपे रहते हैं।

3. समन्वय के रूप में ग्रुप चैट: स्थिर योजना-DAG से लूप में कमांडर तक

यह रीफ़ैक्टर का वह हिस्सा है जो "सोचने का तरीका बदलने" की सबसे अधिक माँग करता है।

पुराना मॉडल था स्थिर योजना: मॉडल पहले योजना/DAG बनाता है और निष्पादक ग्राफ़ के अनुसार चलता है। नया मॉडल उस ग्राफ़ को पूरी तरह हटाकर उसकी जगह लाता है गतिशील ग्रुप चैट समन्वय, जिसमें कमांडर लूप में रहता है.

इसकी उपमा है एक ग्रुप चैट रूम:

  • यह Commander रूम का मेज़बान है, कोई अदृश्य मिडलवेयर नहीं;
  • एजेंट वर्कर रूम में पूर्ण दर्जे वाले, बराबर के सदस्य हैं;
  • सभी संवाद असिंक्रोनस संदेश हैं, जिन्हें कतार में डाला जाता है एक ही साझा संदेश बस के ज़रिए (समानांतर कार्य बाँटने का कोई निजी रास्ता नहीं है)।

कमांडर का "कार्य सौंपना" कोई @somebody सामान्य पाठ में लिख देना नहीं है — किसी LLM का @AgentA मुख्य पाठ में लिखना केवल प्रशिक्षण डेटा से आया मार्कडाउन है और भरोसेमंद नहीं है। कार्य सौंपने का असली संकेत है संरचित टूल कॉल, और रीफ़ैक्टर के बाद यह स्पष्ट अर्थ वाली तीन कार्रवाइयों में सिमट जाता है:

  • dispatch_to — किसी एजेंट को काम पूरा करके परिणाम लौटाने के लिए भेजें, जिसे कमांडर समेकित करे। कई स्वतंत्र कार्य एक साथ बाँटे जा सकते हैं।
  • run_worker — ऐसा उपकार्य जिसकी ज़िम्मेदारी कमांडर खुद रखता है और जिसका परिणाम सिंक्रोनस रूप से लौटता है; अनाम वर्कर कमांडर का "हाथ" है (उपयोगकर्ता को दिखाई नहीं देता), जबकि नाम वाला वर्कर दिखाई देने वाला विशेषज्ञ है।
  • hand_off_to — सौंपें बातचीत को उस एजेंट के; कमांडर अलग हो जाता है और एजेंट सीधे उपयोगकर्ता को उत्तर देता है, इस टर्न में ऊपर से कोई समेकन नहीं होता।

ऑर्केस्ट्रेटर या उप-एजेंट ट्री के बजाय ग्रुप चैट क्यों

बहु-एजेंट व्यवस्था को ग्रुप चैट बनाने से ऐसे कई लाभ मिलते हैं जो पारंपरिक ऑर्केस्ट्रेटर / उप-एजेंट ट्री नहीं दे सकता:

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

टीम की आर्किटेक्चर समीक्षा इस मुद्दे पर भी उतनी ही स्पष्ट थी: ग्रुप चैट बस और लूप में कमांडर ही है Orkas का बहु-एजेंट स्वरूप; प्रक्रिया के भीतर समानांतर उप-एजेंट कार्य भेजने का एक और रास्ता जोड़ना "ग्रुप चैट में कार्य भेजने का केवल एक रास्ता" होने के अपरिवर्तनीय नियम को तोड़ेगा।

इस संस्करण में नया: संवादात्मक नियंत्रण हस्तांतरण

इस दिशा में सबसे नया हिस्सा है संवादात्मक एजेंट नियंत्रण हस्तांतरण.

समस्या ठोस है: "शिक्षक" जैसा एजेंट एक टर्न में उपयोगकर्ता को सिखाता है, उपयोगकर्ता आगे प्रश्न पूछना चाहता है, लेकिन सिस्टम बातचीत का नियंत्रण वापस कमांडर को दे देता है, जिससे उपयोगकर्ता को फिर से-@ उस एजेंट को हर पंक्ति के लिए संबोधित करना पड़ता है।

समाधान है सर्वर द्वारा नियंत्रित बातचीत का अधिकार + मॉडल द्वारा तय प्राप्तकर्ता:

  • बातचीत का नियंत्रण एक स्थायी स्थिति फ़ील्ड बन जाता है, जो फिर से लोड होने पर भी सहेजा रहता है और मौजूदा स्थिति-बदलाव इवेंट के ज़रिए अपने आप सिंक होता है हर छोर पर — किसी नए इवेंट प्रकार की ज़रूरत नहीं।
  • कमांडर द्वारा इस्तेमाल करने के बाद hand_off_to किसी संवादात्मक एजेंट को बातचीत का नियंत्रण देने के लिए, उपयोगकर्ता के बाद के "बिना-@" वाले संदेश जाते हैं सीधे उसी एजेंट के पास, जब तक एजेंट खुद नियंत्रण वापस न दे दे या उपयोगकर्ता दोबारा कमांडर को संबोधित न करे।
  • एजेंट नियंत्रण वापस देता है एक <handback /> मार्कर से; पार्सिंग सख्ती से वास्तविक मेल की पुष्टि करती है (ताकि सामान्य पाठ में कहीं आया <handback गलती से नियंत्रण हस्तांतरण न मान लिया जाए)।
  • यदि नियंत्रण वापस देते समय कार्य बही में कोई अधूरा काम है, तो कमांडर बही से उसे उठाकर आगे बढ़ता है।

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

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

4. बंद कैटलॉग से खुले होस्ट तक

अगर पहले तीन मुख्य सूत्र बुनियाद को मज़बूत बनाने के बारे में थे, तो यह सभी दरवाज़े और खिड़कियाँ खोल देने के बारे में है — Orkas को एक बंद कैटलॉग से खुले होस्ट में बदलना — और साथ ही सुरक्षा की सीमा पर ज़रा भी समझौता न करना।

इस पुनर्गठन ने कई ऐसे नियंत्रण बिंदुओं को व्यवस्थित रूप से खोला जो पहले "बंद" थे:

  • बाहरी पैकेज। उपयोगकर्ता रिपॉज़िटरी का पता देता है, और Orkas उसे स्थानीय रूप से होस्ट करता है एक फ़ोल्डर में हूबहू क्लोन करके — न कभी सामान्यीकृत किया जाता है, न दोबारा लिखा जाता है, न क्लाउड से सिंक किया जाता है (क्योंकि उसमें तृतीय-पक्ष निर्भरताओं की डायरेक्टरियाँ होती हैं)। एक स्वतंत्र कमांड-लाइन टूल इंस्टॉल/अपडेट/शुरू-बंद करने के पूरे जीवनचक्र को संभालता है, जाँचता है कि वह "स्किल के रूप में" है (उसमें स्किल-विवरण फ़ाइल है) या "CLI के रूप में" (उसमें निष्पादन योग्य एंट्री है), और मेटाडेटा को एक रजिस्ट्री में लिखता है जो पैकेज डायरेक्टरी के बाहर होती है (ताकि आगे पुल करके किए जाने वाले अपडेट में कभी टकराव न हो)। निर्भरताओं की स्थापना "एक बार पूछो, याद रखो" वाली दो-चरणीय पुष्टि से होती है; निष्पादन योग्य एंट्रियों के लिए शिम बनाए जाते हैं और bash टूल के PATH में जोड़े जाते हैं, ताकि मॉडल इन तृतीय-पक्ष CLI को सीधे कॉल कर सके।

  • कई रूट से स्किल लोड करना। स्किल चलाने का एकमात्र प्रवेश बिंदु पहले केवल दो रूट पहचानता था; अब वह चार स्तर पहचानता है — कस्टम / मार्केटप्लेस / बाहरी पैकेज / ग्लोबल — जिन्हें प्राथमिकता के अनुसार चुना जाता है; बाहरी पैकेज के भीतर की स्क्रिप्ट पैकेज के साथ आए निर्भरता परिवेश को प्राथमिकता देती हैं। यह वह नियंत्रण बिंदु है जहाँ पुराने व्यवहार में गड़बड़ी आने का जोखिम सबसे अधिक है, और इसकी जाँच के लिए फ़िक्स्चर का पूरा मैट्रिक्स मौजूद है।

  • ग्लोबल स्किल की पारस्परिक संगतता। Orkas उन ग्लोबल स्किल डायरेक्टरियों से सीधे पढ़ता है जिन्हें उपयोगकर्ता की मशीन पर मौजूद दूसरे एजेंट टूल पहले से संभालते हैं, जिससे स्किल स्तर पर पारस्परिक संगतता मिलती है — उपयोगकर्ता ने एक जगह जो स्किल जुटाई है, वह Orkas में भी काम आती है। उपयोगकर्ता का उन डायरेक्टरियों में स्किल रखना ही उसकी अनुमति है, इसलिए यह डिफ़ॉल्ट रूप से चालू है, और एक मुख्य स्विच भी दिया गया है। तृतीय-पक्ष स्किल के ये विवरण प्रॉम्प्ट इंजेक्शन के लिए अविश्वसनीय सतह हैं, इसलिए इन्हें "खुले स्तर" वाले लोडर से लोड किया जाता है, ये केवल कमांडर को दिखते हैं, और इनकी संरचना ही ऐसी है कि ये किसी एजेंट की स्किल अनुमति-सूची में प्रवेश नहीं कर सकते.

  • उपयोगकर्ता द्वारा कॉन्फ़िगर किया गया MCP। कनेक्टर अब हार्ड-कोड किया हुआ कैटलॉग नहीं हैं। उपयोगकर्ता कोई भी MCP सर्वर जोड़ सकता है — दूरस्थ HTTP रूप में (कम जोखिम) या स्थानीय उप-प्रक्रिया रूप में (अधिक जोखिम)। फ़ॉर्म ही सहमति देने की जगह है (उपयोगकर्ता ने हाथ से जो कमांड टाइप किया है, वह हूबहू दिखाया जाता है), ट्रांसपोर्ट कॉन्फ़िगरेशन (सीक्रेट सहित) पूरी तरह एन्क्रिप्टेड स्टोरेज में जाता है, और कस्टम इंस्टेंस में हमेशा एक तय उपसर्ग होता है, ताकि वे कैटलॉग के किसी आधिकारिक कनेक्टर का रूप कभी न धर सकें।

  • उलटा ब्रिज: मशीन के बाहरी एजेंटों को भी Orkas तक पहुँच देना। यह सबसे दिलचस्प हिस्सा है। उपयोगकर्ता की मशीन पर पहले से मौजूद बाहरी एजेंट टूल पहले Orkas के लिए एक ब्लैक बॉक्स थे; अब Orkas जब उन्हें काम सौंपता है, तो एक ब्रिज चैनल जोड़ता है जिससे वे उलटी दिशा में Orkas की स्किल सूचीबद्ध/पढ़/चला सकते हैं, कनेक्टर कॉल कर सकते हैं और ज्ञान आधार में खोज कर सकते हैं। यह ब्रिज स्थानीय अंतर-प्रक्रिया चैनल पर चलता है (कोई नेटवर्क पोर्ट नहीं खुलता), और प्रमाणीकरण के लिए एक बार इस्तेमाल होने वाला क्रेडेंशियल होता है, जो हर रन के लिए अलग होता है और रन समाप्त होते ही नष्ट हो जाता है। बाहरी प्रभाव डालने वाली हर कनेक्टर कॉल उपयोगकर्ता के पुष्टि संवाद से होकर जाती है — टूल के नाम से पढ़ने/लिखने का अनुमान लगाकर निर्णय नहीं लिया जाता (जो ज़रूरत से ज़्यादा छूट दे सकता है), बल्कि हर (एजेंट, कनेक्टर) जोड़ी के लिए एक पुष्टि होती है, जिसमें वैकल्पिक "हमेशा अनुमति दें" भी होता है।

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

खुला, लेकिन नियंत्रण से बाहर नहीं

दरवाज़े और खिड़कियाँ खोलते समय सबसे ज़्यादा डर तेज़ झोंके का होता है। इस पुनर्गठन का अनुशासन है: "खतरनाक कार्रवाइयों" को शुरू करने वाले एक भी नियंत्रण बिंदु को नहीं छुआ गया। MCP ठीक एक ही जगह से शुरू होता है, स्किल का निष्पादन ठीक एक ही रनर से होता है, और bash ठीक एक ही सैंडबॉक्स एक्ज़िक्यूटर से गुजरता है। इसके ऊपर सुरक्षा की कई और परतें हैं:

  • फ़ाइल संबंधी कार्रवाइयाँ हमेशा पाथ सैंडबॉक्स से गुजरती हैं (वर्कस्पेस + वर्तमान अटैचमेंट + उपयोगकर्ता द्वारा स्पष्ट रूप से अनुमति दी गई डायरेक्टरियाँ), जबकि क्रेडेंशियल डायरेक्टरियों, सिस्टम डायरेक्टरियों और Orkas की अपनी डायरेक्टरियों के लिए अनुमति दी ही नहीं जा सकती;
  • खतरनाक bash (डेटा बाहर भेजना, विनाशकारी विलोपन, विशेषाधिकार बढ़ाना, संवेदनशील पाथ) अनुमति की पुष्टि माँगता है, जिसमें निर्णय "केवल इस बार / इस रन के लिए / अस्वीकार करें" में बाँटा जाता है, और लॉग में केवल श्रेणी और लंबाई दर्ज होती है — कमांड का टेक्स्ट कभी नहीं;
  • बाहरी पैकेज की स्थापना सुरक्षित रूप से रुक जाती है और पूरी तरह मना कर देती है ऐसे पैकेजों को जिनमें सिमलिंक सदस्य हों (ताकि सिमलिंक के ज़रिए सैंडबॉक्स के बाहर की संवेदनशील फ़ाइलों को पढ़ने के दायरे में न लाया जा सके), और क्लोन स्रोत केवल स्वीकृत प्रोटोकॉल की सूची तक सीमित रहता है;
  • क्रेडेंशियल वाले सभी ट्रांसपोर्ट/सीक्रेट संग्रहित अवस्था में एन्क्रिप्टेड रहते हैं, और ब्रिज क्रेडेंशियल हर रन के लिए अलग रखे जाते हैं;
  • ओपन-सोर्स / होस्टेड वितरण से केवल होस्ट के लिए आरक्षित क्षमताएँ छँटाई के एक नियम के तहत हटा दी जाती हैं।

एक वाक्य में: उपयोगकर्ता की हर स्पष्ट कार्रवाई (इंस्टॉल करना / अनुमति देना / फ़ॉर्म भेजना / पुष्टि पर क्लिक करना) सहमति का प्रमाण है, और हर सहमति अपनी उचित सीमा में बँधी रहती है।

5. सत्रों के साथ अधिक समझदार बनना: स्मृति और स्व-विकास

बुनियाद के इस पुनर्निर्माण में दो ऐसे उपतंत्र भी दोबारा बनाए गए जो "एजेंट को उपयोग के साथ अधिक समझदार बनाते हैं," और दोनों एक ही इंजीनियरिंग अनुशासन का पालन करते हैं — डिफ़ॉल्ट रूप से बंद, सीमाबद्ध, निगरानी योग्य.

सत्रों के बीच बनी रहने वाली स्मृति हाइब्रिड पुनर्प्राप्ति का उपयोग करती है: वेक्टर आधारित अर्थगत खोज + कीवर्ड खोज (BM25), जिन्हें RRF (रेसिप्रोकल रैंक फ़्यूज़न) से जोड़ा जाता है ताकि किसी एक माध्यम की विफलता से बचा जा सके; यह स्थानीय स्टोरेज में रहती है (पूर्ण-पाठ इंडेक्स के साथ)। स्मृति दो तरह की होती है — एजेंट के अपने नोट्स और उपयोगकर्ता की पसंद का प्रोफ़ाइल — दोनों पर वर्णों की सीमा होती है, लिखने से पहले इंजेक्शन के खतरों की जाँच होती है, और इन्हें स्थिर स्नैपशॉट के रूप में जोड़ा जाता है हर बारी की शुरुआत में सिस्टम प्रॉम्प्ट में। पूरी स्मृति प्रणाली का काम केवल एजेंट को वर्तमान उपयोगकर्ता की बेहतर समझ देना है; डेटा हमेशा स्थानीय रहता है, और उपयोगकर्ता सेटिंग्स में उसे कभी भी देख, संपादित और निर्यात कर सकता है।

स्व-विकास एजेंट की निजी स्किल लाइब्रेरी (प्लैटफ़ॉर्म की साझा स्किल लाइब्रेरी से अलग संग्रहित) और अपने सोचने के तरीके पर चिंतन की एक परत है। इंजन तय करता है कि चिंतन करना है या नहीं, इसके लिए वह कुछ भारित संकेतोंका उपयोग करता है: उपयोगकर्ता का सुधार (सबसे अधिक भार), किसी जटिल त्रुटि से उबरना, कार्य की जटिलता, किसी ज्ञात कमज़ोरी का सामने आना या उस पर काबू पाना, स्किल का अप्रभावी होना... चिंतन तभी शुरू होता है जब भारित संकेत एक सीमा पार करते हैं। चिंतन स्वयं एक बैकग्राउंड में चलने वाला आवधिक कार्य है (लगभग हर 12 घंटे में एक चक्र, कई घंटों का विराम, कई दिनों वाला फ़ॉलबैक), जो कम लागत वाले छोटे मॉडल से हाल की गतिविधियों का सार पढ़वाकर तय करता है कि स्किल बनानी/सुधारनी है या नहीं और एजेंट का "क्षमता प्रोफ़ाइल" अपडेट करना है या नहीं।

सुरक्षा का सबसे महत्वपूर्ण बिंदु: स्व-विकास केवल उन्हीं सत्रों के लिए चालू होता है जिनसे कोई एजेंट स्पष्ट रूप से जुड़ा हो — डिफ़ॉल्ट कमांडर सत्र विकसित नहीं होता। चिंतन पर दोहरी टोकन सीमा (गिनती + कुल) है, एक एजेंट की विफलता दूसरों को नहीं रोकती, और प्रति रन लागत बेहद कम रखी जाती है। एजेंट को समझदार बनाइए, लेकिन उसे नियंत्रण से बाहर मत जाने दीजिए।

इंजीनियरिंग दर्शन: उचित कारणों से आई जटिलता — सरलीकरण में उसे मिटाएँ नहीं

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

  • सिंक इंजन की कई मर्ज रणनीतियाँ, स्वयं बनाया गया एजेंट लूप, कई परतों वाला प्रदाता रैपर, मोबाइल रिमोट कंट्रोल की सीमा — ये जटिल दिखते हैं, लेकिन हर परत का अपना औचित्य है (कई डिवाइसों में अंततः संगति, गहरा एकीकरण, कई की का रोटेशन, उत्पाद द्वारा तय अंतिम सीमा)। जबरन इन्हें "सरल" करने से केवल डेटा खोएगा और परतों की स्पष्टता धुँधली होगी।
  • जिन चीज़ों को वास्तव में बदलना चाहिए, वे हैं सब कुछ समेटे हुए "गॉड मॉड्यूल" और स्थानीय दोहराव: फूली हुई ग्रुप-चैट बस से स्टेटलेस शुद्ध फ़ंक्शन अलग निकालना (प्रॉम्प्ट संयोजन, कमांडर टूल, CLI की बारी), और कई बार दोहराए गए "पुष्टि संवाद" पैटर्न को एक साझा कंपोनेंट में समेटना।

इस तरह के निर्णय के पीछे परियोजना के बाध्यता दस्तावेज़ में लिखे कठोर अनुशासन हैं: सीमा (एक ही प्रक्रिया, IPC ही एकमात्र रास्ता, रनटाइम केवल डायनेमिक रूप से लोड हो सकता है), परतबंदी (हर परत की निर्भरता की दिशा), सत्य का एकमात्र स्रोत (श्रेणियाँ, टेलीमेट्री वर्गीकरण, डोमेन), और प्रॉम्प्ट से संबंधित हर कमिट पर अनिवार्य "प्रॉम्प्ट ऑडिट"। बुनियाद को ढहाए बिना उसका पूरा पुनर्निर्माण संभव बनाने वाली चीज़ कोई चतुर डिज़ाइन नहीं — इन अपरिवर्तनीय नियमों का लगातार पालन है।

समापन

इन चार मुख्य सूत्रों को साथ रखें, तो यह आमूल पुनर्गठन Orkas को ऐसी एजेंट बुनियाद देता है जो है अपने नियंत्रण में, प्रदाता-निरपेक्ष, गतिशील रूप से समन्वित, बाहरी दुनिया के लिए खुली, और स्वयं विकसित होने में सक्षम:

  • इंजन/अडैप्टर की दो परतों वाला इन-प्रोसेस रनटाइम, जो कोडिंग एजेंट की पूरी ताकत — फ़ाइल संबंधी कार्रवाइयाँ, स्थानीय खोज, सिस्टम टूल, समानांतर कई वर्कर, लंबे समय वाले समाधान — को डेस्कटॉप पर मूल रूप से लाता है और हर क्षमता को वास्तविक उपयोग के योग्य बनाता है;
  • कई परतों वाला मॉडल स्तर, जो की/प्रदाता/नेटवर्क की उथल-पुथल के बीच बातचीत को यथासंभव जारी रखता है;
  • ग्रुप-चैट शैली का, कमांडर की भागीदारी वाला बहु-एजेंट समन्वय, जो "स्थिर योजना" की जगह "गतिशील निर्णय" लाता है और पहली बार एजेंटों के बीच काम सौंपने को सहज बनाता है;
  • एक ऐसा इकोसिस्टम जो बंद कैटलॉग से खुले होस्ट की ओर बढ़ रहा है, जिसमें बाहरी पैकेज, ग्लोबल स्किल, कस्टम MCP और उलटा ब्रिज सब खोल दिए गए हैं — जबकि प्रक्रियाएँ शुरू करने वाले नियंत्रण बिंदु ज़रा भी नहीं बदले;
  • और स्मृति तथा स्व-विकास, जो डिफ़ॉल्ट रूप से बंद, सीमाबद्ध और निगरानी योग्य हैं।

सुविधाएँ एक-एक करके जोड़ी जा सकती हैं, लेकिन बुनियाद का गंभीर पुनर्निर्माण एक ही बार करना सार्थक होता है। एक बार वह हो जाए, तो उसके ऊपर आप जो भी बनाते हैं, वह तेज़ी से बनता है — और इस पुनर्गठन का लक्ष्य ठीक यही नतीजा था।