Claude Code: Hook, Skill hay Subagent — chọn sai mất gì?
Hook là deterministic, Skill là probabilistic, Subagent là isolation. Ba cơ chế mở rộng Claude Code, chi phí token và cách mỗi cái phản đòn.
Bạn muốn Claude Code "luôn chạy linter sau khi sửa file", nên viết một Skill. Nó chạy đúng phần lớn thời gian — phần còn lại Claude tự quyết là task này không cần lint và bỏ qua.
Một bài viết trên Dev.to mô tả đúng tình huống đó, và tác giả kết luận vấn đề không nằm ở mô tả Skill viết chưa đủ chặt: chọn sai cơ chế ngay từ đầu. Dưới đây là ranh giới giữa ba cơ chế, và cách mỗi cái phản đòn.
Một câu để nhớ
Tác giả tóm tắt: "Always do X" là Hook. "Decide whether to do X" là Skill. Hai thứ này không thay thế cho nhau được.
Mở rộng ra ba cơ chế, theo mô tả trong bài: Hook là deterministic — nó kích hoạt theo event dù Claude có muốn hay không. Skill là probabilistic — Claude đọc phần description rồi tự quyết có nạp vào hay không. Subagent là isolation — chạy trong context window riêng và trả về cho bạn một bản tóm tắt.
Câu chốt của bài đáng dán lên tường: Hook lấy đi một quyết định khỏi model, Skill thêm vào một quyết định, Subagent cách ly một quyết định.
Chi phí token khác nhau ra sao
Đây là chỗ ba cơ chế tách hẳn nhau, và cũng là chỗ chọn sai tốn tiền thật:
- Hook gắn vào lifecycle event (
PreToolUse,Stop…) khai báo trongsettings.json, chạy như một shell command bên ngoài context window. Bài viết mô tả chi phí token gần như bằng không, trừ khi bạn cố ý đẩy stdout vào. - Skill dùng progressive disclosure: đầu session chỉ nạp name + description (vài chục token mỗi Skill), phần thân chỉ nạp khi được gọi.
- Subagent chạy trong context window riêng, và chỉ message cuối cùng quay về context cha.
Mỗi cơ chế phản đòn kiểu gì
Phần này là lý do nên đọc kỹ trước khi chọn:
- Hook: một hook thoát với exit code 2 sẽ chặn hành động đó. Và theo bài viết, một
Stophook viết sai có thể làm agent lặp vô hạn. - Skill: description viết phình ra sẽ đánh thuế lên mọi lượt và định tuyến sai. Tệ hơn, model hoàn toàn có thể quyết định không gọi Skill đó.
- Subagent: nó không hỏi lại bạn được giữa chừng, và bản tóm tắt trả về thường rụng mất đúng chi tiết bạn cần.
Cách chọn cho công việc hằng ngày
Ghép mô tả của bài với việc thực tế trong repo, ranh giới khá gọn. Việc phải xảy ra không điều kiện — format khi ghi file, chặn file chứa secret, chạy test trước khi dừng — là Hook; bài viết xếp đúng ba ví dụ này vào nhóm "non-negotiable rules". Việc là một quy trình tái sử dụng mà Claude nên tự chọn khi phù hợp — workflow review, soạn release notes — là Skill. Việc tạo nhiều nhiễu và bạn chỉ cần kết luận — grep toàn repo, lục log, thăm dò song song — là Subagent.
Cấu hình Hook ngắn hơn nhiều người tưởng. Ví dụ minh hoạ từ bài viết, chạy prettier sau mỗi lần Write hoặc Edit:
{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit",
"hooks": [{ "type": "command",
"command": "prettier --write \"$CLAUDE_FILE_PATHS\"" }] } ] } }
Còn một tầng thứ tư: Agent SDK. Theo bài viết, bạn gọi query() từ TypeScript hoặc Python và tự điều khiển vòng lặp agent trong process của mình — đổi lại, bạn tự lo retry, sandboxing, session state và chi phí. Không còn gì tự động nữa.
Kiểm tra nhanh repo của bạn
Mở danh sách Skill đang bật và hỏi từng cái: nếu Claude bỏ qua Skill này, có hỏng gì không? Nếu có, nó đang nằm sai chỗ — chuyển thành Hook. Đó là một buổi chiều tiết kiệm được, đúng như tác giả đã mất.
Không spam, hủy đăng ký bất kỳ lúc nào.