Matt Pocock 是 TypeScript 社群相當知名的教育者 (Total TypeScript),這一年轉做 AI 工程教學。他今年 2 月開的 mattpocock/skills 現在超過 18 萬顆星,是目前最多人用的工程類 skill 集合之一。

他最近放了兩支影片,一支是這套 skills 的完整教學,另一支原本要在 AI Engineer World’s Fair 現場講,因故改成錄影。小編覺得第二支特別有料,因為它談的不是「我做了哪些 skill」,而是「怎麼判斷一個 skill 好不好」。

他把現在的處境叫做 skill hell: 免費的 skill 到處都是,你可以下載、可以自己寫,但你分不出好壞,也不知道它們該怎麼組在一起。缺的不是 skill,是一套判斷 skill 的共用標準。

這套標準他自己也寫成了一個 skill 放在 repo 裡: /writing-great-skills,旁邊附一份 GLOSSARY.md 定義每個術語。小編這篇整理自這兩支影片、repo 原始碼、還有他這半年的 X 貼文。第一節先看這個 repo 有什麼,後面談設計思路。

以下是重點整理:

1. mattpocock/skills 是什麼

這個 repo 就是他自己 .agents 目錄的公開版本,副標寫著「Skills for Real Engineers」(給真正的工程師用的 skills)。他在 README 裡的態度也很明確: 「拿去亂改,改成你自己的」。

「給真正的工程師」這句不是隨口說的。他在 X 上談過「該不該讀 code」這個爭論,認為它根本不是二選一,而是一條光譜,他列了七段: 每一行 diff 都讀 → 掃過每個 diff、只細看重要的行 → 不看 diff 但理解每個 PR 的為什麼 → 抽查 PR → 不看 PR 但定期抽查 codebase → 不看程式碼、只抽查 agent 的執行軌跡 → 程式碼跟系統都不看。他自己的立場是「程式碼就是 agent 執行的環境。忽視它,agent 周圍的世界就會瓦解」,所以他的 skill 有很大一部分在管程式碼本身的設計品質。

repo 裡總共 41 個 skill,分在好幾個資料夾。只有 engineering/productivity/ 這兩個是他認可推出的,共 22 個; 其餘放在 misc/personal/in-progress/deprecated/,他說那些還在實驗、以後可能會刪。

這 22 個照他自己的 user-invoked / model-invoked 分法是:

工程類,你自己打指令叫的:

  • /ask-matt 不知道該用哪個 skill、走哪條流程就問它,它是整組的路由
  • /grill-with-docs 訪談式追問,同時建立專案的領域模型,更新 CONTEXT.md 跟 ADR
  • /to-spec 把目前的對話整理成 spec 發到 issue tracker。它不會再訪談你一次,只做整理
  • /to-tickets 把計畫或 spec 拆成一張張 tracer bullet 票,每張標明要等哪幾張先完成
  • /implement 照 spec 或票實作,在事先講好的接縫上用 /tdd,收尾跑 /code-review
  • /wayfinder 規劃一個 session 裝不下的大工程,在 issue tracker 上做一張決策票的共用地圖
  • /triage 用一套狀態機把進來的 issue 推進到可以動手的狀態
  • /improve-codebase-architecture 掃描 codebase 找可以改善模組設計的地方,用 HTML 報告呈現
  • /setup-matt-pocock-skills 設定 issue tracker、triage 標籤、領域文件位置,每個 repo 跑一次

工程類,agent 也能自己叫的:

  • /tdd red-green 迴圈,一次一個垂直切片
  • /code-review 兩軸 review (規範 + 需求),跑在兩個並行的 subagent 裡
  • /diagnosing-bugs 難 bug 跟效能退化的診斷流程,沒有一個會 red 的回饋迴圈就不准提假設
  • /codebase-design deep module 的共通詞彙與設計紀律
  • /domain-modeling 主動挑戰、釐清專案的術語,寫進 CONTEXT.md 跟 ADR
  • /prototype 做一個用完就丟的原型來回答某個設計問題
  • /research 針對第一手來源查證,結果寫成帶引用的 markdown,跑在背景 agent
  • /resolving-merge-conflicts 逐個 hunk 解 merge 或 rebase 衝突,絕不 --abort

非程式類:

  • /grill-me (你叫) 跟 /grilling (agent 也能叫) 就是那個訪談迴圈,不限程式用途
  • /handoff (你叫) 把目前的對話壓縮成一份交接文件,讓另一個 session 接手
  • /teach (你叫) 跨多個 session 教你一件事,用當前目錄當有狀態的教學工作區。他拿它學會了魔術方塊
  • /writing-great-skills (你叫) 就是這篇文章大半內容的來源

這些 skill 怎麼銜接成一條流程,第 13 節會講。不知道從哪開始就打 /ask-matt,它會依你當下的狀況指出該走哪條路。

最後補一個他常被問、也常被誤會的問題: 「怎麼讓你的 skill 支援 Jira / Linear / beads?」答案是本來就支援。跑 /setup-matt-pocock-skills 的時候跟 agent 說「幫我設成 Jira」就好。skill 讀的是 repo 裡那份本地設定,而不是寫死的整合,所以任何有 CLI 的 issue tracker 它都接得上。

2. skill 存在的目的,是從隨機的系統得到可預測的流程

/writing-great-skills 第一句話就給了定義:

skill 存在的目的,是從一個隨機的系統裡硬是逼出確定性。

這裡的「可預測」有一個明確的限定: 指的是 agent 每次走同樣的流程,不是每次產出同樣的結果。GLOSSARY 特別註明,一個 brainstorming skill 應該要「可預測地發散」,它的 token 每次都不一樣,但行為不變。

這個定義決定了後面所有取捨。對他來說,成本跟可維護性都不是跟可預測性並列的目標,而是它的附帶結果。

3. 每一個 skill 都對準一個軟體工程的老問題

README 有一段定位講得很直接: GSD、BMAD、Spec-Kit 這類做法會幫你把整個流程接管過去,但接管的同時也拿走了你的控制權,而且流程本身出問題時很難查。他要的是小、好改、可組合。

接著他把整套 skill 對應到四個軟體工程的老問題,每個都配一段經典引文:

  • agent 做出來的不是我要的。引 The Pragmatic Programmer 的「沒有人確切知道自己要什麼」。他認為這件事在 AI 時代沒有改變,只是溝通落差換了對象。對策是 grilling session,讓 agent 反過來訪問你。
  • agent 講話太囉嗦。引 Eric Evans 的 Domain-Driven Design。agent 被丟進一個專案,術語只能邊做邊猜,於是一件事要用 20 個字講完。對策是 CONTEXT.md 這份共通詞彙表。他舉的前後對照很清楚: 沒有詞彙表時得說「course 的 section 裡的 lesson 被『變成真的』(也就是在檔案系統裡拿到位置) 的時候會出問題」,有了詞彙表就只要說「materialization cascade 會出問題」。
  • 程式不能動。引 The Pragmatic Programmer 的「回饋的速度就是你的速度上限」。對策是 /tdd 的 red-green 迴圈跟 /diagnosing-bugs
  • 做出一個大泥球 (ball of mud)。引 Kent Beck 跟 Ousterhout 的 deep module。他認為 agent 在加快寫程式的同時也加快了軟體的熵增,所以 /improve-codebase-architecture 建議每隔幾天就跑一次。

小編覺得這組對應就是他設計哲學的核心: 他不是在發明 agent 時代的新流程,而是把已經驗證幾十年的工程紀律翻譯成 agent 讀得懂的格式。這也解釋了為什麼他的 skill 裡到處是 seam、tracer bullet、vertical slice、deep module 這些詞: 它們既是好的工程術語,也是好的 leading word (第 8 節會講這是什麼)。

同一個立場延伸出另一個判斷: greenfield 跟 brownfield 的區分已經不真實了。他常被問「你的 skills 在全新專案上能用嗎」,他的回答是差別只在你的 repo 有沒有設好慣例、有沒有前例可循; 而在程式碼產出速度這麼快的現在,一個新 repo 能維持「新」的狀態頂多兩天到一週。預設就當它是 legacy codebase,即使它才一週大。

4. Trigger: 兩種呼叫方式,兩種完全不同的成本

從這節開始進入他那份檢查清單的四個項目。第一項是「這個 skill 怎麼被叫起來」,只有兩種選擇:

  • model-invoked: 保留 description。agent 看得到、可以自己決定要不要用,別的 skill 也可以呼叫它。代價是這段 description 每一輪都在 context 裡,這個成本他叫 context load
  • user-invoked: 在 frontmatter 加 disable-model-invocation: true (Codex 那邊是 agents/openai.yaml 裡的 policy.allow_implicit_invocation: false)。agent 看不到這段 description,只有人打指令才叫得動,別的 skill 也叫不動。context load 是零,但成本改由人承擔: 你自己就是那個索引,你得記得它存在、記得什麼時候該用。這個成本他叫 cognitive load

小編覺得他這裡最好的一句話是: cognitive load 不是一個要最小化的成本,而是人保有主導權的代價。該讓人判斷的地方就花這個成本,不該的地方才拿掉。這跟一般直覺相反,多數人會預設「能自動就自動」。

5. 他為什麼偏好 user-invoked

他常被問的一個問題是「你的 skills 跟 superpowers 差在哪」,答案就在這個軸上: superpowers 以 model-invoked 為主,他的以 user-invoked 為主。他自己在 X 上的總結是:

Superpowers 是給 agent 超能力,我的 skills 是給你超能力。

他的理由是這樣: 每多一個 model-invoked skill,就多了一個 context pointer,而 pointer 有機率不被跟隨。就算這個 skill 完全符合當下的任務,模型還是可能不叫它。與其想辦法提高命中率,他寧可讓這一整類問題不存在。他還補了一個實務上的考量: 這種不確定性會逼你去替 skill 做 eval,確認它有在對的時機被觸發,那是他寧願避開的麻煩。

代價是他自己得記得這幾十個 skill,這點他也承認。

換來的是什麼? 影片裡安裝器列出 38 個 skill (錄影當時的數量),他把官方那批全裝上,跑 /context,skills 那一欄只佔 660 tokens

user-invoked skill 一多,人就記不住了。他的解法是加一個 router skill: 一個 user-invoked skill,內容就是告訴你有哪些 skill、什麼時候該用哪個,也就是 repo 裡的 /ask-matt。要注意 router 只能告訴你有什麼,不能替你叫起來,因為 user-invoked skill 沒有 description,誰都叫不動它。

還有一條分工規則: user-invoked 可以呼叫 model-invoked,但不能呼叫另一個 user-invoked。這條規則直接決定了他 repo 的分層: user-invoked 是編排層 (/grill-with-docs/to-spec/implement),model-invoked 是可重複使用的紀律層 (/grilling/tdd/code-review/codebase-design)。

同一個偏好也解釋了他為什麼不信任自動的 self-improvement 迴圈,也就是自動產生的記憶、每次 session 結束自動加進 CLAUDE.md 的建議。他的理由有兩層: 建議本身常常很爛; 就算建議是好的,agent 也常常過度依賴它們,讓整個東西變得難以引導。而且這些記憶是 per-project 的,每個專案會用它自己的方式變得難以引導。他想把這個現象叫做 instruction rot。

編按: 這個取捨沒有標準答案,他自己也說兩邊各有各的成本,不是容易的決定。但小編覺得值得注意的是,他把「要不要讓模型自動觸發」當成一個要主動設計的參數,而不是預設值。

6. description 要寫得比本體更省

description 只有 model-invoked 才要寫。它常駐在 context 裡,每個字的成本比本體高,所以要刪得更徹底。他的三條規則:

  • 把 leading word 放到最前面。description 就是這個詞做觸發工作的地方。
  • 一個 branch 一個 trigger。用同義詞換句話說同一件事就是 duplication,例如「build features using TDD… asks for test-first development」其實是同一個 branch 寫了兩次,該合併。
  • 本體已經講過的身份說明就刪掉。description 只留觸發條件,加上「當別的 skill 需要⋯」這種被呼叫的條件。

成效有數字可以看: 他在 v1 的發布說明裡提到,這一輪整理讓 skill description 的 token 成本降了 63%。

7. Structure: steps、reference,和三層的資訊階層

第二項檢查是內部結構。他認為 skill 只由兩種東西組成:

  • steps: 照順序做的動作,每個 step 結束在一個「完成標準」上。
  • reference: 隨時查的定義、規則、範本、參數。

兩種可以任意搭配。/tdd 幾乎全是 reference,/to-spec 是 steps 加一份範本,也有 skill 兩種都有。

接著這些內容排在一個三層的資訊階層上,依 agent 需要它的急迫程度排序:

1. SKILL.md 裡的 step
最上層。agent 要做什麼、按什麼順序做。每個 step 有一個可判定的完成標準。
2. SKILL.md 裡的 reference
次要層。隨時查的定義與規則。很多時候本來就該是平的一組同級規則,這不是壞味道。
3. 推到外部檔案的 reference
用 context pointer 指過去,只有 pointer 被觸發時才載入。可以是 skill 資料夾裡的兄弟檔 (例如 GLOSSARY.md),也可以是完全在 skill 系統外、任何 skill 都能指的一般檔案。

要不要往下推,判準不是「檔案太長」,而是 branch。 這是小編覺得整套結構觀念裡最實用的一條。一個 skill 如果有多種用法,每種用法就是一個 branch。每條 branch 都會用到的留在 SKILL.md 裡,只有部分 branch 用得到的推出去。

他舉的兩個例子剛好對照。/to-spec (演講時還叫 /to-prd) 只有一條路徑,永遠會寫 spec、永遠會確認測試接縫,所以「什麼是測試接縫」跟「spec 範本」兩份 reference 都留在本體。而 /domain-modeling 會做兩件事 (更新詞彙表、寫 ADR),也可能兩件都不做,等於有兩到三條 branch,所以 ADR 範本跟詞彙表範本都推到外部檔案,本體只留一行 pointer 說「如果需要範本,去這個檔案」。

repo 版本比演講多寫了兩點:

  • 共置 (co-location)。階層決定一段內容放在第幾層,共置決定它旁邊放什麼。一個概念的定義、規則、例外要放在同一個標題底下,讀到其中一段就會順便帶到相鄰的部分。
  • pointer 沒被跟隨的時候,先修措辭。他寫得很明確: 決定 agent 什麼時候去讀、讀得多可靠的是 pointer 的措辭,不是它指向什麼。一份必讀的材料放在 pointer 後面卻常常被跳過,那是措辭問題,先改措辭,改不動才搬回本體。

8. Steering 的核心: leading words

第三項檢查是 steering,也就是怎麼讓 agent 真的照你想的做。他說這是整場演講他最想給的一件事。

leading word (Leitwort) 是一個已經存在於模型預訓練裡的壓縮概念。你把它放進 skill 的文字裡,agent 會在思考過程跟輸出裡把這個詞複述出來,複述的同時就改變了行為。它用最少的 token 讓一整類行為固定下來,因為它調用的是模型本來就有的先驗。

他舉的例子是一個很常見的通病: agent 習慣一層一層寫程式,先寫完整個資料庫層、再寫完 schema、再寫完 API、最後才寫前端,不會像人一樣先做出一小塊能動的東西然後求回饋。你當然可以寫「不要一層一層做,先做出一小塊完整能動的東西再往外擴」。但更好的做法是直接用「vertical slice (垂直切片)」這個詞: 這是開發圈本來就通行的說法,模型的先驗會被叫起來。

這個技巧有兩件事值得注意:

  1. 它是可驗證的。 你在 skill 裡寫了 vertical slice,就去 reasoning trace 裡看 agent 有沒有把這個詞說回來。有,代表這個詞有效; 沒有,代表它不夠強。
  2. 它同時作用在觸發上。 當同一個詞出現在你的 prompt、你的文件、你的程式碼裡,agent 會把這個共通語言連到那個 skill,觸發得更準。所以 description 要用你「真的會講的那些詞」來寫。

自創的詞也可以用,但它沒有先驗可以調用,你得多花 token 去定義。優先找既有的詞。

repo 裡把這件事做得很徹底: 幾乎每個術語底下都附一行 _Avoid_:,列出不該用的同義詞/codebase-design 的詞彙表直接寫「這些詞要照字面用,不要換成 component、service、API 或 boundary,語言一致就是整件事的重點」; seam 那條註明「不要用 boundary,這個詞跟 DDD 的 bounded context 撞在一起」。光是「我用了這個詞」還不夠,還要確保它的意思不會被一堆同義詞換來換去而變模糊。

9. 完成標準決定 agent 做多少前置工作

steering 的第二個手段是「完成標準 (completion criterion)」,他拆成兩個軸:

  • 清晰度: agent 分不分得出做完了沒? 模糊的標準 (例如「達成共識」) 會讓它宣稱做完然後進到下一步,這叫 premature completion
  • 要求強度: 標準要求多高,決定 agent 願意做多少 legwork。legwork 指的是它在一個 step 裡自己去讀檔案、探索程式碼、把需要的資訊查出來,而不是丟回來問人。「每一個被改到的 model 都要有交代」跟「產出一份變更清單」,agent 做的前置工作深度差很多。

他拿 plan mode 當反例,而且說他試過的每一種 plan mode 實作都有這個問題: plan mode 有兩步,「問澄清問題」跟「產出計畫」。agent 看得到終點是產出計畫,所以澄清問題那步永遠做得敷衍,問你兩三題就急著開始寫計畫。

他的解法是拆成兩個 skill: /grill-with-docs 負責問,結束之後你才手動叫 /to-specagent 一次只看得到一步,看不到後面,就不會提早結束當前這一步。

repo 版本比演講多補了兩點,都很重要:

  • 順序是先把完成標準寫明確,再考慮拆。 改標準便宜又局部; 只有當標準怎麼寫都模糊、而且你真的觀察到它在趕的時候,才動手拆。
  • 藏後續步驟只在真正的 context 邊界才有效。 交給人手動接續、或丟給 subagent 才算。在同一個 context 裡 inline 呼叫一個 model-invoked skill,後面的步驟還留在 context 裡,什麼都沒藏到。

10. 不要用禁止句

steering 還有一個獨立的失敗模式叫 negation。用禁令來引導會有反效果,因為禁令把被禁的行為帶進了 context,反而讓它更容易出現。他的說法是「不要想大象」: 講完這句,大象就是唯一在場的東西。

「不要寫冗長的註解」,而模型剛剛讀到的模式就是冗長。

修法是改成正面描述目標行為,讓被禁的行為根本不被提到 (「註解寫一行」)。真的只能用禁令當硬性護欄時,也要配一句「那該怎麼做」,讓注意力落在該做的事情上。

11. Pruning: no-op 測試,跟另外三種讓 skill 變長的原因

第四項檢查是刪。他在 X 上把 no-op 講得最直白:

看一下你最喜歡的那個 skill。檢查有沒有這種句子:「commit message 要寫得很詳細」「要徹底」「實作要好讀」。這些句子的共通點是: 它們是 no-op,對 agent 的行為毫無影響。Agent 本來就會寫好的 commit message、本來就會試著徹底、本來就會試著寫好讀的實作。刪掉試試,輸出有變嗎? 沒有? 那這行就是 no-op。Agent 自己寫的 skill 尤其滿是 no-op。

有兩個延伸判斷,小編覺得比 no-op 本身更有價值:

  • no-op 是相對於「模型的預設行為」,不是相對於讀者。 所以兩個人爭論某一行是不是 no-op,其實是在爭論模型的預設行為長什麼樣。這件事該用跑一次來解決,不是用辯的。
  • 太弱的 leading word 本身就是 no-op。 agent 本來就還算徹底,你寫「be thorough」等於沒寫。修法是換一個更強的詞 (relentless),不是換一種技巧。順帶一提,/grilling 的本體真的就是用 relentlessly 這個詞。

另外三種讓 skill 變長的原因,各有各的修法:

  • duplication (同一個意思出現在兩個地方): 除了維護成本跟 token 成本,還有一個少人提的副作用: 重複會不當抬高這個意思在資訊階層上的位階,讓它看起來比實際重要。它剛好是 leading word 的反面: leading word 是刻意重複同一個來提高注意力,duplication 是不小心重複了同一個意思
  • sediment (沉積): 多人共同維護一份文件的預設結局。每個人都往裡面加自己的東西,沒有人有把握去刪別人寫的,內容越積越多。修法是先看結構,把只屬於某條 branch 的東西移到那條 branch 去,過期的直接刪掉。
  • sprawl (單純太長): 每一行都還有效、都不重複,但整份就是太長。修法就是資訊階層: 該推到下層的推出去,該按 branch 拆的拆掉。

12. 他的 skill 實際上有多小

理論講完,看實際的檔案最有說服力。這是 /grill-me全文:

---
name: grill-me
description: A relentless interview to sharpen a plan or design.
disable-model-invocation: true
---

Run a `/grilling` session.

含 frontmatter 20 個英文字。/grill-with-docs 34 個字,多的部分是「用 /domain-modeling skill 一起跑」。/implement 70 個字,內容是「照 spec 或 tickets 做、盡量在事先講好的接縫上用 /tdd、常跑型別檢查、最後跑 /code-review、commit」。

真正有內容的是被它們呼叫的 model-invoked skill。/grilling 全文 136 個字:

Interview me relentlessly about every aspect of this until we reach a shared
understanding. Walk down each branch of the decision tree, resolving dependencies
between decisions one-by-one. For each question, provide your recommended answer.

Ask the questions one at a time, waiting for feedback on each question before
continuing. Asking multiple questions at once is bewildering.

If a *fact* can be found by exploring the environment (filesystem, tools, etc.),
look it up rather than asking me. The *decisions*, though, are mine — put each
one to me and wait for my answer.

Do not act on it until I confirm we have reached a shared understanding.

(中譯: 針對這件事的每一個面向不留情地訪問我,直到我們達成共識。走過決策樹的每一條分支,一個一個解掉決策之間的相依。每個問題都給出你建議的答案。一次問一個問題,等我回覆再繼續,一次丟一堆問題會讓人不知所措。如果一個事實可以靠探索環境 (檔案系統、工具等) 找到,就自己去查,不要問我。但決策是我的,一個一個丟給我,等我回答。在我確認達成共識之前,不要動手。)

這就是「user-invoked 負責編排、model-invoked 負責紀律」的具體樣子,也是「我的 skill 為什麼這麼小」的答案。他自己列的三個理由是: 短的好稽核 (所以才信得過)、好維護、跑起來便宜。

不過他的長 skill 也確實存在: /wayfinder 兩千多字、/writing-great-skills 一千五百多字。所以他的標準不是「一律要短」,而是「每一行都得改變 agent 的行為」。

13. 主流程長什麼樣

第一支影片走完整條流程,就是這五步:

/grill-with-docs/to-spec/to-tickets/implement/code-review

幾個設計細節值得參考:

  • 前三步要在同一個沒中斷過的 context window 裡跑完。 不要 compact 也不要 clear,讓訪談、spec、tickets 建立在同一份思考上。上限是他說的 smart zone: 影片裡他抓 140k,repo 的 /ask-matt 寫約 120k,超過就開始出現注意力衰退。快到上限就用 /handoff 換一個新對話,不要硬撐著在退化的狀態下往下做。
  • spec 是終點,tickets 是路線。 他在 X 上把這件事講得最清楚: 分成兩份文件的好處是,要改方向時你只改 spec、刪掉還沒做的 tickets,不用重寫一整份計畫。每個 ticket 剛好一個 context window 的大小,做完一個就 clear。
  • /code-review 一定跑 subagent。 主 agent 剛剛才把那段程式寫出來,它會覺得自己寫得很好,改不動也審不動。開一份乾淨的 context 才審得出東西。
  • review 分兩軸,而且不合併。 一軸是 Standards: 符不符合這個 repo 自己寫的規範,另外永遠附帶一組 Martin Fowler 的 code smell 當基本檢查 (repo 的規範優先,衝突時以 repo 為準; 工具已經在檢查的就跳過)。另一軸是 Spec: 有沒有真的做到需求要的東西,以及有沒有做多餘的。兩軸並行跑在各自的 subagent 裡免得互相干擾,最後並排呈現,不重新排名也不合併。理由很直白: 完全符合規範但做錯東西、跟做對東西但違反慣例,這兩種情況都很常見,合併排名會讓一軸遮住另一軸。
  • effort 從低往高調,不是從高往低 這條不屬於流程本身,但會影響上面每一步。大部分人拿到新模型會先開高 effort、不行再降,他認為順序反了: effort 本質上就是丟更多 token 進去,這在 benchmark 上很划算 (多花 20% token 換 2% 分數對行銷很好看),但在探索 repo、改一個測試這種日常任務上就只是浪費,而且 token 耗得越多,注意力衰退來得越快。他還提醒: 講你用什麼模型的時候請一起講 effort 等級,同一個模型不同 effort 行為完全不同。

14. repo 本身的幾個做法也值得學

除了 skill 之外,這個 repo 在組織上有幾個做法小編覺得同樣有用:

  • .out-of-scope/ 資料夾: 把「被拒絕的功能請求」跟「為什麼拒絕」寫成文件。例如有人開 issue 說「Codex 一口氣問了我 200 個問題」,要求給 grilling 加問題數量上限。他的回覆文件寫得很好: 加上限會混淆兩種不同的失敗,一種是計畫本身真的沒講清楚所以該多問 (這是正常運作),另一種是模型問了重複或低價值的問題 (這是 prompt 品質問題),後者的修法在 prompt 裡,不在計數器裡。
  • ADR 三原則 (來自他的一則回覆): 決定的當下就寫,正在討論就直接寫進 codebase,不開 PR 直接進 main; 不要怕刪掉或標記過期,一份死掉的 ADR 對誰都沒好處; 只有當一個決定「難以回頭、沒有脈絡的人會覺得奇怪、而且是真的有取捨」時才寫。
  • CONTEXT.md 當專案詞彙表: 每個詞附定義加 _Avoid_,還有一節 Flagged ambiguities 記錄「哪個詞曾經同時代表兩件事,後來怎麼解決的」。他在 README 裡說這可能是整個 repo 最好用的技巧。好處不只是 agent 講話變短: 變數、函式、檔案的命名會跟著一致,agent 在 codebase 裡也更好導航,思考用掉的 token 也更少。

15. 他這套跟主流的 skill 寫法差在哪

前面十四節都在講他自己的主張,小編也擴大搜尋把目前主流的 skill 寫作建議看了一輪 (Anthropic 官方的 skill authoring best practicesAnthropic 工程部落格談 Agent Skills 那篇Perplexity 團隊寫的 skill 維護經驗,加上一批社群指南),放在一起比有三個地方明顯不一樣:

  1. 主流在教你怎麼讓模型選對 skill,他直接把模型觸發關掉。 官方那份 best practices 有很大篇幅在教 description 怎麼寫,前提是「Claude 要從可能上百個 skill 裡挑出對的那一個」,整份文件沒提過關閉模型觸發這個選項。他反過來做: 22 個核心 skill 有 13 個設了 disable-model-invocation: true,你會親手叫的那條主流程從頭到尾都是這種; 模型能自己叫的只剩下 TDD、code review、領域建模這些紀律型的 skill。(第 4、5 節)
  2. 主流用長度決定要不要拆檔案,他用分支決定。 官方建議是「SKILL.md 本體控制在 500 行以內,接近上限就拆成獨立檔案」。他不看長度,看的是這段內容在當前這條路上是不是必經步驟; 而且他認為真正決定 agent 會不會去讀那個檔案的,是指標那句話怎麼寫,不是檔案放在哪裡。(第 7 節)
  3. 主流傾向持續累加,他把「刪」列為四個檢查項之一。 Perplexity 團隊的結論是「skill 基本上只增不減,gotchas 那一節長期下來累積的價值最高」,而且認為負面範例是高訊號內容。他兩點都反過來: skill 會因為 no-op、重複、沉積、過長慢慢失效,定期刪掉是維護的一部分,禁止句本身則被他列為一種失敗模式。(第 10、11 節)

第 3 點是唯一一個兩邊建議完全相反的,小編覺得差別來自使用情境不同。Perplexity 的 skill 跑在自家產品裡給模型用,有 eval 撐著,只有工程師會讀,往 gotchas 一直加是合理的; 他的 skill 是你自己每天打指令叫起來的,你也得讀得懂、記得住,長了就不好用。所以在挑要不要照誰的建議之前,先想清楚你的 skill 是哪一種。

拿去檢查自己的 skill

四項檢查收攏成一份可以直接對照的清單:

1. Trigger 怎麼被叫起來
☐ 這個 skill 需要 agent 自己找到它嗎? 不需要就設 user-invoked,省下 context load
☐ description 有沒有把 leading word 放最前面
☐ description 裡的觸發條件有沒有一個 branch 寫成兩句
☐ user-invoked 多到記不住時,加一個 router skill
2. Structure 內容怎麼排
☐ 分得出哪些是 steps、哪些是 reference 嗎
☐ 這個 skill 有幾條 branch? 只有部分 branch 用得到的材料推去外部檔案
☐ 一個概念的定義、規則、例外有沒有放在同一個標題底下
☐ pointer 後面的必讀材料常被跳過? 先改 pointer 的措辭
3. Steering 怎麼讓它照做
☐ 有沒有一段話可以收攏成一個 leading word
☐ 去 reasoning trace 裡確認那個詞有被複述回來
☐ 每個 step 的完成標準判定得出來嗎? 要求夠不夠高?
☐ agent 老是趕著結束當前步驟 → 先修完成標準,真的不行才拆成兩個 skill
☐ 有沒有禁止句可以改寫成正面描述
4. Pruning 刪到不能再刪
☐ 一句一句做 no-op 測試: 刪掉這句,行為有變嗎?
☐ 沒變就整句刪,不要只修字
☐ 同一個意思有沒有出現在兩個地方
☐ 有沒有沒人動手刪掉的沉積內容
☐ 每行都有效但整份還是太長 → 回頭看 branch 跟資訊階層
✏️ 小編整理自 /writing-great-skills

小編覺得這整套東西最值得學的,其實不是那 22 個 skill,而是他把「寫 skill」本身當成一個工程問題在處理: 有專屬詞彙、有失敗模式分類、有檢查順序。GLOSSARY 裡每個失敗模式都被放在治它的那個手段旁邊 (premature completion 放在 completion criterion 底下、negation 放在 steering 底下),這種編排本身就是他講的共置原則用在自己身上。

最近在想/writing-great-skills 改名成 /writing-for-agents,因為同一套方法對 AGENTS.md、對專案文件一樣成立。這個念頭透露了一件事: skill 沒有什麼特殊之處,它就是「寫給 agent 看的文件」。而寫給 agent 看的文件跟寫給人看的文件,優化目標本來就不同。人讀到重複的叮嚀會覺得慎重,模型讀到的卻是同一個意思在資訊階層上被抬高了位階; 人讀到「請務必徹底」會提高警覺,模型本來就會試著徹底,那行字只是佔位置。