پرامپٹس (Prompts) محض مشورے ہیں۔ ہکس (Hooks) حتمی رکاوٹیں ہیں۔
کئی مہینوں تک، میں نے Claude Code کے ساتھ ایک جونیئر ڈویلپر کی طرح سلوک کیا جسے صرف واضح قواعد و ضوابط کی ضرورت تھی۔ میری پروجیکٹ ہدایات بالکل واضح تھیں: کبھی force-push نہ کریں، کبھی برانچز (branches) ڈیلیٹ نہ کریں، اور کبھی تباہ کن کمانڈز (destructive commands) نہ چلائیں۔ زیادہ تر شاموں میں، یہ کام کر گیا۔ ایجنٹ نے ٹیسٹ لکھے، فنکشنز کو ریفیکٹر (refactor) کیا، اور git ہسٹری سے دور رہا۔ پھر ایک rebase کے دوران سب کچھ بگڑ گیا۔
کانٹیکسٹ ونڈو (context window) git ایرر آؤٹ پٹ سے بھر گئی۔ کنفلکٹ مارکرز (conflict markers)، ڈیٹچڈ HEAD (detached HEAD) پیغامات، اور برانچ ڈائیورجنس (branch divergence) کے وارننگز ٹوکن بہ ٹوکن جمع ہوتے گئے۔ اس شور کے نیچے میری یہ شائستہ ہدایت دفن تھی کہ force-pushing سے بچا جائے۔ ماڈل کے لیے، تھریڈ میں سب سے حالیہ اور نمایاں متن ایرر اسٹریم تھا۔ شماریاتی توجہ (statistical attention) نے پالیسی پر فتح حاصل کر لی۔ ایجنٹ نے ایک ایسی کمانڈ چلا دی جس نے دو گھنٹے کی غیر کمٹ شدہ (uncommitted) لوکل تبدیلیوں کو مٹا دیا۔ یہ کوئی بدنیتی نہیں تھی؛ یہ محض توجہ کا بھٹک جانا تھا۔ یہ فرق اہمیت رکھتا ہے۔ ایک LLM بدنیتی کی وجہ سے اصول نہیں توڑتا۔ وہ انہیں اس لیے توڑتا ہے کیونکہ کانٹیکسٹ ونڈو میں ایک زیادہ بلند پیٹرن عارضی طور پر پہلے سے دی گئی ہدایت پر غالب آ جاتا ہے۔
اس واقعے نے ایجنٹ کی حفاظت (agent safety) کے بارے میں میری سوچ بدل دی۔ ایک ایسا گارڈ ریل (guardrail) جو ننانوے فیصد وقت کام کرتا ہے، وہ ایک خطرہ ہے۔ اگر ناکامی کا طریقہ آپ کا وقت، پیسہ، یا پروڈکشن ڈیٹا ضائع کر دے، تو آپ اسے پرامپٹ کے اندر نہیں چھوڑ سکتے۔ آپ کو ماڈل کے ریژوننگ لوپ (reasoning loop) سے باہر نفاذ (enforcement) کی ضرورت ہے۔
Claude Code hooks بالکل اسی مسئلے کو حل کرتے ہیں۔ یہ چھوٹے اسکرپٹس ہیں جو تین مخصوص لمحات پر ٹول کالز (tool calls) کو روکتے ہیں: ٹول کے چلنے سے پہلے (PreToolUse)، ٹول کے مکمل ہونے کے بعد (PostToolUse)، اور جب ایجنٹ فیصلہ کرتا ہے کہ وہ کام ختم کر چکا ہے (Stop)۔ چونکہ یہ بیرونی کوڈ کے طور پر چلتے ہیں، اس لیے یہ ماڈل کی یادداشت، موڈ، یا کانٹیکسٹ کے دباؤ پر انحصار نہیں کرتے۔ ماڈل آپ کی دی گئی ہر ہدایت بھول سکتا ہے؛ لیکن ہک (hook) پھر بھی "ناں" کہے گا۔
اس ضائع شدہ شام کے بعد میں نے جو ہارسنس (harness) بنایا، وہ یہ رہا۔
گارڈ ہک (Guard Hook): نقصان سے پہلے روک تھام
میرا PreToolUse ہک ہر Bash کمانڈ کا معائنہ کرتا ہے اس سے پہلے کہ شیل (shell) اسے چھوئے۔ میں تباہ کن پیٹرنز کی ایک سخت ڈین لسٹ (denylist) رکھتا ہوں۔ اگر کمانڈ اسٹرنگ کسی خطرناک چیز سے مماثلت رکھتی ہے، تو ہک عمل درآمد کو روک دیتا ہے اور براہ راست ایجنٹ کو ایرر واپس بھیج دیتا ہے۔
وہ پیٹرنز جنہیں میں بلاک کرتا ہوں سادہ اور غیر مبہم ہیں:
git push --forceیا کوئی بھی force-with-lease ورژن جس پر مجھے ابھی بھروسہ نہیں ہےgit reset --hardrm -rf
یہ کوئی پیچیدہ سیکیورٹی ریسرچ نہیں ہے۔ یہ ایک سیٹ بیلٹ ہے۔ لیکن اہم تفصیل یہ ہے کہ بلاک ہونے کے بعد کیا ہوتا ہے۔
میں کبھی بھی سادہ سا "Blocked" نہیں کہتا۔ ایک سیدھا انکار ایجنٹ کو الجھا دیتا ہے اور اسے ایک ایسے لوپ میں پھنسا سکتا ہے جہاں وہ اسی تباہ کن کمانڈ کے مختلف ورژن آزمانے کی کوشش کرتا ہے۔ اس کے بجائے، ایرر میسج میں فرار کا راستہ بھی شامل ہوتا ہے۔ جب ہک کسی ہارڈ ری سیٹ (hard reset) کو پکڑتا ہے، تو وہ ایجنٹ کو بتاتا ہے: “غیر کمٹ شدہ کام کے تحفظ کے لیے یہ کمانڈ بلاک کر دی گئی ہے۔ پہلے ایک چیک پوائنٹ کمٹ کریں، پھر دوبارہ جائزہ لیں۔” یہ اضافی جملہ ایجنٹ کے رویے کو مکمل طور پر بدل دیتا ہے۔ وہ نقصان کو کنٹرول کرنے کی کوشش کرنے کے بجائے حفاظت پیدا کرنے کی طرف مڑ جاتا ہے۔ ہک صرف ایک دیوار نہیں ہے؛ یہ ٹریفک کنٹرول ہے۔
میں نے شیل کمانڈز کے لیے allowlist کے بجائے denylist کا انتخاب کیا۔ شروع میں، میں نے صرف محفوظ git سب کمانڈز کے ایک واضح سیٹ کی اجازت دینے پر غور کیا۔ وہ طریقہ جلد ہی ناکام ہو گیا۔ ایجنٹس تخلیقی طور پر لفظی (creatively literal) ہوتے ہیں۔ وہ حالت چیک کرنے کے لیے git stash push -m "wip" یا git branch --show-current جیسی جائز لیکن غیر متوقع کمانڈز چلاتے ہیں۔ ایک allowlist اس لمحے ہی نارمل ورک فلو کو توڑ دیتی ہے جب ماڈل کوئی ایسی کمانڈ ایجاد کرتا ہے جو درست ہو لیکن لسٹ میں نہ ہو۔ حقیقی طور پر تباہ کن پیٹرنز کی ایک مختصر اور منتخب شدہ denylist ایجنٹ کو کام کرنے کی گنجائش دیتی ہے جبکہ سرحدوں کی حفاظت بھی کرتی ہے۔
فارمیٹر ہک (Formatter Hook): معمول کے کام کو خودکار بنائیں
میں ایجنٹ کو یہ کہنے میں پرامپٹ ٹوکنز ضائع کرتا تھا کہ "فائل ایڈٹ کرنے کے بعد ہمیشہ فارمیٹر چلائیں۔" وہ آدھی بار بھول جاتا تھا۔ باقی آدھی بار، وہ رک جاتا اور پوچھتا کہ کیا فارمیٹ کرنا ہے، جس سے ایک ایسے فیصلے پر ٹول کال ضائع ہو جاتی جس کا صرف ایک ہی صحیح جواب تھا۔
اب میں اسے PostToolUse ہک کے ذریعے سنبھالتا ہوں۔ ایجنٹ کے فائل ایڈٹ کرنے کے بعد، ہک فائل ایکسٹینشن چیک کرتا ہے۔ اگر یہ Python ہے، تو یہ Ruff چلاتا ہے۔ اگر یہ JavaScript یا TypeScript ہے، تو یہ Prettier چلاتا ہے۔ اگر یہ Go ہے، تو یہ gofmt چلاتا ہے۔ ایجنٹ کو معلوم ہی نہیں ہوتا کہ فارمیٹر موجود ہے۔ اسے ضرورت بھی نہیں ہے۔
اسے پرامپٹ سے باہر نکالنے کے دو اثرات ہوئے۔ پہلا یہ کہ کوڈ مستقل طور پر صاف رہتا ہے بغیر ماڈل پر ذہنی بوجھ (cognitive load) ڈالے۔ دوسرا یہ کہ میری پروجیکٹ ہدایات مختصر ہو گئیں۔ ہر وہ "ہمیشہ" (always) اور "کبھی نہیں" (never) جسے آپ پرامپٹ سے ہٹاتے ہیں، وہ ایک ٹوکن ہے جسے ماڈل اصل مسئلہ حل کرنے پر خرچ کر سکتا ہے۔ ہک مستقل اصول (invariant) کا ذمہ دار ہے؛ پرامپٹ مقصد (intent) کا ذمہ دار ہے۔
کوالٹی گیٹ (Quality Gate): "مکمل" کی نئی تعریف
Stop hook اس وقت چلتا ہے جب ایجنٹ یہ فیصلہ کرتا ہے کہ اس نے کام مکمل کر لیا ہے اور سیشن کو ختم کرنے کی کوشش کرتا ہے۔ میں اسے ایسا نہیں کرنے دیتا۔ اس کے بجائے، یہ hook مکمل ٹیسٹ سویٹ (test suite) چلاتا ہے۔ اگر کوئی بھی ٹیسٹ فیل ہو جاتا ہے، تو hook اسٹاپ کمانڈ کو روک دیتا ہے اور ناکامی کا آؤٹ پٹ ایجنٹ کو واپس بھیج دیتا ہے۔
یہ تکمیل (completion) کی تعریف کو بدل دیتا ہے۔ "مکمل" (Done) اب ماڈل کا محض ایک احساس نہیں رہا، بلکہ یہ ایک پیمائش کے قابل گیٹ (measurable gate) بن چکا ہے۔ ایجنٹ صرف اس وقت کام ختم کر سکتا ہے جب harness اس بات کی تصدیق کر دے کہ کوڈ کام کر رہا ہے۔ عملی طور پر، یہ ایک مضبوط فیڈ بیک لوپ (feedback loop) پیدا کرتا ہے۔ ایجنٹ کوڈ لکھتا ہے، سمجھتا ہے کہ کام مکمل ہو گیا ہے، اسٹاپ بٹن دباتا ہے، اور فوراً اسے pytest traceback نظر آتا ہے۔ پھر وہ خود کو درست کرتا ہے، امپورٹ ایرر (import error) یا ٹوٹے ہوئے اسسرشن (assertion) کو ٹھیک کرتا ہے، اور دوبارہ رکنے کی کوشش کرتا ہے۔ میں نے ایجنٹس کو انسانی مداخلت کے بغیر اس لوپ کے اندر تین یا چار بار دہراتے ہوئے دیکھا ہے۔ harness معیار کو یقینی بناتا ہے؛ ماڈل اصلاحی پیچز (patches) فراہم کرتا ہے۔
یہ ایجنٹ انجینئرنگ کے بارے میں کیا سکھاتا ہے
قابل اعتماد خود مختار نظام (autonomous systems) بنانے کے لیے سوچ کے انداز میں تبدیلی کی ضرورت ہوتی ہے۔ آپ طویل پرامپٹس (prompts) لکھنے کے بجائے مضبوط harnesses بنانے کی طرف منتقل ہو جاتے ہیں۔
نفاذ (enforcement) کے لیے hooks کا استعمال کریں اور پالیسی کے لیے prompts کا۔ اگر کوئی اصول سو فیصد وقت تک برقرار رہنا ضروری ہے، تو اسے کوڈ میں ہونا چاہیے، نہ کہ قدرتی زبان (natural language) میں۔ پرامپٹس ابہام (ambiguity)، ذوق (taste) اور آرکیٹیکچر میں بہترین ہوتے ہیں۔ وہ انویریئنٹ (invariants) کے معاملے میں بہت ناقص ہوتے ہیں۔ اگر کوئی غلطی آپ کا پورا دوپہر کا وقت ضائع کر دے یا اس سے بھی بدتر، پروڈکشن اپ ٹائم (production uptime) کو متاثر کرے، تو ایک hook لکھیں۔
مختصر پرامپٹس بہتر نتائج دیتے ہیں۔ جب آپ میکانکی اصولوں کو اسکرپٹس (scripts) میں منتقل کر دیتے ہیں، تو ماڈل کو کم یاد رکھنا پڑتا ہے اور اس کے تضاد کے امکانات بھی کم ہو جاتے ہیں۔ ایجنٹ کا کانٹیکسٹ ونڈو (context window) ایک محدود وسیلہ ہے۔ اسے فارمیٹنگ کے یاد دہانوں سے نہ بھریں۔
آخر میں، یہ تسلیم کریں کہ آپ کا کردار بدل رہا ہے۔ جیسے جیسے ایجنٹس خود مختاری حاصل کرتے ہیں، انسان کا کام مواد تیار کرنے سے بدل کر گارڈ ریلز (guardrails) ڈیزائن کرنے کی طرف منتقل ہو جاتا ہے۔ آپ وہ harness بنا رہے ہیں جو یہ فیصلہ کرتا ہے کہ ماڈل کس چیز کو چھو سکتا ہے، وہ کب کام ختم کر سکتا ہے، اور جب چیزیں غلط ہوں تو اسے کیسا برتاؤ کرنا چاہیے۔ یہ انجینئرنگ ہے، پرامپٹنگ نہیں۔
اس طریقہ کار سے متاثر کرنے والا ذریعہ اور مزید عملی تفصیلات یہاں مل سکتی ہیں۔
اگر آپ AI ایجنٹس کے ساتھ کام کر رہے ہیں اور دوسرے ماہرین کے ساتھ تجربات شیئر کرنا چاہتے ہیں، تو آپ GyaanSetu لرننگ کمیونٹی یہاں تلاش کر سکتے ہیں۔
