یک عامل کدنویس که امروز خیرهکننده عمل میکند، احتمالاً تا سیامین جلسهی کاری به یک بدهی فنی تبدیل میشود. اگر هنوز تصور میکنید برای حل خطاهای تکراری عاملهای هوش مصنوعی باید منتظر مدلهای قدرتمندتر بمانید، احتمالاً در حال اتلاف زمان هستید.
به نقل از گزارش ۷ اکتبر ۲۰۲۶ در stackoverflow.blog، شکست پروژههای بلندمدت کدنویسی با هوش مصنوعی بهندرت ناشی از ضعف مدل است و بیشتر به دلیل نقص در پیکربندی رخ میدهد. در جلسهی اول، عامل با دقت کد را میخواند، تغییری تمیز ایجاد میکند و یک تست مینویسد. اما در جلسهی سیام، چیزی در سیستم دچار پوسیدگی میشود. او دوباره همان فایلها را کشف میکند، تصمیماتی را که سه هفته پیش گرفته بود نقض میکند، دستور اجرای تست را حدس میزند و بهتدریج نوشتن تستها را متوقف میکند، چون کسی آن را به یک الزام تبدیل نکرده است. راهکار این مشکل، ایجاد یک هارنس (Harness) است؛ چیزی شبیه به یک سیستمعامل از قوانین و حافظه که دور مدل زبانی بزرگ (LLM) خام میپیچد تا آن را مهار کند. این مفهوم در واقع لایهای حیاتیتر از خودِ هوش مدل در نرمافزارهای خودگردان است که مدیریت رفتار عامل را بر عهده میگیرد.
بسیاری از توسعهدهندگان بهطور غریزی منتظر مدلهای هوشمندتر میمانند تا کیفیت افتکرده را بازیابند. با این حال، شواهد نشان میدهد که محیط پیرامون مدل، اهرم واقعی تغییر است. طبق گزارش منتشر شده، لنگچین (LangChain) توانست امتیاز یک عامل کدنویس را در محک عمومی Terminal-Bench 2.0 از ۵۲.۸٪ به ۶۶.۵٪ برساند. این جهش ۱۳.۷ امتیازی بدون تغییر در مدل پایه و صرفاً از طریق بهروزرسانی هارنس، بهبود پرامپت سیستمی (System Prompt)، ابزارها و میانافزارهایی مانند خود-تأییدسازی (Self-verification) و تشخیص حلقههای تکرار بهدست آمد.
تصور کنید یک عامل هوش مصنوعی مثل یک کارآموز بسیار ماهر است که حافظهی کوتاهمدت ندارد و تمایل دارد دفترچه راهنمای شرکت را نادیده بگیرد. بدون هارنس، این کارآموز مدام همان فایلها را دوباره کشف میکند و با تصمیمات هفتههای گذشته خود در تضاد قرار میگیرد. هارنس در واقع «قانون اساسی» و «مرز استقلال» عامل است که او را در مسیر درست نگه میدارد. در واقع، مدل شاید تنها ۱۰ درصد از آنچه تعیین میکند شما در پایان یک فصل به نرمافزاری کاربردی برسید یا خیر را تشکیل دهد؛ ۹۰ درصد باقیمانده بر عهدهی هارنس است.
اجزای ششگانهی یک هارنس منضبط
برای جلوگیری از افت کیفیت، یک ساختار منضبط به شش جزء یا مصنوع (Artifact) خاص نیاز دارد. نخست، «قانون اساسی» (Constitution) است؛ فایلی کوتاه و بهینه که در هر جلسه خوانده میشود و گردشکار غیرقابلمذاکره را تعریف میکند: برنامهریزی $ \rightarrow $ مستندسازی $ \rightarrow $ اجرا $ \rightarrow $ تست $ \rightarrow $ بازبینی $ \rightarrow $ ثبت (Commit). این فایل استانداردهای کیفی را تعیین میکند؛ مثلاً الزام میکند که تستها در همان Diff کد باشند، کدهای مرده (Dead Code) را ممنوع میکند، استفاده از Conventional Commits را اجباری میسازد و انضباط آداپتورها را حفظ میکند (مثلاً ممنوعیت استفاده از SDKهای فروشنده در کدهای لایهی Domain). چون این فایل در هر نوبت خوانده میشود، باید کوتاه بماند تا بودجهی پنجرهی زمینه (Context Budget) هدر نرود. در این راستا، استفاده از روشهای حذف قوانین متنی ساده برای مدیریت زمینه، نتایج بهتری نسبت به خلاصهسازیهای مدل-محور نشان داده است.
دوم، «مرز استقلال» (Autonomy Boundary) است. موثرترین پیکربندی آن است که عامل در اقدامات بازگشتپذیر آزاد باشد، اما برای اقدامات غیربازگشتپذیر از انسان اجازه بگیرد. این کار باعث میشود «شعاع تخریب» (Blast Radius) استقلال عامل خطرناک نشود. در یک پیکربندی دسترسیها، این ساختار به این شکل است:
- مجاز (Allow): خواندن، ویرایش، نوشتن، Grep، Glob و دستورات Bash برای
git add:*،git commit:*،npm test:*،npm run:*،npm ci:*وpytest:*. - درخواست اجازه (Ask): دستورات Bash برای
git push:*،npm publish:*،aws:*،terraform apply:*وkubectl apply:*. - ممنوع (Deny): پوشهای اجباری (
git push --force:*یاgit push -f:*) و هر دستوری که از--no-verify*استفاده کند.
این ساختار به عامل اجازه میدهد در یک ساعت دهها کامیت انجام دهد، در حالی که انسان فقط در مرحلهی Push نظارت میکند. توسعهدهندگان باید معناشناسی تطبیق اجراکننده (پیشوند در مقابل زیررشته) را بررسی کنند تا مطمئن شوند الگوهای گستردهای مثل npm:* بهطور تصادفی اجازه npm publish را ندهند در حالی که باید محدود باشد.
سوم، «زمینهٔ لایهبندی شده» (Tiered Context) است. بهجای یک فایل عظیم که پنجرهٔ زمینه را پر کرده و بهمرور زمان فاسد میشود، از ساختار لایهای استفاده میشود:
- Root CONTEXT.md: نقشهی کلی پروژه. شامل این است که پروژه چیست، چگونه اجرا/تست میشود، یک ایندکس تکخطی از ماژولها، ناورداها (Invariants) و محل قرارگیری وضعیتها (State). این فایل حداکثر ۲۰۰ خط است و در شروع جلسه خوانده میشود.
- Per-module CONTEXT.md: مسئولیتهای دقیق، فایلهای کلیدی، وابستگیها، نکات حساس (Gotchas) و دستورالعملهای تست مخصوص همان ماژول. این فایل فقط قبل از ویرایش آن ماژول خاص خوانده میشود.
- DECISIONS.md: یک لاگ «فقط-افزودنی» (Append-only) شامل تاریخ، تصمیم، دلیل، و جایگزینهایی که رد شدهاند.
قانون این است: زمینهی قدیمی (Stale Context) به عنوان یک باگ تلقی میشود و باید در همان تغییری که باعث ابطال آن شده است، اصلاح شود. این رویکرد لایهبندی شده در واقع بنیانی برای پروتکلهای سه-فایلی است که از حلقههای فراموشی و خطاهای حافظه در عاملها جلوگیری میکند.
چهارم، «حافظهی بادوام» (Durable Memory) است. این بخش اطلاعاتی را نگه میدارد که کد بهتنهایی نمیتواند در طول جلسات به عامل منتقل کند. این سیستم از رکوردهای ایندکس شده با فرمت «یک حقیقت در هر فایل» استفاده میکند:
- memory/MEMORY.md: ایندکس کلی که شامل یک خط برای هر حقیقت است.
- user-prefers-X.md: فایلهایی که بر اساس نوع (کاربر، بازخورد، پروژه یا مرجع) دستهبندی شدهاند.
- graph.jsonl: یک فایل JSONL که روابط
{from, rel, to}را برای ماژولها و تصمیمات به عنوان گره (Node) ترسیم میکند. این به عامل اجازه میدهد به سؤال حیاتی پاسخ دهد: «اگر این را تغییر دهم، چه چیزی میشکند؟»
پنجم، «پنل بازبینی» (Review Panel) است. بهجای یک بازبینی ساده توسط خودِ عامل، هارنس چندین زیر-عامل موازی را فعال میکند که هر کدام لنزی متفاوت دارند و فرمت خروجی سختگیرانهای دارند. هر یک حکمی شامل [BLOCKER|MAJOR|MINOR] به همراه درصد اطمینان، شماره فایل و خط، شرح مشکل و راهکار اصلاحی برمیگردانند:
- محصول (Product): بررسی میکند آیا مسئلهی بیان شده حل شده است و در مرحلهی برنامهریزی، گسترش بیرویه دامنه (Scope Creep) را شناسایی میکند.
- معمار (Architect): بر صحت، مدلهای داده، حالتهای شکست (Failure Modes) و جفتشدگی (Coupling) تمرکز میکند.
- زیرساخت (Infra): محدودیت منابع، استراتژیهای استقرار/بازگشت (Rollback) و تابآوری را بازبینی میکند.
- امنیت (Security): احراز هویت، اعتبارسنجی ورودیها، رازها (Secrets) و ردپاهای حسابرسی (Audit Trails) را بررسی میکند.
- تست (Test-Eng): تعیین میکند که آیا مجموعهی تستها واقعی هستند یا فقط «تئاتری برای مسیرهای خوشبینانه» (Happy-path theater) هستند.
تنها موارد BLOCKER یا MAJOR با اطمینان بالا میتوانند مانع تغییر شوند. این کار از غرق شدن توسعهدهنده در جزئیات کوچک جلوگیری کرده و نقاط کوری را میگیرد که یک بازبینی تکمرحلهای از آنها میگذرد.
ششم، «قلاب پس از ویرایش» (Post-Edit Hook) است. اسکریپتی (مثلاً post-edit.py) که بعد از هر ویرایش از طریق یک قلاب PostToolUse در settings.json اجرا میشود. این قلاب رویدادهای Edit ، Write یا MultiEdit را شناسایی میکند.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/post-edit.py"
}
]
}
]
}
}
این اسکریپت رویداد ابزار را از stdin میخواند و یک چکلیست را به عنوان زمینه صادر میکند:
۱. اگر مسئولیت یا فایلهای کلیدی تغییر کردهاند، نزدیکترین CONTEXT.md را بهروز کن.
۲. در صورت تغییر وابستگی یا API، یک یال (Edge) به حافظه/گراف اضافه کن.
۳. یک خط در DECISIONS.md برای ایجاد سابقه بنویس.
۴. حافظه را برای یک حقیقت بادوام بهروز کن.
با ارائه یک چکلیست بهجای بازنویسی خاموش مستندات، عامل ویرایشها را در همان Diff انجام میدهد و ردپای تغییرات را قابل بازبینی نگه میدارد.
مقیاسپذیری در ناوگانهای چندعاملی
وقتی چندین عامل روی یک مخزن کد کار میکنند، اغلب با ویرایش فایلهای یکسان، خنثی کردن کارهای یکدیگر یا بحث مجدد درباره تصمیمات قبلی، با هم تداخل پیدا میکنند. گزارش لنگچین استدلال میکند که عاملها نباید از طریق پیامرسانها یا کانالهای جانبی با هم «ارتباط» برقرار کنند، زیرا این روش مقیاسپذیر نیست و غیرقابل اعتماد است. در عوض، آنها باید از طریق «وضعیت مکتوب مشترک» هماهنگ شوند؛ شبیه به حشراتی که با تغییر محیط اطرافشان، سازههای عظیم میسازند.
این هماهنگی از طریق مصنوعات مشترک زیر مدیریت میشود:
- نقشهی مالکیت (Ownership Map): تعیین میکند هر عامل مالک کدام مسیرهاست. مالکیت پیشفرض بر اساس دایرکتوری است. مثلاً
core/**ممکن است متعلق به عامل B باشد (عامل A میخواند اما ویرایش نمیکند)، در حالی کهservices/service-a/**متعلق به عامل A است. ویرایش مسیرهای مشترک مثلshared/contracts/**نیاز به یک «ادعا» (Claim) دارد. - پروتکل ادعا/آزادسازی (Claim/Release Protocol): یک سیستم حذف متقابل (Mutual Exclusion) ارزان که از افزودن به فایل استفاده میکند. یک عامل یک
## CLAIMبا برچسب زمانی، شناسه تسک و مسیر مینویسد (مثلاً## CLAIM 2026-06-10T14:20Z · agent-A · task-114 · services/service-a/**) و بعداً یک## RELEASEبا هش کامیت ثبت میکند. قبل از ادعا، عاملها ادعاهای باز در چند ساعت اخیر را اسکن میکنند. اگرچه این روش خوشبینانه است و در معرض رقابتهای TOCTOU قرار دارد، اما وقتی یک انسان ادغام (Merge) را انجام میدهد، کافی است. برای حذف متقابل واقعی، عاملها میتوانند از توابع اتمیک مثل شاخههای گیت با نامهای منحصربهفرد یا نوشتنهای شرطی در یک ذخیرهساز هماهنگی استفاده کنند. - لاگ پیشرفت (Progress Log): یک لاگ فقط-افزودنی و زمانبندی شده که عاملها هنگام شروع کار میخوانند تا بدانند چه کارهایی تکمیل شده و چه کسی کجا مشغول است.
برای جلوگیری از «بازگشت خاموش» تصمیمات معماری، سیستم از یک لاگ تصمیمات فقط-افزودنی استفاده میکند. تیمهای انسانی حافظه جمعی (Hallway Memory) دارند، اما عاملها ندارند. بدون این لاگ، یک عامل ممکن است تصمیمی را که ۶ هفته پیش برای دلیلی حیاتی گرفته شده، بهاشتباه «اصلاح» کند چون محدودیت اصلی را درک نمیکند.
هر ورودی (مثلاً DEC-017) به این صورت ساختار مییابد:
- شناسه/تاریخ: مثلاً DEC-017 · 2026-06-10.
- تصمیم: مثلاً «تمام ترافیک مدلها از طریق یک گیتوی واحد هدایت شود».
- دلیل: مثلاً «یک نقطه متمرکز برای محدودیت نرخ (Rate-limit)، ردیابی هزینه، کلید قطع اضطراری و تعویض ارائهدهنده».
- جایگزینهای رد شده: مثلاً «فراخوانیهای SDK در هر سرویس (که باعث پراکندگی هزینه و جفتشدگی میشود»).
- حاکم بر (Governs): مسیرهایی که این تصمیم آنها را محدود میکند (مثلاً
src/**) تا گیت بازبینی قابل اجرا باشد. - ممنوعیت Importها: قوانینی که ماشین میتواند چک کند (مثلاً
["sdk-a", "sdk-b"]).
این تصمیمات میتوانند برای خوانایی ماشین به صورت YAML ذخیره شوند:
- id: DEC-017
date: 2026-06-10
decision: All model traffic goes through one gateway.
why: single chokepoint for rate-limit, cost, kill switch, provider swap.
rejected: [per-service SDK calls]
governs: ["src/**"]
forbids_imports: ["sdk-a", "sdk-b"]
supersedes: null
این تصمیمات با متصل کردن آنها به فرآیند بازبینی، الزامآور میشوند. اگر یک Diff تصمیمی را که در لاگ ثبت شده نقض کند، بیلد رد میشود. برای تغییر یک تصمیم، عامل باید یک ورودی جایگزین بنویسد (مثلاً DEC-031 جایگزین DEC-017 میشود) و به انسان اطلاع دهد. وضعیت «جایگزین شده» (Superseded) به صورت مشتق شده تعیین میشود؛ یعنی اگر ورودی جدیدتری به آن اشاره کند، قدیمی منسوخ شده است. این تضمین میکند که تاریخچه تکامل سیستم قابل مشاهده بماند و هیچ ورودی بهطور خاموش ویرایش نشود.
جمعبندی ساختار منضبط
این رویکرد منضبط، گلوگاه را از «آیا مدل میتواند کد بزند» به «آیا هارنس میتواند مدل را صادق، جهتدار و بازبینیشده نگه دارد» تغییر میدهد. نقش توسعهدهنده از مهندسی پرامپت به معماری سیستم تغییر میکند. شما دیگر فقط با یک مدل صحبت نمیکنید؛ شما در حال ساخت سیستمعاملی هستید که آن مدل را در بر میگیرد.
برای اجتناب از شکستهای رایج، توسعهدهندگان باید از این تلهها دوری کنند:
- نبود مرز استقلال: از پرستاری برای هر کلید زدن یا اجازه دادن به Push/Deployهای بازبینینشده بپرهیزید.
- یک فایل زمینه عظیم: از فایلهایی که فاسد میشوند و بودجه هر نوبت را میبلعند دوری کنید.
- بهروزرسانی زمینه در «بعداً»: قدیمی شدن مستندات را به عنوان یک باگ در همان Diff تلقی کنید.
- یک بازبینی تکنفره: از پنلی با لنزهای متنوع استفاده کنید تا نقاط کور یکسان را حذف کنید.
- قلابهای بازنویسی خاموش: از چکلیستها استفاده کنید تا تغییرات قابل بازبینی بمانند.
- پیامرسانی عامل-به-عامل: از فایلهای مشترک استفاده کنید تا هماهنگی پس از ریاستارتها باقی بماند.
- نبود نقشهی مالکیت: از مالکیت مبتنی بر دایرکتوری و ادعاها برای جلوگیری از تداخل استفاده کنید.
- ویرایش تصمیمات گذشته: همیشه از ورودیهای جایگزین برای حفظ تاریخچه استفاده کنید.
با تبدیل هماهنگی به ویژگی وضعیت مشترک و اجرای یک حلقه سختگیرانه (شروع جلسه $ \rightarrow $ خواندن زمینه ریشه $ \rightarrow $ برنامهریزی $ \rightarrow $ بازبینی پنل $ \rightarrow $ اجرا $ \rightarrow $ بازبینی پنل $ \rightarrow $ تست $ \rightarrow $ ثبت $ \rightarrow $ بهروزرسانی قلاب)، ناوگانی از عاملها میتوانند برای ماهها بهرهور بمانند. این لایهی ساخت (Build) بود؛ پنج لایهی زمان اجرا (قطعیت، ارزیابی، اطمینان، ایمنی و قابلیت عملیاتی) در ادامه میآیند.




گفتگو