Выбор модели · обновлено 2 ноября 2026 г.

OpenAI vs Anthropic API: 7 отличий, которые ломают миграцию

Системный промпт, max_tokens, content blocks, tool use, стриминг и ошибки — сравниваем форматы OpenAI и Anthropic и показываем, что меняется при переходе.

Команда CheApi9 мин чтения
Содержание статьи+

Оба API решают одну задачу, но устроены по-разному. Если просто заменить base_url в OpenAI SDK на Anthropic-совместимый endpoint, код сломается. Ниже — семь отличий, на которых чаще всего спотыкаются при миграции.

1. Системный промпт

В OpenAI system — это сообщение в массиве messages. В Anthropic system — отдельное поле верхнего уровня, а messages содержат только user и assistant. Если отправить system внутри messages, Anthropic вернёт ошибку.

openai.py
# OpenAI
messages = [
    {"role": "system", "content": "Ты — редактор."},
    {"role": "user", "content": "Проверь текст."},
]
anthropic.py
# Anthropic
system = "Ты — редактор."
messages = [
    {"role": "user", "content": "Проверь текст."},
]

2. max_tokens обязателен

У Anthropic параметр max_tokens обязателен. Если его нет, запрос не пройдёт. У OpenAI он опционален, и многие клиенты его не передают. При миграции добавьте явное ограничение — это ещё и защита от неожиданно длинного ответа.

3. Content blocks

Anthropic возвращает content как массив блоков: [{type: "text", text: "..."}]. OpenAI — строку в message.content. Если ваш код делает response.content[0].text, он не заработает с OpenAI; если обращается к строке — не заработает с Anthropic.

normalize.py
def extract_text(response) -> str:
    content = response.content
    if isinstance(content, str):
        return content
    return "".join(
        block.text for block in content if block.type == "text"
    )

4. Tool use

OpenAI описывает функции как {type: "function", function: {...}} и возвращает tool_calls. Anthropic использует input_schema и блоки tool_use. Схемы похожи, но обёртки разные. Универсального формата нет — нужен адаптер или отдельные ветки кода.

5. Стриминг

OpenAI присылает choices[0].delta.content. Anthropic — события content_block_delta с delta.text, а также отдельные события начала и конца блока. Если вы парсите SSE вручную, придётся учитывать типы событий. SDK это скрывают, но не все клиенты используют SDK.

6. Заголовки и версия

OpenAI: Authorization: Bearer. Anthropic: x-api-key и anthropic-version. CheApi принимает оба варианта авторизации, но версию Anthropic лучше передавать явно — 2023-06-01. Тогда поведение не изменится при обновлении upstream.

7. Ошибки

OpenAI возвращает {error: {message, type, code}}. Anthropic — {type: "error", error: {type, message}}. Коды HTTP совпадают, а структура нет. Если у вас есть обработчик ошибок, проверьте, что он понимает оба формата.

errors.py
def error_message(payload):
    if "error" in payload and isinstance(payload["error"], dict):
        return payload["error"].get("message", "Unknown error")
    return payload.get("message", "Unknown error")

Что делать, если нужны обе модели

Есть три пути. Первый — использовать два SDK и нормализовать ответы. Второй — взять фреймворк вроде LangChain, который скрывает различия. Третий — ходить через один OpenAI-совместимый слой, если он поддерживает нужные модели.

CheApi поддерживает оба диалекта: /v1/chat/completions и /v1/responses для OpenAI, /v1/messages для Anthropic. Можно оставить существующие SDK и переключать модели одной строкой, не переписывая приложение.

Чек-лист миграции

  1. Вынесите системный промпт в отдельное поле для Anthropic.
  2. Добавьте max_tokens везде, где его не было.
  3. Нормализуйте извлечение текста из ответа.
  4. Проверьте формат tool_use и tool_result.
  5. Обновите парсер SSE, если он самодельный.
  6. Добавьте обработку обоих форматов ошибок.
  7. Прогоните 20 реальных задач и сравните не только ответы, но и стоимость.

Попробовать

5 млн токенов на тесты

Зарегистрируйтесь, получите ключ и проверьте модели на своих задачах. Карта не нужна.