Для AI-агентов: markdown этой страницы — /docs-content/ai/chat/rate-limits.md индекс документации — /llms.txt
Лимиты запросов и повторы
Обращения к моделям ограничены двухуровневой корзиной, а при пиковой нагрузке платформа может ненадолго отказывать в обслуживании. Оба сигнала — 429 и 503 — означают «повтори позже», а не «запрос неверен». Ни один из них не списывает квоту.
Два уровня корзины
- На ключ — по умолчанию
600запросов в минуту. Корзина привязана к ключу, а не к IP-адресу: клиент за NAT не делит её с другими ключами, а один и тот же ключ с разных адресов имеет общий счётчик. - На пользователя — по умолчанию
1500запросов в минуту суммарно по всем ключам одного пользователя. Это защищает платформу, когда один аккаунт раздаёт десяток ключей агентам и каждый выбирает свой лимит.
Запрос проверяется сначала по ключу, затем по пользователю. Первый исчерпанный счётчик выдаёт 429.
Для отдельных ключей — партнёрских интеграций, пакетных обработчиков — администратор платформы может поднять лимит на ключ. Лимит на пользователя при этом продолжает действовать.
Ответ `429`
{
"error": {
"type": "rate_limit_exceeded",
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded (per-key). Limit: 600 per minute. Retry after 12 seconds.",
"scope": "per-key",
"limit": 600,
"retryAfter": 12
}
}
Поле scope принимает одно из двух значений:
per-key— исчерпан лимит конкретного ключа. Снизьте число одновременных запросов этого ключа.per-user— исчерпан общий лимит аккаунта. Снизьте суммарную нагрузку по всем ключам или попросите администратора платформы поднять лимит.
Вместе с 429 приходят заголовки:
Retry-After: <секунды>— сколько ждать перед следующей попыткой.X-RateLimit-Scope: per-key | per-user— уровень, в который упёрлись. Полезно для логов и метрик клиента.
Лимит проверяется после проверки ключа, поэтому запросы с некорректным ключом (401) квоту не расходуют.
Транзитные `503 pool_exhausted`
Помимо 429, который означает превышение клиентской квоты, платформа может отдать 503 с кодом pool_exhausted, когда внутренний пул соединений временно исчерпан — например, при одновременном пике у нескольких клиентов. Это сигнал «попробуй ещё раз через несколько секунд», а не «инфраструктура сломана». Ответ всегда содержит заголовок Retry-After — целое число секунд от 3 до 7, со случайным разбросом на стороне сервера, чтобы массовое восстановление не било повторно в пул.
{
"error": {
"code": "pool_exhausted",
"type": "server_error",
"retryAfter": 5
}
}
В потоковом режиме (stream: true) статус 200 уже отправлен до того, как платформа узнаёт о перегрузке, поэтому сигнал приходит последним событием потока: data: { "error": { "code": "pool_exhausted", "retryAfter": <число> } }, после чего идёт обычный data: [DONE]. Распознайте code === "pool_exhausted" и повторите запрос через retryAfter секунд.
Есть и третий сигнал перегрузки — 429 ai_congested. Он приходит, когда перегружен пул AI-кластера. Запрос при этом не выполнялся и списания нет. Отличить его от превышения квоты можно по заголовку X-AI-Admission: shed, которого нет у ответа 429 rate_limit_exceeded.
Ответ `429 ai_pacing_limited`
Четвёртый ответ со статусом 429 не связан с нагрузкой на платформу. Он приходит, когда администратор портала включил равномерное расходование AI-квоты и вызов пробил суточное или недельное окно. Тело такого ответа приходит в конверте { "success": false, "error": { ... } }, а не в сыром формате остальных ошибок этой страницы, и несёт поля reason, overageDenied и resetAt. Разбор полей и режимов — на странице AI-квота компании.
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 429 | rate_limit_exceeded |
Превышен лимит запросов. Уровень — в поле scope и заголовке X-RateLimit-Scope |
| 429 | ai_congested |
Пул AI-кластера перегружен. Запрос не выполнялся, списания нет. Ответ несёт заголовок X-AI-Admission: shed |
| 429 | ai_pacing_limited |
Пробито суточное или недельное окно равномерного расходования квоты. Повторите запрос по заголовку Retry-After |
| 503 | pool_exhausted |
Платформа временно перегружена. Повторите запрос через число секунд из Retry-After |
Полный список общих ошибок API — Ошибки.
Готовый рецепт повторов
async function callWithBackoff(makeRequest, { maxAttempts = 5 } = {}) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const res = await makeRequest()
if (res.status === 429 || res.status === 503) {
const retryAfterSec = Number(res.headers.get('retry-after')) || 0
// Соблюдаем Retry-After и добавляем небольшой случайный разброс,
// чтобы параллельные обработчики не возвращались синхронно.
const baseMs = retryAfterSec * 1000 || Math.min(1000 * 2 ** attempt, 30000)
const jitterMs = Math.floor(Math.random() * 1000)
await new Promise(r => setTimeout(r, baseMs + jitterMs))
continue
}
return res
}
throw new Error('Повторы исчерпаны')
}
Что важно:
- Всегда соблюдайте
Retry-After. Он соответствует ожидаемому времени восстановления, меньший интервал ничего не ускоряет, а только нагружает платформу. - Добавляйте собственный случайный разброс поверх серверного — задержка в 100-1000 мс разрывает синхронные циклы обработчиков.
- Ограничивайте количество попыток. Пяти достаточно для большинства сценариев, дальше возвращайте ошибку наружу.
- При
5xxбезRetry-After, например при сбое на стороне провайдера, увеличивайте паузу по экспоненте:min(2^attempt × 1s, 30s)со случайным разбросом. - Не запускайте
Promise.allповерх тысяч записей. Без пауз пакетная обработка упрётся в один из уровней корзины.