Agent Skills ใน Claude API: วิธีใช้ skill สำเร็จรูปโดยไม่ใช้ Claude Code
Markdownวิธีเชื่อมต่อ skill pptx สำเร็จรูปกับ Claude API: container.skills, เครื่องมือเรียกใช้โค้ด, การตรวจสอบการตอบกลับ และการดาวน์โหลดงานนำเสนอผ่าน Files API
อ่านบทความฉบับเต็ม
ประเด็นสำคัญ
คุณสามารถใช้ Agent Skills สำเร็จรูปสำหรับเอกสารผ่าน Claude API โดยตรงได้ โดยระบุ skill ใน container.skills และเปิดใช้ code_execution สำหรับคำขอแรก ให้ใช้การจับคู่โมเดลและเครื่องมือที่เข้ากันได้ตามตัวอย่างอย่างเป็นทางการ ดาวน์โหลดไฟล์ที่สร้างขึ้นแยกต่างหากโดยใช้ file_id ของไฟล์นั้น ตัวอย่างนี้ใช้ API key เดียวกันทั้งสำหรับคำขอและการดาวน์โหลด
คุณดูคำแนะนำเพิ่มเติมได้ในเอกสารประกอบของ Ailoot
สิ่งที่ต้องมี
คู่มือนี้มีไว้สำหรับเรียก API โดยตรงจากโปรแกรม ไม่ใช่การติดตั้ง skill ใน Claude Code คุณต้องมี Claude API key สิทธิ์เข้าถึงโมเดลที่เลือก และ Python 3 โค้ดด้านล่างใช้ไลบรารีมาตรฐานของ Python และ HTTP จึงไม่ขึ้นอยู่กับเวอร์ชันของ SDK ที่คุณติดตั้ง คีย์จะส่งผ่านตัวแปรสภาพแวดล้อม ANTHROPIC_API_KEY อย่าใส่คีย์ไว้ในข้อความโปรแกรมหรือบทสนทนา
API มี skills สำเร็จรูปของ Anthropic ได้แก่ pptx สำหรับงานนำเสนอ, xlsx สำหรับสเปรดชีต, docx สำหรับเอกสาร Word และ pdf สำหรับไฟล์ PDF เชื่อมต่อโดยใช้ type: "anthropic" คู่มือนี้ใช้ skill สำเร็จรูป โดยไม่อัปโหลด skill ที่กำหนดเอง
คู่มือเริ่มต้นฉบับย่ออย่างเป็นทางการ ซึ่งเปิดดูตอนจัดทำเนื้อหานี้ ใช้การจับคู่ claude-opus-5-5 และ code_execution_20260521 ตัวอย่างด้านล่างใช้การจับคู่นี้ ตัวอย่างนี้ตรวจสอบกับเอกสารประกอบแล้ว แต่ไม่ได้รายงานว่ามีการเรียก API แบบเสียค่าใช้จ่ายจริง
ต้องใช้ beta headers ใดบ้าง
ตัวอย่างนี้เป็นไปตามสัญญา HTTP ปัจจุบันของคู่มือเริ่มต้นฉบับย่อ โดยใช้ headers x-api-key, anthropic-version: 2023-06-01 และ content-type: application/json และไม่ส่ง anthropic-beta อย่านำโมเดล วิธีเรียกใช้ และรูปแบบการตอบกลับจากเอกสารคนละรุ่นมาผสมกัน
เอกสาร Files API ระบุด้วยว่า API ออกจากช่วง beta แล้ว header เก่า files-api-2025-04-14 ยังคงใช้รูปแบบการตอบกลับแบบเดิม เมื่อนำ header ออก ระบบจะเปลี่ยนไปใช้รูปแบบปัจจุบัน นี่จึงเป็นเหตุผลว่าทำไมจึงนำตัวอย่างเก่าที่ใช้ client.beta.files มาผสมกับตัวอย่างใหม่โดยตรงไม่ได้
ในที่นี้เราไม่ได้ย้ายบริการเดิมจากสัญญา beta เก่า หากคุณมีบริการลักษณะนี้อยู่แล้ว ให้ตรวจสอบ headers และรูปแบบการตอบกลับก่อน คำว่า beta ในชื่อเมธอดของ SDK เพียงอย่างเดียวยังไม่เพียงพอ เพราะเอกสาร 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, request ID เมื่อผู้ให้บริการส่งมา และข้อความผิดพลาดที่จำกัดความยาวและลบค่า API key ที่ตั้งไว้แล้ว ตรวจว่าข้อความมีข้อมูลส่วนตัวอื่นหรือไม่ก่อนแชร์ เปรียบเทียบข้อผิดพลาดการยืนยันตัวตน สิทธิ์/โมเดล ขีดจำกัดการเรียกเก็บเงิน และรูปแบบคำขอกับ เอกสารข้อผิดพลาดอย่างเป็นทางการ อย่าสรุปว่าทุกความล้มเหลวต้องสร้างงานแบบเสียเงินอีกครั้ง
หาก skill-response.json มีค่า file_id ที่สร้างแล้วและล้มเหลวเฉพาะตอนดาวน์โหลด ให้เก็บการตอบกลับนั้นไว้ แล้วตรวจขั้นตอนเมตาดาทา/ดาวน์โหลดด้วยสิทธิ์ workspace เดิมที่ได้รับอนุญาต อย่ารันส่วนสร้างงานซ้ำเพียงเพื่อดาวน์โหลดผลที่มีอยู่ หากไม่ทราบผลลัพธ์ของคำขอ ให้เก็บ request ID และตรวจสถานะให้ชัดก่อนส่งคำขอสร้างใหม่ เมื่อมีเหตุผลแล้วว่าจำเป็นต้องสร้างใหม่ จึงเปลี่ยนบรรทัดเส้นทางไปยังโฟลเดอร์ที่ยังไม่เคยใช้ เช่น out = Path("skill-output-attempt-2") และคง exist_ok=False ไว้ โฟลเดอร์ใหม่ป้องกันการเขียนทับ แต่ไม่ได้ป้องกันการคิดค่าบริการ API ซ้ำ
ต้องมีสิทธิ์เข้าถึงไฟล์อะไรบ้าง
Files API เชื่อมโยงไฟล์กับ workspace แทนที่จะเชื่อมโยงกับผู้ใช้รายบุคคลในแอปพลิเคชันของคุณหรือกับบทสนทนา ตามเอกสารประกอบ API key ทุกคีย์ที่เข้าถึง workspace นั้นได้ก็เข้าถึงไฟล์ที่อัปโหลดไว้ที่นั่นได้ ตัวอย่างนี้ใช้คีย์เดียวกันสำหรับดาวน์โหลดและสร้างไฟล์ อย่ารับ file_id จากผู้ใช้ปลายทางหรือแหล่งอื่นที่ไม่น่าเชื่อถือ เก็บ ID เหล่านี้ไว้บนเซิร์ฟเวอร์ และจัดการการเชื่อมโยงระหว่างผู้ใช้กับไฟล์ของตนเองภายในแอปพลิเคชัน
ตรวจสอบ metadata ของไฟล์แยกต่างหาก โดยต้องมี downloadable: true เอกสารประกอบอนุญาตให้ดาวน์โหลดไฟล์ที่สร้างด้วย skills หรือเครื่องมือเรียกใช้โค้ด ส่วนไฟล์ที่คุณอัปโหลดมีค่า downloadable: false และการพยายามดาวน์โหลดจะได้ผลลัพธ์ 400 การเข้าถึง workspace และสิทธิ์ดาวน์โหลดไฟล์ใดไฟล์หนึ่งเป็นข้อกำหนดคนละข้อกัน
สำหรับแอปพลิเคชันที่มีผู้ใช้หลายคน เอกสาร Files API แนะนำให้ใช้ workspace แยกสำหรับลูกค้าแต่ละรายเป็นขอบเขตการแยกไฟล์ คำแนะนำนี้เจาะจงเรื่องไฟล์ อย่านำไปขยายใช้กับ entity และสิทธิ์ทั้งหมดโดยไม่ตรวจสอบ API ที่เกี่ยวข้อง
Skills สำเร็จรูปและ skills ที่กำหนดเอง
Skills สำเร็จรูปมี ID คือ pptx, xlsx, docx และ pdf ในเอกสารอ้างอิงรายการ skills แหล่งที่มา custom ระบุว่าเป็นแบบส่วนตัวสำหรับ workspace ขณะที่ anthropic เป็นแบบใช้ร่วมกันและอ่านอย่างเดียว
version: "latest" ในตัวอย่างแรกหมายถึงเวอร์ชันล่าสุดที่เผยแพร่ของ skill สำหรับการผสานระบบที่ทำซ้ำได้ โปรดคำนึงว่าการเลือกนี้อาจเปลี่ยนแปลงได้ หากต้องการเปลี่ยนไปใช้เวอร์ชันที่ระบุแน่นอน คุณต้องเลือกเวอร์ชันที่มีอยู่ของ skill ที่ใช้ แทนที่จะสร้าง ID ขึ้นเองจากตัวอย่าง
ข้อจำกัดและขั้นตอนถัดไป
ตัวอย่างนี้ครอบคลุมเฉพาะการสร้างงานนำเสนอด้วย skill สำเร็จรูปและการดาวน์โหลดไฟล์ ยังไม่ได้ทดสอบการอัปโหลด skills ที่กำหนดเอง การลบ skills หรือการเข้าถึงบริการของบุคคลที่สาม งานเหล่านั้นต้องตรวจสอบ API ที่เกี่ยวข้องแยกต่างหาก
หากงานของคุณเกี่ยวข้องกับไฟล์ในอินเทอร์เฟซ Claude มีคู่มือแยกเรื่องวิธีอัปโหลดไฟล์ไปยัง Claude สำหรับการเรียก API โดยตรง ดูวิธีคำนวณการใช้โทเค็น API หากทำงานในเอเจนต์เทอร์มินัล โปรดอ่านวิธีเลือก skills สำหรับ Claude Code เพราะเชื่อมต่อในอีกวิธีหนึ่ง
สำหรับการตรวจสอบครั้งแรก ใช้ pptx ซึ่งเป็น skill สำเร็จรูปเพียงตัวเดียวก็พอ ตรวจสอบการตอบกลับ ดาวน์โหลดไฟล์ที่ได้รับอนุญาตให้ดาวน์โหลด แล้วเปิดไฟล์ เพิ่ม skills ที่กำหนดเองและการแยกสิทธิ์เข้าถึงระหว่างลูกค้าหลังจากตรวจสอบขั้นตอนนี้แล้ว
เมื่อพร้อมแล้ว มาทำความรู้จักกับ Ailoot
รายละเอียดเพิ่มเติม
คำถามที่พบบ่อย
ทำไมมี file_id แล้วยังนับว่างานนำเสนอเสร็จไม่ได้?
ID บอกว่ามีไฟล์ถูกส่งกลับ ไม่ได้ยืนยันว่าใช้นำเสนอได้ ตรวจเมตาดาทาว่าเป็น downloadable: true ดาวน์โหลดด้วยสิทธิ์ workspace แล้วเปิดตรวจชนิดไฟล์ จำนวนสไลด์ และข้อความ
ดาวน์โหลดทุกไฟล์ที่อัปโหลดเข้า Claude Files API ได้หรือไม่?
ไม่ได้ คู่มือแยกไฟล์ที่สร้างขึ้นซึ่งมี downloadable: true จากไฟล์อัปโหลดที่เป็น downloadable: false สิทธิ์ workspace กับสิทธิ์ดาวน์โหลดไฟล์ใดไฟล์หนึ่งต้องตรวจแยก และห้ามรับ ID ไฟล์ใดก็ได้จากผู้ใช้ปลายทาง