1. Три параметра переезда
Совместимость означает совпадение формата API, а не поведения всех моделей. Поэтому переезд — это замена трёх значений с проверкой, а не слепая подмена адреса. Начните с короткого текстового запроса без tools и большого контекста и зафиксируйте статус, фактическую модель и X-Request-Id.
base_url: https://api.normahub.cc/v1
api_key: YOUR_API_KEY # из личного кабинета, только сервер
model: MODEL_ID # точный ID из каталога или /v1/modelsModel ID берите из актуального каталога или ответом GET /v1/models вашим ключом. ID из чужих README могли переименовать, отключить или закрыть для вашего ключа — каталог не чинится промптом.
2. Выбор маршрута
Один base_url обслуживает несколько маршрутов, но доступность каждого определяет выбранная модель. Chat Completions — маршрут диалогов с messages. Responses API — отдельный маршрут с input, доступный там, где заявлен. Anthropic-совместимые клиенты используют маршрут /v1/messages — его выбирайте по формату клиента, а не по названию модели.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.normahub.cc/v1",
)
# Chat Completions — классический маршрут диалогов
chat = client.chat.completions.create(
model="MODEL_ID",
messages=[{"role": "user", "content": "Привет"}],
)
# Responses API — там, где его заявляет модель
resp = client.responses.create(
model="MODEL_ID",
input="Привет",
)Не смешивайте протоколы вслепую: наличие Claude или GPT в каталоге не означает, что любая модель принимает tools, streaming или одинаковую структуру ответа. Проверяйте endpoint и capabilities каждой модели перед переключением — детали в документации API.
3. Таймауты и повторы
Производственный клиент отличается от примера из README двумя вещами: у каждого запроса есть timeout, а повторы ограничены. SDK сам повторяет временные 429 и 5xx, но число попыток и дедлайн операции задаёте вы. Интерактивному UI чаще лучше быстро показать понятный отказ, чем держать пользователя в очереди повторов.
from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://api.normahub.cc/v1",
timeout=30.0, # секунд на запрос вместо бесконечного ожидания
max_retries=2, # повторы только временных сбоев делает SDK
)
response = client.chat.completions.create(
model="MODEL_ID",
messages=[{"role": "user", "content": "Привет"}],
max_tokens=512, # ограничивает и ответ, и счёт
)Если соединение оборвалось после отправки запроса, результат неизвестен: upstream мог уже обработать операцию. Не повторяйте неидемпотентные действия без собственного ключа идемпотентности. Полные правила — в гайде по ошибкам.
4. SDK помимо OpenAI
Тот же base_url работает с любым OpenAI-совместимым клиентом: LangChain, LiteLLM, Cline и CLI-агенты принимают адрес и ключ в своей конфигурации. Правило одно для всех: ключ на сервере или в переменных окружения процесса, model ID из каталога, первый запрос — маленький. Примеры для конкретных инструментов — в гайде OpenCode и гайде Claude.
5. Безопасность
Вызывайте NormaHub с backend или из локального AI-агента. Не передавайте секретный ключ в браузерный JavaScript, мобильный bundle, публичные логи, CI-артефакты и docker history. Разделяйте ключи по окружениям и интеграциям с собственными лимитами: отзыв одного секрета не должен останавливать весь продукт. Создать и отозвать ключи можно в личном кабинете.