Blog

Agent Skills di Claude API: cara menggunakan skill siap pakai tanpa Claude Code

Markdown

Cara menghubungkan skill pptx siap pakai ke Claude API: container.skills, alat eksekusi kode, memeriksa respons, dan mengunduh presentasi melalui Files API.

Baca artikel lengkap

Poin utama

Agent Skills siap pakai untuk dokumen dapat digunakan melalui Claude API langsung: tentukan skill di container.skills dan aktifkan code_execution. Untuk permintaan pertama, gunakan pasangan model dan alat yang kompatibel dari contoh resmi. Unduh file yang dihasilkan secara terpisah menggunakan file_id-nya; contoh ini menggunakan kunci API yang sama untuk permintaan dan pengunduhan.

Anda dapat menemukan instruksi tambahan di dokumentasi Ailoot.

Yang Anda perlukan

Panduan ini ditujukan untuk memanggil API langsung dari sebuah program, bukan memasang skill di Claude Code. Anda memerlukan kunci Claude API, akses ke model yang dipilih, dan Python 3. Kode di bawah menggunakan pustaka standar Python dan HTTP, jadi tidak bergantung pada versi SDK yang telah Anda pasang. Kunci diteruskan melalui variabel lingkungan ANTHROPIC_API_KEY; jangan masukkan ke dalam teks program atau percakapan.

API ini menyediakan skill Anthropic siap pakai: pptx untuk presentasi, xlsx untuk spreadsheet, docx untuk dokumen Word, dan pdf untuk PDF. Skill tersebut dihubungkan menggunakan type: "anthropic". Panduan ini menggunakan skill siap pakai, tanpa mengunggah skill kustom.

Quickstart resmi, yang dibuka saat materi ini disiapkan, menggunakan pasangan claude-opus-5-5 dan code_execution_20260521. Pasangan itulah yang digunakan di bawah. Contoh ini telah diperiksa terhadap dokumentasi; ini bukan laporan penggunaan API berbayar.

Header beta apa yang diperlukan

Contoh ini mengikuti kontrak HTTP quickstart saat ini: header-nya adalah x-api-key, anthropic-version: 2023-06-01, dan content-type: application/json; contoh ini tidak mengirim anthropic-beta. Jangan gabungkan model, metode pemanggilan, dan format respons dari generasi dokumentasi yang berbeda.

Dokumentasi Files API juga menyatakan bahwa API ini sudah keluar dari beta. Header lama files-api-2025-04-14 mempertahankan format respons lama; menghapus header tersebut beralih ke format saat ini. Itulah sebabnya contoh lama yang menggunakan client.beta.files tidak dapat begitu saja digabungkan dengan contoh baru.

Di sini kita tidak sedang memigrasikan layanan yang sudah ada dari kontrak beta lama. Jika Anda sudah memiliki layanan seperti itu, periksa header dan format responsnya terlebih dahulu. Kata beta dalam nama metode SDK saja tidak cukup: dokumentasi Files API menjelaskan secara terpisah bagaimana berbagai versi SDK berperilaku.

Buat presentasi dan unduh file

Contoh ini mengirim tugas untuk membuat lima slide tentang energi terbarukan, menyimpan seluruh respons ke skill-response.json, lalu mengambil ID file yang dihasilkan. Contoh ini tidak mengambil jalur penyimpanan dari respons model: file disimpan di folder lokal baru bernama skill-output. Jika folder itu sudah ada, program berhenti agar tidak menimpa hasil sebelumnya. Folder dibuat sebelum panggilan API, jadi folder tetap ada setelah panggilan gagal. Periksa dan pertahankan upaya tersebut sebelum mengulangi apa pun; jangan menghapusnya hanya agar proses ulang lolos.

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": "Buat presentasi tentang energi terbarukan dengan 5 slide dalam bahasa pilihan saya.",
    }],
    "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)

Nama result-1.pptx dan seterusnya dipilih untuk tugas presentasi ini. Ekstensi file tidak membuktikan isi file: buka dokumen yang diunduh dan periksa format, jumlah slide, serta teksnya. Jangan menganggap HTTP 200 saja, atau keberadaan file_id, sebagai hasil yang berhasil.

Program ini mencetak stop_reason, yaitu alasan respons berhenti, dan menyimpan seluruh respons untuk diperiksa. Program ini tidak melanjutkan percakapan atau otomatis mengulangi permintaan berbayar. Memiliki file yang sudah diunduh tidak berarti seluruh tugas selesai: periksa respons yang tersimpan dan dokumennya sendiri sebelum memutuskan apakah permintaan lain diperlukan.

Untuk upaya yang gagal, periksa skill-error.json jika ada. File itu merekam status HTTP, ID permintaan bila diberikan, serta pesan galat penyedia yang panjangnya dibatasi dan nilai kunci API terkonfigurasi telah dihapus. Periksa pesan untuk konten pribadi lain sebelum membagikannya. Bandingkan galat autentikasi, izin/model, batas penagihan, dan format permintaan dengan referensi galat resmi; jangan menyimpulkan semua kegagalan memerlukan generasi berbayar lagi.

Jika skill-response.json sudah berisi nilai file_id hasil generasi dan hanya pengunduhan yang gagal, pertahankan respons itu dan diagnosis langkah metadata/pengunduhan dengan akses ruang kerja terotorisasi yang sama. Jangan menjalankan blok generasi lagi hanya untuk mengunduh keluaran yang sudah ada. Jika hasil permintaan belum diketahui, simpan ID permintaannya dan pastikan statusnya sebelum mengirim generasi lain. Hanya setelah memutuskan generasi baru diperlukan, ubah baris keluaran lokal ke jalur yang belum dipakai, misalnya out = Path("skill-output-attempt-2"), dan pertahankan exist_ok=False. Folder baru mencegah penimpaan; folder itu tidak mencegah tagihan API ganda.

Izin file apa yang diperlukan

Files API mengaitkan file dengan sebuah ruang kerja, bukan dengan pengguna individual aplikasi Anda atau percakapan. Menurut dokumentasi, kunci API apa pun yang memiliki akses ke ruang kerja tersebut dapat mengakses file yang diunggah di sana. Contoh ini menggunakan kunci yang sama untuk mengunduh dan menghasilkan file. Jangan pernah menerima file_id dari pengguna akhir atau sumber lain yang tidak tepercaya. Simpan ID ini di server dan kelola pemetaan antara pengguna dan file mereka di aplikasi Anda sendiri.

Periksa metadata file secara terpisah: metadata harus memuat downloadable: true. Dokumentasi mengizinkan pengunduhan file yang dihasilkan oleh skill atau alat eksekusi kode; file yang Anda unggah memiliki downloadable: false, dan upaya mengunduhnya akan mengembalikan 400. Akses ke ruang kerja dan kemampuan mengunduh file tertentu merupakan persyaratan yang terpisah.

Untuk aplikasi multi-pengguna, dokumentasi Files API merekomendasikan ruang kerja terpisah untuk setiap klien sebagai batas isolasi file. Rekomendasi ini khusus untuk file; jangan memperluasnya ke semua entitas dan izin tanpa memeriksa API yang relevan.

Skill siap pakai dan skill kustom

Skill siap pakai memiliki ID pptx, xlsx, docx, dan pdf. Dalam referensi daftar skill, sumber custom dijelaskan sebagai privat untuk ruang kerja, sedangkan anthropic dibagikan dan hanya dapat dibaca.

version: "latest" pada contoh pertama berarti versi skill terbaru yang dipublikasikan. Untuk integrasi yang dapat direproduksi, perlu diingat bahwa pilihan ini dapat berubah; untuk beralih ke versi tetap, pilih versi skill yang sudah ada dan Anda gunakan, bukan ID rekaan dari sebuah contoh.

Batasan dan langkah selanjutnya

Contoh ini hanya mencakup pembuatan presentasi dengan skill siap pakai dan pengunduhannya. Mengunggah skill kustom, menghapusnya, dan mengakses layanan pihak ketiga belum diuji di sini. Tugas-tugas tersebut memerlukan pemeriksaan API terkait secara terpisah.

Jika tugas Anda melibatkan file di antarmuka Claude, ada panduan terpisah tentang cara mengunggah file ke Claude. Untuk pemanggilan langsung, lihat cara menghitung penggunaan token API. Untuk pekerjaan dengan agen terminal, baca cara memilih skill Claude Code: skill tersebut dihubungkan dengan cara yang berbeda.

Untuk pemeriksaan pertama, satu skill siap pakai pptx sudah cukup: periksa respons, unduh file yang diizinkan untuk diunduh, lalu buka file tersebut. Tambahkan skill kustom dan pemisahan akses antarklien setelah pemeriksaan itu.

Saat Anda siap, kenali Ailoot.

Rincian selengkapnya

Pertanyaan tentang Agent Skills di Claude API: cara menggunakan skill siap pakai tanpa Claude Code

Mengapa file_id saja belum cukup untuk menyatakan presentasi selesai?

ID menunjukkan bahwa sebuah file dikembalikan, bukan bahwa file itu merupakan presentasi yang dapat digunakan. Periksa metadata downloadable: true, unduh dengan akses ruang kerja, lalu buka untuk memverifikasi format file, jumlah slide, dan teksnya.

Bisakah saya mengunduh setiap file yang diunggah ke Claude Files API?

Tidak. Panduan membedakan file hasil generasi dengan downloadable: true dari file unggahan dengan downloadable: false. Akses ruang kerja dan izin mengunduh file tertentu merupakan pemeriksaan terpisah; jangan terima ID file sembarang dari pengguna akhir.

Semua artikel