Представьте: вы открываете терминал, вводите двадцать строк кода — и через несколько секунд получаете связный, умный ответ от одной из лучших языковых моделей в мире. Именно так выглядит знакомство с Claude API. Но между «hello world» и настоящим продакшн-сервисом — пропасть из ошибок 429, протёкших API-ключей и счетов, которые оказались неожиданно высокими.

В этом гайде мы пройдём весь путь: от установки пакета до оптимизации затрат в 10 раз. Без воды — только код и проверенные практики.


Установка и первый запрос

Требования минимальны: Python 3.9+ и один pip-вызов.

pip install anthropic

Получить API-ключ можно на console.anthropic.com. Никогда не храните ключ в коде — используйте переменные окружения:

export ANTHROPIC_API_KEY="sk-ant-..."

Теперь самый простой запрос:

import os
from anthropic import Anthropic

client = Anthropic()  # автоматически читает ANTHROPIC_API_KEY из окружения

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Объясни разницу между list и tuple в Python за три предложения."}
    ]
)

print(message.content[0].text)

Всё. Вы сделали первый запрос. Ответ приходит в поле message.content — список блоков, первый из которых содержит текст в .text.

ℹ Структура ответа
message.usage содержит input_tokens и output_tokens — это ваш главный инструмент для контроля затрат. Логируйте их с первого дня.

Выбор модели: таблица актуальных вариантов

На апрель 2026 года в продакшне доступны три основные модели семейства Claude 4.x:

МодельЦена входных токеновЦена выходных токеновКонтекстЛучше всего для
claude-haiku-4-5$1 / 1M$5 / 1M1M токеновКлассификация, короткие ответы, высокая нагрузка
claude-sonnet-4-6$3 / 1M$15 / 1M1M токеновСбалансированные задачи, код, анализ
claude-opus-4-6$5 / 1M$25 / 1M1M токеновСложный reasoning, многошаговые агенты

Выбор модели — это первое и самое важное архитектурное решение. Переплата за Opus там, где справится Haiku, легко превращается в десятикратный перерасход бюджета.

💡 Правило выбора модели
Начинайте с Haiku, переходите к Sonnet только когда качество не устраивает. Opus держите для финального fallback или самых сложных задач.

Стриминг, async и многоходовые диалоги

Стриминг ответа

Для UX критично показывать ответ по мере генерации — не заставлять пользователя ждать полного завершения:

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=2048,
    messages=[{"role": "user", "content": "Напиши функцию быстрой сортировки на Python"}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

Асинхронный клиент

Если ваш сервис на FastAPI или использует asyncio — используйте AsyncAnthropic:

import asyncio
from anthropic import AsyncAnthropic

async_client = AsyncAnthropic()

async def ask(question: str) -> str:
    message = await async_client.messages.create(
        model="claude-haiku-4-5",
        max_tokens=512,
        messages=[{"role": "user", "content": question}]
    )
    return message.content[0].text

async def main():
    results = await asyncio.gather(
        ask("Что такое GIL?"),
        ask("Что такое event loop?"),
        ask("Чем asyncio отличается от threading?"),
    )
    for r in results:
        print(r, "\n---")

asyncio.run(main())

Параллельные запросы через asyncio.gather — стандартный способ сократить latency при обработке батча.

Многоходовый диалог

Контекст передаётся вручную — API stateless:

history = []

def chat(user_input: str) -> str:
    history.append({"role": "user", "content": user_input})
    
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        messages=history
    )
    
    assistant_reply = response.content[0].text
    history.append({"role": "assistant", "content": assistant_reply})
    return assistant_reply

print(chat("Меня зовут Алексей, я пишу на Python"))
print(chat("Как меня зовут?"))  # Claude вспомнит имя из контекста
⚠ Контроль длины контекста
При длинных диалогах история растёт и в какой-то момент превысит max_tokens. Реализуйте обрезку истории или суммаризацию старых сообщений — иначе получите InvalidRequestError.

Prompt Caching: экономия до 90% на повторяющихся промптах

Если у вас есть большой системный промпт, документация, few-shot примеры или любой другой постоянный контент — prompt caching это обязательная функция.


sequenceDiagram
    participant App as Ваше приложение
    participant API as Claude API
    participant Cache as Кэш (TTL 1h)

    App->>API: Запрос 1 (system prompt + вопрос)
cache_control: ephemeral API->>Cache: Записать системный промпт Cache-->>API: Cache WRITE (+25% к цене) API-->>App: Ответ + usage: {cache_creation_input_tokens: N} App->>API: Запрос 2 (тот же system prompt + другой вопрос) API->>Cache: Проверить кэш Cache-->>API: Cache HIT (10% от базовой цены) API-->>App: Ответ + usage: {cache_read_input_tokens: N}

Ценообразование: запись в кэш стоит 125% от базовой цены (разово), каждое попадание — только 10%. При 10+ запросах с одним системным промптом экономия становится ощутимой.

SYSTEM_PROMPT = """
Ты — опытный Python-разработчик и технический ревьюер.
[... 2000 токенов документации и правил ...]
"""

def review_code(code: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        system=[
            {
                "type": "text",
                "text": SYSTEM_PROMPT,
                "cache_control": {"type": "ephemeral"}  # пометить для кэширования
            }
        ],
        messages=[{"role": "user", "content": f"Проверь этот код:\n```python\n{code}\n```"}]
    )
    
    usage = response.usage
    print(f"Cache write: {usage.cache_creation_input_tokens}, "
          f"Cache read: {usage.cache_read_input_tokens}, "
          f"Input: {usage.input_tokens}")
    
    return response.content[0].text
💡 TTL кэша
TTL кэша — 1 час (GA с 2025 года, beta-заголовок больше не нужен). Если промпт не менялся — каждый запрос в течение часа будет попаданием в кэш.

Обработка ошибок и продакшн-практики

Типы ошибок и стратегии

import time
import anthropic
from anthropic import APIError, APIConnectionError, RateLimitError, APIStatusError

def robust_request(messages: list, max_retries: int = 5) -> str:
    delay = 2.0
    
    for attempt in range(max_retries):
        try:
            response = client.messages.create(
                model="claude-sonnet-4-6",
                max_tokens=1024,
                messages=messages
            )
            return response.content[0].text
        
        except RateLimitError as e:
            # 429 — превышен лимит. Ждём retry-after из заголовка
            retry_after = float(e.response.headers.get("retry-after", delay))
            print(f"Rate limit. Ждём {retry_after:.1f}s...")
            time.sleep(retry_after)
            delay = min(delay * 2, 120)  # exponential backoff, cap 2 min
        
        except APIStatusError as e:
            if e.status_code == 529:
                # 529 — API перегружен (отличается от 429!)
                print(f"API overloaded. Попытка {attempt + 1}/{max_retries}")
                time.sleep(delay)
                delay = min(delay * 2, 120)
            else:
                raise  # прочие статус-ошибки не ретраим
        
        except APIConnectionError:
            print(f"Сетевая ошибка. Попытка {attempt + 1}/{max_retries}")
            time.sleep(delay)
    
    raise RuntimeError(f"Не удалось выполнить запрос после {max_retries} попыток")
⚠ 429 vs 529
429 (RateLimitError) — вы превысили свой лимит, нужно снизить интенсивность. 529 — серверная перегрузка на стороне Anthropic, временная. Стратегии разные: для 429 добавьте очередь или снизьте параллелизм; для 529 просто подождите.

Batch API: -50% к цене при асинхронной обработке

Если ваши задачи не требуют ответа в реальном времени — используйте Batch API. Он обрабатывает запросы в течение 24 часов и стоит вдвое дешевле:

# Создаём батч из нескольких запросов
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"req-{i}",
            "params": {
                "model": "claude-haiku-4-5",
                "max_tokens": 256,
                "messages": [{"role": "user", "content": text}]
            }
        }
        for i, text in enumerate(texts_to_process)
    ]
)

print(f"Батч создан: {batch.id}")

# Через некоторое время — получаем результаты
results = client.messages.batches.results(batch.id)
for result in results:
    print(result.custom_id, result.result.message.content[0].text)

Архитектура для продакшна


graph TD
    A[Входящий запрос] --> B{Нужен
быстрый ответ?} B -- Да --> C[Sync / Streaming API] B -- Нет --> D[Batch API
-50% цена] C --> E{Большой
системный промпт?} E -- Да --> F[Prompt Caching
-90% на повторах] E -- Нет --> G[Прямой запрос] F --> H{Выбор модели} G --> H H -- Простая задача --> I[Haiku 4.5
$1/$5] H -- Средняя задача --> J[Sonnet 4.6
$3/$15] H -- Сложный reasoning --> K[Opus 4.6
$5/$25]

Оптимизация затрат: сводная таблица

Комбинируя доступные инструменты, можно снизить счёт в 10–20 раз по сравнению с наивным использованием:

ТехникаЭкономияКогда применять
Выбор Haiku вместо Opusдо 5×Простые классификация, саммаризация
Prompt Caching (попадание)90% на кэшированных токенахПовторяющийся system prompt / документы
Batch API50% на всех токенахОфлайн-задачи без требований к latency
Batch + Cachingдо 95%Массовая обработка с постоянным промптом
Контроль max_tokensдо 30%Ограничить максимум под реальные нужды
Обрезка истории диалогапеременнаяДлинные сессии, чат-боты
📝 Реальный расчёт
Допустим, у вас 10 000 запросов в день, системный промпт 2 000 токенов, ответ 500 токенов. Без оптимизации на Sonnet: ~$5/день. С Haiku + prompt caching: ~$0.25/день. Разница в 20 раз.

Заключение

Claude API для Python — один из самых продуманных LLM-интерфейсов: минимальный бойлерплейт, внятные ошибки, встроенные ретраи. Но разница между «работает» и «работает в продакшне» определяется несколькими ключевыми решениями:

  1. Модель — не берите Opus по умолчанию. Начните с Haiku, переходите выше по необходимости.
  2. Prompt Caching — если системный промпт больше 1 024 токенов и используется повторно, это обязательно.
  3. Batch API — для любых офлайн-задач это честные −50% без каких-либо изменений в логике.
  4. Обработка ошибок — различайте 429 и 529, реализуйте exponential backoff с jitter.
  5. Мониторинг токенов — логируйте usage с первого дня, иначе сюрпризы в счёте гарантированы.

Все эти практики не требуют сложной инфраструктуры — только осознанного использования уже встроенных возможностей SDK.