Туториалы

Claude API: полный гайд для разработчиков

Что такое Claude API?

Claude API — программный интерфейс Anthropic для интеграции моделей Claude в приложения. Работает через Messages API: вы отправляете массив сообщений (user/assistant), получаете ответ модели. Поддерживает text, vision, tool use, streaming, extended thinking и prompt caching. Доступен через REST API, Python SDK и TypeScript SDK.

TL;DR

  • -Claude API работает через Messages API — единый endpoint для текста, изображений, tool use, streaming и extended thinking
  • -Три модели: Opus 4.8 ($5/$25 за MTok) для сложных задач и агентов, Sonnet 4.6 ($3/$15) как баланс скорости и качества, Haiku 4.5 ($1/$5) для массовых операций
  • -Tool use превращает Claude в исполнителя: модель генерирует JSON-вызовы ваших функций, вы возвращаете результат — цикл повторяется до завершения задачи
  • -Prompt caching снижает стоимость повторяющегося контекста в 10 раз (cache read = 10% от базовой цены), Batches API дает 50% скидку на некритичные задачи
  • -Adaptive thinking управляет глубиной рассуждений через `output_config.effort` (low/medium/high/max); старый `budget_tokens` deprecated с Opus/Sonnet 4.6

Claude API — программный интерфейс для работы с моделями Anthropic. Один endpoint — Messages API — покрывает текст, изображения, tool use, streaming и extended thinking. Python SDK, TypeScript SDK, REST — три способа интеграции.

Эта статья — полный справочник. От первого запроса до продвинутых техник: prompt caching, batches, vision. Каждый пример — рабочий код, который можно скопировать и запустить.

Что такое Claude API

Messages API — единый endpoint

Вся работа с Claude проходит через один endpoint: POST https://api.anthropic.com/v1/messages. Вы отправляете массив сообщений с ролями user и assistant, модель генерирует следующее сообщение в диалоге.

Это не completions API в стиле GPT-3 — Messages API построен вокруг диалоговой структуры. Каждый запрос содержит полную историю разговора. Состояние между вызовами не хранится.

Модели

Три модели текущего поколения:

МодельAPI IDКонтекстMax outputЦена (input/output за MTok)
Opus 4.8claude-opus-4-81M128k$5 / $25
Sonnet 4.6claude-sonnet-4-61M128k$3 / $15
Haiku 4.5claude-haiku-4-5200k64k$1 / $5

Opus 4.8 — флагман. Максимальная точность в коде, reasoning, агентных задачах. 1M токенов контекста, 128k output. Выбирайте для задач, где ошибка дорого стоит.

Sonnet 4.6 — рабочая лошадка. Быстрый, умный, в 1.67 раза дешевле Opus по output ($15 vs $25). Подходит для 90% production-задач: чат-боты, генерация контента, анализ документов.

Haiku 4.5 — скорость и экономия. Классификация, извлечение данных, модерация, массовая обработка. В 3 раза дешевле Sonnet по output ($5 vs $15).

Отличие от Claude.ai

Claude.ai — чат-интерфейс. API дает то, чего в чате нет:

  • System prompts — точная настройка поведения модели
  • Tool use — модель вызывает ваши функции
  • Streaming — потоковый вывод токен за токеном
  • Extended thinking — доступ к цепочке рассуждений
  • Prompt caching — кэширование повторяющегося контекста
  • Batches — асинхронная пакетная обработка со скидкой 50%
  • Полный контроль — temperature, stop sequences, metadata

Быстрый старт

Получение API-ключа

  1. Зарегистрируйтесь на console.anthropic.com
  2. Перейдите в Settings → API Keys
  3. Создайте ключ (начинается с sk-ant-)
  4. Пополните баланс в Billing (минимум $5)

Ключ привязан к workspace. Один workspace — один набор ключей, лимитов, биллинга.

Установка SDK

Python:

pip install anthropic

TypeScript:

npm install @anthropic-ai/sdk

SDK берёт ключ из переменной окружения ANTHROPIC_API_KEY:

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

Первый запрос

Python:

import anthropic

client = anthropic.Anthropic()

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

print(message.content[0].text)

TypeScript:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

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

console.log(message.content[0].text);

Ответ в message.content — массив контент-блоков. Для простого текста — один блок с type: "text".

Streaming — потоковый ответ

Streaming отдаёт токены по мере генерации — пользователь видит ответ сразу.

Python:

import anthropic

client = anthropic.Anthropic()

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

TypeScript:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const stream = await client.messages.stream({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  messages: [
    { role: "user", content: "Напиши функцию бинарного поиска на Python." }
  ]
});

for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

Messages API: полный разбор

Параметры запроса

ПараметрТипОбязательныйОписание
modelstringДаID модели: claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5
messagesarrayДаМассив сообщений с ролями user и assistant
max_tokensintegerДаМаксимум токенов в ответе (Opus 4.8/Sonnet 4.6: до 128k, Haiku 4.5: до 64k)
systemstring/arrayНетSystem prompt — инструкции для модели
temperaturefloatНетСлучайность: 0.0-1.0 (default: 1.0). Ниже — детерминированнее
top_pfloatНетNucleus sampling: 0.0-1.0. Альтернатива temperature
top_kintegerНетВыборка из top-K токенов. Для продвинутых кейсов
stop_sequencesarrayНетСтроки, при генерации которых модель останавливается
streambooleanНетПотоковый вывод через Server-Sent Events
metadataobjectНетuser_id для отслеживания и abuse detection

System prompt

System prompt задаёт роль и правила поведения. Передаётся отдельным параметром, не через messages.

Python:

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system="Ты — senior Python-разработчик. Отвечай кратко. Код — с типами и docstrings.",
    messages=[
        {"role": "user", "content": "Напиши декоратор для retry с exponential backoff."}
    ]
)

System prompt — строка или массив контент-блоков. Массив нужен для prompt caching:

system=[
    {
        "type": "text",
        "text": "Ты — senior Python-разработчик. Отвечай кратко.",
        "cache_control": {"type": "ephemeral"}
    }
]

Multi-turn conversations

Claude не хранит состояние между запросами. Для продолжения диалога отправляйте всю историю:

Python:

messages = [
    {"role": "user", "content": "Что такое dependency injection?"},
    {"role": "assistant", "content": "Dependency injection — паттерн, при котором зависимости объекта передаются извне, а не создаются внутри..."},
    {"role": "user", "content": "Покажи пример на Python с dataclass."}
]

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=messages
)

Каждое сообщение — объект с role (user или assistant) и content. Роли чередуются. Два подряд от одной роли — API объединит их.

Stop sequences

Кастомные строки, при генерации которых модель останавливается:

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    stop_sequences=["```", "END"],
    messages=[
        {"role": "user", "content": "Напиши JSON-конфигурацию для nginx."}
    ]
)

# message.stop_reason == "stop_sequence"
# message.stop_sequence == "```"

Полезно для structured output: модель генерирует до определенного маркера, вы парсите результат.

Metadata

user_id в metadata нужен для отслеживания abuse. Добавляйте в production:

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    metadata={"user_id": "user_abc123"},
    messages=[
        {"role": "user", "content": "Привет!"}
    ]
)

Используйте хеши или UUID, не передавайте email или реальные имена.

Tool Use (Function Calling)

Tool use — способ вызывать ваши функции из Claude. Вы описываете инструменты через JSON Schema. Модель решает, когда и какой вызвать, формирует параметры. Вы исполняете вызов и возвращаете результат.

Определение инструментов

Инструмент — это имя, описание и JSON Schema для входных параметров:

tools = [
    {
        "name": "get_weather",
        "description": "Получить текущую погоду в указанном городе.",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "Название города, например: Москва"
                },
                "units": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "Единицы измерения температуры"
                }
            },
            "required": ["city"]
        }
    }
]

Описания критичны. Claude читает их, чтобы решить — вызывать инструмент или нет. Чем точнее описание, тем правильнее выбор.

Цикл tool_use → tool_result

Цикл выглядит так:

  1. Вы отправляете запрос с tools
  2. Claude возвращает блок tool_use с именем инструмента и параметрами
  3. Вы исполняете вызов
  4. Отправляете результат как tool_result
  5. Claude формирует финальный ответ (или вызывает следующий инструмент)

Полный пример: погодный бот

Python:

import anthropic
import json

client = anthropic.Anthropic()

tools = [
    {
        "name": "get_weather",
        "description": "Получить текущую погоду в указанном городе.",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "Город"},
                "units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["city"]
        }
    }
]

def get_weather(city: str, units: str = "celsius") -> dict:
    """Заглушка — в production здесь вызов реального API."""
    return {"city": city, "temperature": 22, "units": units, "condition": "облачно"}

# Шаг 1: отправляем запрос
messages = [{"role": "user", "content": "Какая погода в Москве?"}]

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    messages=messages
)

# Шаг 2: обрабатываем tool_use
if response.stop_reason == "tool_use":
    # Находим блок tool_use в ответе
    tool_block = next(b for b in response.content if b.type == "tool_use")

    # Исполняем вызов
    result = get_weather(**tool_block.input)

    # Шаг 3: возвращаем результат
    messages.append({"role": "assistant", "content": response.content})
    messages.append({
        "role": "user",
        "content": [
            {
                "type": "tool_result",
                "tool_use_id": tool_block.id,
                "content": json.dumps(result)
            }
        ]
    })

    # Шаг 4: получаем финальный ответ
    final_response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        tools=tools,
        messages=messages
    )

    print(final_response.content[0].text)

TypeScript:

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const tools: Anthropic.Tool[] = [
  {
    name: "get_weather",
    description: "Получить текущую погоду в указанном городе.",
    input_schema: {
      type: "object" as const,
      properties: {
        city: { type: "string", description: "Город" },
        units: { type: "string", enum: ["celsius", "fahrenheit"] }
      },
      required: ["city"]
    }
  }
];

function getWeather(city: string, units = "celsius") {
  return { city, temperature: 22, units, condition: "облачно" };
}

const messages: Anthropic.MessageParam[] = [
  { role: "user", content: "Какая погода в Москве?" }
];

const response = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  tools,
  messages
});

if (response.stop_reason === "tool_use") {
  const toolBlock = response.content.find(
    (b): b is Anthropic.ToolUseBlock => b.type === "tool_use"
  )!;

  const result = getWeather(
    (toolBlock.input as any).city,
    (toolBlock.input as any).units
  );

  messages.push({ role: "assistant", content: response.content });
  messages.push({
    role: "user",
    content: [
      {
        type: "tool_result",
        tool_use_id: toolBlock.id,
        content: JSON.stringify(result)
      }
    ]
  });

  const finalResponse = await client.messages.create({
    model: "claude-sonnet-4-6",
    max_tokens: 1024,
    tools,
    messages
  });

  console.log((finalResponse.content[0] as Anthropic.TextBlock).text);
}

tool_choice — контроль вызова инструментов

ЗначениеПоведение
{"type": "auto"}Модель сама решает — вызывать или нет (default)
{"type": "any"}Модель обязана вызвать хотя бы один инструмент
{"type": "tool", "name": "get_weather"}Модель обязана вызвать конкретный инструмент
{"type": "none"}Инструменты отключены
# Принудительный вызов конкретного инструмента
response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "tool", "name": "get_weather"},
    messages=[{"role": "user", "content": "Расскажи о Москве."}]
)

Forced tool use (type: "tool") удобен для structured output: опишите «инструмент» с нужной JSON-структурой — Claude заполнит её.

Параллельные вызовы инструментов

Claude вызывает несколько инструментов за один ход. Ответ содержит несколько блоков tool_use — обработайте все и верните результаты:

# Если Claude вызвал 3 инструмента — возвращаем 3 результата
tool_results = []
for block in response.content:
    if block.type == "tool_use":
        result = execute_tool(block.name, block.input)
        tool_results.append({
            "type": "tool_result",
            "tool_use_id": block.id,
            "content": json.dumps(result)
        })

messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})

Отключить параллельные вызовы: tool_choice: {"type": "auto", "disable_parallel_tool_use": true}.

Extended Thinking

Extended thinking показывает, как Claude рассуждает перед ответом. Модель разбирает задачу по шагам, проверяет гипотезы, выявляет ошибки — и только потом отвечает.

Когда включать

  • Сложная математика и логические задачи
  • Многошаговый анализ кода
  • Задачи с неочевидным решением
  • Любая ситуация, где «подумать дольше» = «ответить лучше»

Параметры

С выходом Claude 4.6 Anthropic перешла на adaptive thinking — модель сама решает, сколько думать. Параметр budget_tokens deprecated начиная с Opus 4.6 и Sonnet 4.6; на Opus 4.7, Opus 4.8 и новее его передача возвращает 400 Bad Request.

Новый синтаксис — thinking: {type: "adaptive"} с управлением глубиной через output_config.effort:

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=16000,
    thinking={"type": "adaptive"},
    output_config={"effort": "high"},  # low | medium | high (default) | max
    messages=[
        {"role": "user", "content": "Докажи, что существует бесконечно много простых чисел p, где p mod 4 == 3."}
    ]
)

effort — мягкий сигнал, не жёсткий лимит токенов. Жёсткая граница — max_tokens. При low/medium Claude может пропустить thinking на простых задачах; при max — всегда думает глубоко.

Чтение thinking-блоков

Ответ содержит thinking и text блоки:

for block in response.content:
    if block.type == "thinking":
        print(f"Размышления: {block.thinking}")
    elif block.type == "text":
        print(f"Ответ: {block.text}")

В моделях Opus 4.7+ и Opus 4.8 thinking по умолчанию скрыт (display: "omitted") — блок возвращается с пустым полем thinking. На более ранних моделях Claude 4 дефолт — display: "summarized" (краткая выжимка рассуждений). Управляйте отображением явно: thinking: {type: "adaptive", display: "summarized"} вернёт суть рассуждений, display: "omitted" скроет их и снизит latency при streaming. Биллинг — за полные thinking-токены независимо от значения display.

Streaming с extended thinking

Python:

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=16000,
    thinking={"type": "adaptive"},
    output_config={"effort": "high"},
    messages=[{"role": "user", "content": "Реализуй красно-черное дерево на Python."}],
) as stream:
    for event in stream:
        if event.type == "content_block_delta":
            if event.delta.type == "thinking_delta":
                print(event.delta.thinking, end="", flush=True)
            elif event.delta.type == "text_delta":
                print(event.delta.text, end="", flush=True)

Ограничения и совместимость

  • На Opus 4.7, Opus 4.8 и новее параметры temperature, top_p и top_k не принимаются при ненулевых значениях (400)
  • Нельзя prefill (начинать ответ assistant-сообщением)
  • Для тяжёлых задач с effort: max рекомендуется max_tokens не менее 64k
  • Для тяжёлых задач рекомендуется Batches API

Стоимость

Thinking-токены тарифицируются как output-токены. Стоимость зависит от реально израсходованного объёма (не от effort — это лишь подсказка). Следите за usage.output_tokens_details.thinking_tokens, а не только usage.output_tokens.

Опция display: "omitted" скрывает thinking-блоки в ответе и снижает latency, но не стоимость — токены всё равно биллятся.

Prompt Caching

Prompt caching сохраняет обработанные токены между запросами. Cache read стоит 10% от базовой цены — экономия в 10 раз на повторяющемся контексте.

Как работает

Помечаете блоки маркером cache_control. Anthropic кэширует результат. Следующий запрос с тем же контентом — cache hit, токены не перечитываются.

Кэш иерархический: toolssystemmessages. Изменение на любом уровне инвалидирует его и все последующие.

TTL: два варианта

TTLCache writeCache readКогда использовать
5 минут (default)1.25x от базовой цены0.1x от базовой ценыЧастые запросы (чаще раза в 5 минут)
1 час2x от базовой цены0.1x от базовой ценыАгентные задачи, длинные сессии

Минимальный размер для кэширования

МодельМинимум токенов
Opus 4.81024
Sonnet 4.61024
Haiku 4.54096

Контент короче минимума не кэшируется — запрос обработается без ошибок, просто без кэша.

Пример: кэширование большого документа

Python:

import anthropic

client = anthropic.Anthropic()

# Большой документ — кэшируем в system prompt
long_document = open("technical_spec.md").read()

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    system=[
        {
            "type": "text",
            "text": "Ты — технический аналитик. Отвечай на вопросы по документу ниже.",
        },
        {
            "type": "text",
            "text": long_document,
            "cache_control": {"type": "ephemeral"}  # 5-минутный кэш
        }
    ],
    messages=[
        {"role": "user", "content": "Какие нефункциональные требования описаны в документе?"}
    ]
)

# Проверяем кэш
usage = response.usage
print(f"Cache write: {usage.cache_creation_input_tokens}")
print(f"Cache read: {usage.cache_read_input_tokens}")
print(f"Uncached: {usage.input_tokens}")

Второй запрос с тем же system prompt — cache hit. cache_read_input_tokens будет ненулевым.

1-часовой кэш

system=[
    {
        "type": "text",
        "text": long_document,
        "cache_control": {"type": "ephemeral", "ttl": "1h"}
    }
]

Используйте 1-часовой кэш в агентных сценариях, где между запросами больше 5 минут.

Автоматическое кэширование

В multi-turn conversations SDK сам расставляет cache breakpoints. Для большинства чат-сценариев явная разметка не нужна.

Vision (мультимодальность)

Claude принимает изображения в сообщениях. Два способа: base64 и URL.

Поддерживаемые форматы

JPEG, PNG, GIF, WebP. Максимальный размер — 20 МБ на изображение.

Base64

Python:

import anthropic
import base64

client = anthropic.Anthropic()

with open("screenshot.png", "rb") as f:
    image_data = base64.standard_b64encode(f.read()).decode("utf-8")

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/png",
                        "data": image_data
                    }
                },
                {
                    "type": "text",
                    "text": "Проанализируй этот UI-скриншот. Найди проблемы с UX."
                }
            ]
        }
    ]
)

print(message.content[0].text)

URL

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "url",
                        "url": "https://example.com/diagram.png"
                    }
                },
                {
                    "type": "text",
                    "text": "Опиши эту архитектурную диаграмму."
                }
            ]
        }
    ]
)

Подсчет токенов для изображений

Стоимость зависит от размера. Изображение масштабируется автоматически — Claude не обрабатывает пиксели 1:1. Примерные значения:

  • Мелкое изображение (до 384x384): ~170 токенов
  • Среднее (до 1024x1024): ~1600 токенов
  • Большое (до 2048x2048): ~6400 токенов

Для точного подсчёта используйте Token Counting API — отдельный endpoint, который считает токены без генерации ответа.

TypeScript-пример: анализ скриншота

import Anthropic from "@anthropic-ai/sdk";
import { readFileSync } from "fs";

const client = new Anthropic();

const imageData = readFileSync("screenshot.png").toString("base64");

const message = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  messages: [
    {
      role: "user",
      content: [
        {
          type: "image",
          source: {
            type: "base64",
            media_type: "image/png",
            data: imageData
          }
        },
        {
          type: "text",
          text: "Что изображено на скриншоте? Перечисли все UI-элементы."
        }
      ]
    }
  ]
});

console.log(message.content[0].text);

Streaming

Server-Sent Events

При stream: true ответ приходит как поток SSE-событий. Основные типы:

СобытиеОписание
message_startНачало сообщения, содержит метаданные
content_block_startНачало контент-блока (text, tool_use, thinking)
content_block_deltaДельта контента: text_delta, thinking_delta, input_json_delta
content_block_stopКонец контент-блока
message_deltaФинальные данные: stop_reason, usage
message_stopКонец сообщения

Python SDK — stream helper

import anthropic

client = anthropic.Anthropic()

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Напиши async HTTP-клиент на Python."}]
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

# После завершения — доступ к полному сообщению
final_message = stream.get_final_message()
print(f"\nТокены: {final_message.usage.input_tokens} in / {final_message.usage.output_tokens} out")

stream.text_stream отдаёт только текст. Для низкоуровневого доступа к событиям — stream.events.

TypeScript SDK — stream

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const stream = await client.messages.stream({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Напиши async HTTP-клиент на TypeScript." }]
});

for await (const event of stream) {
  if (event.type === "content_block_delta" && event.delta.type === "text_delta") {
    process.stdout.write(event.delta.text);
  }
}

const finalMessage = await stream.finalMessage();
console.log(`\nТокены: ${finalMessage.usage.input_tokens} in / ${finalMessage.usage.output_tokens} out`);

Streaming с tool use

При streaming параметры инструмента приходят как input_json_delta — фрагменты JSON:

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "Какая погода в Москве?"}]
) as stream:
    for event in stream:
        if event.type == "content_block_start" and event.content_block.type == "tool_use":
            print(f"Вызов инструмента: {event.content_block.name}")
        elif event.type == "content_block_delta":
            if event.delta.type == "input_json_delta":
                print(f"  параметры: {event.delta.partial_json}", end="")
            elif event.delta.type == "text_delta":
                print(event.delta.text, end="", flush=True)

Собирайте partial_json до content_block_stop, затем парсите полный JSON.

Batches API

Batches API — асинхронная пакетная обработка со скидкой 50%. Запросы не держат HTTP-соединение: отправили пакет, забрали результаты когда готово.

Когда использовать

  • Массовая обработка: классификация тысяч документов
  • Eval-пайплайны: прогон тестов по бенчмарку
  • Генерация контента: пакетное создание описаний
  • Любые задачи, не критичные по latency

Создание batch-запроса

Python:

import anthropic

client = anthropic.Anthropic()

batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": "request-1",
            "params": {
                "model": "claude-sonnet-4-6",
                "max_tokens": 1024,
                "messages": [
                    {"role": "user", "content": "Классифицируй тикет: 'Не работает оплата картой'. Категории: billing, technical, feature_request."}
                ]
            }
        },
        {
            "custom_id": "request-2",
            "params": {
                "model": "claude-sonnet-4-6",
                "max_tokens": 1024,
                "messages": [
                    {"role": "user", "content": "Классифицируй тикет: 'Хочу экспорт в PDF'. Категории: billing, technical, feature_request."}
                ]
            }
        }
    ]
)

print(f"Batch ID: {batch.id}")
print(f"Статус: {batch.processing_status}")

Получение результатов

# Проверяем статус
batch = client.messages.batches.retrieve(batch.id)

if batch.processing_status == "ended":
    # Читаем результаты
    for entry in client.messages.batches.results(batch.id):
        if entry.result.type == "succeeded":
            print(f"{entry.custom_id}: {entry.result.message.content[0].text}")
        else:
            print(f"{entry.custom_id}: ошибка — {entry.result.type}")

TypeScript

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

const batch = await client.messages.batches.create({
  requests: [
    {
      custom_id: "request-1",
      params: {
        model: "claude-sonnet-4-6",
        max_tokens: 1024,
        messages: [
          { role: "user", content: "Суммаризируй: 'Claude API поддерживает streaming, tool use и prompt caching.'" }
        ]
      }
    }
  ]
});

console.log(`Batch ID: ${batch.id}`);

// Позже — получение результатов
const results = await client.messages.batches.results(batch.id);
for await (const entry of results) {
  if (entry.result.type === "succeeded") {
    console.log(`${entry.custom_id}: ${(entry.result.message.content[0] as Anthropic.TextBlock).text}`);
  }
}

Extended output в Batches

Batches API поддерживает увеличенный output: до 300k токенов для Opus 4.8, Opus 4.7, Opus 4.6 и Sonnet 4.6 с beta-заголовком output-300k-2026-03-24. Для генерации длинных документов, книг, отчётов.

Цены и оптимизация

Таблица цен

МодельInputOutputCache write (5m)Cache readCache write (1h)
Opus 4.8$5$25$6.25 (1.25x)$0.50 (0.1x)$10 (2x)
Sonnet 4.6$3$15$3.75 (1.25x)$0.30 (0.1x)$6 (2x)
Haiku 4.5$1$5$1.25 (1.25x)$0.10 (0.1x)$2 (2x)

Batches API — 50% скидка на все модели.

Все цены за миллион токенов (MTok).

Стратегии оптимизации

1. Выбирайте модель под задачу

Не гоняйте Opus 4.8 на классификации — Haiku справится за 1/25 стоимости. Sonnet закрывает большинство production-задач. Opus берите когда ошибка дорого стоит.

2. Prompt caching для повторяющегося контекста

Если system prompt и контекстные документы одинаковы — кэшируйте. Cache read обходится в 10% от базовой цены. При 100k токенов кэшированного контекста:

  • Без кэша: 100k * $3/MTok = $0.30 за запрос (Sonnet)
  • С кэшем: 100k * $0.30/MTok = $0.03 за запрос
  • Экономия: 90% на input-токенах

3. Batches для некритичных задач

Eval-пайплайны, массовая классификация, генерация датасетов — latency не критична. Batches API даёт 50% скидку.

4. Streaming для UX

Streaming на токенах не экономит, но первый символ появляется через секунды — пользователь не ждёт. Для чат-интерфейсов — обязательно.

5. Контролируйте max_tokens

Не ставьте max_tokens: 128000, если ответ занимает 200 токенов. Claude остановится раньше лимита, но завышенное значение замедляет обработку.

6. Мониторинг usage

Каждый ответ содержит usage:

{
  "input_tokens": 2095,
  "output_tokens": 503,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 2000
}

Логируйте. Считайте стоимость по формуле:

cost = (input_tokens * input_price + output_tokens * output_price
        + cache_creation * write_price + cache_read * read_price) / 1_000_000

Structured Outputs

С 2026 года нативный JSON mode доступен через output_config.format — GA без beta-заголовков. Это альтернатива forced tool use: API гарантирует валидный JSON по заданной схеме.

import anthropic
import json

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    output_config={
        "format": {
            "type": "json_schema",
            "json_schema": {
                "name": "person",
                "schema": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "age": {"type": "integer"},
                        "role": {"type": "string"}
                    },
                    "required": ["name", "age", "role"]
                }
            }
        }
    },
    messages=[
        {"role": "user", "content": "Иван Петров, 35 лет, senior developer"}
    ]
)

data = json.loads(response.content[0].text)
# {"name": "Иван Петров", "age": 35, "role": "senior developer"}

Когда что выбирать:

  • output_config.format — проще, не требует инструментального контекста, подходит для большинства случаев
  • Forced tool use — если уже используете инструменты в том же запросе или нужна более сложная логика роутинга

MCP Connector

MCP Connector позволяет подключать remote MCP серверы прямо из Messages API — без отдельного MCP-клиента. Полезно для агентных сценариев: модель сама вызывает инструменты из ваших MCP-сервисов.

Требует beta-заголовок mcp-client-2025-11-20.

import anthropic

client = anthropic.Anthropic()

response = client.beta.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    mcp_servers=[
        {
            "type": "url",
            "url": "https://your-mcp-server.example.com/mcp",
            "name": "my-tools",
            "authorization_token": "YOUR_TOKEN"  # опционально
        }
    ],
    tools=[
        {
            "type": "mcp_toolset",
            "mcp_server_name": "my-tools"  # имя сервера из mcp_servers
        }
    ],
    messages=[
        {"role": "user", "content": "Выполни задачу, используя доступные инструменты."}
    ],
    betas=["mcp-client-2025-11-20"]
)

Конфигурация инструментов находится в массиве tools в виде объекта mcp_toolset. Можно ограничить набор инструментов через allowlist/denylist:

tools=[
    {
        "type": "mcp_toolset",
        "mcp_server_name": "my-tools",
        "default_config": {"enabled": False},   # allowlist: отключаем всё по умолчанию
        "configs": {
            "tool1": {"enabled": True},          # включаем только нужные
            "tool2": {"enabled": True}
        }
    }
]

Важные ограничения:

  • Поддерживаются только MCP tool calls — prompts и resources не поддерживаются
  • Доступен на Claude API, Claude Platform on AWS и Microsoft Foundry; Bedrock и Google Cloud — не поддерживаются
  • Результаты инструментов приходят из внешней системы — применяйте те же меры доверия, что и к user input (риск indirect prompt injection)

Best Practices

Error handling и retries

Стандартные HTTP-коды. Основные ошибки:

КодПричинаДействие
400Невалидный запросПроверьте параметры
401Неверный API-ключПроверьте ANTHROPIC_API_KEY
429Rate limitRetry с exponential backoff
529API перегруженRetry через 30-60 секунд
500Серверная ошибкаRetry с backoff

Python SDK делает retry автоматически:

# SDK автоматически ретраит 429 и 5xx
client = anthropic.Anthropic(
    max_retries=3,  # default: 2
    timeout=60.0     # секунды
)

Для кастомной логики:

import time
from anthropic import RateLimitError, APIStatusError

def call_with_retry(client, max_retries=3, **kwargs):
    for attempt in range(max_retries):
        try:
            return client.messages.create(**kwargs)
        except RateLimitError:
            wait = 2 ** attempt  # 1s, 2s, 4s
            print(f"Rate limit, жду {wait}s...")
            time.sleep(wait)
        except APIStatusError as e:
            if e.status_code >= 500:
                time.sleep(2 ** attempt)
                continue
            raise
    raise Exception("Все попытки исчерпаны")

Безопасность API-ключей

  • Храните ключ в переменных окружения, не в коде
  • Используйте разные ключи для dev/staging/production
  • Ротируйте ключи регулярно
  • Один workspace — один проект (изоляция биллинга и лимитов)
  • В CI/CD — через секреты (GitHub Secrets, Vault)
# Правильно
client = anthropic.Anthropic()  # берёт из ANTHROPIC_API_KEY

# Неправильно
client = anthropic.Anthropic(api_key="sk-ant-api03-...")  # ключ в коде

Structured output (JSON mode)

Рекомендуемый способ — output_config.format (описан в отдельной секции выше). Для совместимости с более старым кодом или сложных случаев — два классических подхода:

Подход 1: Инструкция в промпте + prefill

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Извлеки данные из текста: 'Иван Петров, 35 лет, senior developer'. Верни JSON с полями name, age, role."},
        {"role": "assistant", "content": "{"}  # prefill — Claude продолжит JSON
    ]
)
# Результат начинается с { — парсите как JSON
result = "{" + message.content[0].text

Подход 2: Forced tool use

tools = [{
    "name": "extract_person",
    "description": "Извлечь данные о человеке.",
    "input_schema": {
        "type": "object",
        "properties": {
            "name": {"type": "string"},
            "age": {"type": "integer"},
            "role": {"type": "string"}
        },
        "required": ["name", "age", "role"]
    }
}]

message = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "tool", "name": "extract_person"},
    messages=[
        {"role": "user", "content": "Иван Петров, 35 лет, senior developer"}
    ]
)

# Гарантированный JSON в tool_use.input
tool_block = next(b for b in message.content if b.type == "tool_use")
person = tool_block.input  # {"name": "Иван Петров", "age": 35, "role": "senior developer"}

Forced tool use надёжнее — Claude всегда вернёт валидный JSON по схеме.

Rate limits

Лимиты зависят от модели и плана. Основные метрики:

  • Requests per minute (RPM) — количество запросов в минуту
  • Tokens per minute (TPM) — количество токенов в минуту
  • Tokens per day (TPD) — суточный лимит

Заголовки ответа содержат текущие лимиты:

anthropic-ratelimit-requests-limit: 1000
anthropic-ratelimit-requests-remaining: 999
anthropic-ratelimit-requests-reset: 2026-04-09T12:00:00Z
anthropic-ratelimit-tokens-limit: 80000
anthropic-ratelimit-tokens-remaining: 79500

Стратегии:

  1. Exponential backoff при 429 — SDK делает это автоматически
  2. Пакетная обработка через Batches API — не попадает под RPM/TPM лимиты
  3. Несколько workspace’ов для изоляции лимитов между проектами
  4. Cache hits не считаются в rate limits — ещё один повод кэшировать

Logging и monitoring

Каждый ответ содержит id (msg_...) и usage. Логируйте оба значения:

import logging

logger = logging.getLogger("claude_api")

response = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Привет"}]
)

logger.info(
    "API call",
    extra={
        "message_id": response.id,
        "model": response.model,
        "input_tokens": response.usage.input_tokens,
        "output_tokens": response.usage.output_tokens,
        "stop_reason": response.stop_reason,
    }
)

В production подключайте observability: Langfuse, LangSmith или собственный pipeline. Трекайте latency, стоимость на запрос, распределение по моделям.

Итого

Claude API — один endpoint, три модели, набор мощных фичей.

Для старта: установите SDK, получите ключ, отправьте первый запрос. Sonnet 4.6 подойдёт для 90% задач.

Для production: prompt caching на повторяющемся контексте, streaming для UX, Haiku для массовых операций, Batches для eval-пайплайнов.

Для сложных задач: adaptive thinking (thinking: {type: "adaptive"} + output_config.effort) для reasoning, tool use для интеграции с внешними системами, MCP Connector для подключения к remote MCP-серверам напрямую из API, Opus 4.8 когда точность критична.

Structured outputs: output_config.format — нативный JSON mode без beta-заголовков, GA с 2026 года.

Вся документация — docs.anthropic.com. SDK: anthropic-sdk-python, anthropic-sdk-typescript. Примеры и рецепты — anthropic-cookbook.

Часто задаваемые вопросы

Как получить API-ключ Claude?
Зарегистрируйтесь на console.anthropic.com, перейдите в Settings → API Keys, создайте ключ. Ключ привязан к workspace. Пополните баланс в Billing — минимальный депозит $5. Ключ начинается с sk-ant-.
Сколько стоит Claude API?
Цены за миллион токенов (MTok): Opus 4.8 — $5 input / $25 output, Sonnet 4.6 — $3 / $15, Haiku 4.5 — $1 / $5. Prompt caching снижает стоимость повторного чтения до 10% от базовой цены. Batches API дает 50% скидку.
Чем Claude API отличается от Claude.ai?
Claude.ai — чат-интерфейс для конечных пользователей. API дает полный контроль: system prompts, tool use (function calling), streaming, extended thinking, prompt caching, batches. Можно встроить Claude в любое приложение, автоматизировать обработку и масштабировать.
Какую модель Claude выбрать?
Opus 4.8 (`claude-opus-4-8`) — для агентов, сложного кода и задач, требующих глубокого reasoning (1M контекст, 128k output). Sonnet 4.6 (`claude-sonnet-4-6`) — основная рабочая модель: быстрая, умная, дешевле Opus (1M контекст, 128k output). Haiku 4.5 (`claude-haiku-4-5`) — для классификации, извлечения данных, массовых операций (200k контекст, 64k output).