Promptlar öneridir. Hooklar ise kesin durduruculardır.

Aylarca Claude Code'a, sadece net temel kurallara ihtiyacı olan bir junior geliştiriciymiş gibi davrandım. Proje talimatlarım çok netti: asla force-push yapma, asla dalları (branch) silme, asla yıkıcı komutlar çalıştırma. Çoğu akşam bu işe yarıyordu. Ajan testler yazıyor, fonksiyonları refactor ediyor ve git geçmişine dokunmuyordu. Sonra bir rebase işlemi ters gitti.

Bağlam penceresi (context window) git hata çıktılarıyla doldu. Çakışma işaretleri (conflict markers), ayrılmış HEAD (detached HEAD) mesajları ve dal sapması (branch divergence) uyarıları token token üst üste bindi. Bu gürültünün altına, force-push yapmaktan kaçınmamı söyleyen nazik talimatım gömülüp kalmıştı. Model için, thread'deki en güncel ve belirgin metin hata akışıydı. İstatistiksel dikkat, politikayı alt etti. Ajan, iki saatlik kaydedilmemiş yerel değişikliği silen bir komut çalıştırdı. Kötü niyetli değildi; sadece dikkati dağılmıştı. Bu ayrım önemlidir. Bir LLM, kin beslediği için kuralları çiğnemez. Kuralları, bağlam penceresindeki daha baskın bir kalıbın geçici olarak önceki bir talimatın önüne geçmesi nedeniyle çiğner.

Bu olay, ajan güvenliği hakkındaki düşüncelerimi değiştirdi. Yüzde doksan dokuz oranında çalışan bir koruma bariyeri (guardrail) bir risk teşkil eder. Eğer hata modu size zaman, para veya üretim verisi kaybettiriyorsa, bunu prompt içinde bırakamazsınız. Modelin muhakeme döngüsünün dışında bir zorlayıcı mekanizmaya ihtiyacınız vardır.

Claude Code hookları tam olarak bunu çözer. Bunlar, araç çağrılarını üç belirli anda yakalayan küçük scriptlerdir: bir araç çalıştırılmadan önce (PreToolUse), bir araç işini bitirdikten sonra (PostToolUse) ve ajan işinin bittiğine karar verdiğinde (Stop). Harici kod olarak çalıştıkları için modelin hafızasına, ruh haline veya bağlam baskısına bağımlı değillerdir. Model, ona verdiğiniz her talimatı unutabilir; hook yine de "hayır" diyecektir.

İşte o kaybedilen akşamdan sonra inşa ettiğim düzenek.

Koruma Hook'u: Hasar Oluşmadan Önce Müdahale Edin

PreToolUse hook'um, her Bash komutunu kabuk (shell) tarafından işlenmeden önce inceler. Yıkıcı kalıplardan oluşan sıkı bir denylist (engellenenler listesi) tutuyorum. Eğer komut dizisi tehlikeli bir şeyle eşleşirse, hook yürütmeyi durdurur ve doğrudan ajana bir hata döndürür.

Engellediğim kalıplar basit ve net:

  • git push --force veya henüz güvenmediğim herhangi bir force-with-lease varyantı
  • git reset --hard
  • rm -rf

Bu sofistike bir güvenlik araştırması değil. Bu bir emniyet kemeridir. Ancak kritik detay, engelleme işleminden sonra ne olduğudur.

Asla kaba bir "Engellendi" yanıtı vermem. Düz bir reddediş ajanın kafasını karıştırır ve onu aynı yıkıcı komutun varyasyonlarını denediği bir döngüye hapsedebilir. Bunun yerine, hata mesajı bir kaçış yolu içerir. Hook bir hard reset yakaladığında ajana şunu söyler: "Bu komut, kaydedilmemiş çalışmaları korumak için engellendi. Önce bir checkpoint commit'le, sonra tekrar değerlendir." Bu fazladan cümle ajanın davranışını tamamen değiştirir. Hasar kontrolü yapmaya çalışmaktan, güvenlik oluşturmaya yönelir. Hook sadece bir duvar değil, bir trafik kontrolüdür.

Kabuk komutları için bir allowlist (izin verilenler listesi) yerine denylist kullanmayı tercih ettim. İlk başta sadece belirli bir güvenli git alt komutu setine izin vermeyi düşündüm. Bu yöntem hızla başarısız oldu. Ajanlar, komutları yaratıcı bir şekilde harfiyen uygularlar. Durumu kontrol etmek için git stash push -m "wip" veya git branch --show-current gibi meşru ama beklenmedik komutlar çalıştırırlar. Bir allowlist, model geçerli ama listede olmayan bir komut uydurduğu anda normal iş akışını bozar. Gerçekten yıkıcı kalıplardan oluşan kısa ve özenle seçilmiş bir denylist, sınırları korurken ajana hareket alanı sağlar.

Formatlayıcı Hook'u: Rutin İşleri Otomatize Edin

Eskiden ajana "dosya düzenledikten sonra her zaman formatlayıcıyı çalıştır" demek için prompt token'larını boşa harcardım. Yarım zamanında bunu unutuyordu. Diğer yarısında ise durup formatlayıp formatlamayacağını soruyor, tek bir doğru cevabı olan bir karar için bir araç çağrısını (tool call) yakıyordu.

Artık bunu bir PostToolUse hook'u ile hallediyorum. Ajan bir dosyayı düzenledikten sonra, hook dosya uzantısını kontrol eder. Eğer Python ise Ruff çalıştırır. JavaScript veya TypeScript ise Prettier çalıştırır. Go ise gofmt çalıştırır. Ajan formatlayıcının varlığından haberdar bile değildir. Haberdar olmasına da gerek yoktur.

Bunu prompt dışına taşımanın iki etkisi oldu. Birincisi, modele bilişsel yük bindirmeden kod tutarlı bir şekilde temiz kalıyor. İkincisi, proje talimatlarım kısaldı. Bir prompt'tan çıkardığınız her "her zaman" ve "asla" ifadesi, modelin gerçek problem çözmeye harcayabileceği bir token'dır. Değişmez kurala hook, niyete ise prompt sahip çıkar.

Kalite Kapısı: "Bitti" Kavramını Yeniden Tanımlamak

Stop kancası, ajan görevi tamamladığına karar verdiğinde ve oturumu sonlandırmaya çalıştığında çalışır. Buna izin vermiyorum. Bunun yerine kanca, tüm test paketini çalıştırır. Eğer herhangi bir test başarısız olursa, kanca durdurma komutunu engeller ve hata çıktısını ajana geri döndürür.

Bu, tamamlanma tanımını değiştirir. “Bitti” artık modelin hissettiği bir duygu değildir; ölçülebilir bir eşiktir. Ajan, ancak harness kodun çalıştığını onayladığında işini bitirebilir. Pratikte bu, sıkı bir geri bildirim döngüsü oluşturur. Ajan kodu yazar, bittiğini düşünür, durdur düğmesine basar ve anında bir pytest traceback'i görür. Ardından kendi kendini düzeltir, import hatasını veya bozuk assertion'ı giderir ve tekrar durdurmayı dener. Ajanların bu döngü içinde insan müdahalesi olmadan üç veya dört kez yineleme yaptığını gözlemledim. Harness kaliteyi zorunlu kılar; model ise yamaları sağlar.

Bu, Ajan Mühendisliği Hakkında Ne Öğretiyor

Güvenilir otonom sistemler inşa etmek, bir zihniyet değişimi gerektirir. Daha uzun promptlar yazmaktan, daha sıkı harness'lar inşa etmeye geçiş yaparsınız.

Zorunluluklar için kancaları, politikalar için ise promptları kullanın. Eğer bir kuralın yüzde yüz geçerli olması gerekiyorsa, bu doğal dilde değil, kodda yer almalıdır. Promptlar belirsizlik, beğeni ve mimari konularında mükemmeldir; ancak değişmezler (invariants) konusunda berbattırlar. Eğer bir hata size bir öğleden sonranızı kurtarmakla veya daha kötüsü, üretim (production) çalışma süresiyle (uptime) mal olacaksa, bir kanca yazın.

Daha kısa promptlar daha iyi sonuçlar verir. Mekanik kuralları script'lere taşıdığınızda, modelin hatırlaması ve çelişmesi gereken şey azalır. Ajanın bağlam penceresi (context window) kıt bir kaynaktır. Onu biçimlendirme hatırlatıcılarıyla doldurmayın.

Son olarak, rolünüzün değiştiğini kabul edin. Ajanlar özerklik kazandıkça, insanın işi içerik üretmekten koruma bariyerlerini (guardrails) tasarlamaya kayar. Modelin neye dokunabileceğine, ne zaman bitirebileceğine ve işler ters gittiğinde nasıl davranması gerektiğine karar veren harness'ı siz inşa ediyorsunuz. Bu mühendisliktir, prompt yazmak değil.

Bu yaklaşıma ilham veren kaynak ve ek uygulama detayları burada bulunabilir.

Eğer yapay zeka ajanlarıyla bir şeyler inşa ediyorsanız ve diğer uygulayıcılarla bilgi alışverişinde bulunmak istiyorsanız, GyaanSetu öğrenme topluluğunu burada bulabilirsiniz.