<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Skills 從零開始 on KbWen Blog</title>
    <link>https://www.kbwen.com/series/skills-%E5%BE%9E%E9%9B%B6%E9%96%8B%E5%A7%8B/</link>
    <description>KbWen 的個人技術部落格，分享 Python、機器學習、深度學習、資料工程與 AI 開發的學習筆記與實作心得。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <image>
      <url>https://www.kbwen.com/images/og-default.png</url>
      <title>KbWen Blog</title>
      <link>https://www.kbwen.com/</link>
    </image>
    
    <lastBuildDate>Thu, 28 May 2026 11:00:00 +0800</lastBuildDate><atom:link href="https://www.kbwen.com/series/skills-%E5%BE%9E%E9%9B%B6%E9%96%8B%E5%A7%8B/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>怎麼寫你的第一個 skill — 從一個煩躁的 prompt 開始</title>
      <link>https://www.kbwen.com/writing-your-first-skill/</link>
      <pubDate>Thu, 28 May 2026 11:00:00 +0800</pubDate><dc:creator>KbWen</dc:creator>
      <guid>https://www.kbwen.com/writing-your-first-skill/</guid>
      <description>你的第一個 skill 不會長得像書裡那些 production-grade 的成熟形態,它會長得像「你重複打三次的同一個 prompt」。從那裡開始,比從一個成熟框架的 skill 倒著學容易很多。</description>
      <content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> 你的第一個 skill 不會長得像書裡那些 production-grade 的成熟形態, 它會長得像「你重複打三次的同一個 prompt」。本篇示範一個假設的 4 行入門版怎麼寫、存到哪裡、為什麼會沒跑、撞坑後怎麼修, 然後對照我自己框架裡真的在用的 17 行版本 — 看那些多出來的東西其實都是「撞坑後加上的補丁」, 不是設計階段一次想出來的。</p>
</blockquote>
<hr>
<p>你有沒有打過同一個 prompt 三次?同一段話、同一個格式、同一個角度, 三次。第三次你會開始煩, 第四次你會想:這個我能不能存起來?</p>
<p>那一刻其實就是你的第一個 skill。</p>
<p>不是說那個 prompt 寫得有多好, 是「想存起來」這個衝動就是 skill 出現的位置 — 你已經辨識出一個重複會發生的模式。剩下的事沒什麼神秘的, 把它丟進一個 <code>.md</code> 檔, 用 slash 叫出來而已。</p>
<p>前三篇我談過 skill 是什麼 ——<a href="/what-makes-an-ai-skill-different-from-a-prompt/">跟 prompt 的差別在哪一層</a>、<a href="/skill-boundary-design/">邊界怎麼劃</a>、<a href="/anatomy-of-a-13-line-skill/">拆一個 13 行的 dispatcher 給你看</a>。但這篇有個之前都沒講的事:你的第一個 skill 不會長得像那些。你看過的成熟 skill, 不管是我框架裡的還是別人的, 都是寫了很多次、撞了幾次坑之後才變成那樣的。直接從那邊倒著學, 容易卡在「為什麼要有這條」這種對學習沒幫助的地方。比較好的起點, 就是你那個煩躁的 prompt。</p>
<h2 id="假設你常做研究">假設你常做研究</h2>
<p>舉個例子。你最近常請 AI 幫你看一些雜七雜八的研究筆記 — 三段你 google 來的東西、半段別人 Slack 給你的、一張 issue 截圖貼的內文。你想把它分類:哪些是已經查證的事實、哪些是還沒驗證但你假設成立的、哪些是現在還不知道的問題。</p>
<p>每次貼進去你都打差不多的字:「幫我把下面這團分成 Facts / Assumptions / Unknowns, 三個列點。」打過三次, 想存。</p>
<p>我框架裡其實沒這個 skill, 但你入門版大概會長這樣:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="gh"># /structure-findings
</span></span></span><span class="line"><span class="cl">Take the messy research notes I paste in. Split them into three groups:
</span></span><span class="line"><span class="cl">Facts (verified knowns), Assumptions (believed but not checked), Unknowns (open questions).
</span></span><span class="line"><span class="cl">Input: $ARGUMENTS
</span></span></code></pre></div><p>那 4 行做了什麼?第一行 <code>/structure-findings</code> 是觸發詞, 你在 Claude Code 裡打那個 slash 命令時, 它會找這個檔。中間兩行是你原本的 prompt, 不過從你打字直接送, 變成寫進檔案裡。最後一行 <code>$ARGUMENTS</code> 是 placeholder — 你輸入「<code>/structure-findings</code> 接著貼一坨筆記」的時候, 那一坨會被代進去。</p>
<p>老實說, 大概這樣就夠了, 一個能跑的 skill 已經在你手上。</p>
<h2 id="然後它沒跑">然後它沒跑</h2>
<p>把那 4 行存到 <code>.claude/commands/structure-findings.md</code>。注意是 project-local — Claude Code 從你開 session 的目錄(cwd)往下找這個資料夾, 找不到就當作這個 skill 不存在。</p>
<p>在 Claude Code 裡打 <code>/structure-findings 貼上你那團研究筆記</code>, 看它有沒有動。</p>
<p>如果你跟我一樣會撞坑, 大概會撞到三種:</p>
<p><strong>打完沒反應。</strong> 多半是 cwd 不對。你以為的「我已經在這個專案裡了」跟 Claude Code 認的 cwd 不一定一樣 — 它從哪個目錄開的 session, 就只在那裡(以及更上層)找 <code>.claude/commands/</code>。檢查一下 session 開在哪。</p>
<p><strong><code>$ARGUMENTS</code> 是空的, 它把你的話當成不重要的尾巴。</strong> 兩個可能 — 一個是你 skill 內容裡根本沒寫到要用 <code>$ARGUMENTS</code> placeholder, 一個是 Claude Code 的某些版本對 placeholder 的解讀有差異。這條建議直接對著 <a href="https://code.claude.com/docs/en/skills">Claude Code 官方 skills 文件</a> 確認當前版本怎麼算。</p>
<p><strong>跑了, 但結果跟你直接打 prompt 沒兩樣。</strong> 我第一次撞到這個有點傻 — 想說我都存成檔了, 怎麼還是 prompt 的感覺。後來發現差別其實在那 4 行裡有沒有「規定輸出長什麼樣」。如果你只寫「幫我分類」, 結果就會跟你直接打字一樣鬆。把「Facts / Assumptions / Unknowns 各列成一段, 標題粗體」這種輸出格式寫死進去, 它才有 skill 的樣子。要不要寫死, 你跑兩次就會知道。</p>
<p>順帶一提, 這三個坑我自己都踩過, 第三個還踩了兩次才認帳。</p>
<h2 id="同樣的事-在我框架裡">同樣的事, 在我框架裡</h2>
<p>我自己日常在用的框架 AgentCortex 裡, 有一個 skill 叫 <code>/research</code>。它做的事比剛剛那個假設的 <code>/structure-findings</code> 大 — 但你打開那份 workflow, 會發現裡面有一個步驟長得跟你剛剛寫的東西幾乎一模一樣。</p>
<p><code>/research</code> 的 workflow 規定 AI 把找到的東西用六個類別寫出來(規矩寫得比我當下需要的多一點, 後來才知道為什麼):<strong>Facts</strong>(查證過的)、<strong>Unknowns</strong>(需要再找的)、<strong>Assumptions</strong>(相信但沒驗證的)、<strong>Risks</strong>(風險, 分高中低)、<strong>Official References</strong>(查過的官方資料)、<strong>Next Actions</strong>(具體下一步)。</p>
<p>你看出來了嗎?你那個假設的 4 行 <code>/structure-findings</code>, 基本上就是 <code>/research</code> workflow 的其中一個 step — 把雜亂內容分成 Facts / Assumptions / Unknowns 那塊。我多加了 Risks、Refs、Next Actions 三個類別, 但骨子是同一件事。這幾個多出來的類別都是一段時間累積出來的, 不是設計階段一次想到的。</p>
<h2 id="production-grade-的版本長什麼樣">production grade 的版本長什麼樣</h2>
<p>那 production 形態具體長什麼樣?我把真實的 <code>/research</code> skill 貼出來給你看 — 路徑是 <code>.claude/commands/research.md</code>, 17 行:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="gh"># /research
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Execute the canonical workflow: <span class="sb">`.agent/workflows/research.md`</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="gu">## Required reads before execution
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">1.</span> <span class="sb">`AGENTS.md`</span> — global directives (Intent Router, Gate Engine, Sentinel)
</span></span><span class="line"><span class="cl"><span class="k">2.</span> <span class="sb">`.agentcortex/context/current_state.md`</span> — SSoT
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="gu">## Execution
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Follow every step in <span class="sb">`.agent/workflows/research.md`</span> sequentially.
</span></span><span class="line"><span class="cl">The user&#39;s task description is: $ARGUMENTS
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">-</span> This is a research-only workflow. No implementation — only understanding.
</span></span><span class="line"><span class="cl"><span class="k">-</span> Investigate first, report after. Ground findings in evidence.
</span></span><span class="line"><span class="cl"><span class="k">-</span> End response with ⚡ ACX.
</span></span></code></pre></div><p>跟假設的 4 行版對著看, 多了什麼:</p>
<p><strong>Required reads。</strong> 我規定 AI 在執行前先讀兩份檔 — 一個是專案的全局 directives, 一個是目前系統狀態的 single source of truth。為什麼?因為早期我發現 AI 如果直接接到指令, 它的答案會跟我系統現在的狀態脫節。多了這條, 它至少先把當下的 context 拉進來。</p>
<p><strong><code>$ARGUMENTS</code> 還在, 身邊多了配套。</strong> 「research-only, no implementation」「investigate first, report after」— 這些是行為約束。不是說 prompt 不能寫這些, 是當你把它寫進 skill 而不是每次都重打, 那條約束就變成這個 skill 的契約的一部分。</p>
<p><strong>它指向另一個檔, 不在這 17 行裡。</strong> 跟<a href="/anatomy-of-a-13-line-skill/">上一篇</a> 拆 <code>/codex-cli</code> 看到的是同一個模式 — 真正執行細節在 <code>.agent/workflows/research.md</code>, skill 本體只負責把任務 dispatch 出去。順帶一提這是我框架的習慣, 不是 Claude Code 自帶, 你不照這套也完全可以。</p>
<p>每一個多出來的東西, 都不是設計階段就想到的, 是某次撞到一個失敗模式之後加上去的。「為什麼要 required reads?」因為有一次它答得超脫離現實。「為什麼加 read-only?」因為有一次它沒被約束就動了不該動的東西。行數就是這樣一坑一坑長出來的, 不是設計成這樣的。</p>
<h2 id="你的下一個轉折點">你的下一個轉折點</h2>
<p>寫了幾個 atomic skill 之後, 你會開始注意一件事 — 有些 skill 老是接在一起跑。第一次你不會發現, 第三次你就會發現自己每次都這樣串。</p>
<p>你先 <code>/structure-findings</code>, 把筆記分成三類。看完那份報告, 你想接著問:這些 Assumptions 裡哪些風險最高?所以你開了第二個 skill <code>/list-risks</code>。看完風險, 你想決定下一步, 又呼叫第三個 <code>/next-actions</code>。</p>
<p>你發現了嗎 — 這三個 atomic 加起來, 幾乎就是我前面 <code>/research</code> 那六類(少了 Refs)。三個 skill 跑完才完成一次「研究」, 而且每次研究都是這三個一起跑。</p>
<p>那大概就是 workflow 開始浮出來的時候。你還沒想設計它, 它自己就長出來了。Workflow 不是設計階段就分好的東西, 是你重複幾次、撞到模式、自然分出來的。當你發現自己有幾個 atomic 老是同序列出現, 把它們綁成一份, 給一個總的 skill 觸發 — 那就是我 <code>/research</code> 跟它那份 workflow 檔的由來。</p>
<h2 id="從那個煩躁的-prompt-開始">從那個煩躁的 prompt 開始</h2>
<p>寫 skill 這件事我還在摸索, 但有一個觀察愈來愈確定:<strong>從 production-grade skill 倒著學, 比從那個煩躁的 prompt 正著走難很多。</strong></p>
<p>倒著學要你猜「為什麼有這條」、「為什麼分成這幾層」、「為什麼要 dispatch」 — 都是抽象的設計題。正著走只要你做一件事:把下次想存的 prompt 真的存起來, 跑跑看, 撞到坑就修。修個幾次, 上面那些「為什麼」會自己浮出來。</p>
<p>我不會說我自己當初一定就是這樣開始的(實在記不清了), 但回頭看那些長到 17 行的 skill, 它們最早一定有一個 4 行的祖先, 而那個 4 行的祖先, 一定有一個更早的 — 某個我打到第三次煩躁的 prompt。</p>
<p>最後一句重要的話:每個工具的 skill 慣例都不一樣 ——<a href="https://code.claude.com/docs/en/skills">Claude Code 官方 skills 文件</a>、<a href="https://developers.openai.com/codex">OpenAI Codex CLI docs</a>、Cursor 的 <code>.cursor/rules</code>、AGENTS.md 規範, 各自有自己的形狀。寫之前對一次, 之後也記得回去對 — blog 文會過期, 官方文件不會。</p>
<p><em>Agentic OS 是開源專案:<a href="https://github.com/KbWen/agentic-os">github.com/KbWen/agentic-os</a></em></p>
<hr>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="/what-makes-an-ai-skill-different-from-a-prompt/">一個 AI Skill 和 Prompt 到底差在哪</a> — skill 在 stack 裡放哪一層</li>
<li><a href="/skill-boundary-design/">Skill 邊界設計:從能力到合約</a> — 為什麼邊界比能力重要</li>
<li><a href="/anatomy-of-a-13-line-skill/">13 行的 skill:AI 起稿,我事後才看懂</a> — 拆一個 dispatcher-style skill 給你看</li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>13 行的 skill:AI 起稿,我事後才看懂</title>
      <link>https://www.kbwen.com/anatomy-of-a-13-line-skill/</link>
      <pubDate>Wed, 27 May 2026 11:00:00 +0800</pubDate><dc:creator>KbWen</dc:creator>
      <guid>https://www.kbwen.com/anatomy-of-a-13-line-skill/</guid>
      <description>我請 AI 幫我寫一個能從 Claude Code 呼叫 Codex CLI 的 skill,它給我 13 行 markdown。13 行很小,但 skill 跟 prompt 真正的差別不在這 13 行裡——在它指過去的那一份東西裡。</description>
      <content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> 我請 AI 幫我寫一個能從 Claude Code 裡呼叫 OpenAI Codex CLI 的 skill,它給我 13 行 markdown。看起來小到不像個東西。但這 13 行不是 skill 的全部——真正讓它變成 skill 而不是 prompt 的,是它指過去的那一份比較厚的東西。Skill 是契約的形狀,不是指令的形狀。</p>
</blockquote>
<hr>
<p>前三篇我談過 skill 是什麼。<a href="/what-makes-an-ai-skill-different-from-a-prompt/">一個 AI Skill 和 Prompt 到底差在哪</a> 把它放進 stack 裡的某一層, <a href="/skill-boundary-design/">Skill 邊界設計</a> 講為什麼邊界比能力重要, <a href="/skill-design-as-interface-design/">Skill Design as Interface Design</a> 是英文版用 API 設計的角度寫的。</p>
<p>這篇換個角度:<strong>真的拿一個給你看。</strong></p>
<p>挑 <code>/codex-cli</code> 這個 skill,因為它小到適合當教材。它在我那邊的工作是:從 Claude Code 想把某個任務丟給 OpenAI 的 codex CLI 去跑,我打 <code>/codex-cli 修 README 的 typo</code>,它就接手。</p>
<h2 id="13-行長這樣">13 行長這樣</h2>
<p>我請 AI 幫我寫第一版的時候,它給我這個:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl"><span class="gh"># /codex-cli
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Execute the canonical workflow: <span class="sb">`.agent/workflows/codex-cli.md`</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="gu">## Execution
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">Follow every step in <span class="sb">`.agent/workflows/codex-cli.md`</span> sequentially.
</span></span><span class="line"><span class="cl">The user&#39;s task description is: $ARGUMENTS
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">-</span> [OPTIONAL MODULE] Requires globally installed <span class="sb">`codex`</span> CLI
</span></span><span class="line"><span class="cl">  (<span class="sb">`npm install -g @openai/codex`</span>).
</span></span><span class="line"><span class="cl"><span class="k">-</span> If CLI is unavailable, inform the user and fall back to native execution.
</span></span><span class="line"><span class="cl"><span class="k">-</span> End response with ⚡ ACX.
</span></span></code></pre></div><p>就這樣。13 行。沒有複雜的 prompt engineering, 沒有冗長的 system message, 沒有 chain-of-thought 模板。第一次看到的時候我有點疑惑:這就是一個 skill?</p>
<p>是。然後不是。</p>
<h2 id="這-13-行做了什麼">這 13 行做了什麼</h2>
<p>最上面 <code>/codex-cli</code> 是觸發詞——在 Claude Code 裡打那個 slash 命令,這個檔就被載入。<code>$ARGUMENTS</code> 是個 placeholder,我打的「修 README 的 typo」會被代進去, 成為這個 skill 真正要處理的 input。下面那兩條 bullet, 是 fallback 條款:工具不在的時候怎麼辦。</p>
<p>到這裡, 它做完了一個 skill 該做的事——接到一個輸入, 告訴 AI 去執行哪一份 protocol, 並且講清楚如果工具不在的話退路是什麼。</p>
<p>但它不是 prompt。Prompt 是「你扮演一個資深工程師,請幫我&hellip;」這種把指令塞滿的東西。Skill 比較像 dispatcher——它指向別的地方, 自己只負責定義契約。</p>
<h2 id="但-13-行不是全部">但 13 行不是全部</h2>
<p>那 13 行裡有一句很安靜的話:</p>
<blockquote>
<p>Execute the canonical workflow: <code>.agent/workflows/codex-cli.md</code></p>
</blockquote>
<p>被指過去的這個 workflow 檔, 比那 13 行厚很多。<code>/codex-cli</code> 自己很瘦, 因為它把厚的東西外包出去了。</p>
<p>打開那份 workflow, 裡面寫的大概是這幾類東西:codex 真的能不能用要先確認一次, 不能用就退回去。任務丟過去之前要先包一份護欄上去——「不要動指定範圍以外的檔案、不要重構沒被要求的程式碼、如果不確定範圍就停下來問」。等 codex 跑完, 還要拉一次 <code>git diff</code> 看它有沒有越界, 越界就回滾。</p>
<p>這才是 skill 跟 prompt 真正的分水嶺。Prompt 給你的是「請小心」, skill 給你的是「跑完幫我比對, 超出範圍就回滾」。</p>
<h2 id="一個我必須講的疤痕">一個我必須講的疤痕</h2>
<p>回到最前面那句:「我請 AI 幫我寫」。</p>
<p>AI 寫得很好。看起來很專業, 該有的環節都有。我看了一眼覺得不錯, 直接合進去。</p>
<p>跑起來才發現問題:<strong>那些 codex CLI 的旗標, 有幾個是 AI 編出來的。</strong></p>
<p>不是它故意騙我, 是它根據訓練資料裡 codex CLI 的「應該長什麼樣」推測出來。但我那時候用的版本根本沒有那幾個旗標。前前後後修了兩三次, 跑一次 <code>codex --help</code>, 把實際存在的東西對回去, 才把這份 workflow 校準到真的能跑。</p>
<p>這就是我要寫這篇的原因。網路上很多在教「怎麼讓 AI 幫你寫 skill」, 沒人講事後看會發現什麼。我看到的是:AI 很會生 skill 的形狀, 但它對外部工具的真實 API 是用猜的。</p>
<p>那我學到什麼?不是「不要讓 AI 寫 skill」。寫得快, 結構也對。我學到的是 boundary 該畫在哪——agent 起稿結構沒問題, 我要做的是 verify 它生出來的東西對不對得上現實。Skill 的 dispatcher 部分 AI 寫沒問題, 被它指過去的那份 protocol, 特別是真實工具的旗標, 一定要對著 <code>--help</code> 校過再用。</p>
<h2 id="skill-是契約的形狀">Skill 是契約的形狀</h2>
<p>回到主題。一個 skill 最小可以多小?13 行。但那 13 行只是一張請帖, 真正的契約寫在它指過去的地方。</p>
<p>第一版讓 AI 寫沒關係, 它對形狀的直覺很好。要記得補的是 fallback 條款——「工具不在的時候怎麼辦」這條, 是讓它變成 skill 而不是 prompt 的最低門檻。然後任何指向外部工具的旗標, 親自跑一次 <code>--help</code> 對。AI 不會故意騙你, 但它會用很有把握的口氣猜。</p>
<p>老實說, 寫 skill 這件事我還在摸索。每次重看自己舊的 skill 都會發現邊界又該收一點。但有一件事我蠻確定:skill 是契約形狀的東西, 不是指令形狀的——這個區別比任何 prompt engineering 技巧都重要。</p>
<p>下一篇會拆 <code>ask-openrouter</code>——那是我自己寫的一個 repo, 把 OpenRouter 包成一個 repo-aware 的 CLI。它在這個系列裡的位置剛好相反:不是包外部工具的 dispatcher, 是那個被 skill 包起來的工具本身。同一條 boundary, 從反方向看。</p>
<p>最後一句重要的話:如果你準備自己動手寫一個 skill, 記得每個工具的慣例都不一樣 ——<a href="https://code.claude.com/docs/en/skills">Claude Code 官方 skills 文件</a>、<a href="https://developers.openai.com/codex">OpenAI Codex CLI docs</a>、Cursor 的 <code>.cursor/rules</code>、AGENTS.md 規範, 各自有自己的形狀。寫之前對著官方文件再確認一次, 包括這篇——blog 文會過期, 官方文件不會等你。</p>
<p><em>Agentic OS 是開源專案:<a href="https://github.com/KbWen/agentic-os">github.com/KbWen/agentic-os</a></em></p>
<hr>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="/what-makes-an-ai-skill-different-from-a-prompt/">一個 AI Skill 和 Prompt 到底差在哪</a> — 把 skill 放回 stack 裡, 它不在 prompt 那一層, 也不在 agent 那一層</li>
<li><a href="/skill-boundary-design/">Skill 邊界設計:從能力到合約</a> — 邊界鬆掉等於一次沒講的破壞性變更</li>
<li><a href="/skill-design-as-interface-design/">Skill Design as Interface Design</a> — 英文版用 API 設計的角度寫同一件事</li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Skill 邊界設計:從能力到合約</title>
      <link>https://www.kbwen.com/skill-boundary-design/</link>
      <pubDate>Mon, 25 May 2026 13:00:00 +0800</pubDate><dc:creator>KbWen</dc:creator>
      <guid>https://www.kbwen.com/skill-boundary-design/</guid>
      <description>一個 skill 會多可預測,大概就看它的邊界劃得多清楚。把它當能力清單,它會亂跑;把它當合約(講好輸入、輸出、不碰什麼),它就比較像一個設計良好的 API。</description>
      <content:encoded><![CDATA[<blockquote>
<p><strong>TL;DR:</strong> 一個 skill 會多可預測,大概就看它的邊界劃得多清楚。把它當成「能力」(這個 skill 讓 AI 會做 X),它容易亂跑;把它當成「合約」(講好輸入、輸出、以及它不會碰什麼),它就比較像一個設計良好的 API。重點不是寫更多「要小心」,而是把它能碰的範圍框住。</p>
</blockquote>
<hr>
<p>我有個 skill,前一天還用得好好的,隔天就開始亂搞:我要它做 A,它順手把旁邊的 B 也「幫我」改了。我第一個反應是怪模型今天狀況不好。後來才想通,問題在我自己——當初寫這個 skill 的時候,我只說了它「會做什麼」,沒說它「不能碰什麼」。</p>
<p>這是<a href="/skill-design-as-interface-design/">英文版</a>的中文對照,英文那篇用 API 設計的角度談;這篇是我自己怎麼從「能力」這個想法,慢慢搬到「合約」這個想法的過程。</p>
<h2 id="能力清單-vs-合約">能力清單 vs 合約</h2>
<p>我們很習慣用「能力」來描述一個 skill:「這個 skill 讓 AI 會跑測試」「這個會幫我部署」。這種講法很自然,也很容易讓你之後被嚇到。因為「會跑測試」這句話沒有邊。它沒講會讀什麼、會動什麼、遇到不在預期內的狀況時會怎麼處理。</p>
<p>合約天生就有邊。它講清楚什麼東西進去、什麼東西出來、以及哪些地方它不會碰。框架文件裡有一句講得比我直接:skill 應該被當成「有版本、受政策約束、能力被框住的封裝」,而不是「一堆鬆散的 prompt 檔」。這跟<a href="/what-makes-an-ai-skill-different-from-a-prompt/">一個 AI Skill 和 Prompt 到底差在哪</a>講的是同一件事:重點不是 AI「能」做那件事,而是那件事被「講清楚」了。</p>
<h2 id="合約先行先想清楚它不該做什麼">合約先行:先想清楚它不該做什麼</h2>
<p>我看過一個還算貼切的比喻:skill 像是你交給一位很強的廚師的食譜。食譜提供的是結構:材料、順序、限制;廚師提供的是判斷,什麼時候醬汁該再收一下、什麼時候可以換個材料。你不會因為廚師很強,就把食譜寫成「做一道好吃的菜」。</p>
<p>skill 也一樣。模型本身的判斷力很好,所以你要補的不是判斷,是結構。而結構裡最常被漏掉的,就是那條「不要碰」的線。我現在寫一個 skill,會先問自己一個問題:<strong>這個 skill 最不該做的事是什麼?</strong> 把那條線寫進去,比再多寫三條「請謹慎處理」都有效。</p>
<h2 id="邊界鬆掉其實是一次沒講的破壞性變更">邊界鬆掉,其實是一次沒講的破壞性變更</h2>
<p>框架裡有一個原則我覺得很受用:<strong>寧可在邊界上把關,也不要去微管模型怎麼想</strong>。一個會亂跑的 skill,你通常修不好它的「想法」;你能做的是把它能碰的範圍(哪些檔案、哪些工具、多少預算)框起來。</p>
<p>一個 skill 的範圍如果隨著時間悄悄變大,那其實是你發佈了一次「破壞性變更」卻沒有改版本號。而呼叫它的人(就是你自己)會用最經典的方式發現這件事:在出事的時候。這也是<a href="/ai-agent-common-pitfalls-and-fixes/">AI 代理常見痛點</a>裡那個「能力邊界」缺口最貴的一種表現形式。範圍,只是它最容易爆出來的地方。</p>
<h2 id="我把一個-skill-從能力改成合約的前後">我把一個 skill 從能力改成合約的前後</h2>
<p>回到開頭那個亂改 B 的 skill。它原本的描述大概是「整理這個模組的程式碼」。很開放,聽起來很厲害,結果就是它對「整理」的理解跟我不一樣。</p>
<p>我後來把它改寫成比較像合約的樣子:輸入是「指定的那幾個檔案」,輸出是「格式化後的同一批檔案 + 一份它改了什麼的清單」,然後明確寫上「不要新增或刪除檔案、不要碰指定範圍以外的東西」。改完之後它沒有變笨,只是不再自作主張。差別不在能力,在邊界。</p>
<p>順帶一提,邊界清楚的 skill 通常也比較便宜。skill 是漸進載入的:AI 先讀那一小段 metadata 判斷現在用不用得上,真的要用才載入完整內容。一個邊界小而清楚的 skill,光看它的「合約」就能被快速略過;一個什麼都做的 skill,得把整包拖進 context 才發現其實不該用它。這跟我在 <a href="/token-cost-and-budget-tiers/">Token 成本</a>那篇講的是同一個方向:清楚的小合約,既好預測也比較省。</p>
<h2 id="還在摸索">還在摸索</h2>
<p>老實說,一個 skill 該有的合約長什麼樣,我很少一開始就想對。通常是看它在哪裡越界,再把線畫在那裡。但這個框架本身,先講好它承諾什麼、它不碰什麼,然後把對這兩者的任何更動都當成一次正式的改版,到目前為止站得住。</p>
<p><em>Agentic OS 是開源專案:<a href="https://github.com/KbWen/agentic-os">github.com/KbWen/agentic-os</a></em></p>
<hr>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="/beyond-prompt-from-instructions-to-building-systems/">只會 Prompt 已經不夠了:從「下指令」到「蓋系統」</a> — Skill 是這個系統思維裡的其中一層,先弄清楚整張地圖</li>
<li><a href="/ai-governance-with-prompts-and-skills/">只用 Prompt 和技能,也能做到基本治理</a> — 把合約思維用在 Skill 之外的層面:記憶檔、範圍宣告</li>
<li><a href="/work-log-cross-session-continuity/">Work Log:跨 session 的記憶機制</a> — Skill 解決能力邊界,Work Log 解決時間邊界</li>
</ul>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
