Claude API: полный гайд для разработчиков
Что такое Claude API?
Claude API - программный интерфейс Anthropic для интеграции моделей Claude в приложения. Работает через Messages API: вы отправляете массив сообщений (user/assistant), получаете ответ модели. Поддерживает text, vision, tool use, streaming, adaptive thinking и prompt caching. Доступен через REST API, Python SDK и TypeScript SDK.
TL;DR
- -Claude API работает через Messages API - единый endpoint для текста, изображений, tool use, streaming и thinking
- -Четыре актуальные модели: Opus 5.5 ($4/$20 за MTok) для агентов и сложных задач, Sonnet 5.5 ($2/$10) - баланс скорости и качества, Haiku 5.5 (от $0.10/$0.50) для массовых операций, Fable 5.1 ($10/$50) для самых тяжёлых рассуждений
- -Tool use превращает Claude в исполнителя: модель генерирует JSON-вызовы ваших функций, вы возвращаете результат - цикл повторяется до завершения задачи
- -Чтение из prompt cache стоит 10% от базовой цены input (5% на Opus 5.5 и Sonnet 5.5, 2.5% на Fable 5.1), Batches API даёт 50% скидку на некритичные задачи
- -На актуальных моделях thinking включён по умолчанию, глубину задаёт `output_config.effort` (low/medium/high/xhigh/max); `budget_tokens`, `temperature`/`top_p`/`top_k` и prefill возвращают 400
Claude API - программный интерфейс для работы с моделями Anthropic. Один endpoint - Messages API - покрывает текст, изображения, tool use, streaming и thinking. Python SDK, TypeScript SDK, REST - три способа интеграции.
Эта статья - полный справочник. От первого запроса до продвинутых техник: prompt caching, batches, vision. Каждый пример - рабочий код, который можно скопировать и запустить.
Если Claude скрыт за endpoint вашего продукта, публичный контракт стоит описать отдельно. Гайд по REST API design разбирает naming, ошибки, версионирование и генерацию OpenAPI для слоя, к которому обращаются клиенты.
Что такое Claude API
Messages API - единый endpoint
Вся работа с Claude проходит через один endpoint: POST https://api.anthropic.com/v1/messages. Вы отправляете массив сообщений с ролями user и assistant, модель генерирует следующее сообщение в диалоге.
Это не completions API в стиле GPT-3 - Messages API построен вокруг диалоговой структуры. Каждый запрос содержит полную историю разговора. Состояние между вызовами не хранится.
Модели
Четыре актуальные модели (на ноябрь 2026):
| Модель | API ID | Контекст | Max output | Цена (input/output за MTok) |
|---|---|---|---|---|
| Fable 5.1 | claude-fable-5-1 | 1M | 128k | $10 / $50 |
| Opus 5.5 | claude-opus-5-5 | 1M | 128k | $4 / $20 |
| Sonnet 5.5 | claude-sonnet-5-5 | 1M | 128k | $2 / $10 |
| Haiku 5.5 | claude-haiku-5-5 | 1M | 128k | $0.10 / $0.50 для промптов до 100K токенов, $0.50 / $2.50 сверх |
Opus 5.5 - основной флагман для долгих агентных задач в коде и работе со знаниями. Документация Anthropic советует начинать именно с него. Дефолтный effort у него medium, поэтому для задач, где нужна глубина, задавайте уровень явно.
Sonnet 5.5 - рабочая лошадка: лучшее сочетание скорости и интеллекта для повседневного кода, агентов и корпоративных задач. Вдвое дешевле Opus 5.5 и по input, и по output ($2/$10 против $4/$20).
Haiku 5.5 - скорость и экономия. Классификация, извлечение данных, роутинг, задачи субагентов. На промптах до 100K токенов в 20 раз дешевле Sonnet 5.5; выше этого порога все цены запроса растут в 5 раз.
Fable 5.1 - самая сильная модель линейки, для тяжёлых рассуждений и долгих агентных задач. Самая медленная и дорогая: берите её, когда Opus 5.5 на высоком effort всё ещё не дотягивает на ваших eval’ах.
Opus 5, Sonnet 5, Haiku 4.5, Fable 5 и модели Opus/Sonnet 4.x теперь в статусе legacy: они доступны, сроки отключения - на странице model deprecations. Если переходите с Sonnet 4.6, Haiku 4.5 или более старых моделей, пересчитайте токены: у Claude 4.7 и новее другой токенайзер, на тот же текст он даёт примерно в 1–1.35 раза больше токенов (в среднем около 30%, по данным страницы цен).
Отличие от Claude.ai
Claude.ai - чат-интерфейс. API дает то, чего в чате нет:
- System prompts - точная настройка поведения модели
- Tool use - модель вызывает ваши функции
- Streaming - потоковый вывод токен за токеном
- Thinking - сводка рассуждений модели и управление их глубиной через
effort - Prompt caching - кэширование повторяющегося контекста
- Batches - асинхронная пакетная обработка со скидкой 50%
- Полный контроль - effort, stop sequences, metadata
Быстрый старт
Получение API-ключа
- Зарегистрируйтесь в Claude Console на platform.claude.com
- Перейдите в Settings → API Keys
- Создайте ключ
- Пополните баланс в Billing
Ключ привязан к workspace. Один workspace - один набор ключей, лимитов, биллинга.
Для локальной разработки ключ можно не заводить: поставьте CLI ant и выполните ant auth login - SDK подхватят эти учётные данные сами.
Установка SDK
Python:
pip install anthropic
TypeScript:
npm install @anthropic-ai/sdk
Примеры рассчитаны на текущие мажорные версии (anthropic 2.x для Python, @anthropic-ai/sdk 1.x для TypeScript). По умолчанию они отправляют версию API 2026-10-21.
SDK берёт ключ из переменной окружения ANTHROPIC_API_KEY:
export ANTHROPIC_API_KEY="your-api-key"
Первый запрос
Python:
import anthropic
client = anthropic.Anthropic()
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
messages=[
{"role": "user", "content": "Объясни разницу между REST и GraphQL в трех предложениях."}
]
)
for block in message.content:
if block.type == "text":
print(block.text)
TypeScript:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const message = await client.messages.create({
model: "claude-sonnet-5-5",
max_tokens: 4096,
messages: [
{ role: "user", content: "Объясни разницу между REST и GraphQL в трех предложениях." }
]
});
for (const block of message.content) {
if (block.type === "text") {
console.log(block.text);
}
}
Ответ в message.content - массив контент-блоков. На актуальных моделях thinking включён по умолчанию, поэтому перед блоком text может идти один или несколько блоков thinking. Выбирайте блоки по type, а не по позиции: код вида content[0].text на таких ответах ломается.
Streaming - потоковый ответ
Streaming отдаёт токены по мере генерации - пользователь видит ответ сразу.
Python:
import anthropic
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-sonnet-5-5",
max_tokens=4096,
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 = client.messages.stream({
model: "claude-sonnet-5-5",
max_tokens: 4096,
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-5-5, claude-sonnet-5-5, claude-haiku-5-5, claude-fable-5-1 |
messages | array | Да | Массив сообщений с ролями user и assistant |
max_tokens | integer | Да | Жёсткий потолок output вместе с thinking (актуальные модели: до 128k; выше 21 333 SDK требует streaming) |
system | string/array | Нет | System prompt - инструкции для модели |
thinking | object | Нет | Режим thinking: на актуальных моделях по умолчанию {"type": "adaptive"}; display определяет, что попадёт в thinking-блоки |
output_config | object | Нет | effort (глубина рассуждений и расход токенов) и format (structured outputs) |
temperature, top_p, top_k | - | - | Не передавайте: на моделях 5.5 и Fable 5.1 недефолтные значения дают 400, а с версии API 2026-10-21 любое значение даёт 400 на всех моделях. В текущих мажорных версиях SDK этих параметров уже нет |
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-5-5",
max_tokens=4096,
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-5-5",
max_tokens=4096,
messages=messages
)
Каждое сообщение - объект с role (user или assistant) и content. Роли чередуются. Два подряд от одной роли - API объединит их. Последним не должно быть сообщение assistant: Claude 4.6 и новее отклоняют заготовленное начало ответа (prefill) с ошибкой 400.
Stop sequences
Кастомные строки, при генерации которых модель останавливается:
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
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-5-5",
max_tokens=4096,
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с именем инструмента и параметрами - Вы исполняете вызов
- Отправляете обратно сообщение assistant без изменений (вместе с блоками
thinking) и результат какtool_result - Claude формирует финальный ответ (или вызывает следующий инструмент)
Шаг 4 на актуальных моделях важен: API отклоняет изменённые, переставленные или частично выкинутые thinking-блоки с ошибкой 400. Добавляйте response.content как есть, не фильтруя блоки по типу.
Полный пример: погодный бот
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-5-5",
max_tokens=4096,
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: возвращаем результат (сообщение assistant — без изменений, вместе с thinking-блоками)
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-5-5",
max_tokens=4096,
tools=tools,
messages=messages
)
for block in final_response.content:
if block.type == "text":
print(block.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-5-5",
max_tokens: 4096,
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-5-5",
max_tokens: 4096,
tools,
messages
});
for (const block of finalResponse.content) {
if (block.type === "text") {
console.log(block.text);
}
}
}
На Opus 5.5 и Sonnet 5.5 короткие заметки, которые модель пишет между вызовами инструментов, приходят не в text, а в блоках thinking - и по умолчанию пустыми. Если интерфейс показывает этот прогресс, задайте thinking: {"type": "adaptive", "display": "summarized"} (или display: "updates" с beta-заголовком thinking-display-updates-2026-08-18).
tool_choice - контроль вызова инструментов
| Значение | Поведение |
|---|---|
{"type": "auto"} | Модель сама решает - вызывать или нет (default) |
{"type": "any"} | Модель обязана вызвать хотя бы один инструмент. На Opus 5.5, Sonnet 5.5 и Fable 5.1 - ошибка 400 |
{"type": "tool", "name": "get_weather"} | Модель обязана вызвать конкретный инструмент. На Opus 5.5, Sonnet 5.5 и Fable 5.1 - ошибка 400 |
{"type": "none"} | Инструменты отключены |
Принудительный вызов по-прежнему работает на Haiku 5.5 и legacy-моделях:
# Принудительный вызов конкретного инструмента (Haiku 5.5)
response = client.messages.create(
model="claude-haiku-5-5",
max_tokens=4096,
tools=tools,
tool_choice={"type": "tool", "name": "get_weather"},
messages=[{"role": "user", "content": "Расскажи о Москве."}]
)
На Opus 5.5, Sonnet 5.5 и Fable 5.1 используйте tool_choice: {"type": "auto"}, назовите инструмент в промпте и поставьте инструменту strict: true, чтобы аргументы всегда совпадали со схемой. Если нужен только JSON заданной структуры, берите structured outputs.
Параллельные вызовы инструментов
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
Thinking даёт Claude порассуждать перед ответом. Модель разбирает задачу по шагам, проверяет гипотезы, выявляет ошибки - и только потом отвечает. Сырую цепочку рассуждений API не отдаёт никогда: максимум - её сводку.
Когда включать
- Сложная математика и логические задачи
- Многошаговый анализ кода
- Задачи с неочевидным решением
- Любая ситуация, где «подумать дольше» = «ответить лучше»
На актуальной линейке вопрос скорее не «включать ли», а «насколько глубоко»: thinking включён по умолчанию, а глубину регулирует effort.
Параметры
С выходом Claude 4.6 Anthropic перешла на adaptive thinking - модель сама решает, сколько думать. Ручной режим thinking: {type: "enabled", budget_tokens: N} на всех актуальных моделях возвращает 400 Bad Request.
Как актуальные модели обрабатывают поле thinking:
| Модель | Без thinking | Выключить thinking | effort по умолчанию |
|---|---|---|---|
| Opus 5.5 | adaptive | Нельзя: {"type": "disabled"} даёт 400 | medium |
| Fable 5.1 | adaptive | Нельзя: {"type": "disabled"} даёт 400 | high |
| Sonnet 5.5 | adaptive | disabled даёт 400; {"type": "between_tools"} отключает предварительное thinking при effort high и ниже | high |
| Haiku 5.5 | adaptive | {"type": "disabled"} при effort high и ниже | medium |
Все четыре принимают все пять уровней effort: low, medium, high, xhigh, max. Глубина задаётся через output_config.effort:
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
output_config={"effort": "high"}, # low | medium | high | xhigh | max
messages=[
{"role": "user", "content": "Докажи, что существует бесконечно много простых чисел p, где p mod 4 == 3."}
]
)
effort - мягкий сигнал, не жёсткий лимит токенов. Жёсткая граница - max_tokens, и она покрывает thinking вместе с текстом ответа. Чтобы снизить стоимость или latency, сначала понижайте effort; чтобы дать модели больше глубины - повышайте. На простых запросах Claude может вовсе не думать - тогда thinking-блока в ответе не будет.
Чтение thinking-блоков
Ответ содержит thinking и text блоки:
for block in response.content:
if block.type == "thinking":
print(f"Размышления: {block.thinking}")
elif block.type == "text":
print(f"Ответ: {block.text}")
На всех актуальных моделях (Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5) по умолчанию display: "omitted": блок приходит с пустым полем thinking и только с signature. На Opus 4.6, Sonnet 4.6 и более ранних моделях дефолтом был display: "summarized". Чтобы видеть суть рассуждений, задайте thinking: {type: "adaptive", display: "summarized"}, как в примере выше. display: "omitted" ускоряет первый токен текста при streaming. Биллинг - за полные thinking-токены независимо от значения display.
Streaming с extended thinking
Python:
with client.messages.stream(
model="claude-sonnet-5-5",
max_tokens=16000,
thinking={"type": "adaptive", "display": "summarized"},
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)
Без display: "summarized" события thinking_delta приходят с пустой строкой, и пользователь видит паузу перед ответом.
Ограничения и совместимость
- Не передавайте
temperature,top_pиtop_k: на Fable 5.1 и моделях 5.5 недефолтные значения дают 400, а с версии API2026-10-21- любые - Нельзя prefill: Claude 4.6 и новее отклоняют заготовленное последнее сообщение assistant с ошибкой 400
- Принудительный вызов инструмента (
tool_choiceany/tool) на Opus 5.5, Sonnet 5.5 и Fable 5.1 даёт 400 max_tokensпокрывает thinking и ответ; приeffort: xhighилиmaxначинайте с 64k- При
max_tokensбольше 21 333 SDK требует streaming: используйте.stream()и.get_final_message() - Для очень длинного output у Batches API есть режим до 300k токенов (см. ниже)
Стоимость
Thinking-токены тарифицируются как output-токены, даже если текст рассуждений вам не возвращается. Стоимость зависит от реально израсходованного объёма (effort его направляет, но не ограничивает). usage.output_tokens - это оплачиваемое число, и thinking в него входит, поэтому оно не совпадёт с длиной видимого текста.
Опция display: "omitted" скрывает thinking-блоки в ответе и снижает latency, но не стоимость - токены всё равно биллятся.
Prompt Caching
Prompt caching сохраняет обработанные токены между запросами. Чтение из кэша стоит 10% от базовой цены input на большинстве моделей, 5% на Opus 5.5 и Sonnet 5.5 и 2.5% на Fable 5.1. Сравнение с OpenAI, Gemini и DeepSeek и формула окупаемости собраны в разборе prompt caching у разных вендоров.
Как работает
Помечаете блоки маркером cache_control. Anthropic кэширует результат. Следующий запрос с тем же контентом - cache hit, токены не перечитываются.
Кэш иерархический: tools → system → messages. Изменение на любом уровне инвалидирует его и все последующие. Смена настроек thinking или уровня effort тоже начинает новый префикс кэша.
TTL: два варианта
| TTL | Cache write | Cache read | Когда использовать |
|---|---|---|---|
| 5 минут (default) | 1.25x от базовой цены | 0.1x от базовой цены (0.05x на Opus 5.5 и Sonnet 5.5, 0.025x на Fable 5.1) | Частые запросы (чаще раза в 5 минут) |
| 1 час | 2x от базовой цены | Как выше | Агентные задачи, длинные сессии |
Минимальный размер для кэширования
| Модель | Минимум токенов |
|---|---|
| Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5, Opus 5 | 512 |
| Sonnet 5, Opus 4.8, 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-5-5",
max_tokens=4096,
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 минут.
Автоматическое кэширование
По умолчанию кэширования нет - без cache_control ничего не кэшируется. Самый простой вариант, с которого документация Anthropic и советует начинать, - один cache_control верхнего уровня в запросе: API сам ставит breakpoint на последний кэшируемый блок и сдвигает его по мере роста истории. Он занимает один из 4 доступных слотов для breakpoint.
Vision (мультимодальность)
Claude принимает изображения в сообщениях. Два способа: base64 и URL.
Поддерживаемые форматы
JPEG, PNG, GIF, WebP (у анимации берётся только первый кадр). Максимальный размер - 10 МБ на изображение (в base64) через Claude API, 5 МБ на Amazon Bedrock. Максимальные размеры - 8000x8000 px.
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-5-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data
}
},
{
"type": "text",
"text": "Проанализируй этот UI-скриншот. Найди проблемы с UX."
}
]
}
]
)
for block in message.content:
if block.type == "text":
print(block.text)
URL
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "url",
"url": "https://example.com/diagram.png"
}
},
{
"type": "text",
"text": "Опиши эту архитектурную диаграмму."
}
]
}
]
)
Подсчет токенов для изображений
Claude обрабатывает изображение патчами 28×28 пикселей: оно стоит ⌈width / 28⌉ × ⌈height / 28⌉ токенов. Крупные изображения сначала уменьшаются. Все актуальные модели относятся к high-resolution tier (Claude 4.7 и новее): до 2576 px по длинной стороне и до 4 784 токенов на изображение; у старых моделей предел - 1568 px и 1 568 токенов. Примеры для актуальных моделей:
- 200x200 px: 64 токена
- 1000x1000 px: 1 296 токенов
- 1920x1080 px: 2 691 токен
- 3840x2160 px: уменьшается до 2576x1449, 4 784 токена
То же изображение может стоить примерно до трёх раз больше токенов, чем на модели standard tier. Если детали не нужны, уменьшайте картинку до отправки. Для точного подсчёта используйте 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-5-5",
max_tokens: 4096,
messages: [
{
role: "user",
content: [
{
type: "image",
source: {
type: "base64",
media_type: "image/png",
data: imageData
}
},
{
type: "text",
text: "Что изображено на скриншоте? Перечисли все UI-элементы."
}
]
}
]
});
for (const block of message.content) {
if (block.type === "text") {
console.log(block.text);
}
}
Streaming
Server-Sent Events
При stream: true ответ приходит как поток SSE-событий. Основные типы:
| Событие | Описание |
|---|---|
message_start | Начало сообщения, содержит метаданные |
content_block_start | Начало контент-блока (text, tool_use, thinking) |
content_block_delta | Дельта контента: text_delta, thinking_delta, signature_delta, input_json_delta |
content_block_stop | Конец контент-блока |
message_delta | Финальные данные: stop_reason, usage |
message_stop | Конец сообщения |
На актуальных моделях поток обычно начинается с блока thinking, поэтому не считайте первый content_block_start текстом - ветвитесь по типу блока.
Python SDK - stream helper
import anthropic
client = anthropic.Anthropic()
with client.messages.stream(
model="claude-sonnet-5-5",
max_tokens=4096,
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.
TypeScript SDK - stream
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const stream = client.messages.stream({
model: "claude-sonnet-5-5",
max_tokens: 4096,
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-5-5",
max_tokens=4096,
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-соединение: отправили пакет, забрали результаты когда готово. В пакет помещается до 100 000 запросов или 256 МБ; большинство пакетов обрабатывается меньше чем за час, результаты хранятся 29 дней.
Когда использовать
- Массовая обработка: классификация тысяч документов
- Eval-пайплайны: прогон тестов по бенчмарку
- Генерация контента: пакетное создание описаний
- Любые задачи, не критичные по latency
Создание batch-запроса
Python:
import anthropic
client = anthropic.Anthropic()
batch = client.messages.batches.create(
requests=[
{
"custom_id": "request-1",
"params": {
"model": "claude-sonnet-5-5",
"max_tokens": 4096,
"messages": [
{"role": "user", "content": "Классифицируй тикет: 'Не работает оплата картой'. Категории: billing, technical, feature_request."}
]
}
},
{
"custom_id": "request-2",
"params": {
"model": "claude-sonnet-5-5",
"max_tokens": 4096,
"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":
text = "".join(b.text for b in entry.result.message.content if b.type == "text")
print(f"{entry.custom_id}: {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-5-5",
max_tokens: 4096,
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") {
const text = entry.result.message.content
.filter((b): b is Anthropic.TextBlock => b.type === "text")
.map((b) => b.text)
.join("");
console.log(`${entry.custom_id}: ${text}`);
}
}
Extended output в Batches
Batches API поддерживает увеличенный output: до 300k токенов для Opus 5.5, Sonnet 5.5, Haiku 5.5, Opus 5, Sonnet 5, Opus 4.8, Opus 4.7, Opus 4.6 и Sonnet 4.6 с beta-заголовком output-300k-2026-03-24 (через client.beta.messages.batches.create). Для генерации длинных документов, книг, отчётов. Одна генерация на 300k токенов может идти больше часа - учитывайте 24-часовое окно обработки пакета.
Цены и оптимизация
Как выбрать между Opus и Sonnet под задачу и бюджет - в отдельном сравнении.
Таблица цен
| Модель | Input | Output | Cache write (5m) | Cache read | Cache write (1h) |
|---|---|---|---|---|---|
| Fable 5.1 | $10 | $50 | $12.50 (1.25x) | $0.25 (0.025x) | $20 (2x) |
| Opus 5.5 | $4 | $20 | $5 (1.25x) | $0.20 (0.05x) | $8 (2x) |
| Sonnet 5.5 | $2 | $10 | $2.50 (1.25x) | $0.10 (0.05x) | $4 (2x) |
| Haiku 5.5 (промпт до 100K токенов) | $0.10 | $0.50 | $0.125 (1.25x) | $0.01 (0.1x) | $0.20 (2x) |
| Haiku 5.5 (промпт больше 100K токенов) | $0.50 | $2.50 | $0.625 (1.25x) | $0.05 (0.1x) | $1 (2x) |
| Opus 5 (legacy) | $5 | $25 | $6.25 (1.25x) | $0.50 (0.1x) | $10 (2x) |
| Sonnet 5 (legacy) | $2 | $10 | $2.50 (1.25x) | $0.20 (0.1x) | $4 (2x) |
| Haiku 4.5 (legacy) | $1 | $5 | $1.25 (1.25x) | $0.10 (0.1x) | $2 (2x) |
Batches API - 50% скидка на все модели.
У Haiku 5.5 в длину промпта входят все input-токены, включая чтение и запись кэша; запрос сверх порога платит повышенные цены за всё, в том числе за output. Остальные актуальные модели берут одну и ту же цену за токен на всём контексте в 1M.
Fast mode на Opus 5.5 (speed: "fast", Claude API) стоит $8 / $40 и не работает с Batches API.
Все цены за миллион токенов (MTok). Источник - страница цен Anthropic.
Стратегии оптимизации
1. Выбирайте модель под задачу
Не гоняйте Opus 5.5 на классификации - Haiku 5.5 справится за 1/40 цены (на промптах до 100K токенов). Sonnet 5.5 закрывает повседневные задачи вдвое дешевле Opus. Opus 5.5 берите, когда ошибка дорого стоит, а Fable 5.1 - только если Opus 5.5 на высоком effort не справляется.
2. Prompt caching для повторяющегося контекста
Если system prompt и контекстные документы одинаковы - кэшируйте. На Sonnet 5.5 чтение из кэша стоит 5% от базовой цены. При 100k токенов кэшированного контекста:
- Без кэша: 100k × $2/MTok = $0.20 за запрос (Sonnet 5.5)
- С кэшем: 100k × $0.10/MTok = $0.01 за запрос
- Экономия: 95% на input-токенах
3. Batches для некритичных задач
Eval-пайплайны, массовая классификация, генерация датасетов - latency не критична. Batches API даёт 50% скидку.
4. Streaming для UX
Streaming на токенах не экономит, но первый символ появляется через секунды - пользователь не ждёт. Для чат-интерфейсов - обязательно.
5. Контролируйте max_tokens и effort
max_tokens - жёсткий потолок для thinking и ответа вместе: поставите слишком мало - ответ обрежется. Чтобы тратить меньше токенов, понижайте effort: он уменьшает весь ответ, включая thinking. При смене модели прогоните подбор effort заново: у Opus 5.5 дефолт medium, у Sonnet 5.5 - high.
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
Нативный JSON mode доступен через output_config.format - GA без beta-заголовков, работает на всех актуальных моделях. API гарантирует валидный JSON по заданной схеме.
import anthropic
import json
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
output_config={
"format": {
"type": "json_schema",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"role": {"type": "string"}
},
"required": ["name", "age", "role"],
"additionalProperties": False
}
}
},
messages=[
{"role": "user", "content": "Иван Петров, 35 лет, senior developer"}
]
)
text = next(b.text for b in response.content if b.type == "text")
data = json.loads(text)
# {"name": "Иван Петров", "age": 35, "role": "senior developer"}
В Python ещё проще client.messages.parse() с Pydantic-моделью: SDK сам строит схему, валидирует ответ и кладёт объект в parsed_output (пример - в разделе про JSON mode ниже).
Когда что выбирать:
output_config.format- проще, не требует инструментального контекста, подходит для большинства случаев- Strict tool use (
strict: trueу инструмента) - если в том же запросе уже есть инструменты и нужны аргументы строго по схеме. Принудительныйtool_choiceна Opus 5.5, Sonnet 5.5 и Fable 5.1 даёт 400, поэтому на этих моделях инструмент вызывают черезautoи указание в промпте
MCP Connector
MCP Connector позволяет подключать remote MCP серверы прямо из Messages API - без отдельного MCP-клиента. Полезно для агентных сценариев: модель сама вызывает инструменты из ваших MCP-сервисов.
Требует beta-заголовок mcp-client-2025-11-20. На Claude API есть и более новый mcp-client-2026-09-15: он умеет всё то же и добавляет фиксацию списка инструментов сервера.
import anthropic
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
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 не поддерживаются
- Сервер должен быть доступен публично по HTTP (Streamable HTTP или SSE); локальные STDIO-серверы напрямую не подключить
- Доступен в beta на Claude API, Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed) и Microsoft Foundry; на Amazon Bedrock не поддерживается
- Результаты инструментов приходят из внешней системы - применяйте те же меры доверия, что и к 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="your-api-key") # ключ в коде
Structured output (JSON mode)
Рекомендуемый способ - output_config.format (описан в отдельной секции выше). Старый приём с prefill (закончить messages сообщением assistant {) больше не работает: Claude 4.6 и новее отклоняют его с ошибкой 400. Два других подхода:
Подход 1: client.messages.parse() с Pydantic-моделью
from pydantic import BaseModel
class Person(BaseModel):
name: str
age: int
role: str
response = client.messages.parse(
model="claude-sonnet-5-5",
max_tokens=4096,
messages=[
{"role": "user", "content": "Извлеки данные из текста: 'Иван Петров, 35 лет, senior developer'."}
],
output_format=Person,
)
person = response.parsed_output # Person(name='Иван Петров', age=35, role='senior developer')
SDK превращает модель в JSON Schema, отправляет её как output_config.format и валидирует ответ.
Подход 2: Strict tool use
tools = [{
"name": "extract_person",
"description": "Извлечь данные о человеке.",
"strict": True,
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"role": {"type": "string"}
},
"required": ["name", "age", "role"],
"additionalProperties": False
}
}]
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
tools=tools,
messages=[
{"role": "user", "content": "Вызови extract_person для текста: Иван Петров, 35 лет, senior developer"}
]
)
# При strict: true tool_use.input всегда соответствует схеме
tool_block = next((b for b in message.content if b.type == "tool_use"), None)
if tool_block:
person = tool_block.input # {"name": "Иван Петров", "age": 35, "role": "senior developer"}
strict: true гарантирует аргументы по схеме, но при tool_choice: auto вызывать ли инструмент, решает модель - поэтому назовите его в промпте и проверьте, что блок пришёл. На Haiku 5.5 и legacy-моделях вызов по-прежнему можно форсировать через tool_choice: {"type": "tool", "name": "extract_person"}.
Rate limits
Лимиты зависят от модели и usage tier организации. Основные метрики:
- Requests per minute (RPM) - количество запросов в минуту
- Input tokens per minute (ITPM) - считается только некэшированный input:
cache_read_input_tokensв лимит не входят - Output tokens per minute (OTPM) - сгенерированные токены;
max_tokensна лимит не влияет
Заголовки ответа содержат текущие лимиты:
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 делает это автоматически; если в ответе есть заголовок
retry-after, подождите указанное число секунд - Пакетная обработка через Batches API - у него свои лимиты, и на rate limits Messages API он не влияет
- Несколько workspace’ов для изоляции лимитов между проектами
- Чтение из кэша не считается в ITPM - ещё один повод кэшировать
Logging и monitoring
Каждый ответ содержит id (msg_...) и usage. Логируйте оба значения:
import logging
logger = logging.getLogger("claude_api")
response = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=4096,
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, получите ключ, отправьте первый запрос. Anthropic советует начинать с Opus 5.5; Sonnet 5.5 вдвое дешевле и быстрее.
Для production: prompt caching на повторяющемся контексте, streaming для UX, Haiku 5.5 для массовых операций, Batches для eval-пайплайнов. Читайте блоки ответа по type и уберите из старого кода temperature, prefill и принудительный tool_choice.
Для сложных задач: adaptive thinking с output_config.effort для reasoning, tool use для интеграции с внешними системами, MCP Connector для подключения к remote MCP-серверам напрямую из API, Opus 5.5 когда точность критична, Fable 5.1 - когда не хватает и его.
Structured outputs: output_config.format - нативный JSON mode без beta-заголовков.
Вся документация - platform.claude.com/docs. SDK: anthropic-sdk-python, anthropic-sdk-typescript. Примеры и рецепты - anthropic-cookbook.