先講結論:想讓 Claude Code 穩定完成一件事,別只告訴它「怎麼做」,還要寫清楚「什麼時候不准說做完了」。
一份能用的 Skill,不是更長的 prompt。它是一張驗收單。
這是我做 baodao-skill 之後最想留下的結論。這個專案把台灣日常查詢整理成 AI 代理能讀的技能:發票對獎、YouBike、垃圾車、停車位,也有郵資、所得稅與勞健保的本地計算。現在有 27 個技能,開發過程寫成了 30 篇鐵人賽施工日記。
不是 27 支政府 API。有些來源是公開網頁或檔案,有些技能完全不連網;也不是「全部免金鑰」,目前三個技能需要免費申請的政府資料金鑰。把這些差別講清楚,本身就是技能的一部分。
如果你搜尋 Claude Code Skills,是想知道怎麼把 AI 從「會寫程式」變成「能放心交一件事」,這篇不用從第一天開始追。我們直接看最重要的差別。
Claude Code 官方文件的基本單位很簡單:一個目錄,一份 SKILL.md。前面的 YAML 描述用途,後面的 Markdown 寫流程,也可以附腳本與參考資料。
檔案很容易寫。難的是裡面的判斷。
例如「查附近診所」:取得官方 JSON,篩地址,印名字。看起來三步就結束。
但健保署的資料 API,limit=40000 不會真的回四萬筆。2026-09-20 實測,它只回 1,000 筆;當時總數是 37,133,要分 38 頁才拿齊。
若只看「有回 JSON、裡面有診所」,你就會把第一頁當成全台灣。查不到某家診所,不是它不存在,是你的世界只有第一頁。
程式可以正常結束,答案卻不能交出去。
我現在把這個差別濃縮成四格:
能做:從哪裡拿資料,怎麼處理?
算對:拿什麼證據驗收,不只看程式沒報錯?
不做:哪些請求超出能力,不能裝作答得出來?
怎麼說:答案帶哪些時間、來源與限制?
這四格是本文的整理方法,不是 Claude Code 的設定欄位,也不是官方規格。
下面用真實修正記錄填它。
做技能很容易有一種衝動:先寫個漂亮的解析器。
但 Day 6 的日記就是反例:處理完行事曆 xlsx,才發現官方結構化 CSV 已經在那裡。這時最有價值的改動不是把 parser 寫得更厲害,而是少做一個 parser。
給 Claude Code 的工作也一樣。我會先把任務改寫成:
先列官方來源與資料格式,找出能直接使用的結構化資料,再決定需不需要解析網頁。找不到可驗證來源,就先報告,不要補一個猜的網址。
這是工作提示,不是一次實測的對話紀錄。
你可以把 AI 當成手很快的同事。但手快之前,要先確認拿的是正確那份檔案。否則效率只是把錯路走得更遠。
我遇過一個比語法錯誤麻煩得多的 bug:台股「漲幅前十名」,原本按 Change 排序。
Change 是漲了幾元,不是漲了幾%。高價股漲十元,不一定比低價股漲一元厲害。
目前文件的算法是:
昨收 = 收盤價 - 價差
漲幅 = 價差 / 昨收
空字串或昨收為 0:略過,不硬算
這個修正記在 2026-10-02 的 CHANGELOG。程式能跑、結果有十支股票、數字也像真的,都不足以抓出它。
所以驗收案例要故意讓「錯算法」和「對算法」分出不同答案。
統編檢核也踩過同一種坑。原本拿 97176270 當第七碼為 7 的特例測試,後來發現它走一般規則就會通過,根本測不到特例有沒有實作。0.8.3 改用合成向量 10000073:不處理特例就不合法,處理特例才合法。
這不是多加一個 assert 的問題。是先問:
如果程式少寫了我要驗的那條規則,這個測試會不會仍然通過?
會的話,那個綠燈沒有替你證明那條規則。
同理,現在的回歸測試會抽出 SKILL.md 裡的程式執行,而不是另外抄一份差不多的算法。文件錯、測試副本對,照樣能得到一個很漂亮、很沒用的綠燈。
「不做」不是推卸,是畫清能力的邊界。
taiwan-stock 是收盤資料,不是盤中報價。taiwan-hospital 是院所名錄,不知道現在排隊多久,也不能幫你掛號。taiwan-id-check 能驗檢查碼,不代表這個身分證字號屬於真人,更不代表查到了誰。
若技能只列功能、不列禁區,使用者一句「那順便幫我……」,任務就可能從查資料滑到你根本沒有的能力。
baodao-skill 的範圍刻意停在查詢與計算:不預約、不購買、不發文。README 也列了評估後沒納入的路線。
有一條線更重要:抓不到資料,不准用猜的資料把流程補完。
發票 parser 曾把頁首、頁尾清冊連結裡的獎項字樣讀進去,結果特獎配到了錯的號碼。0.8.2 的修正是從期別後第一個「獎別」表格開始解析,並加上回歸與煙霧測試。
這時真正值得保存的不是「下次小心」,而是把錯誤的入口封住。資料結構不符合預期,就停;沒有驗證過的號碼,就不報。
我另外寫了一篇 HTTP 200 不等於成功,專門整理資料抓取的假成功。這篇更想補上後半句:AI 說「完成」,也不等於驗收通過。
假設技能真的拿到 YouBike 車數。只回答「還有三台」,資訊仍然少一半。
哪個站?資料幾點更新?是一般車還是電輔車?空欄位是零,還是沒有資料?
所以專案另外整理了共通的回應規則:
-9 等缺值如實說「無資料」,不能換成零。這些規則不會讓回答更炫。它們只是讓讀者知道能信到哪裡。
我喜歡把它想成食品標示:菜可以很好吃,但包裝上還是要寫保存期限。你不能用廚藝取代保存期限。
不需要一開始就做 27 個。選一件你常問、資料來源清楚、結果可驗證的小事,先做一個。
下面是作者用的骨架,不是可直接查詢的成品;把來源、欄位與案例補齊,再讓代理使用:
---
name: my-data-lookup
description: 查詢某項公開資料;使用者問相關資料時使用。
---
## 能做
- 使用已驗證的官方來源。
- 寫明必要參數、分頁方式與資料更新頻率。
## 算對
- 回應不是錯誤頁,必要欄位齊全。
- 資料日期符合請求;需要全量時驗證分頁完整性。
- 至少一個會讓錯算法失敗的驗收案例。
## 不做
- 不猜缺值,不把歷史資料說成即時資料。
- 超出查詢範圍或來源無法驗證時,停下來說明。
## 怎麼說
- 回答附來源、資料時間與限制。
- 將已知值、推算值、無法確認的部分分開。
在 Claude Code,專案技能可放 .claude/skills/my-data-lookup/SKILL.md;個人技能可放 ~/.claude/skills/my-data-lookup/SKILL.md。用途描述幫它判斷何時載入,也可以直接用 /my-data-lookup 呼叫。以 官方 Skills 文件 為準。
若想看現成案例,baodao-skill README 提供的單技能安裝方式是:
# 需要 Node.js 18+ 與 npx;安裝前先讀公開倉庫內容
npx --yes skills add tahodev/baodao-skill --skill invoice-winning-numbers -g
安裝不是驗收。裝好之後,拿一個你已知道答案的案例、一個邊界案例、一個應該拒答的請求試它。尤其發票與期限這類重要資訊,仍要對照官方公告。
30 天的收尾文章沒有寫「完美完成」。它記下當時的數字:2026-10-07 的統計有 28 次排程 run,13 綠、15 紅。
紅燈也不是 15 次 API 壞掉。Day 29 拆開後,10 次在 counts 步驟,5 次在 URL 檢查。部分問題是把會變動的院所、停車場數量寫死,檢查本身在誤報。
後來改成漂移警告、完整性檢查,還得處理兩次請求之間 total 改變的情況。綠燈若包含網路限制的 WARN 或略過,也不能說那個來源已經驗證成功。
這些是當時的紀錄,不是今天的 CI 狀態。
它們教我的不是「測試越多越好」,而是:每盞燈到底證明了什麼,要說得出來。
Claude Code 能幫你把流程做快。Skills 能把可重複的做法留住。但「答案可以交給人使用」這件事,還需要驗收、拒答與回報方式。
你下次寫 Skill,可以先不加更多步驟。先加一句:
遇到什麼情況,我寧可回答不知道,也不交出一個看起來成功的答案?
那句話,常常比下一百行程式更有用。
原始材料與延伸閱讀:
SKILL.md 是正本。