TL;DR: Tạo được subagent chỉ là “chạy được”. Viết chuẩn production cần 8 kỷ luật: pin
modeltheo vai, chặnmaxTurns, least-privilegetools, một trách nhiệm hẹp, output có cấu trúc, ghi findings ra file, body gọn, và fence dữ liệu web. Cuối bài có checklist copy-paste.
Quick Decision: Đã tạo được subagent? Bài này để viết cho chuẩn. Mới bắt đầu, chưa gõ /agents lần nào, hãy đọc Sub-agents là gì trước rồi quay lại.
Mình từng để một subagent review code mà quên gỡ Write khỏi tools. Nó đọc file, thấy một bug nhỏ, rồi tự sửa luôn file đang đọc. Không ai bảo nó sửa. Report trả về vẫn “đã review, không có vấn đề lớn”, còn diff thì âm thầm thay đổi. Mình mất 20 phút mới hiểu vì sao một agent “chỉ đọc” lại làm bẩn working tree.
Đó là khoảng cách giữa subagent “chạy được” và subagent “viết chuẩn”. Một subagent là một AI assistant con, có context window riêng, system prompt riêng, và bộ tool riêng, được Claude Code spawn ra để làm một việc hẹp rồi trả kết quả về. Tạo nó thì dễ. Viết nó để không tự bắn vào chân mình mới là phần khó.
Skip bài này nếu: bạn chưa từng gõ /agents tạo một subagent nào. Đọc bài prerequisite ở trên trước.
Đọc tiếp nếu: bạn đã có vài subagent đang chạy nhưng chúng ẩu (quên giới hạn tool, body phình, output rác).
Subagent “chạy được” khác “viết chuẩn” ở đâu?
Một subagent “chạy được” là file Markdown có name và description, gọi lên thì Claude Code nạp được, làm xong việc. Theo docs Anthropic, chỉ name và description là hai field bắt buộc (code.claude.com/docs/en/sub-agents, truy cập 25/06/2026). Hết. Phần còn lại đều có default. Nên ngưỡng “chạy được” rất thấp, ai cũng vượt qua trong 2 phút.
Subagent “viết chuẩn” thì khác về bản chất. Nó tôn trọng ranh giới quyền hạn: reviewer không có Write. Nó có trần để không loop vô tận. Output của nó có cấu trúc, máy đọc được, không phải một khối văn xuôi tràn về context cha. Và nó khai báo rõ mình KHÔNG làm gì, để không giẫm chân agent khác.
Khoảng cách này không hiện ra ở demo. Demo nào cũng chạy đẹp. Nó hiện ra ở lần thứ 50, khi agent gặp input lạ, khi context đầy, khi nó được spawn song song với 3 agent khác. Lúc đó “chạy được” sẽ làm bẩn repo, còn “viết chuẩn” thì dừng đúng chỗ. Tám nguyên tắc dưới đây là cách thu hẹp khoảng cách đó.

Anatomy của một frontmatter subagent chuẩn
Frontmatter là khối YAML đầu file, nằm giữa hai dấu ---, quy định hành vi của subagent. Theo docs, đây là toàn bộ các field được hỗ trợ và ý nghĩa của chúng (/en/sub-agents, truy cập 25/06/2026).
| Field | Vai trò | Lưu ý |
|---|---|---|
name |
Định danh, lowercase-hyphen, duy nhất | Bắt buộc. Filename không cần trùng |
description |
Claude dùng để tự route việc | Bắt buộc. Đây là tín hiệu auto-delegate |
model |
sonnet, opus, haiku, fable, full-id, hoặc inherit |
Default = inherit (theo phiên cha) |
tools |
Allowlist tool; omit = inherit HẾT | Đây là chỗ dễ sai nhất |
disallowedTools |
Denylist; áp TRƯỚC tools |
Tool có ở cả hai bị gỡ |
maxTurns |
Trần số lượt agentic | Chống loop vô tận |
skills |
Preload kiến thức lúc khởi động | Thay vì nhồi vào body |
effort, background, isolation, color |
Tinh chỉnh runtime + hiển thị | Đều portable |
Còn body, phần văn bản dưới frontmatter, chính là system prompt của riêng subagent đó. Không phải prompt đầy đủ của Claude Code, chỉ là chỉ dẫn cho con agent này. Đây là một ví dụ YAML thật cho một reviewer read-only:
---
name: blog-reviewer
description: >
Quality reviewer cho blog draft. Chấm rubric 5 category
và chặn draft dưới ngưỡng. Use proactively sau mỗi lần
draft hoặc rewrite.
model: sonnet # alias | full-id | inherit (default inherit)
maxTurns: 12 # trần số lượt agentic
tools: Read, Grep, Glob # allowlist; omit = inherit HẾT
# disallowedTools: Write, Edit # denylist, áp trước tools
# skills: source-tiers # preload thay vì nhồi body
---
Body = system prompt của riêng agent này (KHÔNG phải prompt
đầy đủ của Claude Code). Một việc hẹp, một output có cấu trúc.
8 nguyên tắc viết subagent production-grade
Tám nguyên tắc này là phần lõi của bài. Mỗi cái mình ghi theo cấu trúc: quy tắc, tại sao, rồi ví dụ ngắn.

N1: Pin model theo vai trò
Default của model là inherit, tức là subagent chạy cùng model với phiên cha (/en/sub-agents, truy cập 25/06/2026). Nhưng để mặc định không phải lúc nào cũng đúng. Docs Anthropic ghi rõ một lợi ích của subagent là kiểm soát chi phí bằng cách route việc sang model nhanh và rẻ hơn như Haiku (/en/best-practices, truy cập 25/06/2026).
Theo mình, cách chia đơn giản: việc cơ học, đọc nhiều, ít phán xét (researcher, translator, validator) thì để haiku hoặc sonnet, vừa nhanh vừa rẻ. Việc cần phán xét cao (writer, reviewer, adversary) thì để inherit, thường là Opus. Một subagent dịch 50 file mà chạy Opus là phí, cả thời gian lẫn chi phí.
N2: Chặn maxTurns
maxTurns đặt trần số lượt agentic mà subagent được phép chạy. Không có trần, một agent gặp input lạ có thể loop: thử, fail, thử lại, fail, mãi mãi, đốt token và treo cả pipeline. Mình đặt agent hẹp ở 8 đến 12 lượt, agent đa nguồn (đọc nhiều file, nhiều lần search) ở khoảng 20. Con số không thiêng, quan trọng là CÓ trần.
N3: Least-privilege tools
Đây là nguyên tắc mình đào sâu nhất, vì nó là cái mình từng sai. Quy tắc: bắt đầu từ ZERO tool rồi thêm dần, đừng để omit. Vì khi bạn omit field tools, subagent inherit TOÀN BỘ tool của phiên cha (/en/sub-agents, truy cập 25/06/2026). Một reviewer đáng lẽ chỉ đọc bỗng có cả Write, Edit, Bash.
Reviewer và validator KHÔNG được có Write hay Edit. Đây chính là câu chuyện đầu bài: mình quên gỡ Write khỏi reviewer, nó tự fix file đang đọc, report vẫn báo sạch. Với Bash, hãy scope hẹp: Bash(npm test) thay vì full Bash. Cẩn thận MCP wildcard. Và đừng cấp tool Agent trừ khi subagent đó thực sự được phép spawn agent khác. disallowedTools áp trước tools, nên nếu lỡ inherit rộng, bạn có thể dùng denylist để chốt chặn.

tools kéo theo toàn bộ quyền của phiên cha. Khai báo allowlist để giữ subagent đúng vai.N4: Một trách nhiệm hẹp
Một subagent nên làm đúng một việc. “Review chất lượng draft” là một việc. “Review draft, sửa lỗi, rồi publish” là ba việc nhồi vào một, và agent đa-nhiệm là agent khó debug. Kèm theo, mình luôn thêm một khối “không làm gì” vào body: ví dụ “việc dịch thuật, để agent /translate; KHÔNG tự dịch ở đây”. Khối này chống chồng lấn khi nhiều agent cùng chạy.
N5: Output discipline
Report của subagent phải có cấu trúc, không phải văn xuôi. Mình thường yêu cầu: điểm theo từng category, mức severity (Critical đến Low), và một trailer máy đọc được như BLOCKING: true hoặc BLOCKING: false (lý do). Quan trọng hơn: tách tín hiệu deterministic (đếm số, đo độ dài, thứ tái lập được) khỏi tín hiệu LLM-judge (đánh giá độ sâu, độ cuốn, vốn có nhiễu ±). Tín hiệu LLM-judge để advisory, đừng bao giờ làm hard gate, vì chạy lại hai lần ra hai số khác nhau.
N6: Persistence thay vì return
Subagent sinh ra để xử lý việc phụ mà output dài, nếu trả thẳng về sẽ làm ngập context cha. Nguyên tắc của mình: agent output dài (ví dụ một bản draft 2000 từ) thì GHI ra file findings/<tên>.md hoặc .json, rồi chỉ return một dòng tóm tắt với đường dẫn. Agent judge nhỏ thì để read-only, trả về một scorecard gọn.
Lý do kỹ thuật: subagent chạy trong context riêng (fork). Nếu bạn để nguyên một draft khổng lồ chảy ngược qua main, bạn vừa giết cái lợi context-isolation, vừa đốt token cha. Truyền đường dẫn, để các leaf tự đọc từ disk.
N7: Body gọn, preload thay vì inline
System prompt của subagent nên tập trung vào một việc, đừng nhồi vào đó những bảng quy tắc dài (danh sách nguồn, danh sách cụm từ cấm). Những bảng dùng chung nên đẩy vào một skill rồi preload qua field skills:. Lý do: nhồi inline làm prompt phình, và khi bạn cập nhật quy tắc ở một chỗ thì các agent khác bị drift vì còn giữ bản cũ. Một nguồn sự thật, preload, không copy.
N8: Bảo mật agent web-facing
Bất kỳ subagent nào có WebFetch hoặc WebSearch đều phải coi nội dung tải về là DATA, không phải lệnh. Một trang web có thể chứa câu “ignore previous instructions” để chiếm quyền agent của bạn (prompt injection). Cách phòng: fence nội dung ngoài lại (ví dụ EXTERNAL CONTENT (untrusted) … END EXTERNAL CONTENT), strip các pattern kiểu “ignore previous” hay “system:” trước khi return, và cite nguồn chứ đừng dán nguyên khối về.
Tại sao description quyết định subagent có được gọi hay không?
description không phải phần mô tả cho đẹp. Đó là tín hiệu Claude dùng để TỰ route việc cho subagent (/en/sub-agents, truy cập 25/06/2026). Description mơ hồ thì agent của bạn có thể không bao giờ được gọi tự động, dù nó viết chuẩn đến đâu.
Công thức mình dùng có bốn phần: Vai trò, cộng chuyên môn cụ thể, cộng when-to-use, cộng một action cue. Action cue là cụm như “Use proactively” hay “Use immediately after X”, chính docs khuyên đưa cụm “use proactively” vào description để Claude chủ động gọi. Ví dụ: “Quality reviewer cho blog draft. Chấm rubric 5 category và chặn draft dưới ngưỡng. Use proactively sau mỗi lần draft hoặc rewrite.” Bạn vẫn luôn force chạy được bằng cách gọi tên agent hoặc @-mention nó.
Portability: subagent ship ra hai đường khác nhau thế nào?
Một subagent có thể đến tay người dùng theo hai đường, và hai đường này KHÔNG bình đẳng về field. Đường thứ nhất: cài trực tiếp vào ~/.claude/agents/ (user scope), toàn bộ frontmatter hoạt động. Đường thứ hai: đóng gói qua plugin marketplace. Còn một chỗ thứ ba hay quên: project scope, tức thư mục .claude/agents/ commit thẳng vào git để chia cho cả team. Khi trùng tên, Claude Code ưu tiên theo thứ tự managed, rồi --agents CLI, rồi project .claude/agents/, rồi user ~/.claude/agents/, cuối cùng mới tới plugin.
Điểm chí mạng: plugin subagent BỎ QUA ba field là hooks, mcpServers, và permissionMode (/en/sub-agents, truy cập 25/06/2026). Lưu ý memory KHÔNG nằm trong danh sách bị bỏ qua, nó vẫn portable. Hệ quả thực tế: đừng enforce một invariant (ví dụ giới hạn write-scope) bằng hooks, vì khi ai đó cài agent của bạn qua plugin, hook thành no-op và invariant biến mất âm thầm. Chỉ dựa vào subset portable: name, description, tools, disallowedTools, model, maxTurns, skills, effort, background, isolation, color.
Nesting và flat-dispatch: subagent có nên spawn subagent?
Subagent CÓ thể spawn subagent. Từ Claude Code v2.1.172, một subagent có thể spawn subagent con của nó, độ sâu tối đa là 5, và một subagent ở độ sâu 5 không nhận tool Agent nên không spawn tiếp được (/en/sub-agents, truy cập 25/06/2026). Giới hạn này cố định, không cấu hình được. Một fork cũng không spawn được fork khác.
Nhưng “làm được” không có nghĩa là “nên làm”. Theo mình, với phần lớn trường hợp, hãy chọn flat dispatch: main thread là dispatcher duy nhất, các subagent là leaf, không tự gọi nhau. Lý do là khả năng đọc hiểu (legibility). Khi agent này gọi agent kia gọi agent kia nữa, bạn rất khó lần ra ai đã làm gì lúc nào. Để enforce flat dispatch, đơn giản là omit tool Agent khỏi mọi subagent.

3 hiểu lầm về subagent cần bỏ
Có vài niềm tin sai về subagent lan truyền trong cộng đồng. Mình verify ba cái phổ biến nhất với docs Anthropic (truy cập 25/06/2026), kèm verdict.
| Hiểu lầm | Sự thật theo docs |
|---|---|
| “Subagent không thấy được CLAUDE.md” | SAI. Subagent nạp đầy đủ memory hierarchy. Chỉ hai agent built-in Explore và Plan mới bỏ qua CLAUDE.md. |
| “Subagent không nest, không resume được” | SAI. Nest được từ v2.1.172, depth ≤5; resume qua SendMessage với agent ID (trừ Explore/Plan vốn one-shot). |
| “Chuyện subagent rẻ hơn là hoang đường” | Không hẳn. Docs coi route việc sang model rẻ như Haiku là một cách control cost. Còn việc bạn có gói flat-rate hay không thì tùy gói, đó là ý kiến chứ không phải claim của docs. |
Pre-ship checklist cho subagent
Đây là checklist mình chạy qua trước khi ship bất kỳ subagent nào. Copy-paste và tick từng dòng.

[ ] name + description rõ, action-oriented ("Use proactively")
[ ] model set theo vai trò; maxTurns có trần
[ ] tools least-privilege; read-only judge KHÔNG có Write/Edit; KHÔNG có Agent
[ ] một trách nhiệm hẹp + khối "không làm gì" (Cross-Skill Delegation)
[ ] output có cấu trúc; tách deterministic khỏi LLM-judge; có trailer máy đọc
[ ] output dài ghi ra findings/; output nhỏ read-only + return gọn
[ ] KHÔNG trả full draft về main; truyền đường dẫn thay thế
[ ] body gọn; bảng dùng chung preload qua skills:, không inline
[ ] agent web-facing có fence dữ liệu untrusted
[ ] chỉ dựa vào frontmatter field portable (không enforce bằng hooks)
[ ] chạy validate plugin trước khi ship
Những sai lầm hay mắc khi viết subagent
Năm anti-pattern dưới đây mình gặp nhiều nhất, gồm cả ở chính code của mình.
- Omit
toolsđể cho nhanh. Hậu quả: subagent inherit hết tool, kể cảWrite,Edit,Bash. Reviewer của bạn giờ sửa được file. Luôn khai báo allowlist tối thiểu. - Reviewer có
Write. Đúng cái lỗi của mình. Một agent read-only mà có quyền ghi sẽ tự sửa file rồi báo cáo “sạch”. Read-only judge không bao giờ cóWrite/Edit. descriptionmơ hồ. “Agent xử lý nội dung” thì Claude không biết khi nào gọi. Agent viết chuẩn mà description dở thì coi như chết, không ai gọi.- Nhồi bảng quy tắc vào body. Prompt phình, lại drift khi quy tắc đổi. Preload qua
skills:. - Trả full draft về main. Một bản draft 2000 từ chảy ngược qua context cha vừa đốt token vừa giết context-isolation. Ghi ra
findings/, return đường dẫn.
FAQ
Nên đặt maxTurns bao nhiêu?
Không có con số chuẩn cho mọi agent. Theo cách của mình: agent hẹp một việc (reviewer, validator) đặt 8 đến 12 lượt; agent đa nguồn cần đọc nhiều file, search nhiều lần thì khoảng 20. Nguyên tắc cốt lõi là phải CÓ trần để chống loop vô tận, còn con số cụ thể bạn tinh chỉnh theo độ phức tạp việc.
Có nên cấp tool Agent cho subagent không?
Mặc định là không. Cấp Agent nghĩa là subagent đó được phép spawn subagent khác, mở ra nesting và làm orchestration khó đọc. Theo mình, hầu hết trường hợp nên chọn flat dispatch và omit Agent khỏi mọi subagent. Chỉ cấp khi bạn thực sự thiết kế một agent điều phối có chủ đích.
Subagent có thấy CLAUDE.md không?
Có. Theo docs Anthropic, subagent tùy biến nạp đầy đủ memory hierarchy, bao gồm cả CLAUDE.md (/en/sub-agents, truy cập 25/06/2026). Ngoại lệ duy nhất là hai agent built-in Explore và Plan, chúng bỏ qua CLAUDE.md và git status. Nên đừng giả định subagent của bạn “không biết gì về project”.
Nên pin model nào cho reviewer?
Reviewer là việc phán xét cao, nên mình để inherit (thường là Opus của phiên cha) hoặc pin thẳng opus. Ngược lại, với agent cơ học như researcher hay translator, pin haiku/sonnet để nhanh và rẻ hơn, đúng như docs gợi ý route việc sang model rẻ để control cost (/en/best-practices, truy cập 25/06/2026).
Kết
Tạo subagent là việc 2 phút. Viết nó cho chuẩn production là việc của kỷ luật: model đúng vai, có trần maxTurns, tool least-privilege, một trách nhiệm hẹp, output có cấu trúc, ghi findings ra file, body gọn, và fence dữ liệu web. Cái lỗi reviewer-tự-sửa-file của mình đáng lẽ không xảy ra nếu mình tick qua checklist trước khi ship.
Hãy lưu checklist ở trên lại và chạy qua nó mỗi lần. Khi đã quen viết subagent chuẩn, bước tiếp theo là ghép chúng với Skills để agent vừa có quyền hẹp vừa có kiến thức sâu. Mình viết riêng về cách phối hợp đó ở Skills và Sub-agents. Nếu bạn muốn đóng gói các lệnh hay dùng thành shortcut, xem thêm Slash Commands trong Claude Code.
