- Blokir operasi berbahaya sebelum dieksekusi, seperti perintah shell yang merusak atau akses file yang tidak sah
- Log dan audit setiap pemanggilan tool untuk kepatuhan, debugging, atau analitik
- Transform input dan output untuk membersihkan data, menyuntikkan kredensial, atau mengalihkan jalur file
- Memerlukan persetujuan manusia untuk tindakan sensitif seperti penulisan database atau panggilan API
- Track lifecycle sesi untuk mengelola state, membersihkan resources, atau mengirim notifikasi
Cara kerja hooks
Sebuah event terjadi
Sesuatu terjadi selama eksekusi agent dan SDK menembakkan event: tool akan dipanggil (
PreToolUse), tool mengembalikan hasil (PostToolUse), subagent dimulai atau berhenti, agent idle, atau eksekusi selesai. Lihat daftar lengkap events.SDK mengumpulkan hooks terdaftar
SDK memeriksa hooks yang terdaftar untuk tipe event tersebut. Ini termasuk callback hooks yang Anda berikan di
options.hooks dan shell command hooks dari file pengaturan ketika settingSources atau setting_sources entry yang sesuai diaktifkan, yang mana untuk opsi query() default.Matchers memfilter hooks mana yang berjalan
Jika hook memiliki pola
matcher (seperti "Write|Edit"), SDK mengujinya terhadap target event (misalnya, nama tool). Hooks tanpa matcher berjalan untuk setiap event dari tipe tersebut.Fungsi callback dieksekusi
Setiap fungsi callback hook yang cocok menerima input tentang apa yang terjadi: nama tool, argumennya, ID sesi, dan detail spesifik event lainnya.
Callback Anda mengembalikan keputusan
Setelah melakukan operasi apa pun (logging, panggilan API, validasi), callback Anda mengembalikan output object yang memberi tahu agent apa yang harus dilakukan: izinkan operasi, blokir, modifikasi input, atau suntikkan konteks ke dalam percakapan.
PreToolUse (langkah 1) dengan matcher "Write|Edit" (langkah 3) sehingga callback hanya terjadi untuk tools penulisan file. Ketika dipicu, callback menerima input tool (langkah 4), memeriksa apakah jalur file menargetkan file .env, dan mengembalikan permissionDecision: "deny" untuk memblokir operasi (langkah 5):
Available hooks
SDK menyediakan hooks untuk tahap berbeda dari eksekusi agent. Beberapa hooks tersedia di kedua SDK, sementara yang lain hanya TypeScript.| Hook Event | Python SDK | TypeScript SDK | Apa yang memicunya | Contoh use case |
|---|---|---|---|---|
PreToolUse | Ya | Ya | Permintaan pemanggilan tool (dapat memblokir atau memodifikasi) | Blokir perintah shell berbahaya |
PostToolUse | Ya | Ya | Hasil eksekusi tool | Log semua perubahan file ke audit trail |
PostToolUseFailure | Ya | Ya | Kegagalan eksekusi tool | Tangani atau log kesalahan tool |
PostToolBatch | Tidak | Ya | Batch lengkap pemanggilan tool terselesaikan, sekali per batch sebelum panggilan model berikutnya | Suntikkan konvensi sekali untuk seluruh batch |
UserPromptSubmit | Ya | Ya | Pengajuan prompt pengguna | Suntikkan konteks tambahan ke dalam prompts |
MessageDisplay | Tidak | Ya | Pesan asisten dengan teks selesai, sekali per pesan dengan teks pesan lengkap | Redaksi atau format ulang teks yang ditampilkan tanpa mengubah transcript |
Stop | Ya | Ya | Penghentian eksekusi agent | Simpan state sesi sebelum keluar |
SubagentStart | Ya | Ya | Inisialisasi subagent | Track spawning tugas paralel |
SubagentStop | Ya | Ya | Penyelesaian subagent | Agregasi hasil dari tugas paralel |
PreCompact | Ya | Ya | Permintaan compaction percakapan | Arsipkan transcript lengkap sebelum merangkum |
PermissionRequest | Ya | Ya | Dialog permission akan ditampilkan | Custom permission handling |
SessionStart | Tidak | Ya | Inisialisasi sesi | Inisialisasi logging dan telemetry |
SessionEnd | Tidak | Ya | Penghentian sesi | Bersihkan resources sementara |
Notification | Ya | Ya | Pesan status agent | Kirim update status agent ke Slack atau PagerDuty |
Setup | Tidak | Ya | Setup/maintenance sesi | Jalankan tugas inisialisasi |
TeammateIdle | Tidak | Ya | Teammate menjadi idle | Reassign pekerjaan atau notifikasi |
TaskCompleted | Tidak | Ya | Background task selesai | Agregasi hasil dari tugas paralel |
ConfigChange | Tidak | Ya | File konfigurasi berubah | Reload pengaturan secara dinamis |
WorktreeCreate | Tidak | Ya | Git worktree dibuat | Track isolated workspaces |
WorktreeRemove | Tidak | Ya | Git worktree dihapus | Bersihkan workspace resources |
Konfigurasi hooks
Untuk mengonfigurasi hook, berikan di fieldhooks dari opsi agent Anda (ClaudeAgentOptions di Python, object options di TypeScript):
hooks adalah dictionary (Python) atau object (TypeScript) di mana:
- Keys adalah nama hook event (misalnya,
'PreToolUse','PostToolUse','Stop') - Values adalah array dari matchers, masing-masing berisi pola filter opsional dan fungsi callback Anda
Matchers
Gunakan matchers untuk memfilter kapan callbacks Anda terjadi. Fieldmatcher cocok dengan nilai berbeda tergantung pada tipe hook event. Misalnya, tool-based hooks cocok dengan nama tool, sementara hooks Notification cocok dengan tipe notifikasi. Lihat referensi hooks Claude Code untuk daftar lengkap nilai matcher untuk setiap tipe event.
SDK matchers mengikuti aturan yang sama dengan matchers dalam file settings: matcher yang hanya berisi huruf, digit, _, dan | dibandingkan sebagai string yang tepat, dengan | memisahkan alternatif, jadi Write|Edit cocok dengan tepat kedua tools tersebut. Matcher *, string kosong, atau menghilangkan matcher sepenuhnya cocok dengan setiap kemunculan event; matcher yang berisi karakter lain apa pun dievaluasi sebagai regular expression, jadi ^mcp__ cocok dengan setiap MCP tool. Matcher seperti mcp__memory hanya berisi huruf dan underscore, jadi dibandingkan sebagai string yang tepat dan tidak cocok dengan tool apa pun; gunakan mcp__memory__.* untuk cocok dengan setiap tool dari server tersebut.
| Option | Type | Default | Description |
|---|---|---|---|
matcher | string | undefined | Pola yang cocok dengan field filter event, mengikuti aturan perbandingan di atas. Untuk tool hooks, ini adalah nama tool. Built-in tools termasuk Bash, Read, Write, Edit, Glob, Grep, WebFetch, Agent, dan lainnya (lihat Tool Input Types untuk daftar lengkap). MCP tools menggunakan pola mcp__<server>__<action>. |
hooks | HookCallback[] | - | Diperlukan. Array dari fungsi callback untuk dieksekusi ketika pola cocok |
timeout | number | 60 | Timeout dalam detik |
matcher untuk menargetkan tools spesifik kapan pun memungkinkan. Matcher dengan 'Bash' hanya berjalan untuk perintah Bash, sementara menghilangkan pola menjalankan callbacks Anda untuk setiap kemunculan event. Perhatikan bahwa untuk tool-based hooks, matchers hanya memfilter berdasarkan nama tool, bukan jalur file atau argumen lainnya. Untuk memfilter berdasarkan jalur file, periksa tool_input.file_path di dalam callback Anda.
Callback functions
Inputs
Setiap hook callback menerima tiga argumen:- Input data: object yang diketik berisi detail event. Setiap tipe hook memiliki bentuk input sendiri (misalnya,
PreToolUseHookInputmencakuptool_namedantool_input, sementaraNotificationHookInputmencakupmessage). Lihat definisi tipe lengkap di referensi SDK TypeScript dan Python.- Semua hook inputs berbagi
session_id,cwd, danhook_event_name. agent_iddanagent_typediisi ketika hook terjadi di dalam subagent. Di TypeScript, ini berada di base hook input dan tersedia untuk semua tipe hook. Di Python, ini hanya ada diPreToolUse,PostToolUse, danPostToolUseFailure.
- Semua hook inputs berbagi
- Tool use ID (
str | None/string | undefined): mengkorelasikan eventsPreToolUsedanPostToolUseuntuk pemanggilan tool yang sama. - Context: di TypeScript, berisi property
signal(AbortSignal) untuk pembatalan. Di Python, argumen ini dicadangkan untuk penggunaan di masa depan.
Outputs
Callback Anda mengembalikan object dengan dua kategori fields:- Top-level fields bekerja sama pada setiap event:
systemMessagemenampilkan pesan kepada pengguna, dancontinue(continue_di Python) menentukan apakah agent terus berjalan setelah hook ini. hookSpecificOutputmengontrol operasi saat ini. Fields di dalamnya tergantung pada tipe hook event. Untuk hooksPreToolUse, di sinilah Anda menetapkanpermissionDecision("allow","deny","ask", atau"defer"),permissionDecisionReason, danupdatedInput. Mengembalikan"defer"mengakhiri query sehingga Anda dapat melanjutkannya nanti. Untuk hooksPostToolUse, Anda dapat menetapkanadditionalContextuntuk menambahkan informasi ke hasil tool. Untuk mengganti output tool sebelum Claude melihatnya, tetapkanupdatedToolOutput, yang bekerja untuk tool apa pun di kedua SDK. FieldupdatedMCPToolOutputyang lebih lama mengganti output MCP tool saja dan sudah usang.
{} untuk mengizinkan operasi tanpa perubahan. SDK callback hooks menggunakan format output JSON yang sama dengan Claude Code shell command hooks, yang mendokumentasikan setiap field dan opsi spesifik event. Untuk definisi tipe SDK, lihat referensi SDK TypeScript dan Python.
Ketika multiple hooks atau permission rules berlaku, deny mengambil prioritas atas defer, yang mengambil prioritas atas ask, yang mengambil prioritas atas allow. Jika hook apa pun mengembalikan
deny, operasi diblokir terlepas dari hooks lainnya.Asynchronous output
Secara default, agent menunggu hook Anda kembali sebelum melanjutkan. Jika hook Anda melakukan side effect (logging, mengirim webhook) dan tidak perlu mempengaruhi perilaku agent, Anda dapat mengembalikan async output sebagai gantinya. Ini memberi tahu agent untuk melanjutkan segera tanpa menunggu hook selesai:| Field | Type | Description |
|---|---|---|
async | true | Sinyal mode async. Agent melanjutkan tanpa menunggu. Di Python, gunakan async_ untuk menghindari reserved keyword. |
asyncTimeout | number | Optional timeout dalam milliseconds untuk operasi background |
Async outputs tidak dapat memblokir, memodifikasi, atau menyuntikkan konteks ke dalam operasi karena agent telah melanjutkan. Gunakan hanya untuk side effects seperti logging, metrics, atau notifikasi.
Contoh
Modifikasi input tool
Contoh ini mengintersepsi pemanggilan tool Write dan menulis ulang argumenfile_path untuk menambahkan /sandbox, mengalihkan semua penulisan file ke direktori sandboxed. Callback mengembalikan updatedInput dengan jalur yang dimodifikasi dan permissionDecision: 'allow' untuk auto-approve operasi yang ditulis ulang:
Ketika menggunakan
updatedInput, Anda juga harus menyertakan permissionDecision: 'allow' untuk auto-approve input yang dimodifikasi atau permissionDecision: 'ask' untuk menampilkannya kepada pengguna. Dengan 'defer', updatedInput diabaikan. Selalu kembalikan object baru daripada mutating tool_input asli.Tambahkan konteks dan blokir tool
Contoh ini memblokir penulisan ke direktori/etc dan menjelaskan alasannya kepada model dan pengguna:
permissionDecision: 'deny'menghentikan pemanggilan tool.permissionDecisionReasonmemberitahu model mengapa, sehingga menghindari percobaan ulang.systemMessagemenunjukkan kepada pengguna apa yang terjadi.
Auto-approve tools spesifik
Secara default, agent dapat meminta permission sebelum menggunakan tools tertentu. Contoh ini auto-approves read-only filesystem tools (Read, Glob, Grep) dengan mengembalikanpermissionDecision: 'allow', membiarkan mereka berjalan tanpa konfirmasi pengguna sambil meninggalkan semua tools lainnya tunduk pada pemeriksaan permission normal:
Daftarkan multiple hooks
Ketika event terjadi, semua hooks yang cocok berjalan secara paralel. Untuk keputusan permission, hasil yang paling ketat menang: satudeny memblokir pemanggilan tool terlepas dari apa yang dikembalikan hooks lainnya. Karena urutan penyelesaian tidak dapat diprediksi, tulis setiap hook untuk bertindak secara independen daripada mengandalkan hook lain yang telah berjalan terlebih dahulu.
Contoh di bawah ini mendaftarkan tiga pemeriksaan independen untuk setiap pemanggilan tool:
Filter dengan multi-tool matchers
Gunakan multi-tool matchers untuk berbagi satu callback di seluruh tools terkait. Contoh ini mendaftarkan tiga matchers dengan scope berbeda:- Daftar exact yang dipisahkan pipe (
Write|Edit|Delete) memicufile_security_hookhanya untuk file modification tools. - Regex (
^mcp__) memicumcp_audit_hookuntuk tool MCP apa pun yang namanya dimulai denganmcp__. - Matcher yang dihilangkan memicu
global_loggeruntuk setiap pemanggilan tool terlepas dari nama.
Lacak aktivitas subagent
Gunakan hooksSubagentStop untuk memantau ketika subagents menyelesaikan pekerjaan mereka. Lihat tipe input lengkap di referensi SDK TypeScript dan Python. Contoh ini mencatat ringkasan setiap kali subagent selesai:
Buat HTTP requests dari hooks
Hooks dapat melakukan operasi asynchronous seperti HTTP requests. Tangkap errors di dalam hook Anda daripada membiarkan mereka menyebar, karena exception yang tidak ditangani dapat mengganggu agent. Contoh ini mengirim webhook setelah setiap tool selesai, mencatat tool mana yang berjalan dan kapan. Hook menangkap errors sehingga webhook yang gagal tidak mengganggu agent:Teruskan notifikasi ke Slack
Gunakan hooksNotification untuk menerima notifikasi sistem dari agent dan meneruskannya ke layanan eksternal. Notifikasi terjadi untuk tipe event seperti:
permission_promptketika Claude memerlukan permissionidle_promptketika Claude menunggu inputauth_successketika authentication selesaielicitation_dialog,elicitation_complete, danelicitation_responseuntuk alur elicitation user-prompt
message dengan deskripsi yang dapat dibaca manusia dan secara opsional title.
Contoh ini meneruskan setiap notifikasi ke channel Slack. Ini memerlukan Slack incoming webhook URL, yang Anda buat dengan menambahkan app ke workspace Slack Anda dan mengaktifkan incoming webhooks:
Perbaiki masalah umum
Hook not firing
- Verifikasi nama hook event benar dan case-sensitive (
PreToolUse, bukanpreToolUse) - Periksa bahwa pola matcher Anda cocok dengan nama tool dengan tepat
- Pastikan hook berada di bawah tipe event yang benar di
options.hooks - Untuk non-tool hooks seperti
StopdanSubagentStop, matchers cocok dengan fields berbeda (lihat matcher patterns) - Hooks mungkin tidak terjadi ketika agent mencapai batas
max_turnskarena sesi berakhir sebelum hooks dapat dieksekusi
Matcher not filtering as expected
Matchers hanya cocok dengan nama tool, bukan jalur file atau argumen lainnya. Untuk memfilter berdasarkan jalur file, periksatool_input.file_path di dalam hook Anda:
Hook timeout
- Tingkatkan nilai
timeoutdalam konfigurasiHookMatcher - Gunakan
AbortSignaldari argumen callback ketiga untuk menangani pembatalan dengan baik di TypeScript
Tool blocked unexpectedly
- Periksa semua hooks
PreToolUseuntuk returnspermissionDecision: 'deny' - Tambahkan logging ke hooks Anda untuk melihat apa
permissionDecisionReasonyang mereka kembalikan - Verifikasi pola matcher tidak terlalu luas (matcher kosong cocok dengan semua tools)
Modified input not applied
-
Pastikan
updatedInputberada di dalamhookSpecificOutput, bukan di top level: -
Kembalikan
permissionDecision: 'allow'untuk auto-approve input yang dimodifikasi, atau'ask'untuk menampilkannya kepada pengguna untuk persetujuan -
Sertakan
hookEventNamedihookSpecificOutputuntuk mengidentifikasi tipe hook mana output-nya
Session hooks not available in Python
SessionStart dan SessionEnd dapat didaftarkan sebagai SDK callback hooks di TypeScript, tetapi tidak tersedia di Python SDK (HookEvent menghilangkannya). Di Python, mereka hanya tersedia sebagai shell command hooks yang didefinisikan dalam file pengaturan (misalnya, .claude/settings.json). Untuk memuat shell command hooks dari aplikasi SDK Anda, sertakan setting source yang sesuai dengan setting_sources atau settingSources:
client.receive_response() sebagai trigger Anda.
Subagent permission prompts multiplying
Ketika spawning multiple subagents, masing-masing mungkin meminta permissions secara terpisah. Subagents tidak secara otomatis mewarisi parent agent permissions. Untuk menghindari prompts berulang, gunakan hooksPreToolUse untuk auto-approve tools spesifik, atau konfigurasi permission rules yang berlaku untuk sesi subagent.
Recursive hook loops with subagents
HookUserPromptSubmit yang spawns subagents dapat membuat infinite loops jika subagents tersebut memicu hook yang sama. Untuk mencegah ini:
- Periksa indikator subagent di hook input sebelum spawning
- Gunakan shared variable atau session state untuk track apakah Anda sudah berada di dalam subagent
- Scope hooks untuk hanya berjalan untuk sesi top-level agent
systemMessage not appearing in output
FieldsystemMessage menampilkan pesan kepada pengguna, bukan model. Secara default SDK tidak menampilkan hook output di message stream, jadi pesan mungkin tidak muncul kecuali Anda mengatur includeHookEvents (include_hook_events di Python). Untuk meneruskan konteks ke model sebagai gantinya, kembalikan additionalContext.
Jika Anda perlu menampilkan hook decisions ke aplikasi Anda dengan andal, log mereka secara terpisah atau gunakan dedicated output channel.
Related resources
- Claude Code hooks reference: full JSON input/output schemas, event documentation, dan matcher patterns
- Claude Code hooks guide: shell command hook examples dan walkthroughs
- TypeScript SDK reference: hook types, input/output definitions, dan configuration options
- Python SDK reference: hook types, input/output definitions, dan configuration options
- Permissions: kontrol apa yang dapat dilakukan agent Anda
- Custom tools: build tools untuk extend agent capabilities