Agent Hooks
Ajan yaşam döngüsü kancaları
Ajanın yaşam döngüsündeki belirli anlarda (araç çağrısından önce, sonra, oturum başında, yanıt bitince) harness tarafından kesin olarak çalıştırılan, kullanıcı tanımlı komutlar.
Bir ajana system prompt'ta "her dosya düzenlemesinden sonra linter çalıştır" diyebilirsin. Çoğu zaman uyar, bazen unutur. Hook'lar bu "çoğu zaman"ı "her zaman"a çevirir: kuralı modele değil, ajanı çalıştıran harness'a emanet edersin. Kısa formül: prompt'lar ve skill'ler öneridir, hook'lar garantidir.
Hook, harness'ın yaşam döngüsündeki bir olaya bağlanan komuttur. Claude Code'da en sık kullanılan olaylar: - SessionStart — oturum açılırken (ör. git durumunu bağlama ekle) - UserPromptSubmit — kullanıcı mesajı modele gitmeden önce - PreToolUse — araç çalışmadan hemen önce; çağrıyı engelleyebilir - PostToolUse — araç başarıyla bittikten sonra (format, lint, test) - Stop — model yanıtını bitirmek üzereyken; "henüz bitmedin" diyebilir
Mekanik basittir: harness olay verisini (araç adı, girdi, oturum
bilgisi) JSON olarak hook'un stdin'ine yazar. Hook bir kabuk
betiği, HTTP uç noktası ya da küçük bir model değerlendirmesi olabilir.
Cevabını çıkış kodu ve stdout ile verir: exit 0 "devam",
exit 2 "engelle" demektir ve stderr'e yazılan mesaj modele geri
beslenir. Daha ince kontrol için JSON döner — örneğin PreToolUse'da
permissionDecision: "deny".
Model hook'un varlığından haberdar bile olmayabilir; sadece sonucunu görür. Bu yüzden hook'lar ajan davranışını deterministik hale getirmenin en sağlam yoludur.
Fabrikadaki emniyet kilidi gibi. Operatöre "pres inerken elini çek" diye eğitim verirsin (prompt), ama yine de makineye iki elle basılmadan çalışmayan bir buton takarsın (hook). Eğitim davranışı yönlendirir; kilit, operatör ne kadar yorgun olursa olsun kazayı fiziksel olarak imkânsız kılar.
Bir ekip Claude Code ile çalışıyor ve iki sorun yaşıyor: ajan bazen
rm -rf ile fazla geniş silme yapıyor, bazen de düzenlediği dosyayı
formatlamayı unutuyor.
Çözüm .claude/settings.json içinde iki hook:
1. PreToolUse + Bash eşleştiricisi: komut rm -rf içeriyorsa
betik permissionDecision: "deny" döner, Claude gerekçeyi görür ve
başka yol arar.
2. PostToolUse + Edit|Write eşleştiricisi: her düzenlemeden sonra
formatter otomatik çalışır.
Artık bu iki kural hiçbir prompt'a, modelin o anki dikkatine ya da bağlam penceresinin dolmasına bağlı değil. Dosya repoya commit'lendiği için ekipteki herkes aynı korumayı alır.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-rm.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write ."
}
]
}
]
}
}#!/bin/bash
# Harness araç girdisini JSON olarak stdin'e yazar
COMMAND=$(jq -r '.tool_input.command')
if echo "$COMMAND" | grep -q 'rm -rf'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "rm -rf hook tarafından engellendi"
}
}'
else
exit 0 # karar yok; normal izin akışı devam eder
fi- Bir kural istisnasız uygulanmalıysa (format, lint, gizli dosyalara dokunmama)
- Tehlikeli araç çağrılarını model kararından bağımsız olarak engellemek istiyorsan
- Oturum başında bağlama dinamik bilgi eklemek için (git durumu, açık işler)
- Ajanın işi bitirdiğini iddia ettiği anda testleri çalıştırıp doğrulamak için (Stop)
- Denetim kaydı (audit log) ya da bildirim gibi yan etkiler için
- Kural yoruma açıksa ve bağlama göre değişiyorsa — bu iş prompt ya da skill'in
- Her araç çağrısında saniyeler süren ağır işler — ajan döngüsünü yavaşlatır
- Tek başına güvenlik sınırı olarak — hook bir katmandır, sandbox'ın yerini tutmaz
Sessiz kalmayı onay sanmak
PreToolUse hook'u exit 0 ile ve çıktı vermeden biterse bu 'izin verildi' demek değildir; çağrı normal izin akışına döner. Engellemek için açıkça exit 2 ya da permissionDecision: "deny" gerekir.
Stop hook'unu sonsuz döngüye sokmak
Stop hook'u her seferinde engellerse ajan durmak bilmez. Girdideki stop_hook_active alanını kontrol et; Claude Code ayrıca art arda 8 devam etmeden sonra turu zorla bitirir.
Hook'un kendisini güvenlik açığına çevirmek
Hook senin yetkilerinle çalışan bir kabuk komutudur. Değişkenleri tırnakla, .. içeren yolları reddet, .env ve anahtar dosyalarına dokunma, betiklere $CLAUDE_PROJECT_DIR ile mutlak yoldan eriş.