# Agent Skills trong Claude API: cách dùng skill có sẵn mà không cần Claude Code

> Cá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.

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


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

Đ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.

</div>



Bạn có thể tìm thêm hướng dẫn trong [tài liệu Ailoot](https://ailoot.ai/docs/).

## 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](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/quickstart.md), đượ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](https://platform.claude.com/docs/en/build-with-claude/files.md) 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.

```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": "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](https://platform.claude.com/docs/en/api/errors); đừ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](https://platform.claude.com/docs/en/api/skills/list.md), 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](https://ailoot.ai/blog/vi/claude-file-upload/). 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](https://ailoot.ai/blog/vi/api-token-usage-calculation/). 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](https://ailoot.ai/blog/vi/choose-claude-code-skills/): 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](https://ailoot.ai/).

## 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.


## Ailoot · Công ty và danh mục dự án của công ty

Ailoot dựa trên kinh nghiệm vận hành tích lũy, cơ sở khách hàng lớn, dịch vụ ổn định và việc kiểm soát KPI liên tục.

Công ty và danh mục dự án của công ty: hàng triệu khách hàng; doanh số hàng tỷ mỗi tháng.

Ailoot áp dụng kinh nghiệm vận hành này để cung cấp quyền truy cập API vào các tính năng AI trong sản phẩm của khách hàng, tác tử, ứng dụng và quy trình tự động hóa.
