Free

Slash Commands nâng cao: subagent và điều phối công cụ

Dùng tham chiếu @file, allowed-tools, subagent và tool MCP để nâng slash command từ phím tắt lên thành thư viện workflow của team.


Hai bài trước nói về slash command là gì (một file Markdown) và cách dùng tiền tố ! để bơm output shell vào context. Bài này đi xa hơn: làm sao để một command điều phối những năng lực mạnh nhất của Claude Code — tham chiếu file, subagent, công cụ MCP — và giữ quyền trong tầm kiểm soát.

Khi viết đến tầng này, command không còn chỉ là "phím tắt cho prompt" mà đã trở thành các workflow nhỏ có thể tái sử dụng.


Tham chiếu @file: cách tiêm nội dung tĩnh hợp lý hơn !cat

!cat file.md có thể nhét nội dung file vào context, nhưng nó đi qua shell và có vài nhược điểm: mỗi lần kích hoạt phải dựng một tiến trình con; đường dẫn file có khoảng trắng hoặc ký tự đặc biệt phải escape thêm; và Claude Code không nhận diện nó là "một file" mà chỉ xem là một đoạn text.

Tham chiếu @ thì native:

---
description: Review thay đổi theo quy chuẩn dự án
---

Tham khảo các quy chuẩn sau:

@.claude/context/coding-standards.md
@.claude/context/security-checklist.md

Giờ hãy review các thay đổi trong git diff, chỉ ra mọi chỗ vi phạm quy chuẩn.

!`git diff HEAD`

@path bảo Claude Code "đính file này vào hội thoại như một attachment". Khác biệt nằm ở:

Tình huống Dùng !cat Dùng @
Path đến từ tham số ($ARGUMENTS) ✅ Chỉ có thể !cat @ không hỗ trợ mở rộng biến
Quy chuẩn, template cố định của dự án ⚠️ Dùng được nhưng nặng ✅ Native, đỡ một lần shell
Nội dung động (diff, log, kết quả test) ✅ Bắt buộc ! ❌ Không được

Quy luật: file tĩnh dùng @, output động dùng !, path có tham số dùng !cat $ARGUMENTS.


allowed-tools: đặt biên quyền cho command

Mặc định, khi command chạy, model được dùng tất cả tool có trong session. Đôi khi đó không phải điều bạn muốn — ví dụ /review là tác vụ review chỉ đọc, bạn không muốn nó "tiện tay" sửa dù chỉ một dòng code.

Thêm allowed-tools vào frontmatter, trong thời gian command có hiệu lực chỉ những tool được liệt kê mới được phép:

---
description: Review code chỉ đọc
allowed-tools: Read, Grep, Glob, Bash(git diff:*), Bash(git log:*)
---

Review sự khác biệt giữa branch hiện tại và master, chỉ đọc không sửa.

!`git diff master...HEAD`

Vài điểm cần lưu ý:

  • Bash(git diff:*) là cấp quyền chi tiết — chỉ cho phép các lệnh bash bắt đầu bằng git diff, git push sẽ bị chặn
  • Read / Grep / Glob chỉ rõ chỉ cấp các tool chỉ đọc
  • Không liệt kê Edit / Write, nên model dù có muốn sửa code cũng không gọi được

Tương tự, một command quyền cao như /deploy có thể được cấp quyền theo chiều ngược lại:

---
description: Deploy branch hiện tại
allowed-tools: Bash(kamal deploy:*), Bash(git push:*), Read
---

Ghi cứng "command này được làm gì" đáng tin hơn nhiều so với việc mỗi lần chạy lại dựa vào xét duyệt thủ công từng prompt bash.


Gọi subagent: cô lập những công việc ngốn context

Có những tác vụ sẽ làm vỡ context của hội thoại chính — duyệt hàng chục file để tìm mọi call site của một hàm, chạy thống kê codebase, kéo một đoạn log lớn để phân tích. Làm thẳng trong hội thoại chính thì hàng ngàn dòng output sẽ nằm lại trong context, và các lượt đối thoại sau sẽ chậm đi và kém thông minh.

Cách đúng là giao việc đó cho subagent: subagent chạy trong một context độc lập, xong chỉ mang kết luận về hội thoại chính. Trong command chỉ cần chỉ thị rõ:

---
description: Điều tra sâu mọi cách dùng của một symbol
allowed-tools: Task
---

Dùng subagent Explore điều tra sâu mọi cách dùng của symbol sau: $ARGUMENTS

Yêu cầu subagent bao quát:
- Tất cả call site (kể cả file test)
- Các tình huống nghiệp vụ đã được chạm tới
- Có cách triển khai thay thế tương đương hay không

Sau khi subagent trả kết quả, chỉ đưa lại cho tôi bản tóm tắt ≤300 từ, đừng dán đoạn code gốc.

Kích hoạt /trace SomeClass#some_method, Claude Code sẽ dựng một subagent Explore quét codebase song song, còn hội thoại chính chỉ nhận được kết luận đã được chắt lọc. Không có output grep, không có đoạn file, context sạch sẽ.

Cách chơi cao hơn:

---
description: Điều tra song song ba phương án ứng cử
allowed-tools: Task
---

Dựng đồng thời 3 subagent, lần lượt điều tra ba hướng triển khai sau:

1. Dùng ActiveJob + Sidekiq sẵn có
2. Dùng Solid Queue
3. Tự xây queue nhẹ

Mỗi agent trả lời: khối lượng công việc, rủi ro, mức độ xâm lấn vào code hiện có. Khi cả ba kết luận về, tôi sẽ tự so sánh.

Ba subagent chạy song song, hội thoại chính chỉ chờ một lượt kết quả. Đây là một trong những đòn bẩy lớn nhất mà command mang lại — biến những tác vụ nghiên cứu "tốn rất nhiều token mới rút ra được kết luận" thành một workflow chỉ cần một cú chạm.


Gọi công cụ MCP: cho command chạm tới hệ thống ngoài

Nếu session đã kết nối đến MCP server (Linear, GitHub, Sentry, proxy database tự xây, v.v.), command có thể chỉ thị cho model gọi thẳng các tool đó:

---
description: Sinh todo triển khai từ Linear issue
allowed-tools: mcp__linear__*, Read, Grep
---

Đọc toàn bộ mô tả và comment của Linear issue $ARGUMENTS.

Kết hợp với hiện trạng codebase (tự dùng Grep/Read tìm các file liên quan), lập một danh sách todo triển khai:
- Cần sửa những file nào
- Mỗi bước commit riêng hay gộp chung
- Có điểm mơ hồ nào cần confirm với PM trước không

Đừng bắt đầu viết code, chỉ ra kế hoạch.

mcp__linear__* cấp quyền cho mọi tool Linear MCP, model có thể kéo chi tiết issue, comment, trạng thái. Cả command trở thành điểm khởi động cho workflow "từ ticket tới kế hoạch triển khai".

Điểm mấu chốt: khi ghi tên tool MCP trong allowed-tools phải dùng tiền tố đầy đủ (mcp__<server>__<tool>), nếu không quyền sẽ không có hiệu lực.


Cái bẫy khi compose command: slash không mở rộng đệ quy

Một ngộ nhận rất phổ biến: viết /test trong file của /review và nghĩ rằng sẽ kích hoạt command test. Không đâu. Slash command chỉ được mở rộng một lần ở tầng input cấp cao nhất của người dùng; /xxx bên trong một command chỉ là text thường — model đọc được nó, nhưng Claude Code sẽ không đi thực thi.

Muốn compose nhiều command, có vài cách đúng:

Cách A: Tách logic dùng chung ra file context, các command dùng @ hoặc !cat để tham chiếu

@.claude/context/review-checklist.md
@.claude/context/security-checklist.md

Cách B: Trong command ghi rõ "làm giống như /review" + lặp lại các chỉ thị then chốt

Không thanh lịch nhưng hiệu quả. Chỉ cần prompt đủ rõ, model sẽ đi theo cùng một lối.

Cách C: Một command dùng tool Task để dựng subagent, prompt của subagent lại dùng lại chính bộ file context đó

Điều phối workflow thực sự đều đi theo con đường này. Command cha chịu trách nhiệm điều phối và tổng hợp, subagent chịu trách nhiệm thực thi các bước cụ thể.

Anti-pattern cần tránh: viết command dài hàng trăm dòng, cố gắng dùng một chỉ thị làm xong mọi thứ. Một khi độ mịn vỡ ra, chi phí bảo trì sẽ tăng vọt, và một command cũng sẽ ngốn hết budget token của một lượt chạy.


Thời điểm dùng bộ ba

Đến đây, các cơ chế để tiêm "năng lực bên ngoài" vào command của Claude Code về cơ bản đã đủ. Chọn thế nào:

Nhu cầu Cơ chế ưu tiên
Quy chuẩn, template, tài liệu context cố định Tham chiếu @file
Trạng thái thời gian thực (diff, log, kết quả test, query DB) Tiêm !shell
Nội dung file có tham số !cat $ARGUMENTS
Nghiên cứu ngốn context, tìm kiếm liên file subagent qua Task
Hệ thống ngoài (issue tracker, monitoring, dữ liệu production) Công cụ MCP + allowed-tools
Workflow nhiều bước tuần tự/song song Command cha điều phối subagent

Biên quyền được khai báo rõ qua allowed-tools, nhất là với các command dùng chung trong team — ghi cứng nó được làm gì đáng tin hơn là dựa vào duyệt thủ công mỗi lần.


Một ví dụ gần production

Ráp tất cả lại, hãy xem một command "điều tra hướng triển khai dựa trên Linear ticket":

---
description: Tạo phương án triển khai dựa trên Linear ticket
allowed-tools: mcp__linear__*, Task, Read, Grep, Glob, Bash(git log:*)
---

## Context

@.claude/context/architecture.md
@.claude/context/coding-standards.md

## Hiện trạng codebase

!`git log --oneline -10`

## Nhiệm vụ

Kéo mô tả, comment và các ticket liên quan của Linear ticket $ARGUMENTS.

Sau đó dựng hai subagent chạy song song:
1. Cái thứ nhất: tìm trong codebase mọi implementation liên quan hiện có, các module có thể tái sử dụng
2. Cái thứ hai: đánh giá rủi ro — thay đổi lần này sẽ chạm vào những đường code lưu lượng cao nào, có khoảng hở về test coverage không

Sau khi cả hai agent trả kết quả, xuất ra:
- Các bước triển khai (sắp theo thứ tự phụ thuộc)
- Danh sách rủi ro
- Khuyến nghị độ mịn commit

Đừng bắt đầu viết code.

Kích hoạt /plan ENG-4213, một chỉ thị chạy xong tất cả: kéo ticket → điều tra codebase song song → đánh giá rủi ro → tổng hợp phương án. Người dùng chỉ cần đọc kết luận rồi quyết định bắt tay vào làm.


Đây chính là vòng cung trọn vẹn của ba bài đầu trong loạt slash command: định nghĩa prompt tái sử dụng (intro) → tiêm context động (context) → điều phối công cụ và subagent (bài này). Đến tầng này, .claude/commands/ không còn là phím tắt nữa, mà là thư viện workflow nhỏ của cả team.