# Agent Skills ใน Claude API: วิธีใช้ skill สำเร็จรูปโดยไม่ใช้ Claude Code

> วิธีเชื่อมต่อ skill pptx สำเร็จรูปกับ Claude API: container.skills, เครื่องมือเรียกใช้โค้ด, การตรวจสอบการตอบกลับ และการดาวน์โหลดงานนำเสนอผ่าน Files API

Source: https://ailoot.ai/blog/th/claude-api-agent-skills/
Canonical: https://ailoot.ai/blog/th/claude-api-agent-skills/
Language: th
Publisher: Ailoot (https://ailoot.ai/)
Translation: guide-039
Revision: sha256-97ce0666ed1932b971b19019f3375e58b18f70809cfc58e9bbf7f13b5a276d6d


<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaway for this section">

ประเด็นสำคัญ

คุณสามารถใช้ Agent Skills สำเร็จรูปสำหรับเอกสารผ่าน Claude API โดยตรงได้ โดยระบุ skill ใน `container.skills` และเปิดใช้ `code_execution` สำหรับคำขอแรก ให้ใช้การจับคู่โมเดลและเครื่องมือที่เข้ากันได้ตามตัวอย่างอย่างเป็นทางการ ดาวน์โหลดไฟล์ที่สร้างขึ้นแยกต่างหากโดยใช้ `file_id` ของไฟล์นั้น ตัวอย่างนี้ใช้ API key เดียวกันทั้งสำหรับคำขอและการดาวน์โหลด

</div>



คุณดูคำแนะนำเพิ่มเติมได้ใน[เอกสารประกอบของ Ailoot](https://ailoot.ai/docs/)

## สิ่งที่ต้องมี

คู่มือนี้มีไว้สำหรับเรียก 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 ที่กำหนดเอง

[คู่มือเริ่มต้นฉบับย่ออย่างเป็นทางการ](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/quickstart.md) ซึ่งเปิดดูตอนจัดทำเนื้อหานี้ ใช้การจับคู่ `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](https://platform.claude.com/docs/en/build-with-claude/files.md) ระบุด้วยว่า 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 จึงยังอยู่แม้การเรียกจะล้มเหลว ตรวจสอบและเก็บความพยายามครั้งนั้นไว้ก่อนทำสิ่งใดซ้ำ อย่าลบโฟลเดอร์เพียงเพื่อให้รันใหม่ผ่าน

```python
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 ที่ตั้งไว้แล้ว ตรวจว่าข้อความมีข้อมูลส่วนตัวอื่นหรือไม่ก่อนแชร์ เปรียบเทียบข้อผิดพลาดการยืนยันตัวตน สิทธิ์/โมเดล ขีดจำกัดการเรียกเก็บเงิน และรูปแบบคำขอกับ [เอกสารข้อผิดพลาดอย่างเป็นทางการ](https://platform.claude.com/docs/en/api/errors) อย่าสรุปว่าทุกความล้มเหลวต้องสร้างงานแบบเสียเงินอีกครั้ง

หาก `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](https://platform.claude.com/docs/en/api/skills/list.md) แหล่งที่มา `custom` ระบุว่าเป็นแบบส่วนตัวสำหรับ workspace ขณะที่ `anthropic` เป็นแบบใช้ร่วมกันและอ่านอย่างเดียว

`version: "latest"` ในตัวอย่างแรกหมายถึงเวอร์ชันล่าสุดที่เผยแพร่ของ skill สำหรับการผสานระบบที่ทำซ้ำได้ โปรดคำนึงว่าการเลือกนี้อาจเปลี่ยนแปลงได้ หากต้องการเปลี่ยนไปใช้เวอร์ชันที่ระบุแน่นอน คุณต้องเลือกเวอร์ชันที่มีอยู่ของ skill ที่ใช้ แทนที่จะสร้าง ID ขึ้นเองจากตัวอย่าง

## ข้อจำกัดและขั้นตอนถัดไป

ตัวอย่างนี้ครอบคลุมเฉพาะการสร้างงานนำเสนอด้วย skill สำเร็จรูปและการดาวน์โหลดไฟล์ ยังไม่ได้ทดสอบการอัปโหลด skills ที่กำหนดเอง การลบ skills หรือการเข้าถึงบริการของบุคคลที่สาม งานเหล่านั้นต้องตรวจสอบ API ที่เกี่ยวข้องแยกต่างหาก

หากงานของคุณเกี่ยวข้องกับไฟล์ในอินเทอร์เฟซ Claude มีคู่มือแยกเรื่อง[วิธีอัปโหลดไฟล์ไปยัง Claude](https://ailoot.ai/blog/th/claude-file-upload/) สำหรับการเรียก API โดยตรง ดู[วิธีคำนวณการใช้โทเค็น API](https://ailoot.ai/blog/th/api-token-usage-calculation/) หากทำงานในเอเจนต์เทอร์มินัล โปรดอ่าน[วิธีเลือก skills สำหรับ Claude Code](https://ailoot.ai/blog/th/choose-claude-code-skills/) เพราะเชื่อมต่อในอีกวิธีหนึ่ง

สำหรับการตรวจสอบครั้งแรก ใช้ `pptx` ซึ่งเป็น skill สำเร็จรูปเพียงตัวเดียวก็พอ ตรวจสอบการตอบกลับ ดาวน์โหลดไฟล์ที่ได้รับอนุญาตให้ดาวน์โหลด แล้วเปิดไฟล์ เพิ่ม skills ที่กำหนดเองและการแยกสิทธิ์เข้าถึงระหว่างลูกค้าหลังจากตรวจสอบขั้นตอนนี้แล้ว





เมื่อพร้อมแล้ว มาทำความรู้จักกับ [Ailoot](https://ailoot.ai/)

## คำถามที่พบบ่อย

### ทำไมมี file_id แล้วยังนับว่างานนำเสนอเสร็จไม่ได้?

ID บอกว่ามีไฟล์ถูกส่งกลับ ไม่ได้ยืนยันว่าใช้นำเสนอได้ ตรวจเมตาดาทาว่าเป็น `downloadable: true` ดาวน์โหลดด้วยสิทธิ์ workspace แล้วเปิดตรวจชนิดไฟล์ จำนวนสไลด์ และข้อความ

### ดาวน์โหลดทุกไฟล์ที่อัปโหลดเข้า Claude Files API ได้หรือไม่?

ไม่ได้ คู่มือแยกไฟล์ที่สร้างขึ้นซึ่งมี `downloadable: true` จากไฟล์อัปโหลดที่เป็น `downloadable: false` สิทธิ์ workspace กับสิทธิ์ดาวน์โหลดไฟล์ใดไฟล์หนึ่งต้องตรวจแยก และห้ามรับ ID ไฟล์ใดก็ได้จากผู้ใช้ปลายทาง


## Ailoot · บริษัทและพอร์ตโฟลิโอโครงการของบริษัท

Ailoot อาศัยประสบการณ์การดำเนินงานที่สั่งสม ฐานลูกค้าขนาดใหญ่ บริการที่เสถียร และการติดตาม KPI อย่างต่อเนื่อง

บริษัทและพอร์ตโฟลิโอโครงการของบริษัท: ลูกค้าหลายล้านราย; ยอดขายระดับหลายพันล้านต่อเดือน.

Ailoot นำประสบการณ์การดำเนินงานนี้มาใช้เพื่อให้เข้าถึงฟังก์ชัน AI ผ่าน API ในผลิตภัณฑ์ของลูกค้า เอเจนต์ แอปพลิเคชัน และระบบอัตโนมัติ
