實作第一個 Agent Skill

在了解了設計原則後,這篇文章將帶你從零開始,實際動手寫出一個可運作的 Agent Skill。

許多開發者剛接觸 AI 工具開發時,常常不知道該從何下手:「我該建立哪些檔案?」「檔案內容的格式長什麼樣子?」為了解決這個問題,業界逐漸形成了一些標準化的規範。這裡我們將以廣泛支援 Claude 與各式 Agent 的 agentskills.io 規範為基礎,並結合 ChatGPT 自訂動作 (Custom Actions) 的概念,為你詳細拆解技能的開發步驟。

標準化技能的資料夾結構

一個結構良好的 Agent Skill 不應該只是一段散落的提示詞 (Prompt),而是一個具備完整封裝的模組。根據標準規範,一個完整的技能通常包含以下資料夾結構:

my-web-scraper-skill/       # 技能的根目錄(資料夾名稱通常等於技能名稱)
├── SKILL.md                # 【必填】核心設定檔:包含技能的元資料與執行指令
├── scripts/                # 【選填】可執行的腳本程式碼(如 Python, Node.js, Bash)
├── references/             # 【選填】參考文件(如 API 文件、Schema 定義)
└── assets/                 # 【選填】靜態資源(如輸出格式的範本檔)

這種結構的好處是「漸進式揭露」。Agent 在初始化時只會讀取 SKILL.md 的頭部資訊;直到它確定要使用這個技能時,才會進一步讀取底下的 scripts/references/,大幅節省 Token 的消耗。

核心檔案:SKILL.md 的撰寫格式

SKILL.md 是整個技能的大腦。它由兩個部分組成:上方的 YAML Front Matter (用來定義元資料),以及下方的 Markdown 本文 (用來撰寫給 AI 看的指令)。

1. 定義元資料 (Front Matter)

這部分是寫給 Agent 的「大腦」看的,讓它知道什麼時候該呼叫這個工具。

---
name: web-scraper-skill
description: 從指定的網址擷取網頁內容,並轉換為乾淨的 Markdown 格式。當使用者要求「讀取網頁」、「總結文章」或提供一個 HTTP 網址時,請使用這個技能。
compatibility: 需要 Python 3.10+ 與 BeautifulSoup 函式庫
---
  • name: 技能的唯一識別碼(只能使用小寫字母與連字號,且必須與資料夾名稱相同)。
  • description: 最重要的一環!你必須在這裡寫下「這個技能的作用」以及「觸發的時機」。ChatGPT 或 Claude 都是依靠這段文字來決定是否執行此工具。
必要的 Frontmatter 只有 name, description,其他皆可省略。

2. 撰寫執行指令 (Instructions)

在 Front Matter 之後,你要用自然語言加上 Markdown 語法,明確告訴 Agent 觸發技能後該做哪些事。

當你需要讀取網頁內容時,請嚴格遵守以下步驟:

1. 檢查使用者提供的網址是否為有效的 HTTP/HTTPS 連結。
2. 在終端機中執行我們的爬蟲腳本:
   ```bash
   python scripts/fetch.py "<目標網址>"
   ```
3. 腳本會將結果輸出為 Markdown。請讀取輸出結果,並根據使用者的原始需求進行總結或回答。

**注意事項 (Gotchas):**

- 如果遇到 403 Forbidden 錯誤,請告訴使用者該網站可能阻擋了爬蟲,請勿嘗試重複請求。

在這段指令中,我們清楚定義了 Agent 的操作步驟,甚至把可能遇到的錯誤處理方式都寫進去了。

實戰範例:結合 Scripts 打造網頁擷取技能

為了讓 Agent 能穩定執行任務,我們不應該讓 AI 自己去「猜」怎麼寫爬蟲程式,而是預先寫好一支腳本放在 scripts/ 資料夾中。

以下是 scripts/fetch.py 的簡單範例:

# scripts/fetch.py
import sys
import requests
from bs4 import BeautifulSoup

def fetch_url(url):
    try:
        # 實作簡單的網頁擷取邏輯
        headers = {'User-Agent': 'Mozilla/5.0'}
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()

        soup = BeautifulSoup(response.text, 'html.parser')
        # 提取文字並印出
        print(soup.get_text(separator='\n', strip=True)[:2000]) # 限制輸出長度
    except Exception as e:
        print(f"Error fetching URL: {str(e)}", file=sys.stderr)

if __name__ == "__main__":
    if len(sys.argv) > 1:
        fetch_url(sys.argv[1])
    else:
        print("請提供目標網址", file=sys.stderr)

這樣設計為什麼好? 當 Claude (例如在 Claude Code 環境下) 收到「幫我總結 https://example.com 的內容」時:

  1. 它會配對到 web-scraper-skill 的 description。
  2. 閱讀 SKILL.md 的指令,得知需要執行 python scripts/fetch.py "https://example.com"
  3. Agent 在背景執行該腳本,拿回乾淨的文字內容。
  4. Agent 將文字內容結合自己的語言能力,生成最終總結給使用者。

在 Claude 與 ChatGPT 上的實務差異

雖然上述的 SKILL.md 資料夾結構是針對支援本地開發環境的 Agent(如 Claude Code 或 VS Code Agent)所設計,但背後的開發邏輯與線上平台的設定是完全相通的。

如果你是要在 ChatGPT 上開發 Custom GPTs,或是撰寫 Claude 的 Tool Schema:

  • SKILL.md 裡的 description,就等同於你在平台上填寫的 "Description" 欄位。
  • SKILL.md 裡的指令與腳本邏輯,則會轉換為提供給平台的 OpenAPI Schema (定義 API 端點、參數格式),而實際的 scripts/fetch.py 邏輯則會部署在你自己的後端伺服器上。

掌握了如何切割模組、撰寫精準的 Description 以及規劃防呆指令後,無論你使用的是哪一種 AI 平台,都能寫出高穩定性的 Agent Skills!