Konfigurasi Lingkungan Kerja untuk Memangkas Boilerplate Pasaran yang Dihasilkan AI Agent
Ketika Anda mengintegrasikan AI agent ke dalam lingkungan pengembangan nyata, kelemahannya akan dengan cepat terungkap. Tanpa memahami konteks domain, agent sering kali secara mekanis mengobral factory pattern, atau terus-menerus memuntahkan fungsi utility yang sama sekali tidak berguna. Laporan analisis terhadap 623 juta baris commit yang dirilis oleh GitClear pada tahun 2024 menunjukkan bahwa setelah alat AI makin meluas, duplikasi kode melonjak hingga 81%, sementara rasio refactoring untuk merapikan kode lama anjlok dari 25% menjadi di bawah 10%. Akibat adanya recency bias pada context window, agent cenderung melarikan diri ke pola standar yang paling umum dalam data pelatihan untuk menghindari risiko. Kita harus menekan malafungsi agent dengan menyatakan aturan arsitektur dan logika sinkronisasi yang dibagi dalam tim secara eksplisit melalui berkas konteks.
1. Mencegah Penyimpangan Aturan pada Legacy Codebase
Untuk mengendalikan panduan yang berbeda-beda di setiap alat pengembangan, Anda harus memulainya dengan mengunggah AGENTS.md di root proyek sebagai single source of truth. Alat seperti Cursor dan Claude Code membaca aturan ini. File .cursorrules tunggal sudah lama ditinggalkan. Pecah dan tempatkan berkas MDC di dalam direktori .cursor/rules/, lalu panggil @AGENTS.md di dalam CLAUDE.md pada lingkungan Claude Code untuk mencegah aturan mengalami decay atau terabaikan.
`yaml
description: Backend API and Domain Service architectural constraints
globs: apps/api//*.ts, services//*.ts
alwaysApply: false
Backend Architectural Constraints
Mandatory Patterns
- Use Canonical Response DTOs located in
apps/api/src/common/dto.
- All database mutations must go through the Unit of Work pattern defined in
services/shared/uow.
Explicit Negative Constraints
- NEVER create single-child base classes or single-implementation interfaces.
- NEVER write wrapper functions that merely pass arguments to lower-level services.
- NEVER implement strategy or factory patterns when standard conditional logic (if/switch) suffices.
- NEVER add defensive "just-in-case" try-catch blocks that return dummy fallback values without rethrowing.
`
Jika total panjang konteks melebihi 800 baris atau sekitar 2.000 token, agent akan mulai mengabaikan batasan yang ditulis di bagian atas. Sisakan hanya batasan melarang yang benar-benar tidak boleh dilanggar di dalam AGENTS.md, dan geser rekam keputusan arsitektur (Architecture Decision Records) secara detail ke direktori docs/context/.
Urutan Penerapan Batasan
- Isi Pekerjaan: Pilih 1 modul inti, lalu tentukan pola yang dilarang beserta aturan pengecualiannya.
- Cara Eksekusi:
- Buat
AGENTS.md di root proyek, lalu tuliskan batasan yang melarang single-implementation interface dan defensive try-catch.
- Konfigurasikan batasan YAML Frontmatter dan jalur file target (
globs) pada lokasi .cursor/rules/backend-constraints.mdc.
- Tambahkan sintaks
@AGENTS.md ke dalam CLAUDE.md untuk menyelaraskan lingkungan.
- Hasil yang Diharapkan: Pembuatan boilerplate yang tidak perlu berkurang, sehingga waktu yang dihabiskan untuk perbaikan kode berkurang sekitar 4 jam per minggu.
2. Pipeline Verifikasi Kode Agent
Di balik kode agent yang terlihat meyakinkan, terdapat jebakan yang tersembunyi. Menurut hasil studi Veracode pada tahun 2024, celah keamanan tingkat OWASP Top 10 ditemukan pada 45% kode yang disarankan oleh AI. Praktik menyembunyikan error dengan membungkus logika yang berisiko gagal menggunakan try-catch seadanya lalu mengembalikan empty object atau null dilakukan 47% lebih sering dibandingkan saat ditulis oleh manusia. Masalah seperti melewatkan optimistic locking pada operasi Read-Modify-Write atau memanggil DB berulang kali di dalam loop (masalah N+1) juga kerap terjadi.
| Area Verifikasi |
Item Verifikasi Detail |
Pola Berisiko & Jebakan Agent |
Kriteria Pemblokiran Merge |
| Celah Keamanan |
Penggunaan Parameterized Query, isolasi tenant, konfirmasi paket tak terotorisasi |
SQL Injection berbasis konkatenasi string, pemanggilan paket tak terverifikasi hasil halusinasi |
Kurangnya validasi input, pemblokiran saat penambahan dependensi eksternal dari sumber tak jelas |
| Bottleneck Performa |
Lazy loading ORM, nested loop dalam Hot path, indeks DB |
Query iterasi entitas individual di dalam loop, penyaringan seluruh tabel di memori |
Pemblokiran jika terdapat pemanggilan DB/API eksternal di dalam loop, pemblokiran jika pagination tidak diterapkan |
| Keandalan Tipe |
Verifikasi Strict Type, penanganan eksepsi Boundary, kontrol konkurensi |
Penggunaan as any berlebihan, menyembunyikan error dengan Empty Catch block |
Pemblokiran jika terdapat any dan casting as tanpa aturan, pemblokiran Catch block tanpa logging |
Kode tes yang dibuat oleh agent cenderung sebatas tes tautologis yang hanya menyalin-tempel kode implementasi. Tes seperti ini sama sekali tidak dapat menangkap cacat bisnis yang sebenarnya. Anda harus menerapkan aturan secara tegas: "Jika sudah ada utility yang ada, hapus utility baru yang dibuat oleh agent dan gunakan kembali kode yang sudah ada."
Prosedur Verifikasi Manual
- Isi Pekerjaan: Isikan daftar periksa yang memverifikasi keamanan, performa, dan tipe ke dalam templat pekerjaan dan CI gate.
- Cara Eksekusi:
- Masukkan item Parameterized Query, pencegahan query N+1, dan larangan penggunaan
any ke dalam templat PR.
- Pasang alat analisis statis pada Git Pre-commit Hook untuk menolak commit jika mendeteksi
as any atau await di dalam loop.
- Saat peninjauan (review), paksa penggantian utility yang dibuat sembarangan oleh agent dengan modul umum yang sudah ada.
- Hasil yang Diharapkan: Mencegah terjadinya insiden lolosnya cacat seperti query N+1 atau memory leak ke lingkungan produksi.
3. Decomposed Prompting untuk Mencegah Kebuntuan Berpikir
Jika Anda memasukkan logika penyelesaian (settlement) yang rumit atau pemrosesan pesanan berbasis state machine ke dalam satu prompt tunggal, agent akan terjebak dalam tool-calling loop atau hanya memuntahkan kode berupa cangkang kosong. Hal ini terjadi karena urutan alokasi token menjadi kacau saat mencoba menangani desain skema, antarmuka API, penanganan eksepsi, dan aturan bisnis sekaligus.
`
[Tahap 1: Data Modeling] -> Pembuatan DB Entity, Zod Schema
│
▼ (Meneruskan hasil output sebagai konteks)
[Tahap 2: Definisi Interface] -> Definisi API DTO, Custom Error, Service Signature
│
▼ (Meneruskan hasil output Tahap 1+2 sebagai konteks)
[Tahap 3: Implementasi Logika Bisnis] -> Penyelesaian Transaksi, Transisi Status, Kontrol Konkurensi
`
Melakukan proses ini secara manual bolak-balik cukup merepotkan. Lebih baik menulis skrip otomatisasi CLI (scripts/agent-decomposed-build.ts) untuk mengikat keluaran dari tahap sebelumnya agar masuk sebagai konteks masukan untuk tahap berikutnya.
`typescript
import { execSync } from 'child_process';
import * as fs from 'fs';
interface TaskPipeline {
featureName: string;
stage1Prompt: string;
stage2Prompt: string;
stage3Prompt: string;
}
async function runDecomposedAgentPipeline(pipeline: TaskPipeline) {
console.log([Stage 1] Executing Data Modeling for ${pipeline.featureName}...);
const stage1Output = execSync(claude --print "${pipeline.stage1Prompt}").toString();
fs.writeFileSync(./tmp/${pipeline.featureName}_stage1.ts, stage1Output);
console.log([Stage 2] Executing Interface Definition...);
const stage2InputPrompt = ${pipeline.stage2Prompt}\n\nContext Models:\n${stage1Output};
const stage2Output = execSync(claude --print "${stage2InputPrompt}").toString();
fs.writeFileSync(./tmp/${pipeline.featureName}_stage2.ts, stage2Output);
console.log([Stage 3] Executing Business Logic Implementation...);
const stage3InputPrompt = ${pipeline.stage3Prompt}\n\nContext Models:\n${stage1Output}\n\nContext Contracts:\n${stage2Output};
const stage3Output = execSync(claude --print "${stage3InputPrompt}").toString();
fs.writeFileSync(./src/services/${pipeline.featureName}.service.ts, stage3Output);
console.log([Pipeline Complete] Business logic generated cleanly without cognitive stagnation.);
}
`
Membangun Skrip Decomposed Prompting
- Isi Pekerjaan: Menetapkan templat prompt 3 tahap dan mengunggah skrip CLI yang mengeksekusinya secara berurutan.
- Cara Eksekusi:
- Pecah prompt menjadi 3 bagian: pemodelan data, definisi antarmuka, dan implementasi logika bisnis.
- Tulis
scripts/agent-decomposed-build.ts untuk menghubungkan keluaran sebelumnya agar masuk ke dalam konteks prompt berikutnya.
- Jalankan skrip ini saat membuat modul baru yang rumit.
- Hasil yang Diharapkan: Fenomena agent yang bingung dan tidak memberi jawaban akan hilang, dan rasio pengerjaan ulang untuk membongkar kode secara manual turun dari kisaran 20% menjadi di bawah 5%.
4. Pengaturan untuk Menyisipkan Dasar Keputusan di Dalam Kode
Makin sering alat coding AI digunakan, makin banyak 'kode khusus tulis' (write-only code) yang menumpuk tanpa alasan mengapa kode tersebut dibuat demikian. Kode yang tidak mencatat trade-off dari pilihan arsitektur akan menjadi beban yang sulit disentuh oleh manusia di kemudian hari. Anda harus memaksakan aturan dalam AGENTS.md agar agent menuliskan komentar standar TSDoc di dalam kode sumber saat membuat kode.
`typescript
/**
- @description Processes deferred settlement payouts for multi-vendor orders.
- @why Uses pessimistic database locking on the Wallet entity instead of optimistic locking because payout calculation involves high-frequency concurrent balance updates.
- @tradeoff Slight P95 latency increase under high contention in exchange for 0% financial drift.
- @complexity Time: O(N log N) due to vendor sorting | Space: O(N) for batch processing buffer.
*/
export async function processDeferredSettlement(orderId: string): Promise {
if (account.hasOutstandingBalance()) {
this.applySettlementHold(account);
}
}
`
Untuk mencegah ketidaksesuaian konfigurasi agent antar pengembang, tetapkan AGENTS.md sebagai single source of truth, lalu jalankan skrip (tools/sync-agent-rules.ts) yang menyinkronkannya dengan CLAUDE.md dan .cursor/rules/global.mdc setiap kali melakukan commit.
`typescript
import * as fs from 'fs';
import * as path from 'path';
const AGENTS_MD_PATH = path.join(__dirname, '../AGENTS.md');
const CLAUDE_MD_PATH = path.join(__dirname, '../CLAUDE.md');
const CURSOR_RULE_PATH = path.join(__dirname, '../.cursor/rules/global.mdc');
function syncRules() {
if (!fs.existsSync(AGENTS_MD_PATH)) {
console.error('Error: AGENTS.md does not exist.');
process.exit(1);
}
const baseRules = fs.readFileSync(AGENTS_MD_PATH, 'utf-8');
const claudeContent = # AUTOMATICALLY GENERATED FROM AGENTS.md - DO NOT EDIT DIRECTLY\n\n${baseRules};
fs.writeFileSync(CLAUDE_MD_PATH, claudeContent);
const mdcHeader = ---\ndescription: Global Agent Rule Sync\nglobs: **/*\nalwaysApply: true\n---\n\n;
fs.writeFileSync(CURSOR_RULE_PATH, ${mdcHeader}${baseRules});
console.log('Successfully synchronized AGENTS.md to CLAUDE.md and Cursor MDC rules.');
}
syncRules();
`