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.8 | claude-opus-4-8 | 1M | 128k | $5 / $25 |
| Sonnet 4.6 | claude-sonnet-4-6 | 1M | 128k | $3 / $15 |
| Haiku 4.5 | claude-haiku-4-5 | 200k | 64k | $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-ключа
- Зарегистрируйтесь на console.anthropic.com
- Перейдите в Settings → API Keys
- Создайте ключ (начинается с
sk-ant-) - Пополните баланс в 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: полный разбор
Параметры запроса
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
model | string | Да | ID модели: claude-opus-4-8, claude-sonnet-4-6, claude-haiku-4-5 |
messages | array | Да | Массив сообщений с ролями user и assistant |
max_tokens | integer | Да | Максимум токенов в ответе (Opus 4.8/Sonnet 4.6: до 128k, Haiku 4.5: до 64k) |
system | string/array | Нет | System prompt — инструкции для модели |
temperature | float | Нет | Случайность: 0.0-1.0 (default: 1.0). Ниже — детерминированнее |
top_p | float | Нет | Nucleus sampling: 0.0-1.0. Альтернатива temperature |
top_k | integer | Нет | Выборка из top-K токенов. Для продвинутых кейсов |
stop_sequences | array | Нет | Строки, при генерации которых модель останавливается |
stream | boolean | Нет | Потоковый вывод через Server-Sent Events |
metadata | object | Нет | 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
Цикл выглядит так:
- Вы отправляете запрос с
tools - Claude возвращает блок
tool_useс именем инструмента и параметрами - Вы исполняете вызов
- Отправляете результат как
tool_result - 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, токены не перечитываются.
Кэш иерархический: tools → system → messages. Изменение на любом уровне инвалидирует его и все последующие.
TTL: два варианта
| TTL | Cache write | Cache read | Когда использовать |
|---|---|---|---|
| 5 минут (default) | 1.25x от базовой цены | 0.1x от базовой цены | Частые запросы (чаще раза в 5 минут) |
| 1 час | 2x от базовой цены | 0.1x от базовой цены | Агентные задачи, длинные сессии |
Минимальный размер для кэширования
| Модель | Минимум токенов |
|---|---|
| Opus 4.8 | 1024 |
| Sonnet 4.6 | 1024 |
| Haiku 4.5 | 4096 |
Контент короче минимума не кэшируется — запрос обработается без ошибок, просто без кэша.
Пример: кэширование большого документа
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. Для генерации длинных документов, книг, отчётов.
Цены и оптимизация
Таблица цен
| Модель | Input | Output | Cache write (5m) | Cache read | Cache 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 |
| 429 | Rate limit | Retry с exponential backoff |
| 529 | API перегружен | 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
Стратегии:
- Exponential backoff при 429 — SDK делает это автоматически
- Пакетная обработка через Batches API — не попадает под RPM/TPM лимиты
- Несколько workspace’ов для изоляции лимитов между проектами
- 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.