# Agent Skills na API Claude: como usar skills sem Claude Code

> Como usar a skill pptx na API Claude: container.skills, execução de código, verificação da resposta e transferência da apresentação pela Files API.

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


<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Ponto principal desta secção">

Ponto principal

As Agent Skills prontas a utilizar para documentos podem ser usadas diretamente através da API Claude: especifica a skill em `container.skills` e ativa `code_execution`. Para o primeiro pedido, utiliza a combinação compatível de modelo e ferramenta do exemplo oficial. Transfere o ficheiro gerado separadamente através do respetivo `file_id`; o exemplo utiliza a mesma chave de API para o pedido e para a transferência.

</div>



Podes encontrar instruções adicionais na [documentação da Ailoot](https://ailoot.ai/docs/).

## O que vais precisar

Este guia destina-se a chamadas diretas à API a partir de um programa, em vez da instalação de uma skill no Claude Code. Vais precisar de uma chave da API Claude, de acesso ao modelo selecionado e do Python 3. O código abaixo utiliza a biblioteca padrão do Python e HTTP, pelo que não depende da versão do SDK que tens instalada. A chave é passada através da variável de ambiente `ANTHROPIC_API_KEY`; não a incluas no texto do programa nem numa conversa.

A API disponibiliza skills Anthropic prontas a utilizar: `pptx` para apresentações, `xlsx` para folhas de cálculo, `docx` para documentos Word e `pdf` para ficheiros PDF. São ligadas através de `type: "anthropic"`. Este guia utiliza uma skill pronta a utilizar, sem carregar uma skill personalizada.

O [guia de início rápido oficial](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/quickstart.md), consultado durante a preparação deste material, utiliza a combinação `claude-opus-5-5` e `code_execution_20260521`. É essa a combinação utilizada abaixo. Este exemplo foi verificado face à documentação; não é um relato de uma chamada paga à API.

## Que cabeçalhos beta são necessários

O exemplo segue o contrato HTTP atual do guia de início rápido: os cabeçalhos são `x-api-key`, `anthropic-version: 2023-06-01` e `content-type: application/json`; não envia `anthropic-beta`. Não combines um modelo, um método de chamada e um formato de resposta de gerações diferentes da documentação.

A [documentação da Files API](https://platform.claude.com/docs/en/build-with-claude/files.md) também indica que a API já não está em beta. O cabeçalho antigo `files-api-2025-04-14` mantém os formatos de resposta antigos; ao remover o cabeçalho, passam a ser utilizados os formatos atuais. É por isso que um exemplo antigo com `client.beta.files` não pode simplesmente ser combinado com um novo.

Aqui não estamos a migrar um serviço existente do contrato beta antigo. Se já tens um serviço desse tipo, verifica primeiro os respetivos cabeçalhos e formatos de resposta. A palavra `beta` no nome de um método do SDK não é suficiente por si só: a documentação da Files API explica separadamente o comportamento das diferentes versões do SDK.





## Criar uma apresentação e transferir o ficheiro

O exemplo envia uma tarefa para criar cinco diapositivos sobre energias renováveis, guarda a resposta completa em `skill-response.json` e, em seguida, extrai os IDs dos ficheiros gerados. Não obtém um caminho para guardar da resposta do modelo: os ficheiros são guardados numa nova pasta local chamada `skill-output`. Se essa pasta já existir, o programa para para não substituir o resultado anterior. A pasta é criada antes da chamada à API, pelo que também permanece após uma chamada falhada. Inspecione e conserve essa tentativa antes de voltar a agir; não a elimine só para conseguir repetir o programa.

```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": "Cria uma apresentação sobre energias renováveis com 5 diapositivos no idioma que prefiro.",
    }],
    "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("Não foi gerado nenhum file_id; inspeciona 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("Este ficheiro não pode ser transferido através da Files API")
    target = out / f"result-{index}.pptx"
    target.write_bytes(request(file_path + "/content", binary=True))
    print("Guardado:", target)
```

Os nomes `result-1.pptx` e seguintes foram escolhidos para esta tarefa de apresentação. Uma extensão de ficheiro não comprova o que o ficheiro contém: abre o documento transferido e verifica o formato, o número de diapositivos e o texto. Não consideres apenas uma resposta HTTP 200 ou a presença de um `file_id` como um resultado bem-sucedido.

O programa apresenta `stop_reason`, o motivo pelo qual a resposta terminou, e guarda a resposta completa para inspeção. Não continua a conversa nem repete automaticamente o pedido pago. Ter um ficheiro transferido não significa que a tarefa esteja concluída: inspeciona a resposta guardada e o próprio documento antes de decidires se é necessário outro pedido.

Se uma tentativa falhar, consulte `skill-error.json`, se existir. Regista o estado HTTP, o ID do pedido quando fornecido e uma mensagem de erro limitada do fornecedor, com a chave de API configurada removida. Antes de partilhar a mensagem, verifique se contém outros dados privados. Compare erros de autenticação, permissões ou modelo, limites de faturação e formato do pedido com a [referência oficial de erros](https://platform.claude.com/docs/en/api/errors); nem todas as falhas exigem uma nova geração paga.

Se `skill-response.json` já contiver valores `file_id` gerados e apenas uma transferência tiver falhado, conserve a resposta e diagnostique a etapa dos metadados ou da transferência com o mesmo acesso autorizado ao espaço de trabalho. Não volte a executar o bloco de geração apenas para transferir um resultado existente. Se o resultado do pedido for desconhecido, preserve o ID do pedido e esclareça o seu estado antes de enviar outra geração. Só depois de decidir que é necessária uma nova geração, altere a linha da pasta local para um caminho ainda não utilizado, por exemplo `out = Path("skill-output-attempt-2")`, e mantenha `exist_ok=False`. Uma pasta nova impede a substituição de ficheiros; não impede uma cobrança duplicada pela API.

## Que permissões de ficheiro são necessárias

A Files API associa os ficheiros a um espaço de trabalho, e não a um utilizador individual da tua aplicação ou a uma conversa. Segundo a documentação, qualquer chave de API com acesso a esse espaço de trabalho pode aceder aos ficheiros aí carregados. O exemplo utiliza a mesma chave para transferir e gerar. Nunca aceites um `file_id` de utilizadores finais ou de outras fontes não fidedignas. Guarda estes IDs no servidor e mantém, na tua própria aplicação, o mapeamento entre os utilizadores e os respetivos ficheiros.

Verifica os metadados do ficheiro separadamente: têm de conter `downloadable: true`. A documentação permite transferir ficheiros gerados por skills ou pela ferramenta de execução de código; os ficheiros que carregas têm `downloadable: false` e uma tentativa de transferência devolve 400. O acesso ao espaço de trabalho e a possibilidade de transferir um determinado ficheiro são requisitos distintos.

Para uma aplicação multiutilizador, a documentação da Files API recomenda um espaço de trabalho separado para cada cliente como limite de isolamento dos ficheiros. Esta recomendação diz respeito especificamente aos ficheiros; não a alargues a todas as entidades e permissões sem consultares a API relevante.

## Skills prontas a utilizar e skills personalizadas

As skills prontas a utilizar têm os IDs `pptx`, `xlsx`, `docx` e `pdf`. Na [referência da lista de skills](https://platform.claude.com/docs/en/api/skills/list.md), a origem `custom` é descrita como privada para o espaço de trabalho, enquanto `anthropic` é partilhada e só de leitura.

`version: "latest"` no primeiro exemplo significa a versão publicada mais recente da skill. Para uma integração reproduzível, tem em conta que esta seleção pode mudar; para passar a uma versão fixa, é necessário escolher uma versão existente da skill que utilizas, em vez de inventar um ID a partir de um exemplo.

## Limitações e próximo passo

O exemplo abrange apenas a criação de uma apresentação com uma skill pronta a utilizar e a transferência do ficheiro. O carregamento de skills personalizadas, a sua eliminação e o acesso a serviços de terceiros não foram testados aqui. Essas tarefas exigem uma verificação separada da API relevante.

Se a tua tarefa envolver ficheiros na interface do Claude, existe um guia separado sobre [como carregar um ficheiro para o Claude](https://ailoot.ai/blog/pt-pt/claude-file-upload/). Para chamadas diretas, consulta [como calcular a utilização de tokens da API](https://ailoot.ai/blog/pt-pt/api-token-usage-calculation/). Para trabalhar num agente de terminal, lê [como escolher skills do Claude Code](https://ailoot.ai/blog/pt-pt/choose-claude-code-skills/): são ligadas de outra forma.

Para a primeira verificação, basta uma skill `pptx` pronta a utilizar: inspeciona a resposta, transfere um ficheiro que seja permitido transferir e abre-o. Acrescenta skills personalizadas e a separação de acesso entre clientes depois dessa verificação.





Quando estiveres pronto, fica a conhecer a [Ailoot](https://ailoot.ai/).

## Perguntas frequentes

### Porque não basta um file_id para considerar a apresentação concluída?

O ID indica que foi devolvido um ficheiro, não que seja uma apresentação utilizável. Verifique nos metadados `downloadable: true`, transfira-o com acesso ao espaço de trabalho e abra-o para verificar o formato, o número de diapositivos e o texto.

### Posso transferir qualquer ficheiro carregado para a API Files do Claude?

Não. O guia distingue ficheiros gerados com `downloadable: true` de ficheiros carregados com `downloadable: false`. O acesso ao espaço de trabalho e a permissão para transferir um ficheiro específico são verificações separadas; não aceite IDs arbitrários de ficheiros dos utilizadores finais.


## Ailoot · A empresa e a sua carteira de projetos

A Ailoot assenta numa experiência operacional consolidada, numa ampla base de clientes, num serviço estável e no acompanhamento contínuo dos KPI.

A empresa e a sua carteira de projetos: milhões de clientes; vendas mensais na ordem dos milhares de milhões.

A Ailoot aplica essa experiência operacional ao acesso por API a funcionalidades de IA nos produtos dos clientes, agentes, aplicações e automatizações.
