Blogg

Agent Skills i Claude API: slik bruker du en ferdig skill uten Claude Code

Markdown

Slik kobler du en ferdig pptx-skill til Claude API: container.skills, verktøyet for kodekjøring, kontroll av svaret og nedlasting av presentasjonen via Files API.

Les hele artikkelen

Hovedpoeng

Ferdige Agent Skills for dokumenter kan brukes direkte gjennom Claude API: angi skillen i container.skills og aktiver code_execution. For den første forespørselen bør du bruke kombinasjonen av modell og verktøy fra det offisielle eksemplet. Last ned den genererte filen separat ved hjelp av file_id; eksemplet bruker samme API-nøkkel for forespørselen og nedlastingen.

Du finner flere instruksjoner i Ailoot-dokumentasjonen.

Dette trenger du

Denne veiledningen handler om å kalle API-et direkte fra et program, ikke om å installere en skill i Claude Code. Du trenger en Claude API-nøkkel, tilgang til den valgte modellen og Python 3. Koden nedenfor bruker standardbiblioteket i Python og HTTP, så det spiller ingen rolle hvilken SDK-versjon du har installert. Nøkkelen sendes via miljøvariabelen ANTHROPIC_API_KEY; ikke legg den inn i programteksten eller en samtale.

API-et tilbyr ferdige Anthropic-skills: pptx for presentasjoner, xlsx for regneark, docx for Word-dokumenter og pdf for PDF-filer. De kobles til med type: "anthropic". Denne veiledningen bruker en ferdig skill, uten å laste opp en egendefinert skill.

Den offisielle hurtigstarten, som ble åpnet da dette materialet ble utarbeidet, bruker kombinasjonen claude-opus-5-5 og code_execution_20260521. Det er denne kombinasjonen som brukes nedenfor. Eksemplet er kontrollert mot dokumentasjonen; det er ikke en rapport om en betalt API-kjøring.

Hvilke beta-headere trengs

Eksemplet følger det gjeldende HTTP-kontrakten i hurtigstarten: headerne er x-api-key, anthropic-version: 2023-06-01 og content-type: application/json; det sender ikke anthropic-beta. Ikke kombiner en modell, en kallmetode og et svarformat fra forskjellige generasjoner av dokumentasjonen.

Dokumentasjonen for Files API sier også at API-et ikke lenger er i beta. Den gamle headeren files-api-2025-04-14 beholder de gamle svarformatene; hvis du fjerner headeren, byttes det til de gjeldende formatene. Derfor kan ikke et gammelt eksempel med client.beta.files uten videre kombineres med et nytt.

Her migrerer vi ikke en eksisterende tjeneste fra den gamle beta-kontrakten. Hvis du allerede har en slik tjeneste, bør du først kontrollere headerne og svarformatene. Ordet beta i navnet på en SDK-metode er ikke nok i seg selv: dokumentasjonen for Files API forklarer særskilt hvordan ulike SDK-versjoner fungerer.

Opprett en presentasjon og last ned filen

Eksemplet sender en oppgave om å lage fem lysbilder om fornybar energi, lagrer hele svaret i skill-response.json og henter deretter ut ID-ene til de genererte filene. Det henter ikke en lagringsbane fra modellens svar: filene lagres i en ny lokal mappe som heter skill-output. Hvis mappen allerede finnes, stopper programmet for å unngå å overskrive det forrige resultatet. Mappen opprettes før API-kallet og blir derfor liggende også etter et mislykket kall. Undersøk og bevar forsøket før du gjør noe på nytt; ikke slett mappen bare for å få en ny kjøring til å gå gjennom.

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": "Lag en presentasjon om fornybar energi med 5 lysbilder på språket jeg foretrekker.",
    }],
    "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)

Navnene result-1.pptx og så videre er valgt for denne presentasjonsoppgaven. En filendelse beviser ikke hva filen inneholder: åpne det nedlastede dokumentet og kontroller formatet, antallet lysbilder og teksten. Ikke betrakt HTTP 200 alene eller det at en file_id finnes som et vellykket resultat.

Programmet skriver ut stop_reason, årsaken til at svaret ble avsluttet, og lagrer hele svaret for gjennomgang. Det fortsetter ikke samtalen og gjentar ikke den betalte forespørselen automatisk. At du har lastet ned en fil, betyr ikke at hele oppgaven er fullført: kontroller det lagrede svaret og selve dokumentet før du avgjør om det trengs en ny forespørsel.

Etter et mislykket forsøk må du undersøke skill-error.json hvis filen finnes. Den inneholder HTTP-status, en eventuell forespørsels-ID fra leverandøren og en avgrenset feilmelding med den konfigurerte API-nøkkelen fjernet. Kontroller meldingen for annet privat innhold før du deler den. Sammenlign autentiseringsfeil, tilgangs- og modellfeil, faktureringsgrenser og formatfeil med den offisielle feilreferansen; ikke alle feil krever en ny betalt generering.

Hvis skill-response.json allerede inneholder genererte file_id-verdier og bare en nedlasting mislyktes, fortsetter du nedlastingen med de kjente ID-ene i stedet for å generere presentasjonen på nytt. Er utfallet av genereringen ukjent, må du avklare det opprinnelige forsøket først. FileExistsError for skill-output er en lokal mappekonflikt, ikke en API-feil. Velg bevisst en ny, ubrukt utdatamappe bare for en begrunnet ny generering; behold exist_ok=False og ikke overskriv det tidligere forsøket. En annen mappe hindrer ikke dobbeltgenerering eller doble kostnader.

Hvilke filtillatelser trengs

Files API knytter filer til et arbeidsområde, ikke til en enkelt bruker av applikasjonen din eller til en samtale. Ifølge dokumentasjonen kan alle API-nøkler med tilgang til arbeidsområdet få tilgang til filene der. Eksemplet bruker samme nøkkel for nedlasting som for generering. Ikke godta en file_id fra sluttbrukere eller andre kilder du ikke stoler på. Lagre disse ID-ene på serveren og hold oversikt over koblingen mellom brukere og filene deres i din egen applikasjon.

Kontroller filmetadataene separat: de må inneholde downloadable: true. Dokumentasjonen tillater nedlasting av filer som er generert av skills eller verktøyet for kodekjøring; filer du laster opp, har downloadable: false, og et nedlastingsforsøk gir 400. Tilgang til arbeidsområdet og muligheten til å laste ned en bestemt fil er separate krav.

For en applikasjon med flere brukere anbefaler dokumentasjonen for Files API et eget arbeidsområde for hver kunde som grense for filisolering. Denne anbefalingen gjelder spesifikt filer; ikke utvid den til alle entiteter og tillatelser uten å kontrollere det aktuelle API-et.

Ferdige skills og egendefinerte skills

ID-ene for ferdige skills er pptx, xlsx, docx og pdf. I referansen for skills-listen beskrives kilden custom som privat for arbeidsområdet, mens anthropic er delt og skrivebeskyttet.

version: "latest" i det første eksemplet betyr den nyeste publiserte versjonen av skillen. For en reproduserbar integrasjon bør du være oppmerksom på at dette valget kan endres; hvis du vil bytte til en fast versjon, må du velge en eksisterende versjon av skillen du bruker, ikke finne på en ID fra et eksempel.

Begrensninger og neste steg

Eksemplet dekker bare å lage en presentasjon med en ferdig skill og å laste den ned. Opplasting og sletting av egendefinerte skills og tilgang til tredjepartstjenester er ikke testet her. Disse oppgavene krever en separat kontroll av det aktuelle API-et.

Hvis oppgaven din gjelder filer i Claude-grensesnittet, finnes det en egen veiledning om hvordan du laster opp en fil til Claude. For direkte kall, se hvordan du beregner API-tokenbruk. For arbeid i en terminalagent kan du lese hvordan du velger Claude Code-skills: de kobles til på en annen måte.

Til den første kontrollen holder det med én ferdig pptx-skill: undersøk svaret, last ned en fil som det er tillatt å laste ned, og åpne den. Legg til egendefinerte skills og tilgangsdeling mellom kunder etter denne kontrollen.

Når du er klar, kan du bli kjent med Ailoot.

Flere detaljer

Spørsmål om denne veiledningen: Agent Skills i Claude API: slik bruker du en ferdig skill uten Claude Code

Hvorfor er ikke file_id nok til å erklære presentasjonen ferdig?

ID-en viser at en fil ble returnert, ikke at presentasjonen er brukbar. Kontroller at metadataene sier downloadable: true, last ned med tilgang til arbeidsområdet, og åpne filen for å verifisere format, antall lysbilder og tekst.

Kan jeg laste ned alle filer lastet opp til Claude Files API?

Nei. Veiledningen skiller mellom genererte filer merket downloadable: true og opplastede filer merket downloadable: false. Tilgang til arbeidsområdet og tillatelse til å laste ned en bestemt fil er separate kontroller. Ikke godta vilkårlige fil-ID-er fra sluttbrukere.

Alle artikler