Skills และ Subagents
สองวิธีขยาย Claude Code ที่คนสับสนกันบ่อย skill คือความรู้ที่โหลดเข้ามาตอนต้องใช้ subagent คือการแยกงานออกไปทำในบริบทของตัวเอง บทนี้บอกว่าใช้อันไหนเมื่อไร พร้อมช่อง frontmatter ครบทุกตัว
บทที่ 10 | Skills และ Subagents กลุ่มเป้าหมาย: คนที่เขียน CLAUDE.md จนยาวเกินไปแล้ว และเริ่มสงสัยว่าควรแยกของออกไปไว้ที่ไหน
เส้นแบ่งที่ควรจำก่อนอย่างอื่น
Skill คือความรู้หรือขั้นตอนที่โหลดเข้ามาเมื่อถึงเวลาต้องใช้ ส่วน Subagent คือการยกงานไปให้อีกบริบทหนึ่งทำ แล้วส่งผลกลับมา
| Skill | Subagent | |
|---|---|---|
| อยู่ที่ | .claude/skills/ชื่อ/SKILL.md | .claude/agents/ชื่อ.md |
| ช่องบังคับ | ไม่มีช่องไหนบังคับ (แนะนำ description) | name และ description |
| เรียกด้วย | /ชื่อ หรือ Claude เลือกเองจาก description | @ชื่อ หรือ Claude มอบหมายเอง |
| บริบท | อยู่ในบทสนทนาเดิม | แยกออกไป มองไม่เห็นบทสนทนาของคุณ |
| เหมาะกับ | ขั้นตอนที่ทำซ้ำ ความรู้อ้างอิง | งานที่ทำขนานกันได้ งานที่ไม่อยากให้เปลืองบริบทหลัก |
| ย้ายไปใช้ที่อื่นได้ไหม | ได้ ตามสเปก Agent Skills | ไม่ เป็นของ Claude Code เท่านั้น |
เกณฑ์เลือกง่าย ๆ ถ้าอยากให้ Claude รู้ บางอย่าง ใช้ skill ถ้าอยากให้ Claude ไปทำ บางอย่างแล้วกลับมา ใช้ subagent
10.1 Skills
วางไว้ที่ไหน
| ตำแหน่ง | พาธ | ใช้กับ |
|---|---|---|
| Enterprise | ผ่าน managed settings | ทุกคนในองค์กร |
| ส่วนตัว | ~/.claude/skills/<ชื่อ>/SKILL.md | ทุกโปรเจกต์ของคุณ |
| โปรเจกต์ | .claude/skills/<ชื่อ>/SKILL.md | โปรเจกต์นี้เท่านั้น |
| ปลั๊กอิน | <plugin>/skills/<ชื่อ>/SKILL.md | ที่ที่เปิดใช้ปลั๊กอินนั้น |
เมื่อชื่อชนกัน ลำดับคือ Enterprise ชนะ Personal ชนะ Project
ตัวอย่างที่เล็กที่สุดที่ใช้ได้จริง
---
description: ตรวจ PR ตามเช็กลิสต์ของทีม ใช้เมื่อผู้ใช้ขอให้รีวิว PR
argument-hint: [pr-number]
allowed-tools: Read, Grep, Bash(gh pr view *)
---
รีวิว PR หมายเลข $ARGUMENTS ตามลำดับนี้
1. ดูขนาด diff ถ้าเกิน 400 บรรทัดให้บอกก่อนว่าใหญ่เกินรีวิวจริง
2. ตรวจว่า test เขียนจากสเปกหรือจาก implementation
3. ตรวจว่ามีไฟล์นอกขอบเขตถูกแตะไหม
ช่อง frontmatter ทั้งหมด
ไม่มีช่องไหนบังคับ แต่ description เป็นช่องที่ แนะนำ เพราะ Claude ใช้มันตัดสินว่าจะหยิบ skill นี้มาใช้เมื่อไร ถ้าไม่ใส่ ระบบจะใช้ย่อหน้าแรกของเนื้อหาแทน
| ช่อง | ทำอะไร |
|---|---|
name | ชื่อที่แสดงในรายการ ค่าตั้งต้นคือชื่อโฟลเดอร์ |
description | ทำอะไรและควรใช้เมื่อไร ใส่เคสหลักไว้ต้นประโยค เพราะข้อความรวมของ description กับ when_to_use ถูกตัดที่ 1,536 ตัวอักษรในรายการ skill |
when_to_use | บริบทเพิ่มเติมว่าเมื่อไรควรเรียก เช่นวลีที่เป็นตัวกระตุ้น นับรวมในเพดาน 1,536 ตัวอักษรเดียวกัน |
argument-hint | คำใบ้ตอน autocomplete เช่น [issue-number] |
arguments | ชื่อของอาร์กิวเมนต์ตามตำแหน่ง เพื่อใช้ $ชื่อ ในเนื้อหา |
disable-model-invocation | true เพื่อกัน Claude หยิบเอง ให้เรียกได้ด้วย /ชื่อ เท่านั้น |
user-invocable | false เพื่อซ่อนจากเมนู / ให้เฉพาะ Claude เรียกได้ |
allowed-tools | เครื่องมือที่ใช้ได้โดยไม่ต้องขออนุญาต เฉพาะในเทิร์นที่เรียก skill นี้ สิทธิ์หมดเมื่อคุณส่งข้อความถัดไป |
disallowed-tools | เครื่องมือที่ถูกถอดออกจากมือ Claude ระหว่าง skill นี้ทำงาน |
model | โมเดลที่ใช้ระหว่าง skill นี้ทำงาน ใช้ inherit เพื่อคงโมเดลเดิม ไม่ถูกบันทึกลง settings เทิร์นถัดไปกลับเป็นโมเดลเดิม |
effort | ระดับความพยายาม low medium high xhigh max |
context | ใส่ fork เพื่อให้รันใน subagent ที่แยกบริบท |
agent | ชนิดของ subagent เมื่อใช้ context: fork |
background | ใช้ได้เมื่อ context: fork เท่านั้น ใส่ false เพื่อรอผลในเทิร์นเดียวกัน ค่าตั้งต้นคือ true |
hooks | hook ที่ลงทะเบียนตอนเรียก skill และ อยู่ต่อไปตลอด session ที่เหลือ |
paths | glob จำกัดว่าจะให้ skill ทำงานเมื่อแตะไฟล์แบบไหน |
shell | shell สำหรับคำสั่งฝังในเนื้อหา bash (ตั้งต้น) หรือ powershell |
metadata | แผนที่ YAML อิสระสำหรับเครื่องมือของคุณเอง Claude Code ไม่แตะเนื้อหาข้างใน |
license | ไลเซนส์ ตามสเปก Agent Skills Claude Code รับไว้แต่ไม่ทำอะไรกับมัน |
compatibility | ข้อกำหนดด้านสภาพแวดล้อม ยาวได้ไม่เกิน 500 ตัวอักษร |
ถ้าจะเอา skill ไปใช้นอก Claude Code เช่นอัปโหลดขึ้น claude.ai หรือใช้ผ่าน Skills API ใช้ได้แค่หกช่อง คือ
namedescriptionlicensecompatibilitymetadataและallowed-toolsช่องอื่นทำให้แพ็กเกจไม่ผ่าน
ตัวแปรที่แทนค่าได้ในเนื้อหา skill
| ตัวแปร | ได้อะไร |
|---|---|
$ARGUMENTS | อาร์กิวเมนต์ทั้งหมดที่ส่งมา |
$ARGUMENTS[N] / $N | อาร์กิวเมนต์ตามลำดับ นับจาก 0 |
$ชื่อ | อาร์กิวเมนต์ที่ประกาศไว้ในช่อง arguments |
${CLAUDE_SESSION_ID} | รหัส session ปัจจุบัน |
${CLAUDE_EFFORT} | ระดับความพยายามที่ใช้อยู่ |
${CLAUDE_SKILL_DIR} | โฟลเดอร์ที่ SKILL.md อยู่ ใช้อ้างสคริปต์ที่แถมมากับ skill โดยไม่ต้องสนใจ working directory |
${CLAUDE_PROJECT_DIR} | รากโปรเจกต์ ตัวเดียวกับที่ hook ได้รับ |
${CLAUDE_PLUGIN_ROOT} | โฟลเดอร์ติดตั้งของปลั๊กอิน ใช้ได้เฉพาะใน skill ของปลั๊กอิน |
${CLAUDE_PLUGIN_DATA} | โฟลเดอร์ข้อมูลถาวรของปลั๊กอิน อยู่รอดหลังอัปเดต |
ตัวที่มีค่าที่สุดในทางปฏิบัติคือ ${CLAUDE_SKILL_DIR} เพราะทำให้ skill พกสคริปต์มาเองได้
allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *)
วิธีจัดโครงเมื่อ skill เริ่มยาว
my-skill/
├── SKILL.md ← ภาพรวม ควรอยู่ใต้ 500 บรรทัด
├── reference.md ← โหลดเมื่อถูกอ้างถึง
├── examples.md
└── scripts/
└── helper.py ← ถูกรัน ไม่ถูกโหลดเข้าบริบท
หลักคือ ให้ SKILL.md เป็นสารบัญ ไม่ใช่ตำราทั้งเล่ม เนื้อหาละเอียดแยกไฟล์แล้วลิงก์ไป Claude จะไปอ่านเมื่อต้องใช้จริง นี่คือสิ่งที่เรียกว่า progressive disclosure และเป็นเหตุผลว่าทำไม skill ถึงกินบริบทน้อยกว่าการยัดทุกอย่างลง CLAUDE.md
/skill-doctor — หา skill ที่กินที่แต่ไม่มีใครใช้
พิมพ์ /skill-doctor เพื่อดูรายงานว่า skill แต่ละตัวกิน token เท่าไร ถูกเรียกบ่อยแค่ไหน ตัวไหนไม่เคยถูกเรียกเลย ปลั๊กอินไหนไม่ได้ใช้มานาน และควรไปปิดที่ไหน
ใช้เมื่อ session เริ่มช้าลงหรือบริบทเต็มเร็วผิดปกติ
10.2 Subagents
รูปร่างของไฟล์
---
name: code-reviewer
description: รีวิวโค้ดด้านคุณภาพและแนวปฏิบัติที่ดี
tools: Read, Glob, Grep
model: sonnet
---
คุณคือผู้รีวิวโค้ด เมื่อถูกเรียก ให้วิเคราะห์โค้ดแล้วให้ข้อเสนอแนะที่เจาะจง
และลงมือแก้ตามได้จริง ทั้งด้านคุณภาพ ความปลอดภัย และแนวปฏิบัติ
name ต้องเป็นตัวพิมพ์เล็ก ใช้ยัติภังค์ได้ ห้ามมีเครื่องหมายทวิภาค เพราะชื่อนี้ถูกใช้เป็น agent_type ใน hook ด้วย
วางไว้ที่ไหน เรียงตามลำดับความสำคัญ
| ตำแหน่ง | ขอบเขต |
|---|---|
| Managed settings | ทั้งองค์กร (สูงสุด) |
ธง --agents ตอนเปิด | เฉพาะ session นั้น |
.claude/agents/ | โปรเจกต์นี้ commit เข้า repo ได้ |
~/.claude/agents/ | ทุกโปรเจกต์ของคุณ |
agents/ ของปลั๊กอิน | ที่ที่เปิดใช้ปลั๊กอิน (ต่ำสุด) |
เรียกอย่างไร
ใช้ code-reviewer ดูการเปลี่ยนแปลงล่าสุดให้หน่อย
Claude มอบหมายเองจาก description แต่ถ้าอยาก การันตี ว่าถูกเรียกแน่ ให้ @-mention ชื่อ agent ตรง ๆ
ตั้งเป็นค่าตั้งต้นของทั้ง session ก็ได้
claude --agent code-reviewer
บริบทที่ subagent เห็นและไม่เห็น — จุดที่ต้องเข้าใจให้ถูก
นี่คือสาเหตุของความผิดหวังที่พบบ่อยที่สุดเวลาใช้ subagent
สิ่งที่มันได้รับ คือ system prompt ของตัวเอง (ไม่ใช่ของ Claude Code), ข้อความมอบหมายงานที่ Claude สรุปให้, ไฟล์ CLAUDE.md ทุกระดับ, สถานะ git และ skill ที่ preload ไว้
สิ่งที่มันไม่ได้รับ คือ ประวัติบทสนทนาของคุณ รวมถึง output style, auto memory และ skill ที่เคยถูกเรียกไปแล้ว
แปลว่า ถ้าคุณคุยกับ Claude มาสิบรอบแล้วบอกว่า “ให้ subagent ทำต่อ” subagent จะไม่รู้เรื่องสิบรอบนั้นเลย สิ่งที่มันรู้คือสิ่งที่ Claude สรุปส่งไปให้เท่านั้น ถ้าอยากให้มันรู้ ต้องเขียนลงไฟล์
ข้อยกเว้นคือ fork ซึ่งสืบทอดทุกอย่าง ทั้งประวัติบทสนทนา system prompt เครื่องมือ และโมเดล ข้อดีของ fork คือมันทำงานเสร็จแล้วส่งกลับมาแค่ผลลัพธ์ บทสนทนาหลักจึงไม่รก
ช่อง frontmatter ที่ใช้บ่อย
| ช่อง | ทำอะไร |
|---|---|
name (บังคับ) | ตัวระบุ ตัวพิมพ์เล็ก ห้ามมีทวิภาค |
description (บังคับ) | เมื่อไร Claude ควรมอบหมายให้ตัวนี้ |
tools | รายการเครื่องมือที่ใช้ได้ ถ้าไม่ใส่จะสืบทอดทั้งหมด |
disallowedTools | รายการเครื่องมือที่ถูกถอดออก |
model | sonnet opus haiku fable รหัสเต็ม หรือ inherit เพื่อใช้โมเดลของตัวแม่ |
permissionMode | โหมดสิทธิ์ของ agent ตัวนี้ |
maxTurns | จำนวนเทิร์นสูงสุดก่อนหยุด ผลลัพธ์จะถูกทำเครื่องหมายว่าไม่สมบูรณ์ |
skills | skill ที่จะ preload เข้าบริบทของมัน |
hooks | hook ประจำวงจรชีวิตของ agent ตัวนี้ |
isolation | ใส่ worktree เพื่อให้ทำงานใน git worktree แยก |
effort | ระดับความพยายาม |
color | สีที่แสดงในรายการงาน |
การซ้อนและจำนวนที่รันพร้อมกัน
ตามค่าตั้งต้น subagent ซ้อนได้ลึก 3 ชั้นจากบทสนทนาหลัก และ รันพร้อมกันได้สูงสุด 20 ตัว ปรับได้ผ่านตัวแปรแวดล้อม CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH และ CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS
ถ้าไม่อยากให้ agent ตัวหนึ่งเรียก agent ต่อได้ ให้ไม่ใส่ Agent ใน tools
---
name: read-only-agent
tools: Read, Grep, Glob
---
หรือจำกัดว่าให้เรียกได้แค่บางตัว
tools: Agent(worker, researcher), Read, Bash
ลำดับการเลือกโมเดลของ subagent
เลือกจากตัวแรกที่เจอ
- ค่า
modelที่ส่งตอนเรียกครั้งนั้น - ช่อง
modelในนิยามของ subagent - ตัวแปรแวดล้อม
CLAUDE_CODE_SUBAGENT_MODEL - โมเดลของบทสนทนาหลัก
subagent ที่มีมาให้ในตัว
| ชื่อ | เครื่องมือ | ใช้ทำอะไร |
|---|---|---|
| Explore | อ่านอย่างเดียว | ค้นและวิเคราะห์โค้ดเบสอย่างรวดเร็ว |
| Plan | อ่านอย่างเดียว | ค้นคว้าก่อนเข้าโหมดวางแผน |
| General-purpose | ทั้งหมดที่มี | งานหลายขั้นตอนที่ซับซ้อน |
ปิดได้ด้วย deny rule
{ "permissions": { "deny": ["Agent(Explore)", "Agent(Plan)"] } }
10.3 กับดักที่เจอจริง
เขียน description ให้ Claude อ่านออก ไม่ใช่ให้คนอ่านสวย ทั้ง skill และ subagent ถูกเลือกจากช่องนี้ ถ้าเขียนว่า “เครื่องมือช่วยงาน” มันจะไม่ถูกหยิบมาใช้เลย ให้เขียนว่าเมื่อไรควรใช้ ด้วยคำที่ผู้ใช้จะพิมพ์จริง
อย่าคาดหวังให้ subagent รู้เรื่องที่คุยกันมา ถ้างานต้องใช้บริบทที่สะสมมา ให้ใช้ skill แบบ context: fork หรือเขียนบริบทลงไฟล์ก่อน
allowed-tools ของ skill หมดอายุเร็วกว่าที่คิด สิทธิ์นั้นอยู่แค่เทิร์นที่เรียก พอคุณส่งข้อความถัดไปก็หมด
hooks ใน skill ไม่หมดอายุ ต่างจาก allowed-tools ตรงที่ hook ที่ลงทะเบียนตอนเรียก skill อยู่ต่อไปตลอด session ระวังตอนเขียน skill ที่ติดตั้ง hook หนัก ๆ
skill ที่ไม่มีใครใช้ยังกินบริบท เพราะรายการ skill ทั้งหมดถูกส่งเข้าไปให้ Claude เห็น นี่คือเหตุผลที่ /skill-doctor มีอยู่
คำศัพท์ประจำบท
| คำ | ความหมาย |
|---|---|
| Skill | ชุดขั้นตอนหรือความรู้ใน SKILL.md ที่โหลดเข้ามาเมื่อต้องใช้ |
| Subagent | บริบทแยกที่รับงานไปทำแล้วส่งผลกลับ |
| Fork | subagent ที่สืบทอดบริบททั้งหมดของบทสนทนาหลัก |
| Progressive disclosure | การให้ SKILL.md เป็นสารบัญ แล้วโหลดไฟล์ละเอียดเมื่อถึงเวลา |
${CLAUDE_SKILL_DIR} | พาธของโฟลเดอร์ skill ใช้อ้างสคริปต์ที่แถมมาด้วย |