Claude API 中的 Agent Skills:如何不使用 Claude Code 就能使用現成技能
Markdown如何將現成的 pptx 技能連接至 Claude API:container.skills、程式碼執行工具、檢查回應,以及透過 Files API 下載簡報。
閱讀全文
重點
文件用的現成 Agent Skills 可以透過直接呼叫 Claude API 使用:在 container.skills 中指定技能,並啟用 code_execution。第一次提出請求時,請使用官方範例中的相容模型與工具組合。生成的檔案需另外使用其 file_id 下載;範例使用相同的 API 金鑰提出請求並下載檔案。
您可以在 Ailoot 文件中找到更多指引。
透過 Claude API 使用 Agent Skills 需要準備什麼?
本指南說明如何從程式直接呼叫 API,而不是在 Claude Code 中安裝技能。您需要 Claude API 金鑰、所選模型的使用權限,以及 Python 3。以下程式碼使用 Python 標準函式庫和 HTTP,因此不受您安裝的 SDK 版本影響。金鑰透過 ANTHROPIC_API_KEY 環境變數傳入;請勿將金鑰放在程式文字或對話中。
API 提供 Anthropic 的現成技能:簡報用的 pptx、試算表用的 xlsx、Word 文件用的 docx,以及 PDF 用的 pdf。這些技能透過 type: "anthropic" 連接。本指南使用現成技能,不會上傳自訂技能。
撰寫本資料時開啟的官方快速入門指南,使用的是 claude-opus-5-5 與 code_execution_20260521 的組合。以下範例也使用這組搭配。此範例已對照文件檢查,並非付費 API 執行結果的報告。
需要哪些 Beta 標頭
範例遵循快速入門指南目前的 HTTP 契約:標頭為 x-api-key、anthropic-version: 2023-06-01 和 content-type: application/json;不會傳送 anthropic-beta。請勿混用不同版本文件中的模型、呼叫方式和回應格式。
Files API 文件也指出,API 已不再處於 Beta 階段。舊的 files-api-2025-04-14 標頭會保留舊版回應格式;移除該標頭則會切換為目前的格式。因此,使用 client.beta.files 的舊範例不能直接與新範例混用。
本指南不會將既有服務從舊版 Beta 契約遷移。如果您已經有這類服務,請先檢查它使用的標頭和回應格式。SDK 方法名稱中有 beta 一字,本身並不足以判斷;Files API 文件另有說明不同 SDK 版本的行為。
建立簡報並下載檔案
此範例會送出一項建立五張再生能源主題投影片的任務,將完整回應儲存到 skill-response.json,接著擷取生成檔案的 ID。它不會從模型回應中取得儲存路徑,而是將檔案存到新建的本機資料夾 skill-output。如果該資料夾已存在,程式就會停止,以免覆寫先前的結果。 資料夾在 API 呼叫之前就會建立,因此呼叫失敗後也會留下。再次執行前,先檢查並保留該次嘗試;不要只為了讓重跑通過就刪除資料夾。
import json
import os
from pathlib import Path
from urllib.error import HTTPError
from urllib.request import Request, urlopen
API = "https://api.anthropic.com/v1"
KEY = os.environ["ANTHROPIC_API_KEY"]
HEADERS = {
"x-api-key": KEY,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
}
def request(path, payload=None, binary=False):
data = None if payload is None else json.dumps(payload).encode("utf-8")
req = Request(API + path, data=data, headers=HEADERS)
try:
with urlopen(req, timeout=600) as result:
body = result.read()
except HTTPError as error:
try:
details = json.loads(error.read().decode("utf-8"))
except (ValueError, UnicodeError):
details = {}
info = details.get("error", {})
request_id = error.headers.get("request-id") or details.get("request_id")
diagnostic = {
"http_status": error.code,
"request_id": request_id,
"error_type": info.get("type"),
"message": str(info.get("message", "No JSON error message")).replace(KEY, "[REDACTED]")[:1000],
}
(out / "skill-error.json").write_text(
json.dumps(diagnostic, ensure_ascii=False, indent=2), encoding="utf-8"
)
raise RuntimeError(
f"Claude API HTTP {error.code}; request_id={request_id}; inspect skill-error.json"
) from None
return body if binary else json.loads(body)
out = Path("skill-output")
out.mkdir(exist_ok=False)
response = request("/messages", {
"model": "claude-opus-5-5",
"max_tokens": 16000,
"container": {
"skills": [{"type": "anthropic", "skill_id": "pptx", "version": "latest"}]
},
"messages": [{
"role": "user",
"content": "請以我偏好的語言製作一份包含 5 張投影片、主題為再生能源的簡報。",
}],
"tools": [{"type": "code_execution_20260521", "name": "code_execution"}],
})
(out / "skill-response.json").write_text(
json.dumps(response, ensure_ascii=False, indent=2), encoding="utf-8"
)
print("stop_reason:", response.get("stop_reason"))
file_ids = []
for block in response["content"]:
if block["type"] == "bash_code_execution_tool_result":
result = block["content"]
if result["type"] == "bash_code_execution_result":
for item in result["content"]:
file_id = item.get("file_id")
if file_id and file_id not in file_ids:
file_ids.append(file_id)
if not file_ids:
raise RuntimeError("No generated file_id; inspect skill-response.json")
for index, file_id in enumerate(file_ids, start=1):
from urllib.parse import quote
file_path = "/files/" + quote(file_id, safe="")
metadata = request(file_path)
if metadata.get("downloadable") is not True:
raise RuntimeError("This file cannot be downloaded through Files API")
target = out / f"result-{index}.pptx"
target.write_bytes(request(file_path + "/content", binary=True))
print("Saved:", target)
result-1.pptx 等名稱是為這項簡報任務選用的。檔案副檔名無法證明檔案內容;請開啟下載的文件,檢查其格式、投影片數量和文字。不要只憑 HTTP 200 或出現 file_id 就認定結果成功。
程式會輸出 stop_reason,也就是回應停止的原因,並儲存完整回應供檢查。它不會繼續對話,也不會自動重複付費請求。下載到檔案不代表整項任務已完成:在決定是否需要再次提出請求前,請檢查儲存的回應和文件本身。
若嘗試失敗,請檢查是否有 skill-error.json。其中記錄 HTTP 狀態、供應商提供的請求 ID,以及已移除設定金鑰並限制長度的供應商錯誤訊息。分享前仍須檢查是否含有其他私人資料。請將驗證、權限/模型、帳務上限與請求格式錯誤,對照官方錯誤參考文件,不要認為所有失敗都需要重新付費生成。
如果 skill-response.json 已有生成的 file_id,只有下載失敗,請保留回應,以相同且獲授權的工作區權限檢查中繼資料及下載步驟。不要為了下載既有輸出就重跑生成區塊。若請求結果不明,先保留請求 ID 並查清狀態,再送出另一個生成請求。只有確認需要新生成後,才將本機輸出行改為未使用的路徑,例如 out = Path("skill-output-attempt-2"),並保留 exist_ok=False。新資料夾能避免覆寫,不能防止 API 重複收費。
需要哪些檔案權限
Files API 會將檔案關聯至工作區,而非您應用程式中的個別使用者或對話。根據文件說明,任何具有該工作區存取權的 API 金鑰,都能存取上傳到其中的檔案。範例使用相同金鑰進行下載與生成。請勿接受終端使用者或其他不受信任來源提供的 file_id。請將這些 ID 儲存在伺服器上,並在自己的應用程式中維護使用者與其檔案之間的對應關係。
請另外檢查檔案中繼資料:其中必須包含 downloadable: true。文件允許下載由技能或程式碼執行工具生成的檔案;您上傳的檔案則會是 downloadable: false,嘗試下載時會回傳 400。工作區存取權和下載特定檔案的權限是兩項不同的要求。
對於多使用者應用程式,Files API 文件建議為每位客戶使用獨立工作區,作為檔案隔離邊界。這項建議只針對檔案;未檢查相關 API 前,不要將其延伸到所有實體和權限。
現成技能與自訂技能
現成技能的 ID 為 pptx、xlsx、docx 和 pdf。在技能清單參考文件中,custom 來源被描述為工作區專用,而 anthropic 則是共用且唯讀。
第一個範例中的 version: "latest" 代表該技能最新發布的版本。若要建立可重現的整合,請留意所選版本可能會變動;若要切換到固定版本,必須選擇您所用技能的一個既有版本,而非使用範例中虛構的 ID。
限制與下一步
此範例只涵蓋使用現成技能建立簡報並下載。這裡尚未測試上傳或刪除自訂技能,以及存取第三方服務。這些工作需要另外檢查相關 API。
若您的任務涉及 Claude 介面中的檔案,請參閱另一篇指南:如何將檔案上傳至 Claude。若要直接呼叫 API,請參閱如何計算 API Token 使用量。若要在終端機代理程式中工作,請閱讀如何選擇 Claude Code 技能:它們的連接方式不同。
初步檢查只需使用一個現成的 pptx 技能:檢查回應、下載允許下載的檔案,並開啟檔案。完成這項檢查後,再新增自訂技能和客戶間的存取隔離。
準備好之後,來認識 Ailoot。
更多詳情
常見問題:Claude API 中的 Agent Skills:如何不使用 Claude Code 就能使用現成技能
為什麼拿到 file_id 還不能宣告簡報完成?
ID 只代表有檔案回傳,不能證明它是可用簡報。請確認中繼資料為 downloadable: true,透過工作區權限下載,再開啟檢查檔案格式、投影片數量與文字。
Claude Files API 上傳的任何檔案都可以下載嗎?
不是。指南區分標示 downloadable: true 的生成檔案,與標示 downloadable: false 的上傳檔案。工作區存取與特定檔案的下載權限需分開確認,不要接受終端使用者任意提供的檔案 ID。