Agentic Development Part 5: Verifikasi dan Guardrail Agent
Part 2 membahas observation dan self-verification sebagai salah satu komponen inti agent — bagaimana agent mengevaluasi hasil tindakannya sendiri sebelum melangkah ke iterasi berikutnya. Part 3 membahas definition of done sebagai kriteria yang harus dipenuhi tiap task. Artikel ini menyatukan keduanya dari sudut pandang yang lebih sistemik: bagaimana memformalkan verifikasi menjadi mekanisme otomatis yang nyata dan independen, bukan sekadar agent yang “merasa” pekerjaannya sudah benar. Semakin besar otonomi yang diberikan ke agent — seperti dibahas di Part 1 — semakin penting guardrail yang membatasi dampak ketika sesuatu berjalan salah. Artikel ini membahas lapisan guardrail dari yang paling deterministik sampai yang melibatkan manusia, pola reviewer agent independen, strategi membatasi blast radius lewat sandboxing, dan kriteria menentukan kapan manusia wajib turun tangan.
Kenapa Self-Verification Agent Tidak Cukup
Observation yang dibahas di Part 2 — agent membaca dan menafsirkan hasil tindakannya sendiri — adalah komponen yang penting tapi punya keterbatasan struktural yang tidak bisa diselesaikan hanya dengan membuat modelnya lebih baik. Masalahnya bukan kemampuan, tapi posisi: agent yang mengevaluasi pekerjaannya sendiri menggunakan proses reasoning yang sama dengan yang menghasilkan pekerjaan itu, rawan terhadap bias konfirmasi — kecenderungan menganggap pendekatan yang sudah diambil sebagai benar, karena evaluasi dan eksekusi berasal dari rangkaian penalaran yang sama.
Ini bukan masalah unik AI agent — manusia punya keterbatasan serupa, itulah sebabnya code review oleh orang lain tetap jadi praktik standar meskipun developer yang menulis kode sudah menguji sendiri pekerjaannya. Kesalahan asumsi yang membuat seseorang menulis kode yang salah cenderung juga membuat orang yang sama tidak menyadari kesalahan itu saat mengevaluasi ulang hasilnya — perspektif yang sama menghasilkan blind spot yang sama.
flowchart LR
A[Agent Menulis Kode] --> B[Agent Sama Mengevaluasi Hasilnya]
B --> C{Bias Konfirmasi}
C -- Asumsi Salah Sejak Awal --> D[Evaluasi Tetap Tidak Mendeteksi Masalah]
E[Agent Menulis Kode] --> F[Verifikasi Independen: Test/Reviewer Terpisah]
F --> G{Sumber Evaluasi Berbeda}
G -- Tidak Berbagi Asumsi yang Sama --> H[Masalah Lebih Mungkin Terdeteksi]Implikasinya: self-verification dari Part 2 tetap penting sebagai lapisan pertama — agent yang bahkan tidak memeriksa hasilnya sendiri jelas lebih buruk daripada yang memeriksa. Tapi self-verification tidak boleh jadi satu-satunya lapisan untuk pekerjaan yang konsekuensinya berarti. Dibutuhkan sumber evaluasi yang independen dari proses yang menghasilkan kode — baik berupa test otomatis yang ditulis terpisah dari implementasi, agent reviewer yang berbeda, atau review manusia — yang tidak mewarisi asumsi yang sama dengan yang menghasilkan pekerjaan tersebut.
Self-verification dan verifikasi independen bukan pilihan salah satu — keduanya saling melengkapi. Self-verification menangkap kesalahan yang jelas terlihat dengan cepat tanpa menunggu lapisan berikutnya; verifikasi independen menangkap kesalahan yang tidak terlihat dari sudut pandang yang sama dengan yang menghasilkan pekerjaan.
Lapisan Guardrail: dari Deterministik ke Probabilistik
Guardrail yang efektif bekerja sebagai stack berlapis, bukan satu mekanisme tunggal. Setiap lapisan menangkap jenis kegagalan yang berbeda, dan lapisan-lapisan ini sebaiknya disusun dari yang paling murah dan paling andal di awal, sampai yang paling mahal dan dicadangkan untuk kasus yang benar-benar membutuhkannya.
| Lapisan | Sifat | Menangkap |
|---|---|---|
| Test otomatis & linter | Deterministik, cepat, murah | Regresi fungsional, pelanggaran gaya kode, error sintaks |
| Static analysis & type-check | Deterministik, menangkap kelas kesalahan lebih luas | Inkonsistensi tipe, pola kode berisiko, dependency yang tidak aman |
| Contract test terhadap spec | Deterministik, memverifikasi kesesuaian kontrak | Penyimpangan dari skema API/data yang sudah disepakati (rujuk Part 3 series Spec-Driven Development) |
| Reviewer agent independen | Probabilistik tapi independen dari proses eksekusi | Kesalahan logika, penyimpangan dari intent yang tidak tertangkap test eksplisit |
| Human review | Paling mahal, paling lambat, tapi paling kontekstual | Keputusan arsitektur, trade-off bisnis, risiko yang butuh judgment manusia |
flowchart TD
A[Perubahan Agent] --> B[Test Otomatis & Linter]
B -- Lolos --> C[Static Analysis & Type-Check]
B -- Gagal --> Z[Kembalikan ke Agent untuk Perbaikan]
C -- Lolos --> D[Contract Test terhadap Spec]
C -- Gagal --> Z
D -- Lolos --> E[Reviewer Agent Independen]
D -- Gagal --> Z
E -- Tidak Ada Temuan Berarti --> F{Risiko Tinggi?}
E -- Ada Temuan --> Z
F -- Ya --> G[Human Review]
F -- Tidak --> H[Lolos, Lanjut]
G --> HPola berlapis ini efektif karena setiap lapisan punya biaya dan tingkat keandalan yang berbeda. Lapisan deterministik (test, linter, type-check) murah dijalankan dan hasilnya pasti — tidak ada ambiguitas apakah test lolos atau gagal. Lapisan ini sebaiknya menyaring sebanyak mungkin masalah sebelum sampai ke lapisan yang lebih mahal. Reviewer agent independen dan human review dicadangkan untuk hal yang tidak bisa ditangkap secara deterministik — kesalahan logika halus, keputusan trade-off, atau risiko yang butuh konteks lebih luas dari yang bisa diverifikasi otomatis.
Investasi terbaik untuk meningkatkan keandalan guardrail biasanya bukan menambah lapisan baru, tapi memperkuat lapisan deterministik yang sudah ada — coverage test yang lebih baik, contract test yang lebih ketat. Lapisan deterministik yang kuat mengurangi beban pada lapisan probabilistik yang lebih mahal dan lebih lambat.
Guardrail Sebagai Pagar, Bukan Penghambat
Ada kesalahpahaman umum bahwa guardrail yang baik berarti membatasi agent seketat mungkin. Dalam praktiknya, guardrail yang didesain dengan baik berfungsi sebagai pagar yang membatasi dampak kesalahan, bukan penghambat yang mematikan otonomi yang sebenarnya bermanfaat. Bedanya ada di mana batasan ditempatkan — pada jenis tindakan yang diizinkan di tiap fase kerja, bukan pada seberapa sering agent diinterupsi.
Salah satu pola praktis: izin tool dibatasi sesuai fase kerja, bukan diberikan secara seragam sepanjang sesi. Mengingat kembali pemisahan planner dan executor dari Part 2 — fase perencanaan idealnya hanya punya akses tool yang sifatnya membaca dan mengeksplorasi (read-only), sementara akses untuk benar-benar mengubah sesuatu (write, eksekusi perintah yang mengubah state) baru diberikan setelah rencana disetujui dan masuk ke fase eksekusi.
Fase Planning:
Tool yang diizinkan: read file, search/grep, baca dokumentasi
Tool yang TIDAK diizinkan: write file, jalankan perintah destruktif,
panggil API eksternal yang mengubah state
Fase Eksekusi (setelah rencana disetujui):
Tool yang diizinkan: write file dalam scope task yang disetujui,
jalankan test, commit ke branch kerja
Tool yang TIDAK diizinkan: push langsung ke branch utama, akses
kredensial production, modifikasi di luar scope task
Pembatasan berdasarkan fase ini memberi otonomi penuh untuk eksplorasi (yang risikonya rendah karena tidak mengubah apapun) sambil tetap menahan tindakan yang berisiko (yang mengubah state) di belakang gerbang persetujuan. Ini berbeda secara mendasar dari pendekatan “minta approval di setiap langkah” yang menghilangkan keuntungan otonomi sama sekali — guardrail berbasis fase membatasi kapan tindakan berisiko boleh terjadi, bukan membatasi seberapa banyak pekerjaan yang boleh dilakukan agent secara otonom.
Laporan kajian keamanan agent produksi menemukan bahwa kombinasi akses data privat, paparan terhadap konten yang tidak tepercaya, dan kemampuan melakukan tindakan keluar — disebut sebagai kombinasi berisiko tinggi — muncul di hampir semua agent yang dikaji. Guardrail yang efektif biasanya menyasar memutus salah satu dari tiga elemen ini, bukan mencoba mengontrol ketiganya sekaligus secara manual di setiap momen.
Automated Gate Sebelum Lanjut Task Berikutnya
Part 4 series Spec-Driven Development dan Part 3 series ini sama-sama membahas checkpoint review antar task group sebagai praktik penting. Automated gate adalah versi terformalisasi dari checkpoint itu — syarat eksplisit dan otomatis yang harus dipenuhi sebelum agent diizinkan melangkah ke task berikutnya, bukan sekadar “review manual kalau sempat”.
sequenceDiagram
participant Agent
participant Gate as Automated Gate
participant NextTask as Task Berikutnya
Agent->>Gate: Selesai Task Group N
Gate->>Gate: Jalankan test suite lengkap
Gate->>Gate: Jalankan linter & type-check
Gate->>Gate: Verifikasi contract test sesuai spec
alt Semua Gate Lolos
Gate->>NextTask: Izinkan Lanjut
else Ada yang Gagal
Gate->>Agent: Kembalikan dengan Detail Kegagalan
Agent->>Agent: Perbaiki Sebelum Mencoba Lagi
endSistem agentic yang baik memperlakukan kegagalan gate ini sebagai bagian dari loop normal, bukan kejadian luar biasa — agent diharapkan memperbaiki dan mencoba lagi, menjalankan ulang test, dan mengirim ulang hasil untuk evaluasi, tanpa perlu campur tangan manusia di setiap percobaan ulang ini. Manusia baru perlu turun tangan ketika perbaikan berulang tetap gagal mencapai kondisi lolos gate — sinyal bahwa masalahnya kemungkinan bukan sekadar bug kecil, tapi kesalahpahaman yang lebih mendasar tentang task atau spec yang diberikan.
Yang penting dipastikan: gate ini benar-benar wajib, bukan opsional yang bisa dilewati ketika terburu-buru. Begitu ada pengecualian “kali ini lewati saja gate-nya karena buru-buru”, praktik itu cenderung berulang dan akhirnya guardrail kehilangan fungsi sebagai pagar yang konsisten.
Reviewer Agent Independen
Salah satu pola yang efektif untuk mengatasi keterbatasan self-verification yang dibahas di awal artikel adalah menggunakan agent kedua, terpisah dari agent yang mengerjakan implementasi, khusus untuk mereview hasilnya. Karena agent reviewer ini tidak berbagi rangkaian penalaran yang sama dengan agent implementer — context-nya dimulai segar, hanya melihat hasil akhir dan spec, bukan proses berpikir yang menghasilkan keputusan implementasi — reviewer ini tidak mewarisi bias konfirmasi yang sama.
flowchart LR
A[Agent Implementer] -->|Hasil + Diff| B[Agent Reviewer<br/>Context Terpisah]
C[Spec & Acceptance Criteria] --> B
B --> D{Temuan?}
D -- Tidak Ada Temuan Berarti --> E[Lolos]
D -- Ada Temuan --> F[Kembalikan ke Implementer]
F --> APola ini efektif tapi punya jebakan yang perlu diperhatikan: reviewer yang diminta secara umum untuk “mencari masalah” cenderung selalu menemukan sesuatu untuk dilaporkan, bahkan ketika pekerjaan yang direview sebenarnya sudah baik — karena itulah yang diminta untuk dilakukan. Mengejar setiap temuan reviewer tanpa pertimbangan justru mendorong ke arah over-engineering: lapisan abstraksi tambahan yang tidak perlu, kode defensif berlebihan, atau test untuk skenario yang secara realistis tidak mungkin terjadi.
ANTI-PATTERN (mengejar semua temuan reviewer):
Reviewer melaporkan 12 "potential issue". Implementer mencoba
menangani semuanya, termasuk yang sebenarnya tidak relevan dengan
correctness atau requirement yang dinyatakan, menghasilkan kode
yang lebih kompleks dari yang dibutuhkan.
BENAR (filter berdasarkan relevansi terhadap requirement):
Instruksikan reviewer untuk hanya menandai temuan yang mempengaruhi
correctness atau requirement yang dinyatakan secara eksplisit di
spec, dan memperlakukan sisanya sebagai opsional — bukan kewajiban
yang harus ditangani sebelum lolos.
Batasan lain dari pola ini: reviewer agent, meski independen secara context, tetap merupakan sistem probabilistik dengan keterbatasan yang sama dengan agent manapun — bisa melewatkan kesalahan, atau menandai sesuatu yang sebenarnya bukan masalah. Reviewer agent adalah lapisan tambahan yang berguna, bukan pengganti penuh untuk human review pada perubahan yang berisiko tinggi.
Mendeteksi dan Membatasi Blast Radius
Istilah blast radius — seberapa luas dampak yang bisa ditimbulkan kalau sesuatu berjalan salah — menjadi konsep sentral dalam mendesain guardrail untuk agent yang otonomi tindakannya makin besar. Semakin mampu sebuah agent bertindak, semakin besar pula potensi blast radius-nya jika terjadi kesalahan atau penyalahgunaan, sehingga pembatasan blast radius perlu jadi pertimbangan desain eksplisit, bukan asumsi bahwa agent akan selalu bertindak sesuai harapan.
Strategi paling efektif untuk membatasi blast radius adalah isolasi eksekusi — menjalankan agent di lingkungan yang terpisah sepenuhnya dari sistem produksi dan sistem developer:
- Filesystem yang dibatasi — agent hanya punya akses ke direktori project yang relevan, bukan seluruh home directory atau sistem file yang lebih luas
- Isolasi jaringan — domain yang bisa diakses agent dibatasi secara eksplisit (allowlist), mencegah komunikasi keluar yang tidak diinginkan ke domain yang tidak dikenal
- Lingkungan kerja terpisah (worktree/branch terisolasi) — perubahan dilakukan di branch atau worktree terpisah, bukan langsung di branch utama, sehingga perubahan yang bermasalah bisa dibuang tanpa mempengaruhi kode yang sudah stabil
- Kredensial dengan hak akses minimal — agent diberi token dengan masa berlaku pendek dan hak akses seminimal mungkin yang dibutuhkan untuk task tersebut, bukan kredensial dengan akses penuh yang dipakai untuk semua keperluan
flowchart TD
A[Agent Bertindak] --> B{Di Lingkungan Terisolasi?}
B -- Ya: Sandbox/Worktree Terpisah --> C[Kesalahan Terbatas di Sandbox]
C --> D[Mudah Di-rollback: Buang Sandbox]
B -- Tidak: Langsung di Sistem Utama --> E[Kesalahan Berpotensi Menyebar Luas]
E --> F[Rollback Sulit & Berisiko]Prinsip yang mendasari semua strategi ini sama: anggap output agent sebagai tidak tepercaya secara default, dan terapkan batasan itu secara struktural lewat isolasi teknis — bukan secara heuristik dengan berharap agent “akan berperilaku baik” karena sudah diberi instruksi untuk tidak melakukan hal tertentu. Instruksi semacam “jangan akses direktori X” bisa diabaikan atau dilewati; pembatasan filesystem yang sebenarnya tidak bisa.
Mengandalkan instruksi semata (“tolong jangan sentuh file ini”) sebagai satu-satunya guardrail adalah praktik yang rapuh. Batasan yang benar-benar andal diterapkan secara struktural — lewat permission sistem, isolasi filesystem, atau kontrol jaringan — bukan lewat permintaan baik-baik yang berharap agent mematuhinya secara konsisten di setiap kondisi.
Manfaat tambahan dari isolasi eksekusi: perubahan yang dilakukan di lingkungan terpisah jauh lebih mudah di-rollback dibanding perubahan yang sudah menyebar ke berbagai bagian sistem yang saling terhubung. Kalau task ternyata menghasilkan pendekatan yang salah, membuang seluruh sandbox atau worktree dan memulai ulang jauh lebih sederhana dan lebih aman daripada mencoba membatalkan sebagian perubahan yang sudah tercampur dengan perubahan lain yang valid.
Menentukan Kapan Manusia Wajib Turun Tangan
Tidak semua keputusan bisa atau sebaiknya didelegasikan sepenuhnya ke lapisan otomatis. Beberapa sinyal yang sebaiknya memicu eskalasi wajib ke manusia, terlepas dari seberapa matang lapisan guardrail otomatis yang ada:
Perubahan menyentuh constraint keamanan atau compliance. Mengingat kembali pembahasan constraint di Part 2 series Spec-Driven Development — perubahan yang menyentuh area sensitif seperti otentikasi, enkripsi, atau penanganan data personal layak mendapat review manusia eksplisit, terlepas dari apakah test otomatis sudah lolos.
Scope pekerjaan melebar di luar task yang disepakati. Kalau agent menemukan bahwa menyelesaikan task dengan benar ternyata membutuhkan perubahan di luar scope yang sudah disetujui — mengingat kembali pembahasan scope boundary di Part 3 — ini adalah sinyal untuk berhenti dan mengonfirmasi ke manusia, bukan melanjutkan ekspansi scope secara sepihak.
Ambiguitas yang tidak bisa diselesaikan dari informasi yang tersedia. Ketika spec, context, dan hasil eksplorasi yang ada tetap tidak cukup untuk menentukan pendekatan yang benar dengan keyakinan memadai, melanjutkan dengan asumsi sendiri berisiko menghasilkan pekerjaan yang harus dibongkar ulang. Eskalasi pada titik ini — meminta klarifikasi alih-alih menebak — hampir selalu lebih murah daripada melanjutkan dengan asumsi yang salah.
Gate otomatis gagal berulang kali tanpa kemajuan. Seperti disinggung di bagian automated gate — kalau agent sudah mencoba beberapa kali memperbaiki hasil yang gagal lolos gate dan tetap tidak berhasil, ini sinyal bahwa masalahnya kemungkinan lebih mendasar dari sekadar bug kecil yang bisa diperbaiki lewat iterasi tambahan.
| Sinyal Eskalasi | Kenapa Tidak Bisa Diserahkan ke Otomatis |
|---|---|
| Menyentuh constraint keamanan/compliance | Konsekuensi kesalahan tinggi, butuh judgment kontekstual |
| Scope melebar di luar task yang disepakati | Keputusan tentang prioritas dan cakupan kerja, bukan keputusan teknis murni |
| Ambiguitas tidak terselesaikan dari informasi tersedia | Melanjutkan dengan asumsi salah lebih mahal daripada menunggu klarifikasi |
| Gate otomatis gagal berulang tanpa kemajuan | Kemungkinan kesalahpahaman mendasar, bukan bug kecil |
Definisikan kriteria eskalasi ini secara eksplisit sebagai bagian dari guardrail, bukan diserahkan pada penilaian agent di momen itu juga tentang “apakah ini cukup penting untuk ditanyakan”. Kriteria yang eksplisit dan konsisten mencegah agent melanjutkan pekerjaan berisiko hanya karena pada saat itu terlihat “cukup yakin” untuk lanjut.
Anti-Pattern dalam Guardrail
Beberapa pola yang melemahkan efektivitas guardrail meski terlihat seperti praktik yang masuk akal di permukaan:
Guardrail yang terlalu longgar — semua diverifikasi oleh agent yang sama. Mengandalkan sepenuhnya pada self-verification tanpa lapisan independen, persis masalah yang dibahas di awal artikel. Bias konfirmasi membuat lapisan ini tidak cukup untuk pekerjaan yang konsekuensinya berarti.
Guardrail yang terlalu ketat — approval di setiap baris hingga otonomi hilang. Kebalikan dari masalah di atas: meminta persetujuan manusia di setiap langkah kecil menghilangkan manfaat utama delegasi ke agent. Seperti dibahas di bagian “pagar, bukan penghambat”, batasan yang efektif menyasar jenis tindakan berisiko di fase yang tepat, bukan menginterupsi setiap tindakan tanpa pandang risiko.
Bergantung 100% pada test otomatis tanpa human review sama sekali untuk hal berisiko tinggi. Test yang lolos memberi keyakinan terhadap apa yang sudah dicakup test tersebut, tapi tidak menjamin tidak ada masalah di luar yang dicakup. Untuk perubahan yang menyentuh area sensitif, mengandalkan test lolos sebagai satu-satunya sinyal “aman” mengabaikan jenis risiko yang memang butuh judgment manusia, seperti dibahas di bagian kriteria eskalasi.
Instruksi sebagai satu-satunya bentuk pembatasan, tanpa penegakan struktural. Sudah dibahas di bagian blast radius — meminta agent “tolong jangan lakukan X” tanpa benar-benar mencegahnya secara teknis adalah guardrail yang rapuh dan tidak konsisten.
Mengizinkan pengecualian “lewati gate kali ini” karena terburu-buru. Begitu satu pengecualian dibuat, pengecualian berikutnya jadi lebih mudah dijustifikasi, dan lama-lama gate yang seharusnya wajib kehilangan fungsinya sebagai pagar yang konsisten.
Survei keamanan agent produksi terbaru menemukan bahwa hanya sebagian kecil agent yang dievaluasi benar-benar memenuhi standar kontrol keamanan yang memadai, meski kapabilitasnya terus tumbuh pesat. Kesenjangan antara seberapa mampu agent bertindak dan seberapa baik tindakan itu dikontrol adalah tantangan nyata di lapangan, bukan kekhawatiran teoretis semata.
Ringkasan
- Self-verification saja tidak cukup — agent yang mengevaluasi pekerjaannya sendiri rawan bias konfirmasi karena berbagi rangkaian penalaran yang sama dengan yang menghasilkan pekerjaan tersebut; dibutuhkan sumber evaluasi independen
- Guardrail efektif bekerja sebagai stack berlapis: test otomatis dan linter (deterministik, murah) menyaring sebanyak mungkin masalah sebelum sampai ke reviewer agent atau human review (lebih mahal, dicadangkan untuk kasus yang memang membutuhkannya)
- Guardrail yang baik berfungsi sebagai pagar yang membatasi dampak, bukan penghambat yang mematikan otonomi — pembatasan izin tool berdasarkan fase kerja (read-only saat planning, write saat eksekusi) memberi contoh konkret pendekatan ini
- Automated gate memformalkan checkpoint antar task group menjadi syarat eksplisit dan wajib (test lolos, lint bersih, contract test sesuai spec) sebelum agent diizinkan lanjut — kegagalan gate adalah bagian normal dari loop, bukan kejadian luar biasa
- Reviewer agent independen efektif karena tidak mewarisi bias konfirmasi dari agent implementer, tapi perlu diarahkan untuk fokus pada temuan yang relevan terhadap requirement, bukan mengejar setiap potential issue yang bisa mendorong over-engineering
- Blast radius dibatasi paling efektif lewat isolasi struktural — filesystem dan jaringan yang dibatasi, lingkungan kerja terpisah, kredensial dengan hak akses minimal — bukan lewat instruksi yang berharap dipatuhi
- Eskalasi wajib ke manusia untuk: perubahan menyentuh constraint keamanan, scope yang melebar di luar task disepakati, ambiguitas yang tidak terselesaikan, dan kegagalan gate berulang tanpa kemajuan
- Hindari dua ekstrem yang berlawanan: guardrail yang terlalu longgar (hanya self-verification) dan terlalu ketat (approval di setiap baris) — keduanya sama-sama melemahkan efektivitas otonomi yang seharusnya didapat dari agentic development