अनेक वर्षांपासून, कृत्रिम बुद्धिमत्ता (AI) एडिटरमध्ये तुमच्या शेजारी बसून पुढचे काय येईल याचा अंदाज लावत होती. तुम्ही एक ओळ लिहायचात; ती पुढची ओळ सुचवायची. आर्किटेक्चर, डीबगिंग आणि सिंटॅक्सवर तुमचे नियंत्रण असायचे. आता ही व्यवस्था संपली आहे.

आपण Intent-Driven Development कडे वळत आहोत. तुम्ही लूप्स (loops) आणि कंडिशनल्स (conditionals) टाईप करणे थांबवता. त्याऐवजी, तुम्हाला अपेक्षित असलेले परिणाम तुम्ही वर्णन करता. एक एजंट (agent) तो ध्येय स्वीकारतो, पायऱ्यांचे नियोजन करतो, कोड लिहितो, टेस्ट्स रन करतो आणि तुम्हाला निकाल दिसण्यापूर्वीच स्वतःच्या चुका सुधारतो. कीबोर्ड आता मुख्य साधन राहिलेला नाही. स्पष्ट विचार करणे हे आता मुख्य साधन आहे.

ओळ-दर-ओळ (Line-by-Line) कोडिंगचा अंत

जुन्या कार्यप्रणालीमध्ये (workflow) तुम्हाला प्रत्येक हेतू कंपायलरला समजेल अशा विशिष्ट भाषेत रूपांतरित करावा लागायचा. तुम्ही व्यवसायाची आवश्यकता (business requirement) मनात ठेवायचा आणि मग त्याचे मॅन्युअली फंक्शन्स, इम्पॉर्ट्स, एरर हँडलिंग आणि टेस्ट केसेसमध्ये विभाजन करायचा. Intent-Driven Development ही रूपांतरणाची प्रक्रिया (translation layer) काढून टाकते.

समजा तुम्हाला पेमेंट वेबहुक (payment webhook) इंटिग्रेट करायचा आहे. पूर्वी, तुम्ही रूट हँडलर लिहायचा, पेलोड पार्स (parse) करायचा, सिग्नेचर व्हॅलिडेट करायचा, ट्रान्झॅक्शनमध्ये डेटाबेस अपडेट करायचा आणि पावती ईमेलसाठी क्यू (queue) करायचा. आता तुम्ही फक्त आवश्यकता वर्णन करता: “येणारा Stripe वेबहुक व्हॅलिडेट करा, इव्हेंट आयडेम्पोटंटली (idempotently) रेकॉर्ड करा आणि पावतीची प्रक्रिया सुरू करा. जर डेटाबेसमध्ये लिहिण्यात अपयश आले तर रोल बॅक करा.” एजंट हँडलर लिहितो, पार्सिंग स्ट्रॅटेजी निवडतो, रिट्राय लॉजिक (retry logic) तयार करतो आणि टेस्ट्स जनरेट करतो. तुमची भूमिका आता लेखकाकडून दिग्दर्शकाकडे बदलली आहे.

हे केवळ यासाठी शक्य आहे कारण एजंट केवळ कोड जनरेट करून थांबत नाही. तो एका लूपमध्ये (loop) काम करतो.

एजंट लूपच्या आत

मुख्य काम आता मानवी टायपिंग किंवा मॅन्युअल डीबगिंग राहिलेले नाही. ते जनरेशन आणि व्हॅलिडेशन यांच्यातील एक वेगवान चक्र आहे. एजंट कोड तयार करतो, तुमच्या टेस्ट सुईटवर (test suite) तो रन करतो, आउटपुट वाचतो आणि स्वतःहून त्रुटी सुधारतो. एखादा इम्पॉर्ट विसरणे, टाईप मिसमॅच (type mismatch), किंवा एखादे अ‍ॅसर्शन (assertion) फेल होणे — एजंट स्टॅक ट्रेस (stack trace) पाहतो, फाईल एडिट करतो आणि पुन्हा टेस्ट रन करतो. तुम्ही त्या लूपमध्ये नसता. हे चक्र मशीनच्या वेगाने चालते.

जेव्हा हे लूपच तुटते, तेव्हा तुम्ही हस्तक्षेप करता. कदाचित एजंट दोन डिपेंडन्सीजमधील (dependencies) संघर्ष सोडवू शकत नाही, किंवा तो असा कोड जनरेट करत राहतो जो युनिट टेस्ट्स पास करतो पण उच्च-स्तरीय व्यावसायिक नियमांचे उल्लंघन करतो. अशा सीमांवर मानवी निर्णयाची (human judgment) अजूनही गरज असते.

तुमचे खरे काम: कन्स्ट्रेंट डिझाइनर आणि एज-केस हंटर

जर मशीन फंक्शन्स लिहित असेल, तर तुमच्यासाठी काय उरले आहे? दोन गोष्टी, आणि त्या सिंटॅक्स टाईप करण्यापेक्षा कठीण आहेत.

पहिले म्हणजे, तुम्ही असे कन्स्ट्रेंट्स (constraints) लिहिता जे एजंटला योग्य मार्गावर ठेवतात. एजंटकडे व्यापक ज्ञान असते पण तुमच्या विशिष्ट वातावरणाची (environment) त्याला समज नसते. तुम्हाला त्याला सांगणे आवश्यक आहे: “केवळ अंतर्गत बिलिंग API वापरा, कार्ड टोकन्स कधीही लॉग करू नका आणि रिस्पॉन्स लॅटन्सी (response latency) दोनशे मिलीसेकंदपेक्षा कमी ठेवा.” या सीमा केवळ साधे प्रॉम्प्ट्स नाहीत. त्या अशा स्पेसिफिकेशन्स (specifications) आहेत ज्या यश किंवा अपयश ठरवतात.

दुसरे म्हणजे, एजंट जिथे अपयशी ठरतो अशा १० टक्के प्रकरणांना तुम्ही पकडता. एजंट सामान्य मार्ग (common path) चांगल्या प्रकारे हाताळतात. परंतु सूक्ष्म रेस कंडिशन्स (race conditions), संदिग्ध बिझनेस लॉजिक एज केसेस (edge cases) आणि त्यांच्या ट्रेनिंग डेटातील सुरक्षा गृहितकांवर (security assumptions) ते अडखळतात. वेबहुक हँडलर आणि रिफंड क्रॉन जॉब (refund cron job) मधील रेस ओळखणे, किंवा जनरेट केलेले रिट्राय लॉजिक चार्जेसची पुनरावृत्ती करू शकते हे ओळखणे, यातून तुमची खासियत सिद्ध होते. मशीन सामान्य समस्या सोडवते. तुम्ही धोकादायक अपवाद (exception) पकडता.

कोड रिव्ह्यूच्या जागी 'व्हेरिफिकेशन हार्नेस' वापरा

जेव्हा एखादा एजंट रातोरात पन्नास फाईल्स तयार करू शकतो, तेव्हा ते “योग्य दिसत आहेत का” हे पाहण्यासाठी केवळ 'डिफ्स' (diffs) पाहून रिव्ह्यू करणे तुम्हाला शक्य नाही. कामाचे प्रमाण इतके जास्त असते की मानवी डोळ्यांनी तपासणे अशक्य होते. तुम्हाला अशा 'हार्नेस'ची (harness) गरज आहे जे कोड तुमच्यापर्यंत पोहोचण्यापूर्वीच चुका पकडेल.

हे हार्नेस तीन स्तंभांवर आधारलेले आहे.

ड्युरेबल एक्झिक्यूशन (Durable execution). एजंटची कामे अनेकदा एका सिंगल रिक्वेस्ट टाइमआउटपेक्षा जास्त वेळ चालतात. जर तात्पुरत्या नेटवर्क बिघाडामुळे एखादी पायरी अपयशी ठरली, तर हार्नेस थांबतो, पुन्हा प्रयत्न करतो आणि स्टेट (state) खराब न करता काम पुन्हा सुरू करतो. कामात व्यत्यय आला तरी ते पूर्ण होते.

स्ट्रक्चर्ड आउटपुट्स (Structured outputs). एजंटने व्यवस्थित कॉन्फिगरेशन फाईल परत करेल अशी आशा करण्याऐवजी, तुम्ही आधीच करार (contract) निश्चित करता. JSON Schema सारखी साधने आउटपुट त्वरित व्हॅलिडेट करतात. जर एजंटने आवश्यक फील्ड वगळले किंवा चुकीचा डेटा टाईप वापरला, तर कोड तुमच्या रिपॉझिटरीमध्ये पोहोचण्यापूर्वीच हार्नेस तो नाकारतो.

डायनॅमिक गार्डरेल्स (Dynamic guardrails). एजंटला सीक्रेट्स वाचण्याचे किंवा प्रोडक्शन डेटाबेसमध्ये लिहिण्याचे स्वातंत्र्य नसावे. हार्नेस परवानग्या (permissions) डायनॅमिकली नियंत्रित करतो, एजंटला सँडबॉक्स (sandboxing) करतो जेणेकरून तो केवळ नियुक्त टेस्ट डेटाबेस आणि अंतर्गत एंडपॉइंट्सना स्पर्श करू शकेल. तुम्ही प्रत्येक ओळ तपासत नाही. तुम्ही एजंटभोवती असलेल्या कुंपणाचे (fence) ऑडिट करत असता.

जेव्हा कोड काम करतो पण उत्पादन अपयशी ठरते

येथे एक विरोधाभास आहे. हॅर्नेस (harness) खराब कोड पकडतो, परंतु तो खराब हेतू (intent) पकडू शकत नाही.

जर तुमच्या स्पेसिफिकेशनमध्ये (specification) असे म्हटले असेल की, "प्रत्येक नवीन वापरकर्त्याला स्वागत ईमेल पाठवा," तर एजंट तो ईमेल पाठवणारा स्वच्छ आणि चाचणी केलेला (tested) कोड लिहून देईल. परंतु, तुमचा नेमका अर्थ असा होता की, "वापरकर्त्याने त्यांचा पत्ता सत्यापित केला असेल, मार्केटिंगसाठी संमती दिली असेल आणि त्यांच्या स्थानिक वेळेनुसार कामकाजाच्या तासांमध्ये नोंदणी केली असेल, तरच स्वागत ईमेल पाठवा," हे त्याला समजणार नाही. तो कोड तांत्रिकदृष्ट्या दोषरहित असेल, पण व्यावसायिकदृष्ट्या धोकादायक ठरू शकतो.

Intent-Driven Development मधील खरा धोका म्हणजे अस्पष्ट स्पेसिफिकेशन. अस्पष्ट हेतूमुळे असे सॉफ्टवेअर तयार होते जे चुकीची समस्या पुस्तकी अचूकतेने सोडवते. म्हणूनच, तुम्ही तुमच्या स्पेसिफिकेशनकडे वास्तविक मालमत्ता (assets) म्हणून पाहिले पाहिजे. त्यांचे व्हर्जन (version) करा. स्टेकहोल्डर्ससोबत (stakeholders) त्यांचे पुनरावलोकन करा. एजंटने काम सुरू करण्यापूर्वी प्रत्यक्ष वर्कफ्लोच्या (workflows) आधारे त्यांची पडताळणी करा. चॅट बॉक्समध्ये घाईघाईने लिहिलेला प्रॉम्प्ट (prompt) हे स्पेसिफिकेशन नसते; ती एक जबाबदारी (liability) असते.

इंजिनिअरिंग जजमेंट आता उच्च स्तरावर स्थलांतरित होत आहे

इंजिनिअरिंग जजमेंट नाहीसे होत नाहीये, तर ते उच्च स्तरावर स्थलांतरित होत आहे.

आता तुम्ही मॅप (map) कसा फिरवायचा (iterate) किंवा क्लास हायरार्की (class hierarchy) कशी संरचित करायची यावर मानसिक ऊर्जा खर्च करत नाही. त्याऐवजी, सिस्टीम अपयशी (failure) झाल्यावर काय करणे आवश्यक आहे, कोणता डेटा कधीही उघड (expose) करू नये आणि डिस्ट्रिब्युटेड सर्व्हिसेसमध्ये (distributed services) कोणते नियम (invariants) पाळले पाहिजेत, यावर तुम्ही ऊर्जा खर्च करता. कोडिंगचे कौशल्य आता 'रिक्वायरमेंट्स' (requirements) ठरवण्याचे कौशल्य बनत आहे.

याचा अर्थ असा की, तुमच्या स्पेसिफिकेशनमध्ये देखील तितकीच अचूकता असणे आवश्यक आहे, जी तुम्ही पूर्वी तुमच्या कोडमध्ये वापरत होतात. तुमच्या मर्यादा (constraints) अचूकपणे नमूद करा. फेल्युअर मोड्स (failure modes) स्पष्टपणे परिभाषित करा. बिझनेस रूल्स (business rules) तितक्याच स्पष्टपणे सांगा जितक्या स्पष्टपणे तुम्ही पूर्वी तुमचे टाइप्स (types) घोषित करत होतात. अंमलबजावणी (implementation) एजंट करेल, परंतु ती अंमलबजावणी करण्यासारखी आहे याची खात्री तुम्हाला करावी लागेल.

तुमचा गुणवत्तेचा निकष (quality bar) 'पुल रिक्वेस्ट' (pull request) कडून 'प्रॉम्प्ट' (prompt) कडे वळवा. प्रथम हॅर्नेस (harness) तयार करा. त्यानंतर स्पेसिफिकेशन लिहा. मग मशीनला सिंटॅक्स (syntax) हाताळू द्या, तर तुम्ही समस्या योग्यरित्या परिभाषित केली आहे की नाही आणि सीमा (boundaries) सुरक्षितपणे आखल्या आहेत की नाही यावर लक्ष केंद्रित करा.

जर तुम्हाला या बदलामागच्या कल्पना अधिक सखोलपणे जाणून घ्यायच्या असतील, तर Intent-Driven Development वरील मूळ चर्चा येथे उपलब्ध आहे. AI-native इंजिनिअरिंगशी संबंधित सुरू असलेल्या संवादांसाठी, तुम्ही GyaanSetu community मध्ये देखील सामील होऊ शकता.