| name | writing-great-skills |
| description | อ้างอิงสำหรับการเขียนและแก้ไข skill ให้ดี — คำศัพท์และหลักการที่ทำให้ skill ทำงานได้อย่างคาดเดาได้ |
| disable-model-invocation | true |
skill มีไว้เพื่อรีดความ deterministic ออกจากระบบที่ทำงานแบบ stochastic (สุ่มโดยธรรมชาติ) Predictability — การที่ agent เดิน_กระบวนการ_เดิมทุกครั้งที่รัน ไม่ใช่การผลิต output เหมือนเดิม — คือคุณสมบัติรากฐาน กลไกทุกตัวด้านล่างมีไว้รับใช้สิ่งนี้
คำตัวหนา มีนิยามอยู่ใน GLOSSARY.md เปิดดูที่นั่นเพื่อความหมายฉบับเต็ม
Invocation
มีให้เลือกสองแบบ แลกกันคนละต้นทุน:
- skill แบบ model-invoked ยังเก็บ description ไว้ ทำให้ agent เรียกมันเองได้ และ skill อื่นก็เข้าถึงมันได้ (คุณยังพิมพ์ชื่อเรียกเองได้เหมือนเดิม) แต่มันเพิ่ม context load — description นั่งอยู่ใน context window ทุก turn กลไก: ไม่ต้องใส่
disable-model-invocation และเขียน description ให้ model อ่าน พร้อม trigger phrase ที่ครอบคลุม ("Use when the user wants…, mentions…")
- skill แบบ user-invoked ตัด description ออกจากการรับรู้ของ agent: มีแค่คุณที่พิมพ์ชื่อมันเท่านั้นที่ invoke ได้ — และ skill อื่นก็เรียกไม่ได้ context load เป็นศูนย์ แต่จ่ายเป็น cognitive load แทน: คุณ คือ index ที่ต้องจำเองว่ามันมีอยู่ กลไก: ตั้ง
disable-model-invocation: true แล้ว description จะกลายเป็นข้อความสำหรับคนอ่าน — สรุปหนึ่งบรรทัด ตัด trigger list ทิ้ง
เลือก model-invocation ก็ต่อเมื่อ agent ต้องเข้าถึง skill นั้นได้ด้วยตัวเอง หรือ skill อื่นต้องเรียกมัน ถ้ามันถูกเรียกด้วยมือเท่านั้น ให้ทำเป็น user-invoked แล้วไม่ต้องจ่าย context load เลย
เมื่อ user-invoked skill เพิ่มจำนวนจนเกินกว่าจะจำไหว cognitive load ที่กองสะสมนั้นแก้ได้ด้วย router skill: skill แบบ user-invoked ตัวเดียวที่บอกชื่อ skill ตัวอื่น และบอกว่าเมื่อไหร่ควรหยิบตัวไหน
การเขียน description
description แบบ model-invoked ทำงานสองอย่าง — บอกว่า skill นี้คืออะไร และไล่รายการ branch ที่ควร trigger มัน ทุกคำที่เพิ่มเข้าไปเพิ่ม context load ดังนั้น description ต้องถูก prune หนักยิ่งกว่าตัว body เสียอีก:
- เอา leading word ของ skill ขึ้นหน้าสุด — description คือที่ที่มันทำหน้าที่ด้าน invocation
- หนึ่ง trigger ต่อหนึ่ง branch synonym ที่แค่เรียก branch เดียวกันด้วยชื่อใหม่คือ duplication — "build features using TDD … asks for test-first development" คือ branch เดียวที่ถูกเขียนสองรอบ ยุบให้เหลืออันเดียว เก็บไว้เฉพาะ branch ที่ต่างกันจริง
- ตัด identity ที่มีอยู่ใน body แล้วทิ้งไป ให้ description เหลือแค่ trigger บวกประโยค reach แบบ "when another skill needs…" ถ้าจำเป็น
Information hierarchy
skill ประกอบจากเนื้อหาสองชนิด — step และ reference — ที่ผสมกันได้อิสระ: skill หนึ่งอาจเป็น step ล้วน reference ล้วน หรือทั้งคู่ การตัดสินใจหลักคือจะใช้ชนิดไหน และแต่ละชิ้นควรอยู่ตรงไหนบน information hierarchy — บันไดที่จัดอันดับตามว่า agent ต้องใช้เนื้อหานั้นเร่งด่วนแค่ไหน:
- In-skill step — action ที่เรียงลำดับใน
SKILL.md เป็นชั้นหลัก: สิ่งที่ agent ทำ ตามลำดับ แต่ละ step จบด้วย completion criterion เงื่อนไขที่บอก agent ว่างานเสร็จแล้ว ทำให้มัน_เช็คได้_ (agent แยกออกไหมว่าเสร็จหรือยังไม่เสร็จ?) และในจุดที่สำคัญ ให้มัน_ครอบคลุมถ้วนทั่ว_ ("ทุก model ที่ถูกแก้ต้องถูกไล่ครบ" ไม่ใช่ "ทำรายการการเปลี่ยนแปลงออกมา") — criterion ที่คลุมเครือเชื้อเชิญ premature completion
- In-skill reference — นิยาม กฎ หรือข้อเท็จจริงใน
SKILL.md ที่เปิดดูเมื่อต้องใช้ บ่อยครั้งเป็นชุดเนื้อหาระนาบเดียวที่เท่ากันโดยชอบธรรม (กฎทุกข้อของ review อยู่บนขั้นเดียวกัน) — เป็นการจัดวางที่ดี ไม่ใช่กลิ่นไม่ดี skill นี้ทั้งไฟล์คือ reference
- External reference — reference ที่ถูกดันออกจาก
SKILL.md ไปอยู่ไฟล์แยก เข้าถึงผ่าน context pointer และโหลดเฉพาะตอนที่ pointer ทำงาน (ครอบคลุมตั้งแต่ reference แบบ disclosed — ไฟล์พี่น้องอย่าง GLOSSARY.md ที่ยังเป็นส่วนหนึ่งของ skill — ไปจนถึง external reference เต็มตัวที่อยู่นอกระบบ skill และ skill ไหนก็ชี้ถึงได้)
completion criterion ที่เข้มงวดผลักดันให้เกิด legwork ที่ทั่วถึง — การขุดคุ้ยที่ agent ทำระหว่างงาน — ไม่ว่า skill จะมี step หรือไม่ เพราะ "ทุกกฎถูกใช้ครบ" ผูกมัด reference ระนาบเดียวแบบเดียวกับที่ "ทุก step ทำครบ" ผูกมัด sequence
ดันลงไปน้อยเกิน ชั้นบนก็บวม ดันลงมากเกิน ก็ซ่อนเนื้อหาที่ agent ต้องใช้จริง ความตึงนี้แหละคือทั้งหมดของการตัดสินใจ
Progressive disclosure คือการเลื่อนลงบันได — ออกจาก SKILL.md ไปยังไฟล์ที่ link ไว้ — เพื่อให้ชั้นบนยังอ่านง่าย กลไก: ไฟล์ .md ที่ link ไว้ในโฟลเดอร์ของ skill ตั้งชื่อตามสิ่งที่มันเก็บ (skill นี้ disclose นิยามฉบับเต็มของตัวเองไปไว้ที่ GLOSSARY.md) skill บางตัวถูกใช้มากกว่าหนึ่งแบบ และแต่ละแบบที่ต่างกันคือหนึ่ง branch — การรันคนละครั้งเดินคนละเส้นทางผ่าน skill branching คือ disclosure test ที่สะอาดที่สุด: inline สิ่งที่ทุก branch ต้องใช้ และดันสิ่งที่มีแค่บาง branch เข้าถึงไปไว้หลัง pointer สิ่งที่ตัดสินว่า agent จะไปถึงเนื้อหาเมื่อไหร่และแม่นแค่ไหนคือ_ถ้อยคำ_ของ context pointer ไม่ใช่เป้าหมายของมัน
ขณะที่บันไดตัดสินว่าเนื้อหาชิ้นหนึ่งควรอยู่_ลึกลงไปแค่ไหน_ co-location ตัดสินว่า_อะไรควรอยู่ข้างมัน_เมื่อไปถึงตรงนั้นแล้ว: เก็บนิยาม กฎ และข้อควรระวังของ concept หนึ่งไว้ใต้ heading เดียวกัน ไม่ใช่กระจัดกระจาย เพื่อให้การอ่านส่วนหนึ่งพาเพื่อนบ้านของมันมาด้วย
เมื่อไหร่ควร split
Granularity คือความละเอียดในการแบ่ง skill และการตัดแต่ละครั้งจ่ายด้วย load หนึ่งในสองแบบ ดังนั้น split เฉพาะเมื่อการตัดนั้นคุ้ม การตัดมีสองแบบ:
- ตัดตาม invocation — แยก skill แบบ model-invoked ออกมาเมื่อคุณมี leading word ที่ชัดเจนพอจะ trigger มันได้ด้วยตัวเอง หรือเมื่อ skill อื่นต้องเรียกมัน คุณจ่าย context load ให้ description ตัวใหม่ที่ถูกโหลดตลอดเวลา ดังนั้นการเข้าถึงแบบอิสระนั้นต้องคุ้มค่าจริง
- ตัดตาม sequence — แยกช่วงของ step เมื่อ step ที่รออยู่ข้างหน้า (post-completion steps ของ step หนึ่ง) ล่อให้ agent รีบปิด step ตรงหน้า (premature completion) การเก็บพวกมันให้พ้นสายตากระตุ้นให้ agent ทำ legwork กับงานตรงหน้ามากขึ้น
Pruning
เก็บแต่ละความหมายไว้ใน single source of truth: ที่ทางการที่เดียว เพื่อให้การเปลี่ยนพฤติกรรมเป็นการแก้ที่เดียวจบ
เช็คทุกบรรทัดเรื่อง relevance: มันยังเกี่ยวกับสิ่งที่ skill ทำอยู่ไหม?
จากนั้นล่า no-op ทีละประโยค ไม่ใช่แค่ทีละบรรทัด: รัน no-op test กับแต่ละประโยคแบบแยกเดี่ยว และเมื่อประโยคไหนสอบตก ให้ลบทั้งประโยคแทนที่จะเล็มคำออกจากมัน จงดุดัน — prose ส่วนใหญ่ที่สอบตกควรถูกลบทิ้ง ไม่ใช่ถูกเขียนใหม่
Leading words
leading word คือ concept อัดแน่นที่มีอยู่ใน pretraining ของ model อยู่แล้ว ซึ่ง agent ใช้คิดตามระหว่างรัน skill (เช่น lesson, fog of war, tracer bullets) เมื่อถูกใช้ซ้ำทั่วทั้งข้อความ (แม้ไม่จำเป็นเสมอไป — leading word ที่แรงพออาจต้องใช้แค่ครั้งเดียว) มันสะสมนิยามแบบกระจายและตรึงพฤติกรรมทั้งย่านไว้ด้วย token น้อยที่สุด โดยดึง prior ที่ model ถืออยู่แล้วมาใช้งาน
มันรับใช้ predictability สองต่อ ใน body มันตรึง_การ execute_: agent หยิบพฤติกรรมเดิมทุกครั้งที่คำนั้นโผล่มา ใน description มันตรึง_การ invoke_: เมื่อคำเดียวกันอยู่ทั้งใน prompt เอกสาร และ code ของคุณ agent จะโยงภาษาที่ใช้ร่วมกันนั้นเข้ากับ skill และเรียกมันได้แม่นยำขึ้น
ล่าโอกาส refactor skill ให้ใช้ leading word อยู่เสมอ ชุดคุณสมบัติสามคำที่ถูกสะกดออกมาสามจุด (duplication) description ที่เปลืองทั้งประโยคเพื่อชี้ๆ ไปที่ idea เดียว — แต่ละอันคือข้อความที่ร้องขอให้ถูก collapse เป็น token เดียว ตัวอย่างเช่น:
- "fast, deterministic, low-overhead" -> tight — คุณสมบัติเดียวที่ถูกพูดซ้ำตลอดทั้ง phase — ยุบเป็นคำ pretrained คำเดียว (loop ที่ tight)
- "a loop you believe in" -> red — เปลี่ยน gate ที่คลุมเครือให้เป็น state ที่สังเกตได้แบบ binary (loop จะ red กับ bug นั้น หรือไม่ก็ไม่ red)
คุณชนะสองต่อ: token น้อยลง และ ได้ hook ที่คมขึ้นให้ agent แขวนความคิด ให้ตั้งข้อสันนิษฐานว่าทุก skill กำลังแบกการพูดซ้ำที่ leading word ปลดระวางได้ — ไปหามันให้เจอ
Failure modes
ใช้รายการนี้วินิจฉัยปัญหาที่ user อาจเจอกับ skill
- Premature completion — จบ step ก่อนที่มันจะเสร็จจริง ความสนใจไถลไปอยู่ที่_การได้เสร็จ_ วิธีป้องกันตามลำดับ: ลับ completion criterion ให้คมก่อน (ถูกและแก้เฉพาะจุด); เฉพาะเมื่อมันคลุมเครือจนลดทอนไม่ได้แล้ว และ คุณเห็นอาการรีบจริง ค่อยซ่อน post-completion steps ด้วยการ split (การตัดตาม sequence)
- Duplication — ความหมายเดียวกันอยู่มากกว่าหนึ่งที่ เปลืองทั้ง maintenance และ token และดันความเด่นของความหมายนั้นบนบันไดให้สูงเกินอันดับจริง
- Sediment — ชั้นตะกอนเก่าที่ทับถมเพราะการเพิ่มรู้สึกปลอดภัยแต่การลบรู้สึกเสี่ยง ชะตากรรม default ของ skill ที่ไม่มีวินัยการ prune
- Sprawl — skill ที่ยาวเกินไปเฉยๆ แม้ทุกบรรทัดจะยังสดและไม่ซ้ำกัน ทำร้ายทั้งความอ่านง่าย ความ maintain ง่าย และเปลือง token ทางแก้คือบันได: disclose reference ไปไว้หลัง pointer และ split ตาม branch หรือ sequence เพื่อให้แต่ละเส้นทางแบกเฉพาะสิ่งที่ตัวเองต้องใช้
- No-op — บรรทัดที่ model ทำตามอยู่แล้วโดย default คุณจึงจ่าย load เพื่อพูดสิ่งที่ไม่เปลี่ยนอะไรเลย วิธีทดสอบ: มันเปลี่ยนพฤติกรรมเทียบกับ default ไหม? leading word ที่อ่อน (be thorough ทั้งที่ agent ก็ค่อนข้าง thorough อยู่แล้ว) คือ no-op ทางแก้คือคำที่แรงกว่า (relentless) ไม่ใช่เปลี่ยนไปใช้เทคนิคอื่น
- Negation — การบังคับทิศทางด้วยข้อห้ามให้ผลย้อนศร: don't think of an elephant เอ่ยชื่อช้างและทำให้มันเด่นขึ้นในหัว ไม่ใช่จางลง จง prompt ด้านบวก — ระบุพฤติกรรมเป้าหมายเพื่อไม่ต้องเอ่ยถึงพฤติกรรมต้องห้ามเลย เก็บข้อห้ามไว้เฉพาะกรณี guardrail แข็งๆ ที่เขียนเป็นบวกไม่ได้จริงๆ และถึงตอนนั้นก็ต้องจับคู่กับสิ่งที่ให้ทำแทนเสมอ