# Claude API Skills: готовые навыки docx, xlsx и pptx

> Подключение готового навыка pptx к Claude API: настройка container.skills и code_execution, проверка ответа и скачивание презентации через Files API.

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


<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Ключевые сведения">

Коротко о главном

Готовый Agent Skill для работы с документами можно использовать через прямой вызов Claude API: добавьте навык в `container.skills` и активируйте `code_execution`. Для первого запроса выберите совместимую модель и инструмент из официального примера. Созданный документ скачивается отдельно по `file_id`; в этом примере один API-ключ служит и для запроса, и для загрузки файла.

</div>



Другие инструкции собраны в [документации Ailoot](https://ailoot.ai/docs/).

## Что потребуется

Материал посвящён прямому обращению к API из программы, а не установке навыка в Claude Code. Подготовьте API-ключ Claude, доступ к выбранной модели и Python 3. Приведённый пример использует встроенные средства Python для HTTP-запросов, поэтому ему не нужна конкретная версия SDK. Ключ задаётся в переменной окружения `ANTHROPIC_API_KEY`; не записывайте его в исходный код или сообщения.

Anthropic предоставляет готовые навыки для API: `pptx` для презентаций, `xlsx` для электронных таблиц, `docx` для документов Word и `pdf` для файлов PDF. Для подключения используется тип `"anthropic"`. Ниже применяется готовый навык, без загрузки собственного.

В [официальном quickstart](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/quickstart.md), изученном при подготовке этого материала, приведено сочетание `claude-opus-5-5` и `code_execution_20260521`. Ниже используется именно оно. Это пример, сверенный с документацией, а не свидетельство выполненного платного API-вызова.

## Нужные beta-заголовки

В HTTP-примере сохранены параметры текущего контракта из quickstart: `x-api-key`, `anthropic-version: 2023-06-01` и `content-type: application/json`. Заголовок `anthropic-beta` не добавляется. Не смешивайте модель, формат ответа и способ вызова из разных поколений документации.

Согласно [документации Files API](https://platform.claude.com/docs/en/build-with-claude/files.md), этот API вышел из beta. Устаревший заголовок `files-api-2025-04-14` оставляет прежние форматы ответов; если его убрать, используются актуальные форматы. Поэтому старый вызов через `client.beta.files` не следует без изменений сочетать с новым контрактом.

Здесь речь не идёт о переносе уже работающего сервиса со старого beta-контракта. Если такой сервис у вас есть, сперва проверьте его заголовки и структуру ответов. Наличие слова `beta` в названии метода SDK само по себе ничего не решает: документация Files API отдельно описывает различия между версиями SDK.





## Создайте презентацию и скачайте её

В примере API получает задание подготовить пять слайдов о возобновляемой энергетике. Весь ответ сохраняется в `skill-response.json`, после чего программа находит идентификаторы созданных файлов. Путь для сохранения не берётся из ответа модели: файлы записываются в новую локальную папку `skill-output`. Если эта папка уже создана, выполнение прекращается, чтобы не затереть имеющиеся результаты. Папка создаётся до запроса API, поэтому остаётся и после неудачного вызова. Сначала изучите и сохраните эту попытку; не удаляйте её только для того, чтобы повторный запуск прошёл.

```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": "Create a presentation about renewable energy with 5 slides in my preferred language.",
    }],
    "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)
```

Имена `result-1.pptx` и следующие за ним соответствуют этой задаче по созданию презентации. Само расширение не подтверждает, что внутри файл нужного формата: откройте скачанный документ и проверьте тип, количество слайдов и текст. Один лишь HTTP 200 или полученный `file_id` не означает, что результат готов.

Программа печатает `stop_reason` — причину завершения ответа — и сохраняет полный ответ для последующей проверки. Она не отправляет продолжение диалога и не повторяет платный запрос автоматически. Скачанный файл тоже не гарантирует, что задача выполнена целиком: сначала проверьте сохранённый ответ и сам документ, а затем решайте, нужен ли ещё один запрос.

При неудачной попытке проверьте `skill-error.json`, если он создан. В нём записаны HTTP-статус, идентификатор запроса, если он был передан, и ограниченное сообщение провайдера с удалённым значением настроенного API-ключа. Перед передачей другим людям проверьте сообщение на иные приватные данные. Сопоставляйте ошибки аутентификации, прав или модели, платёжных лимитов и формата запроса с [официальным справочником ошибок](https://platform.claude.com/docs/en/api/errors); не всякая ошибка требует новой платной генерации.

Если в `skill-response.json` уже есть созданные `file_id`, а сбой произошёл при скачивании, сохраните ответ и проверяйте метаданные и загрузку файла с тем же разрешённым доступом к workspace. Не запускайте генерацию заново ради существующего результата. При неизвестном исходе запроса сохраните его ID и выясните статус до новой генерации. Только если новая генерация действительно нужна, задайте свободный путь, например `out = Path("skill-output-attempt-2")`, сохранив `exist_ok=False`. Новая папка предотвращает локальную перезапись, но сама по себе не предотвращает повторный платёж. `FileExistsError` — локальная коллизия папки, а не ответ API.

## Какие разрешения требуются для работы с файлами

Files API связывает файлы с workspace — рабочим пространством, — а не с пользователем вашего приложения или конкретной перепиской. Как сказано в документации, доступ к файлам этого workspace может получить любой API-ключ, которому разрешено работать с ним. Для генерации и скачивания в примере применяется один и тот же ключ. Не принимайте `file_id` от конечного пользователя или из другого недоверенного источника. Храните идентификаторы на сервере, а связь между пользователями и их файлами учитывайте в собственном приложении.

Проверьте и метаданные файла: в них должно быть `downloadable: true`. Документация допускает скачивание файлов, созданных навыками или инструментом выполнения кода. Для загруженных вами файлов значение `downloadable: false`, и попытка получить такой файл вернёт ошибку 400. Доступ к workspace сам по себе не гарантирует возможности скачать каждый файл.

Для приложения с несколькими клиентами документация Files API советует выделять каждому клиенту отдельный workspace, чтобы разделять доступ к файлам. Это рекомендация касается именно файлов; не распространяйте её на другие сущности и разрешения без проверки документации соответствующего API.

## Готовый навык и пользовательский навык

Для готовых навыков предусмотрены идентификаторы `pptx`, `xlsx`, `docx` и `pdf`. В [справке по списку навыков](https://platform.claude.com/docs/en/api/skills/list.md) указано, что источник `custom` означает навык, закрытый для workspace, а `anthropic` — общий, доступный только для чтения.

В первом примере `version: "latest"` обозначает последнюю опубликованную версию навыка. Для интеграции, результаты которой должны воспроизводиться, учитывайте: выбранная версия со временем может измениться. Чтобы закрепить конкретную версию, укажите существующую версию используемого навыка, а не придумывайте идентификатор по образцу.

## Ограничения и дальнейшие действия

Этот пример показывает только создание презентации с готовым навыком и скачивание результата. Загрузка и удаление собственных навыков, а также обращение к сторонним сервисам здесь не рассматривались. Для каждого такого сценария отдельно проверьте соответствующий API.

Если вы работаете с файлами через интерфейс Claude, ознакомьтесь с отдельным материалом [о загрузке файла в Claude](https://ailoot.ai/blog/ru/claude-file-upload/). Для прямых API-вызовов пригодится руководство [по расчёту расхода токенов](https://ailoot.ai/blog/ru/api-token-usage-calculation/). Если же вы используете терминальный агент, прочитайте [о выборе навыков Claude Code](https://ailoot.ai/blog/ru/choose-claude-code-skills/): это другой способ подключения.

Для начальной проверки возьмите один готовый навык `pptx`, проверьте ответ API, скачайте файл с разрешённым доступом и откройте его. Подключайте собственные навыки и настраивайте разделение доступа между клиентами после этой проверки.





Когда будете готовы, познакомьтесь с [Ailoot](https://ailoot.ai/).

## Вопросы и ответы

### Почему file_id недостаточно для завершения задачи с презентацией?

Идентификатор подтверждает возврат файла, но не пригодность презентации. Проверьте метаданные downloadable: true, скачайте файл с доступом к рабочему пространству и откройте его. Проверьте формат, число слайдов и текст.

### Можно ли скачать любой файл, загруженный в Claude Files API?

Нет. Руководство различает созданные файлы с downloadable: true и загруженные с downloadable: false. Доступ к рабочему пространству и разрешение скачивать конкретный файл проверяются отдельно. Не принимайте от конечных пользователей произвольные идентификаторы файлов.


## Ailoot · Компания и портфель её проектов

Ailoot опирается на накопленный опыт работы, большую клиентскую базу, стабильный сервис и постоянный контроль KPI.

Компания и портфель её проектов: миллионы клиентов; продажи на миллиарды ежемесячно.

Этот опыт Ailoot использует для API-доступа к нейросетям в продуктах клиентов, агентах, приложениях и автоматизациях.
