Agent Skills trong Claude API: cách dùng skill có sẵn mà không cần Claude Code
MarkdownCách kết nối skill pptx có sẵn với Claude API: container.skills, công cụ thực thi mã, kiểm tra phản hồi và tải bài thuyết trình qua Files API.
Đọc toàn bộ bài viết
Điểm chính
Bạn có thể dùng Agent Skills có sẵn dành cho tài liệu thông qua Claude API trực tiếp: chỉ định skill trong container.skills và bật code_execution. Với yêu cầu đầu tiên, hãy dùng cặp mô hình và công cụ tương thích trong ví dụ chính thức. Tải riêng tệp đã tạo bằng file_id của tệp; ví dụ sử dụng cùng một API key cho cả yêu cầu lẫn thao tác tải xuống.
Bạn có thể tìm thêm hướng dẫn trong tài liệu Ailoot.
Bạn cần chuẩn bị gì
Hướng dẫn này dành cho việc gọi API trực tiếp từ một chương trình, thay vì cài đặt skill trong Claude Code. Bạn cần có khóa Claude API, quyền truy cập vào mô hình đã chọn và Python 3. Đoạn mã dưới đây dùng thư viện chuẩn của Python và HTTP nên không phụ thuộc vào phiên bản SDK bạn đã cài đặt. Khóa được truyền qua biến môi trường ANTHROPIC_API_KEY; đừng đưa khóa vào nội dung chương trình hoặc cuộc trò chuyện.
API cung cấp các skill dựng sẵn của Anthropic: pptx cho bài thuyết trình, xlsx cho bảng tính, docx cho tài liệu Word và pdf cho tệp PDF. Chúng được kết nối bằng type: "anthropic". Hướng dẫn này dùng skill có sẵn mà không tải lên skill tùy chỉnh.
Hướng dẫn bắt đầu nhanh chính thức, được mở khi tài liệu này được chuẩn bị, sử dụng cặp claude-opus-5-5 và code_execution_20260521. Đây là cặp được dùng bên dưới. Ví dụ này đã được đối chiếu với tài liệu; đây không phải là báo cáo về một lần chạy API có tính phí.
Cần những beta header nào
Ví dụ tuân theo hợp đồng HTTP hiện tại trong hướng dẫn bắt đầu nhanh: các header là x-api-key, anthropic-version: 2023-06-01 và content-type: application/json; ví dụ không gửi anthropic-beta. Đừng kết hợp mô hình, phương thức gọi và định dạng phản hồi từ các thế hệ tài liệu khác nhau.
Tài liệu Files API cũng cho biết API đã hết giai đoạn beta. Header cũ files-api-2025-04-14 giữ lại các định dạng phản hồi cũ; bỏ header này sẽ chuyển sang các định dạng hiện tại. Vì vậy, không thể kết hợp đơn giản một ví dụ cũ dùng client.beta.files với một ví dụ mới.
Ở đây, chúng ta không chuyển một dịch vụ hiện có khỏi hợp đồng beta cũ. Nếu bạn đã có dịch vụ như vậy, hãy kiểm tra header và định dạng phản hồi trước. Chỉ riêng từ beta trong tên phương thức SDK chưa đủ để kết luận: tài liệu Files API giải thích riêng cách các phiên bản SDK khác nhau hoạt động.
Tạo bài thuyết trình và tải tệp xuống
Ví dụ gửi yêu cầu tạo năm trang chiếu về năng lượng tái tạo, lưu toàn bộ phản hồi vào skill-response.json, rồi trích xuất ID của các tệp đã tạo. Chương trình không lấy đường dẫn lưu từ phản hồi của mô hình: các tệp được lưu trong một thư mục cục bộ mới tên là skill-output. Nếu thư mục đó đã tồn tại, chương trình sẽ dừng để không ghi đè kết quả trước đó. Thư mục được tạo trước khi gọi API nên vẫn còn sau một lần gọi thất bại. Hãy kiểm tra và giữ lại lần thử đó trước khi làm lại bất cứ bước nào; đừng xóa thư mục chỉ để lần chạy lại vượt qua kiểm tra.
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": "Tạo bài thuyết trình gồm 5 trang chiếu về năng lượng tái tạo bằng ngôn ngữ tôi muốn.",
}],
"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)
Các tên result-1.pptx và tiếp theo được chọn cho tác vụ tạo bài thuyết trình này. Phần mở rộng của tệp không chứng minh được nội dung bên trong: hãy mở tài liệu đã tải xuống và kiểm tra định dạng, số trang chiếu và văn bản. Đừng coi riêng HTTP 200 hoặc việc có file_id là kết quả thành công.
Chương trình in stop_reason, tức lý do phản hồi kết thúc, và lưu toàn bộ phản hồi để kiểm tra. Chương trình không tiếp tục cuộc trò chuyện hoặc tự động gửi lại yêu cầu có tính phí. Có tệp đã tải xuống không có nghĩa là toàn bộ tác vụ đã hoàn thành: hãy kiểm tra phản hồi đã lưu và chính tài liệu trước khi quyết định có cần gửi yêu cầu khác hay không.
Nếu lần thử thất bại, hãy kiểm tra skill-error.json nếu có. Tệp ghi mã HTTP, ID yêu cầu khi được cung cấp và thông báo lỗi có giới hạn độ dài đã loại bỏ API key được cấu hình. Kiểm tra nội dung riêng tư khác trong thông báo trước khi chia sẻ. Đối chiếu lỗi xác thực, quyền/mô hình, giới hạn thanh toán và định dạng yêu cầu với tài liệu lỗi chính thức; đừng suy ra rằng mọi lỗi đều cần một lần tạo có tính phí khác.
Nếu skill-response.json đã chứa các giá trị file_id được tạo và chỉ bước tải xuống thất bại, hãy giữ phản hồi đó và chẩn đoán bước metadata/tải xuống bằng cùng quyền truy cập workspace đã được cho phép. Đừng chạy lại khối tạo nội dung chỉ để tải kết quả có sẵn. Nếu chưa rõ kết quả yêu cầu, hãy giữ ID yêu cầu và xác minh trạng thái trước khi gửi yêu cầu tạo khác. Chỉ sau khi xác định cần tạo mới, đổi dòng đường dẫn cục bộ sang nơi chưa dùng, chẳng hạn out = Path("skill-output-attempt-2"), và giữ exist_ok=False. Thư mục mới ngăn ghi đè, không ngăn phí API bị tính trùng.
Cần những quyền nào đối với tệp
Files API gắn tệp với một workspace, thay vì với từng người dùng ứng dụng của bạn hoặc một cuộc trò chuyện. Theo tài liệu, mọi API key có quyền truy cập workspace đó đều có thể truy cập các tệp được tải lên đó. Ví dụ dùng cùng một key để tải xuống và tạo tệp. Đừng bao giờ nhận file_id từ người dùng cuối hoặc các nguồn không đáng tin cậy khác. Hãy lưu những ID này trên máy chủ và quản lý ánh xạ giữa người dùng với tệp của họ trong ứng dụng của bạn.
Hãy kiểm tra riêng metadata của tệp: metadata phải có downloadable: true. Tài liệu cho phép tải xuống các tệp do skill hoặc công cụ thực thi mã tạo ra; tệp bạn tải lên có downloadable: false, và yêu cầu tải xuống sẽ trả về 400. Quyền truy cập workspace và quyền tải xuống một tệp cụ thể là hai yêu cầu riêng biệt.
Với ứng dụng nhiều người dùng, tài liệu Files API khuyến nghị dùng một workspace riêng cho mỗi khách hàng làm ranh giới cách ly tệp. Khuyến nghị này chỉ nói cụ thể về tệp; đừng mở rộng nó sang mọi thực thể và quyền nếu chưa kiểm tra API liên quan.
Skill có sẵn và skill tùy chỉnh
Các skill có sẵn có ID pptx, xlsx, docx và pdf. Trong tài liệu tham chiếu danh sách skill, nguồn custom được mô tả là riêng tư trong workspace, còn anthropic được chia sẻ và chỉ đọc.
version: "latest" trong ví dụ đầu tiên có nghĩa là phiên bản mới nhất đã phát hành của skill. Để tích hợp có thể tái lập, hãy lưu ý rằng lựa chọn này có thể thay đổi; nếu chuyển sang một phiên bản cố định, bạn cần chọn một phiên bản đang tồn tại của skill mình dùng, thay vì tự tạo ID từ ví dụ.
Giới hạn và bước tiếp theo
Ví dụ chỉ đề cập đến việc tạo bài thuyết trình bằng skill có sẵn và tải tệp xuống. Việc tải lên skill tùy chỉnh, xóa skill và truy cập dịch vụ bên thứ ba chưa được kiểm thử ở đây. Những tác vụ đó cần được kiểm tra riêng với API liên quan.
Nếu tác vụ của bạn liên quan đến tệp trong giao diện Claude, có hướng dẫn riêng về cách tải tệp lên Claude. Với các lệnh gọi trực tiếp, hãy xem cách tính mức sử dụng token API. Nếu làm việc trong một tác nhân chạy trên terminal, hãy đọc cách chọn skill cho Claude Code: chúng được kết nối theo một cách khác.
Để kiểm tra lần đầu, chỉ cần một skill pptx có sẵn: kiểm tra phản hồi, tải xuống một tệp được phép tải xuống rồi mở tệp. Sau bước kiểm tra đó, hãy thêm skill tùy chỉnh và phân tách quyền truy cập giữa các khách hàng.
Khi đã sẵn sàng, hãy tìm hiểu Ailoot.
Xem thêm chi tiết
Câu hỏi thường gặp
Vì sao file_id chưa đủ để tuyên bố bản trình chiếu hoàn tất?
ID chỉ cho thấy có tệp trả về. Kiểm tra metadata có downloadable: true, tải bằng quyền workspace rồi mở để xác minh định dạng, số slide và văn bản.
Có tải được mọi tệp đã tải lên Claude Files API không?
Không. Hướng dẫn phân biệt tệp tạo ra có downloadable: true với tệp tải lên có downloadable: false. Quyền workspace và quyền tải một tệp cụ thể là hai kiểm tra riêng; không nhận ID tùy ý từ người dùng cuối.