Blog

Agent Skills w Claude API: jak korzystać z gotowej umiejętności bez Claude Code

Markdown

Jak połączyć gotową umiejętność pptx z Claude API: container.skills, narzędzie do wykonywania kodu, sprawdzanie odpowiedzi i pobieranie prezentacji przez Files API.

Przeczytaj cały artykuł

Najważniejsze informacje

Z gotowych Agent Skills do pracy z dokumentami można korzystać bezpośrednio przez Claude API: określ umiejętność w container.skills i włącz code_execution. Przy pierwszym żądaniu użyj zgodnego zestawu modelu i narzędzia z oficjalnego przykładu. Wygenerowany plik pobierz osobno, używając jego file_id; w przykładzie do żądania i pobrania używany jest ten sam klucz API.

Dodatkowe instrukcje znajdziesz w dokumentacji Ailoot.

Co będzie potrzebne

Ten przewodnik dotyczy bezpośredniego wywoływania API z programu, a nie instalowania umiejętności w Claude Code. Potrzebujesz klucza Claude API, dostępu do wybranego modelu i Pythona 3. Poniższy kod korzysta ze standardowej biblioteki Pythona i protokołu HTTP, więc nie zależy od zainstalowanej wersji SDK. Klucz jest przekazywany przez zmienną środowiskową ANTHROPIC_API_KEY; nie umieszczaj go w tekście programu ani w rozmowie.

API udostępnia gotowe umiejętności Anthropic: pptx do prezentacji, xlsx do arkuszy kalkulacyjnych, docx do dokumentów Word i pdf do plików PDF. Łączy się je za pomocą type: "anthropic". Ten przewodnik korzysta z gotowej umiejętności, bez przesyłania własnej.

Otwarty podczas przygotowywania tego materiału oficjalny przewodnik szybkiego startu używa zestawu claude-opus-5-5 i code_execution_20260521. Poniżej zastosowano ten sam zestaw. Przykład został sprawdzony pod kątem zgodności z dokumentacją; nie jest relacją z płatnego wywołania API.

Jakie nagłówki beta są potrzebne

Przykład jest zgodny z aktualnym kontraktem HTTP z przewodnika szybkiego startu: nagłówki to x-api-key, anthropic-version: 2023-06-01 i content-type: application/json; nie wysyła on anthropic-beta. Nie łącz modelu, metody wywołania i formatu odpowiedzi z różnych generacji dokumentacji.

Dokumentacja Files API również informuje, że API nie jest już w wersji beta. Stary nagłówek files-api-2025-04-14 zachowuje stare formaty odpowiedzi; jego usunięcie przełącza API na aktualne formaty. Dlatego starego przykładu korzystającego z client.beta.files nie można po prostu połączyć z nowym.

W tym przewodniku nie migrujemy istniejącej usługi ze starego kontraktu beta. Jeśli korzystasz już z takiej usługi, najpierw sprawdź używane nagłówki i formaty odpowiedzi. Samo słowo beta w nazwie metody SDK nie wystarczy: dokumentacja Files API osobno wyjaśnia, jak zachowują się różne wersje SDK.

Utwórz prezentację i pobierz plik

Przykład wysyła zadanie utworzenia pięciu slajdów o energii odnawialnej, zapisuje całą odpowiedź w pliku skill-response.json, a następnie pobiera identyfikatory wygenerowanych plików. Nie pobiera ścieżki zapisu z odpowiedzi modelu: pliki są zapisywane w nowym lokalnym folderze o nazwie skill-output. Jeśli ten folder już istnieje, program zatrzymuje się, aby nie nadpisać poprzedniego wyniku. Folder powstaje przed wywołaniem API, więc pozostaje także po nieudanej próbie. Zanim cokolwiek ponowisz, sprawdź i zachowaj tę próbę; nie usuwaj folderu tylko po to, aby ponowne uruchomienie przeszło kontrolę.

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": "Utwórz prezentację o energii odnawialnej, składającą się z 5 slajdów, w preferowanym przeze mnie języku.",
    }],
    "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)

Nazwy takie jak result-1.pptx zostały wybrane na potrzeby tego zadania polegającego na utworzeniu prezentacji. Rozszerzenie pliku nie potwierdza jego zawartości: otwórz pobrany dokument i sprawdź jego format, liczbę slajdów oraz tekst. Nie uznawaj samego HTTP 200 ani obecności file_id za dowód powodzenia.

Program wyświetla stop_reason, czyli przyczynę zakończenia odpowiedzi, i zapisuje całą odpowiedź do wglądu. Nie kontynuuje rozmowy ani nie ponawia automatycznie płatnego żądania. Pobrany plik nie oznacza, że całe zadanie zostało ukończone: przed podjęciem decyzji o kolejnym żądaniu sprawdź zapisaną odpowiedź i sam dokument.

W przypadku nieudanej próby sprawdź skill-error.json, jeśli powstał. Zawiera status HTTP, identyfikator żądania, jeśli go podano, i ograniczony komunikat błędu dostawcy z usuniętym skonfigurowanym kluczem API. Przed udostępnieniem sprawdź, czy komunikat nie zawiera innych prywatnych danych. Rozróżnij błędy uwierzytelniania, uprawnień lub modelu, limitów rozliczeniowych i formatu żądania zgodnie z oficjalnym opisem błędów; nie zakładaj, że każda awaria wymaga kolejnego płatnego generowania.

Jeśli skill-response.json zawiera już wygenerowane wartości file_id, a nie powiodło się tylko pobieranie, zachowaj odpowiedź i sprawdź metadane oraz pobieranie pliku z tym samym uprawnionym dostępem do obszaru roboczego. Nie uruchamiaj bloku generowania ponownie tylko po to, aby pobrać istniejący wynik. Gdy wynik żądania jest nieznany, zachowaj jego identyfikator i ustal status przed wysłaniem kolejnego generowania. Dopiero po ustaleniu, że nowe generowanie jest potrzebne, zmień lokalną ścieżkę na nieużywaną, np. out = Path("skill-output-attempt-2"), zachowując exist_ok=False. Nowy folder chroni przed nadpisaniem, ale nie przed podwójną opłatą za API.

Jakie uprawnienia do plików są potrzebne

Files API przypisuje pliki do obszaru roboczego, a nie do poszczególnych użytkowników aplikacji ani do rozmowy. Zgodnie z dokumentacją każdy klucz API mający dostęp do danego obszaru roboczego może uzyskać dostęp do przesłanych tam plików. Przykład używa tego samego klucza do pobrania i wygenerowania pliku. Nigdy nie przyjmuj file_id od użytkowników końcowych ani innych niezaufanych źródeł. Przechowuj te identyfikatory na serwerze i zarządzaj powiązaniami między użytkownikami a ich plikami we własnej aplikacji.

Sprawdź osobno metadane pliku: muszą zawierać downloadable: true. Dokumentacja zezwala na pobieranie plików wygenerowanych przez umiejętności lub narzędzie do wykonywania kodu; przesłane przez Ciebie pliki mają downloadable: false, a próba ich pobrania zwraca błąd 400. Dostęp do obszaru roboczego i możliwość pobrania konkretnego pliku to osobne wymagania.

W przypadku aplikacji dla wielu użytkowników dokumentacja Files API zaleca osobny obszar roboczy dla każdego klienta jako granicę izolacji plików. To zalecenie dotyczy konkretnie plików; nie rozszerzaj go na wszystkie obiekty i uprawnienia bez sprawdzenia odpowiedniego API.

Gotowe umiejętności i umiejętności niestandardowe

Gotowe umiejętności mają identyfikatory pptx, xlsx, docx i pdf. W dokumentacji referencyjnej listy umiejętności źródło custom opisano jako prywatne dla obszaru roboczego, a źródło anthropic jako współdzielone i tylko do odczytu.

W pierwszym przykładzie version: "latest" oznacza najnowszą opublikowaną wersję umiejętności. Jeśli zależy Ci na odtwarzalnej integracji, pamiętaj, że ten wybór może się zmienić; aby przejść na stałą wersję, wybierz istniejącą wersję używanej umiejętności, zamiast wymyślać identyfikator na podstawie przykładu.

Ograniczenia i następny krok

Przykład obejmuje wyłącznie utworzenie prezentacji za pomocą gotowej umiejętności i pobranie pliku. Nie testowano tu przesyłania ani usuwania umiejętności niestandardowych ani dostępu do usług firm trzecich. Te zadania wymagają osobnego sprawdzenia odpowiedniego API.

Jeśli Twoje zadanie dotyczy plików w interfejsie Claude, przeczytaj osobny przewodnik jak przesłać plik do Claude. W przypadku bezpośrednich wywołań sprawdź jak obliczyć użycie tokenów API. Jeśli pracujesz w agencie terminalowym, przeczytaj jak wybrać umiejętności Claude Code: łączy się je w inny sposób.

Do pierwszego sprawdzenia wystarczy jedna gotowa umiejętność pptx: sprawdź odpowiedź, pobierz plik, który można pobrać, i otwórz go. Dodaj umiejętności niestandardowe i separację dostępu między klientami dopiero po tym sprawdzeniu.

Gdy będziesz gotowy, poznaj Ailoot.

Więcej szczegółów

Pytania i odpowiedzi

Dlaczego file_id nie wystarcza do uznania prezentacji za ukończoną?

Identyfikator pokazuje zwrócenie pliku, a nie użyteczność prezentacji. Sprawdź w metadanych downloadable: true, pobierz plik z dostępem do obszaru roboczego i otwórz, aby sprawdzić format, liczbę slajdów i tekst.

Czy mogę pobrać każdy plik przesłany do Claude Files API?

Nie. Przewodnik rozróżnia wygenerowane pliki oznaczone downloadable: true i przesłane pliki oznaczone downloadable: false. Dostęp do obszaru roboczego i pozwolenie pobrania konkretnego pliku to osobne sprawdzenia; nie przyjmuj dowolnych identyfikatorów plików od użytkowników końcowych.

Wszystkie artykuły