跳至主要內容
EMil Wu
EN

#37

實戰 Tips 5:不是 Skill,也不是程式 — 我用合約做出的兩個工具

Practical Tips 5: Not a Skill, Not a Program — Two Tools I Built as Contracts

實戰心得 10 分鐘閱讀
工作台上兩個手作的小工具,一個像提燈、一個像對話框,各自綁著一卷蓋了檢核印章的合約 工作台上兩個手作的小工具,一個像提燈、一個像對話框,各自綁著一卷蓋了檢核印章的合約
我交出去的不是 Skill,也不是程式,而是兩份合約,寫清楚要交出什麼、怎麼檢查,中間留給 Agent 自己長出來

我交出去的兩個工具不是 Skill,也不是程式,而是兩份合約,寫清楚要交出什麼、怎麼檢查,中間留給 Agent 依使用者的情境自己長出來。


10 月初的一個中午,我在公司的企業 Agent 上開始安裝使用給部門或者個人使用的 Document-Bot,一路弄到下午 3 點多,整個三個多小時的過程我只用了一份 md 檔,沒有 skill.md、沒有 Plugin,甚至沒有給他程式,事後用 6 張截圖回報,由我的 Agent GM 整理成試用紀錄[1],沒有限制用 Claude Code,也不限制 Codex,而那份檔案本身也沒有規定該包成什麼形式,Agent 讀完之後,自己用自己的理解建成了平台上的一個 Skill,放在工作目錄下。

接下來他做的事,幾乎就是那份檔案希望他做的,先盤點 Python、Node、markitdown、QMD、SQLite 這些他規劃出來的前置條件,再判斷手上有多少資料,應該只屬於最小的 S 段,所以主動不下載模型(省掉大約 2.19 GB),ingest 之前先宣告預期會變更哪些東西,3 個 wiki 頁、index 和 log。

我用中文整句去問英文文件裡的內容,他答對了,也引用了原文,我再問一個資料裡根本沒有的「怎麼養寵物」,他把問題拆成「寵物/飼養/pet」三個詞分別查,三個都零結果,回答時明說只跑了 BM25 詞彙搜尋,沒有執行語意搜尋,最後建議我匯入資料。

一份「不是 Skill」的東西,交到 Agent Platform(這會是另外一個 Topic)上,最後成為一個 Skill,好像還不錯?我在筆記裡是這樣寫的:「在這樣的情況之下,我不用管工具或平台的適用性,甚至連它是符合 Codex 還是 Claude 的格式都不用擔心。因為要點是提供 Agent 可理解的方法論,剩下的事就讓它去做。」

前兩篇心法(流程不是重點,合約才是、讓 AI 決定流程)講的是企業裡的合約與檢核點,這篇回到我自己手上,講兩個我做出來、既不是 Skill 也不是程式的東西,一個是 Document-Bot,另一個是教 Agent 怎麼說話的 Plain Technical Style。


Document-Bot:從打包一個 Agent,到寫一份方法

Document-Bot 一開始並沒有打算這樣做,9 月 22 日的 v1 計畫裡,他還叫做 Portable Document Agent,交付物是由負責建置的 Agent Dm 用我的 Knowledge Agent(Agent Em)作為基礎框架,簡化之後來「建一個打包好的 standalone agent」[1],固定的目錄樹、一串 Python 腳本、forked skills,再配一套 Dm 從設計做到驗證的 6 步派工流程,最後由 GM 搬移與驗收,又因為我選了支援 Windows 原生,原本兩支可以直接沿用的 .sh 腳本,被降級成要改寫成 Python(一個平台選項,就讓兩支腳本從「沿用」變成「重寫」),當時我說的是「規劃完成就好,是否開工我另外決定」,所以計畫就停在規劃完成的階段。

九天後的 10 月 1 日,我因為決定了 AI 合約的概念,所以重新定義了交付物,我讓 GM 依照我說的記成逐字摘要:「這應該會是一個讓使用者自己建立 Document-Bot 的說明文件…不打包 QMD 跟 LLM Wiki,而是讓使用者自己依照需求建立這些東西…參考 LLM Wiki 的原始網頁,他不是一個完整的 Skill 或者 Agent 打包,而是指引 Agent 建立 LLM Wiki 的說明」,同一場我做了 12 項裁決,Document-Bot 這個名字也是那天定的,LLM Wiki 在上一篇已經介紹過,這裡只補一句,Document-Bot 是站在 LLM Wiki 這個巨人的肩膀上,加了 markitdown 負責把各種格式轉成 markdown,再加了 QMD 負責本地搜尋。

計畫裡有記錄這次轉向的框架講得很清楚:「我們交付的是 Pattern + 判斷方法 + 我們付過代價才知道的陷阱,不是實作」,V2 一口氣把固定目錄結構、Dm 的派工流程、Windows 原生的打包約束整批刪掉,旁邊只註明「使用者的 agent 自己決定」,最後生出來的是一份 Idea File,開頭第一段就寫清楚「It is a pattern, not a package」[1],是一個模式,不是一個安裝包,這就是心法篇說的不定流程,流程從我原本固定寫死的那一份,變成每個 User 的 Agent 自己排的那份。

flowchart TB subgraph V1["V1 計畫(9 月 22 日)Portable Document Agent"] A1["交付物:打包好的 standalone agent"] --> A2["固定目錄樹 · Python 腳本 · forked skills<br/>Dm 從設計到驗證的 6 步派工 · Windows 原生的打包約束"] A2 --> A4["停在規劃完成"] end subgraph V2["V2(10 月 1 日)Document-Bot"] B1["交付物:pattern + 判斷方法 +<br/>付過代價才知道的陷阱"] --> B2["固定目錄、派工流程、打包約束<br/>使用者的 agent 自己決定"] B2 --> B3["It is a pattern, not a package"] end V1 -->|"重新定義交付物"| V2
Document-Bot 從 V1 到 V2:流程還在,只是從我寫死的那一份,變成每個使用者的 Agent 自己排的那一份

Document-Bot 的合約:方法論、工具、檢查清單

我在筆記裡這樣描述 Document-Bot:「給一個方法論,以及搭配這個方法論的工具有哪些,最後是一個檢查清單,讓 AI 自己依照使用者的狀況來建立」,回頭對照那份 idea file,剛好就是三塊:

  • 方法論:Onboarding 七步,檢查前置、盤點語料、檢查當下實際能力、提案並取得同意、安裝並用真實樣本測、用成對問題驗證、把決策寫進 schema,再加上一份 absence contract,把「沒找到」當成一個需要證據、需要範圍、而且工具得先健康的陳述。
  • 工具:Prerequisites,全文唯一刻意寫得很具體的一節,markitdown、QMD、SQLite 加 sqlite-vec、本地的 GGUF 模型,裝了哪個版本就釘住、記下來,但我希望之後連這塊也要 Idea 化。
  • 檢查清單:Verify 的 10 項,成對的「有資料」與「沒資料」問題,還有刻意製造降級狀態,看他會不會老實說「搜尋不完整」,或者說「資料裡沒有」。

至於中間怎麼走,檔案最後一節寫得很直白,目錄名稱、頁面分類、frontmatter、指令、門檻、preset,「and even the chosen tools are examples」,連選好的工具都只是範例,唯一不能改的是「honesty about what was actually searched」[1],也就是老實交代自己到底搜了什麼、沒搜什麼。

為什麼連門檻都不寫死?因為這是付過代價才知道的陷阱,先是版本,QMD 的 rerankScore 在 2.5.3 版是有資料 0.73、沒資料 0.50,到了 2.8.3 變成 0.998 對 0.000014,同一個工具換個版本,分數分佈整個變了樣,把舊門檻沿用過去就是錯的,再來是中文,QMD 2.8.3 對中文的短詞沒有問題,可是整句問「公司的請假規定是什麼」會零命中,拆成「請假 規定」才找得到,如果 Agent 把那個整句的零命中當成答案,就會告訴你「沒有這份資料」,最後是體積,只用 BM25 的時候模型快取是 0 bytes,完整的三個模型加起來大約 2.19 GB,一個只有 20~30 份資料來源的知識庫,要先下載 2 GB 的模型實在是殺雞用牛刀。

所以 Document-Bot 的合約寫的是要通過的檢查,不是要照做的步驟, 畢竟數字一直在變,但我們要把關的檢查不會,所以這份檔案教 Agent 的不是「門檻設在多少」,而是每次升級之後,用成對的問題自己重新量一次。

小 Agent 走著自己選的彎曲小路,旁邊的小幫手沒有重畫路線,而是在終點加固檢核關卡 小 Agent 走著自己選的彎曲小路,旁邊的小幫手沒有重畫路線,而是在終點加固檢核關卡
試用之後改的不是步驟,而是「什麼情況才算做完」

試用改寫的是檢核點,不是步驟

回到那場試用,老實說這只是 N=1,單一平台、單一來源、單一使用者,核心行為都通過了,但 GM 整理時抓到一個疑點,QMD 索引了 4 份文件,wiki 卻只有 3 頁,GM 先猜多出來的是 index 或 log 這類導航檔,寫了一份唯讀的排查 prompt 交給我,我再把它貼回 Agent 裡頭(只查不改,要動手的修正都等我確認),最後找到多出來的是驗證 BM25 時建的一頁測試頁,GM 的推測也就自己更正了。

同一次排查還翻出三件事,第一,absence 沒有記進 log,idea file 的規則 6 明明寫了「Log the gap」,他回答時就是沒做,第二,AGENTS.md 宣稱排除了 index 和 log,實際上沒有任何 ignore 設定,原始文件數也還寫著 0,schema 記的是「打算」而不是「實況」,第三,他沒有記下「為什麼不裝模型」。

試用 3 點 52 分結束,4 點 05 分 GM 就依試用結果改了 4 處(經我同意直接改),第 7 步的前後對照是這樣:

修訂前:7. Record decisions in the schema.
修訂後:7. Record decisions — and why — in the schema. … Write only what is actually configured and verified, not what you intend

決策要附上理由,而且只寫真的設定好、驗證過的,不寫虛的東西,四處修訂沒有一處在教 Agent 該怎麼建,改的全是「什麼情況才算做完」, 其實在試用之前,這份 idea file 自己就先過了一次關,由 Agent Em 起草,GM 對照證據查核,修掉 3 處超出證據的用詞,起草的是 Agent,查核的也是 Agent,我做的是裁決和試用。


Plain Technical Style:教 Agent 說話的設定檔

第二個工具,起點是 AI 太多話,筆記裡寫的是:「我一直遇到的一個問題是跟 AI 溝通時,它的說明或講話方式太冗長、抓不到重點,讓人無法理解」,接著是:「所以 Survey 過後綜合兩個跟說明文字有關係的標準規範,寫出了一個 Output 的 style。它不是一個 skill,而是一個設定檔案,主要是在教 agent 怎麼樣說話、怎麼溝通」(在做這份設定檔的 8 月 7 日當天,另一個平行跑著的 session 裡,我就對 Agent 打了一句「我看不懂你的問題,給我 Context、選項、跟原因」)。

Claude Code 的官方文件說,output style 是一組作用在整個 session、每一次回應上的指示,管的是 Claude 的角色、語氣和回應格式[3],它跟 CLAUDE.md 不一樣,CLAUDE.md 放的是專案慣例,也跟 Skill 不一樣,Skill 只在被叫用或任務吻合時才載入,不會影響無關的回應,而我想教 Agent 的說話方式,本來就該落在每一句話上。

兩個標準規範,一個是 ISO 24495-1:2023《Plain language — Part 1: Governing principles and guidelines》[4],另一個是 ASD 的受控語言標準 ASD-STE100 Simplified Technical English[5],這份設定檔的核心只有兩句:「ISO 24495-1 plain language decides WHAT the reader gets and WHERE it sits. ASD-STE100 Simplified Technical English decides HOW each retained sentence is worded.」[2],就像 code review 裡架構 reviewer 跟 lint 的分工,一個決定這段該不該存在、該放在哪裡,一個只管這行怎麼寫,而且這兩層「ranked, not sequenced」,比的是權責高低,不是誰先誰後,只有結構層可以刪內容、調順序,用字層永遠不准為了字數丟掉事實(lint 再怎麼嫌這行太長,也輪不到它把一段邏輯刪掉)。

ISO 那一層是四個原則,Relevant、Findable、Understandable、Usable,檔案特別寫明它們互相依存,不是流水線,「A response that satisfies three of them still fails.」,四個要同時成立,少一個都不算數,跟驗收條件很像對吧?雖然問題是 Agent 講話太冗長,但這份設定檔卻寫著「Clarity is the goal, not concision. A long answer in short sentences is correct.」,因為我的最終目的還是溝通,所以要的是清楚,不是短,回答可以長,只要每一句都短、清楚,它限制的是每一句話,不是整段回答的長度。

最後一條是讓位條款,使用者、專案指示、被叫用的 Skill,任何更具體的指示都優先,檔案還特別交代「Follow the more specific instruction without comment.」,照做就好,連解釋都不必,對照合約來看,四個原則同時成立是驗收,兩層的權責是條款,更具體的指示優先,就是把中間留給使用者的情境去客製化。

flowchart TB subgraph T["條款:兩層的權責(ranked, not sequenced)"] S["結構層:ISO 24495-1<br/>決定讀者拿到什麼、放在哪裡<br/>只有這層可以刪內容、調順序"] W["用字層:ASD-STE100<br/>決定每一句怎麼寫<br/>永遠不准為了字數丟掉事實"] S ~~~ W end subgraph A["驗收:四個原則同時成立"] P["Relevant · Findable<br/>Understandable · Usable<br/>少一個都不算數"] end subgraph C["客製:更具體的指示優先"] U["使用者 · 專案指示 · 被叫用的 Skill<br/>照做就好,連解釋都不必"] end T ~~~ A T ~~~ C
對照合約來看 Plain Technical Style:兩層的權責是條款,四個原則同時成立是驗收,更具體的指示優先,就是把中間留給使用者的情境去客製

連做的過程,都是一份合約

這份設定不是憑空寫的,8 月 4 日晚上,我先找了網路上兩、三份 STE100 的 output style 規格歸納出一份精簡版,三天後的中午,我開了一個 worktree 用 /goal-design 提出要求,「使用 asd-ste100 規範來管文法跟用字,但是邏輯跟結構採用 ISO24495 的規範」,網路上的資料讓 Agent 自己去平行讀。

/goal-design 把這個需求寫成一份 3988 字的 Goal Condition,驗收 8 項,每一項都要在對話裡拿出證明,工具清單標明「available; agent picks what fits」,有哪些工具可用,由 Agent 挑合適的,邊界是不准 commit、檔案不超過 8 KB、不准編造條文編號,失敗/逃生條件是 30 回合或 60 分鐘,我定下的是要交出什麼、怎麼檢查、哪些線不能踩,沒有任何一個步驟。

接著發生的事,就是合約該有的樣子,負責研究的 Agent 連不上 iso.org (因為完整 ISO 條文要註冊付費下載),最後他找到一份 ISO 授權經銷商的免費試閱版,裡面有真正的條文,接著整理出一張 27 列的權責表,其中 11 項原本兩邊重疊,最後每一項都只有一個擁有者。

小 Agent 敲不開緊閉的大門,自己繞到旁邊的小窗口找到一本試閱冊,四周只有邊界圍欄和終點旗,沒有畫好的路線 小 Agent 敲不開緊閉的大門,自己繞到旁邊的小窗口找到一本試閱冊,四周只有邊界圍欄和終點旗,沒有畫好的路線
合約只定下要交出什麼、怎麼檢查、哪些線不能踩,路是 Agent 自己找的

然後,GM 刻意偏離了一項驗收,原本要求 ISO 那一側一律標成「二手」,他改用三級證據分級,最後回報 PASS WITH DEVIATION,通過,但有偏離,30 回合的預算用了 11 回合。

偏離驗收,在流程的世界裡大概就是失敗,但我自己對這個偏離的理解跟字面規定不同,那份 Condition 的邊界裡寫著不准編造條文編號,但其實原因是背後更上位的一條規則『不說假話』,GM 守住的是那一條,而不是驗收清單的字面,所以回到合約來看,最後我們看的還是有沒有達成目的,因為合約不只是成品的形式,也是做事的方法, 當 Agent 有理由偏離,而且把理由寫清楚,偏離本身就是一份可以被檢查的交付,只要人類同意就可以。

收尾時我又多要了一件事:「…另外幫她寫一個中英文版本的 readme,說明該如何安裝使用,最好是 Agent 讀了可以自行安裝」,所以 README 裡有一段專門寫給 Agent 的安裝流程,最後一步是強制驗證,因為 outputStyle 的值只要大小寫不對,就會掉回 Default,「A successful write is not evidence that the style is active.」[2],寫了不代表真的生效,要讀回來確認,連安裝這件事也需要一個檢核點。


兩個工具的共同點

回頭看筆記,我寫了一句「整個概念其實跟合約的意思是一樣的」,兩個工具攤開來,做的都是同樣三件事:

  1. 寫清楚必須交出什麼,Document-Bot 要交出一個會帶引用回答、沒有資料時給出有範圍「沒有」的知識庫,Plain Technical Style 要交出四個原則同時成立的回應。
  2. 寫清楚怎麼檢查,Document-Bot 用成對的問題和強制降級來驗,Plain Technical Style 把安裝設定都讀進來確認。
  3. 只把真正不能變的東西寫死,Document-Bot 的 Prerequisites 和「對實際搜尋了什麼要誠實」,Plain Technical Style 的「用字層不准為了字數丟掉事實」,其餘全部交給 Agent 依使用者的情境長出來。

話說回來,Document-Bot 我手上有結果的試用只有一次,N=1,計畫裡原本要跑的 Claude Code 和 Codex 試用、minimal 和 maximal 兩個 preset 都還沒有結果,但交付出去之後的回報都是正面的,Plain Technical Style 也沒有量測過套用前後的差異,官方文件自己就說得很白,「It’s an instruction Claude follows, so nothing enforces it.」[3],它是 Claude 會遵守的指示,沒有任何東西強制執行,因為數字會變,檢查不會,這句話我自己一直記著。

流程是寫給今天的工具,合約是寫給明天的規則

或許下一次,你可以打開手上那份寫給 Agent 的 SKILL.md 數一數,有幾行是在告訴他怎麼走,又有幾行是在告訴他,走到哪裡才算到?


參考資料

[1] Emil Wu — Doc-Bot(GitHub repo,最後內容 commit 4ca0c8d,2026-10-02;支持 V1/V2 計畫、idea file 原文「It is a pattern, not a package」「Everything here is optional and changeable except honesty about what was actually searched.」、企業 Agent 平台試用紀錄與 4 處修訂)

[2] Emil Wu — plain-technical-style(GitHub repo,v1.0.0,2026-08-17;支持兩層設計「ranked, not sequenced」、四原則「A response that satisfies three of them still fails.」、「Clarity is the goal, not concision.」與安裝後的讀回驗證)

[3] Claude Code Docs — Output styles(官方文件,2026-10-15 讀取;支持「An output style is a set of instructions that sets Claude’s role, tone, and response format for every response in a session.」、output style 與 CLAUDE.md、Skill 的差異,以及「It’s an instruction Claude follows, so nothing enforces it.」)

[4] ISO/TC 37 — ISO 24495-1:2023 Plain language — Part 1: Governing principles and guidelines(2023-06;支持標準名稱、負責委員會與 relevant、findable、understandable、usable 四原則)

[5] ASD — FAQ: Simplified Technical English (STE)(支持 ASD-STE100 是 ASD 制定的受控語言標準,由 ASD Simplified Technical English Maintenance Group(STEMG)維護)

支持這個系列

如果這系列文章對你有幫助,考慮請我喝杯咖啡