مقالهی اول ما دربارهی فریمورک RPI به «چرا» پرداخت: ایجنتهای کدنویسی وقتی بهترین کار را تحویل میدهند که کار به سه مرحلهی تحقیق (Research)، برنامهریزی (Plan) و پیادهسازی (Implement) تقسیم شود و کانتکست هر مرحله تمیز بماند. این مقاله دربارهی «چطور» است: همان روشی که هر روز با سابایجنتهای Claude Code کار میکنیم، همراه با جاهایی که خراب شد.
هیچکدام از اینها بنچمارک نیست. تجربهی یک تیم کوچک است که یک مونوریپوی حدوداً دوازدهمحصولی (هلپدسک، MES، میزبانی ایمیل، دستیار هوش مصنوعی دانشگاه) را نگه میدارد و بخش بزرگی از کار را یک ایجنت کدنویسی انجام میدهد. بخش مفیدش همان داستانهای شکست است.
خلاصه
- تحقیق همیشه در یک سابایجنت اجرا میشود، نه در گفتوگوی اصلی. خروجیاش یک خلاصه یا یک فایل است.
- برنامهریزی در گفتوگوی اصلی و بهصورت مکتوب انجام میشود، قبل از هر تغییری در کد.
- پیادهسازی در یک یا چند سابایجنت اجرا میشود که هرکدام محدودهی باریک و مالکیت مشخص روی فایلها و ابزارها دارند.
- راستیآزمایی در برابر چیزی که نمیتواند دروغ بگوید: فایلی روی دیسک، بارگذاری تازهی صفحه، مقایسهی طول متن. هرگز در برابر گزارشی که خود ایجنت از کارش میدهد.
چرا تحقیق باید در سابایجنت باشد
تحقیق مرحلهای است که کانتکست را میبلعد. خواندن لاگها، گشتن در کدبیس، گرفتن خروجی Search Console، ورق زدن یک صندوق ایمیل: بیشتر این خروجیها یک بار دیده میشوند و دیگر لازم نیستند. اگر در گفتوگوی اصلی بمانند، در هر نوبت بعدی هم حضور دارند و مدل را از چیزی که Dex Horthy «منطقهی هوشمند» مینامد به «منطقهی کودن» میبرند؛ جایی که دستورها را فراموش میکند و اشتباهها را تکرار.
مستندات سابایجنت Anthropic هدف را صریح میگوید: کانتکست را حفظ کنید و کاوش و پیادهسازی را از گفتوگوی اصلی بیرون نگه دارید. هر سابایجنت پنجرهی کانتکست خودش را دارد و فقط یک خلاصه برمیگرداند.
سابایجنتهای تحقیق ما در عمل دو کار را متفاوت انجام میدهند:
- یافتهها را در یک فایل مینویسند. وقتی موضوعهای همین وبلاگ را تحقیق میکردیم، ایجنت تحقیق یک فایل ساختاریافته با منبعها و کوئریهای هدف نوشت و یک خلاصهی دویستکلمهای برگرداند. نویسندههایی که بعد آمدند فایل را خواندند، نه خلاصه را.
- به آنها گفته میشود چه کاری نکنند. «فقط تحقیق، بدون انتشار، بدون مرورگر» بخشی از دستور است. ایجنت تحقیقی که وسط کار شروع به درست کردن چیزها کند، همان راهی است که به تغییرهای برنامهریزینشده میرسد.
یک مثال از اهمیت مرحلهی تحقیق: Search Console هفتاد و نه صفحه از سایت ما را «صفحهی جایگزین با تگ canonical درست» علامت زد. راه آسان این بود که بیفتیم به جان تگهای canonical. اما وقتی اول نمونهی URLها را باز کردیم، معلوم شد هیچکدام اصلاً روی سایت ما نیستند؛ متعلق به یک سابدامین فراموششده بودند که به سروری اشاره میکرد که ما ادارهاش نمیکنیم. راهحل حذف یک رکورد DNS بود، بدون دست زدن به حتی یک قالب.
برنامهریزی: تنها مرحلهای که در گفتوگوی اصلی میماند
برنامه جایی است که قضاوت شما وارد کار میشود، پس باید جلوی چشمتان بماند. برنامههای ما کوتاه و مشخصاند: کدام فایلها تغییر میکنند، «تمامشده» یعنی چه، چه چیزی صراحتاً خارج از محدوده است و نتیجه چطور بررسی میشود.
مفیدترین عادت این بوده که دستور هر سابایجنت را طوری بنویسیم که انگار برای همکار باتجربهای است که همین الان وارد اتاق شده: چه کاری بکند، به چه چیزی دست نزند، چه گزارش بدهد و در چند کلمه. دستورهایی مثل «بر اساس یافتههایت باگ را درست کن» فکر کردن را به سابایجنت میسپارند و نتیجه هم همین را نشان میدهد. دستورهایی که فایل، تابع و روش بررسی را نام میبرند خیلی بیشتر درست برمیگردند.
پیادهسازی: ایجنتهای موازی به قانون مالکیت نیاز دارند
اجرای همزمان چند ایجنت پیادهسازی همان جایی است که صرفهجویی زمانی واقعی اتفاق میافتد. بیشتر حادثههای ما هم همینجا رخ داد. سه قانون از دلشان بیرون آمد.
۱. هر منبع مشترک فقط یک مالک دارد
برای کارهایی که API ندارند، مثل ردیت، یک گفتوگوی تلگرام یا رابط Search Console، یک مرورگر واقعی را از طریق پورت ریموتدیباگ کنترل میکنیم. دو ایجنت که همزمان یک مرورگر را میرانند یعنی تبهایی که زیر دست هم عوض میشوند و کارهایی که روی صفحهی اشتباه انجام میشوند. برای همین حالا در هر دستور صریح نوشته میشود: «فقط تو اجازهی کار با مرورگر را داری» یا «بدون مرورگر، ایجنت دیگری مالک آن است». همین قاعده برای صندوق ایمیل، مهاجرت دیتابیس یا دیپلوی هم برقرار است.
یاد گرفتیم که «مرورگر» همیشه یک چیز نیست. یک بار ابزار مرورگری که ایجنت از آن استفاده میکرد به نمونهی مرورگر جدا و ایزولهای وصل بود، نه همانی که روی پورت دیباگ بود؛ یک سایت آن را مسدود میکرد در حالی که مرورگر واقعی مشکلی نداشت. بررسی مستقیم فهرست تارگتها (curl localhost:9222/json) و اتصال صریح به آن مشکل را حل کرد.
۲. سریع کامیت کنید و به ورکتری کامیتنشده اعتماد نکنید
وقتی چند نشست روی یک مخزن کار میکنند، کار کامیتنشده شکننده است. یک بار وقتی نشست دیگری در همان ورکتری git reset --hard زد، تغییراتی را از دست دادیم. قانون از آن به بعد: کامیتهای کوچک، فوراً پوششده، و git add فقط با مسیر مشخص تا ایجنت هیچوقت کار نیمهتمام کس دیگری را جارو نکند.
مشکل برعکسش همین ماه پیدا شد. سایت ما از ورکتریای بیلد میشد که فایلهایی داشت که هیچوقت کامیت نشده بودند. کد کامیتشده آنها را ایمپورت میکرد، پس سایت روی همان یک ماشین بیمشکل بیلد میشد. وقتی سایت به سرور جدید منتقل شد، یک checkout تمیز از main بیلد نشد. راهحل کامیت کردن فایلهای جاافتاده و اثباتش با بیلد از یک ورکتری تازه بود. «اینجا بیلد میشود» با «بیلد میشود» یکی نیست.
۳. محدودهی هر ایجنت را به کوچکترین چیز قابلبررسی ببندید
«عنوانهای سئو را بهروز کن» زیادی گشاد است. «فقط meta_title و meta_description این سه سند را تغییر بده، بقیهی فیلدها را دستنخورده نگه دار، بعد صفحهی زنده را curl کن و عنوان جدید را تأیید کن» کاری است که ایجنت درست تمامش میکند. یک بار که اجازه دادیم ایجنت کل سند را بهروز کند، ترجمههای عربی در راه از بین رفتند؛ دستور باریکتر جلوی این را میگرفت.
راستیآزمایی: دنیا را بررسی کنید، نه گزارش را
گرانترین درس همین بود. وقتی ایجنت میگوید «انجام شد»، یعنی خودش فکر میکند انجام شده. خروجی ابزاری هم که به مدل نشان داده میشود همیشه حقیقت نیست.
خروجی ابزار میتواند بیصدا اشتباه باشد
در نشستهای طولانی دیدیم که نتیجهی نمایشدادهشدهی ابزار بیصدا کلمههایی را جا انداخته است. دادهی واقعی سالم بود؛ متنی که مدل دید نه. دو بار نزدیک بود همین به نتیجهگیری غلط برسد، از جمله تشخیص اشتباه اینکه یک وبسایت ورودی فرم را خراب میکند. راهحل ساده است: نتیجه را در فایل بنویسید و فایل را بخوانید، یا بهجای چشم انداختن به متن، طول یا چکسام را مقایسه کنید. حالا قبل از انتشار یک پست از طریق فرم وب، ایجنت بررسی میکند تعداد کاراکترهای فیلد دقیقاً با متن اصلی برابر باشد.
«دکمه کلیک شد» با «پیام ارسال شد» یکی نیست
بدترین حادثهی ما در گفتوگوی وب تلگرام با یک طرف تجاری واقعی بود. ایجنت متن را با یک دستور ویرایش DOM در کادر پیام گذاشت. متن روی صفحه دیده میشد، اما وضعیت پیشنویس داخلی برنامه هیچوقت بهروز نشد. هر تلاش برای ارسال، وضعیت کهنه و ناقص را میخواند و تکرار تلاشها هفت تکهی درهمریخته برای طرف مقابل فرستاد، پیش از آنکه کسی متوجه شود. آنها را از طریق API خود برنامه حذف کردیم و یک پیام تمیز فرستادیم.
دو تغییر از آن بیرون آمد. حالا ورودی از طریق رویدادهای ورودی واقعیای وارد میشود که برنامه واقعاً به آنها گوش میدهد. و بعد از ارسال، ایجنت پیام را از ذخیرهی دادهی خود برنامه میخواند و با متن موردنظر مقایسه میکند، و فقط بعد از آن موفقیت را گزارش میدهد. تیک سبز در رابط کاربری مدرک نیست.
از جایی بررسی کنید که کاربر ایستاده
بعد از دیپلوی، URL زنده را از بیرون بررسی کنید، نه کانتینری را که همین الان ریاستارت کردهاید. ما یک اصلاح سئو را دیپلوی کردیم، روی سرور خودمان تأییدش کردیم و بعداً فهمیدیم DNS دامنه حالا به هاست دیگری اشاره میکند که هنوز بیلد قدیمی را سرو میکند. بررسی هر دو، با curl --resolve برای سرور مبدأ و یک درخواست ساده برای چیزی که عموم میبینند، فوراً آن را نشان میداد.
قالب دستوری که برای ما جواب میدهد
Task: one sentence.
Scope: the exact files, records or pages. What is out of scope.
Ownership: which shared resources you may use (browser, mailbox, deploy).
Rules: no bypassing bot checks, no paid actions, commit by path only.
Verify: the specific check that proves it worked.
Report: under N words, with commit hashes and anything that needs a human.
شبیه سربار به نظر میرسد. در عمل فرق بین یک دور کار و سه دور است.
توصیهی ما به تیمی که با RPI و سابایجنتها شروع میکند
- اول تحقیق را به سابایجنتها بسپارید. ارزانترین برد و کمریسکترین قدم است.
- برنامه را در گفتوگوی اصلی و مکتوب نگه دارید.
- پیادهسازی موازی را فقط وقتی اضافه کنید که برای منابع مشترک قانون مالکیت دارید.
- هر ایجنت را وادار کنید نتیجهاش را در برابر سیستم واقعی ثابت کند. به فایل، بارگذاری تازهی صفحه و چکسام اعتماد کنید، نه به خلاصه.
برای استدلال پشت این سه مرحله بخش اول را ببینید. برای نگاهی گستردهتر به این رشته، راهنمای عملی مهندسی کانتکست Sourcegraph (انگلیسی) همراه خوبی است.
هوش مصنوعی در نوشتن پیشنویس این متن کمک کرد؛ روش کار، حادثهها و راهحلها مال خود ماست.