Rozwiązywanie problemówPrzewodnik
429 Too Many Requests z API AI: ponowienia z backoffem
Co oznacza 429 z API AI i jak sobie z nim radzić: wykładniczy backoff z jitterem, Retry-After i współbieżność agentów, z kodem w Pythonie i JavaScripcie.

Na tej stronie
Błąd 429 Too Many Requests z API AI oznacza, że żądanie zostało odrzucone, ponieważ wysłano zbyt dużo zbyt szybko lub osiągnięto limit na koncie. Rozwiązaniem jest odczekanie i ponowna próba z wykładniczym backoffem i jitterem, użycie nagłówka Retry-After, gdy jest obecny w odpowiedzi, oraz ograniczenie liczby równoległych żądań wysyłanych przez agenta. Nie ponawiaj próby przy 429, który w rzeczywistości jest limitem wydatków lub salda: czekanie tego nie naprawi.
Ten przewodnik opiera się na oficjalnych dokumentacjach limitów szybkości OpenAI i Anthropic, obie sprawdzone 22 października 2026. Żadna ze stron nie podaje daty ostatniej aktualizacji.
Co oznacza 429#
OpenAI opisuje 429 jako żądanie odrzucone z powodu przekroczenia limitu szybkości (rate_limit_error, z kodem slow_down, gdy ruch rośnie zbyt szybko) lub z powodu osiągnięcia twardego limitu wydatków. Anthropic również używa rate_limit_error dla 429. 429 związany z limitem wydatków nie ma nagłówka retry-after i będzie się powtarzać, dopóki dostęp nie zostanie przywrócony.
Dwa sąsiednie kody łatwo pomylić z tym błędem. 503 server_ OpenAI i 529 overloaded_ Anthropic to warunki przeciążenia, a nie Twój limit szybkości. Zwykle obsługuje się je tą samą pętlą ponowień, ale wskazują na inną przyczynę.
Zatem istnieją trzy przypadki, a każdy wymaga innej reakcji:
Przewiń tabelę w prawo →
| Odpowiedź | Przyczyna | Co zrobić |
|---|---|---|
| 429 limit szybkości | Zbyt wiele żądań lub tokenów na minutę | Poczekaj, ponów z backoffem |
| 429 limit wydatków lub salda | Osiągnięto limit konta | Nie ponawiaj; popraw limit lub doładuj saldo |
| 503 / 529 przeciążenie | Strona dostawcy jest zajęta | Ponów z backoffem, z ograniczeniem |
Jeśli skończyło się saldo, przeczytaj błąd „not enough tokens”. W przypadku awarii na poziomie sieci, takich jak przekroczenia limitu czasu i odrzucone połączenia, zobacz typowe błędy połączenia.
Przeczytaj nagłówki, zanim zgadniesz opóźnienie#
OpenAI dokumentuje następujące nagłówki w odpowiedziach z limitem szybkości: Retry-After oraz x-, x-, x- z wariantami -tokens. Inne API mogą wysyłać ich podzbiór lub żadnego, więc napisz klienta tak, aby używał Retry-After, gdy jest obecny, a w przeciwnym razie korzystał z własnego harmonogramu.
Wskazówki OpenAI dotyczące ponowień w skrócie:
- Traktuj
Retry-Afterjako minimalny czas oczekiwania i dodaj do niego niewielkie losowe opóźnienie. - Bez niego używaj wykładniczego backoffu z jitterem.
- Ogranicz zarówno liczbę prób, jak i całkowity czas ponowień.
- Nie nakładaj własnych ponowień na ponowienia SDK.
- Nie ponawiaj prób przy błędach limitu lub rozliczeń.
- Nieudane żądania nadal liczą się do limitu na minutę, więc agresywna pętla pogarsza sytuację.
- W przypadku streamingu nie odtwarzaj żądania po tym, jak już skonsumowałeś jego wynik.
Python: backoff z jitterem#
Oficjalny pakiet openai działa z każdym punktem końcowym zgodnym z OpenAI. Wyłącz własne ponowienia SDK (max_retries=0), aby nie mnożyły się z Twoimi. Identyfikator modelu pochodzi z dokumentacji CheapTokens; identyfikatory różnią się między dostawcami.
import os
import random
import time
from openai import OpenAI, APIStatusError
client = OpenAI(
base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"],
max_retries=0, # we retry ourselves
)
RETRYABLE = {429, 500, 502, 503, 504}
def chat_with_retry(model, messages, max_attempts=5, max_total=60.0):
started = time.monotonic()
for attempt in range(max_attempts):
try:
return client.chat.completions.create(model=model, messages=messages)
except APIStatusError as err:
last = attempt == max_attempts - 1
if err.status_code not in RETRYABLE or last:
raise
header = err.response.headers.get("retry-after")
if header and header.replace(".", "", 1).isdigit():
delay = float(header) + random.uniform(0, 1) # minimum wait + jitter
else:
delay = random.uniform(0, min(30.0, 2.0 ** attempt)) # full jitter
if time.monotonic() - started + delay > max_total:
raise
time.sleep(delay)Górna granica opóźnienia bez nagłówka rośnie 1, 2, 4, 8 sekund (z limitem 30), a random.uniform wybiera losową wartość poniżej niej, więc wiele procesów roboczych nie budzi się w tym samym momencie. Retry-After może być również datą HTTP; powyższy kod obsługuje formę numeryczną, a w przeciwnym razie korzysta z backoffu.
JavaScript: ta sama pętla#
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.cheaptokens.dev/v1",
apiKey: process.env.CHEAPTOKENS_API_KEY,
maxRetries: 0, // we retry ourselves
});
const RETRYABLE = new Set([429, 500, 502, 503, 504]);
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
export async function chatWithRetry(model, messages, maxAttempts = 5, maxTotalMs = 60000) {
const started = Date.now();
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await client.chat.completions.create({ model, messages });
} catch (err) {
const last = attempt === maxAttempts - 1;
if (!RETRYABLE.has(err.status) || last) throw err;
const header = Number(err.headers?.get?.("retry-after"));
const delayMs = Number.isFinite(header) && header > 0
? header * 1000 + Math.random() * 1000 // minimum wait + jitter
: Math.random() * Math.min(30000, 2 ** attempt * 1000); // full jitter
if (Date.now() - started + delayMs > maxTotalMs) throw err;
await sleep(delayMs);
}
}
}Gdy to działa, wywołanie z limitem szybkości po prostu trwa dłużej, a następnie zwraca normalne ukończenie. Gdy nadal zawodzi po ostatniej próbie, zgłaszany jest oryginalny błąd, więc Twój kod może go zalogować lub zakolejkować zadanie na później.
Jak agenci powinni obsługiwać 429#
Pętla agenta wysyła wiele krótkich wywołań, a kilka agentów lub wywołań narzędzi może działać jednocześnie. Samo ponawianie nie wystarczy; zmniejsz szybkość żądań u źródła:
- Ogranicz współbieżność. Semafor 3–5 równoległych wywołań to rozsądny początek; zwiększaj go tylko wtedy, gdy błędy pozostają rzadkie.
- Udostępnij jeden limiter. Jeśli kilka procesów roboczych używa tego samego klucza, dzielą te same limity, więc jedna pętla ponowień na proces nie wystarczy: użyj jednej kolejki lub jednego semafora dla procesu.
- Wycofaj się globalnie. Gdy jedno wywołanie otrzyma 429 z opóźnieniem, wstrzymaj całą pulę na ten czas, a nie tylko zawodne wywołanie.
- Utrzymuj mniejsze żądania. Mniej tokenów na żądanie oznacza mniejszą presję na limity tokenów na minutę: przytnij historię i dane wyjściowe narzędzi. Zobacz jak oszacować koszt agenta AI, gdzie zużywają się tokeny.
- Zatrzymaj się przy błędach niepodlegających ponowieniu. 401, 400 lub błąd salda nie naprawi się sam; zawiedź szybko i zgłoś.
import asyncio
limit = asyncio.Semaphore(4) # at most 4 requests in flight
async def run(job):
async with limit:
return await call_model(job) # your async call with the retry loop aboveUruchamiaj pętle agentów na CheapTokens#
W przypadku pętli agentów z wieloma krótkimi wywołaniami CheapTokens oferuje MiniMax-M2.7: jedna cena o każdej porze dnia, kontekst 180K, do 8192 tokenów na odpowiedź i jedno saldo dla wszystkich modeli. Wyjście kosztuje $0.15 za 1M tokenów, a łącznie, licząc wejście i wyjście razem, jest taniej niż OpenRouter. Działa przez punkt końcowy zgodny z OpenAI https:/. Powyższy kod już wskazuje ten punkt końcowy; ustaw identyfikator modelu z dokumentacji CheapTokens i uruchom go.
Aktualne ceny dla obciążenia 500 000 wejściowych i 100 000 wyjściowych:
| Model | Wejście $/1M | Wyjście $/1M | Koszt | OpenRouter |
|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.014 | $0.0282 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.0175 | $0.0394 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.04 | $0.27 |
500 000 tokenów wejściowych i 100 000 tokenów wyjściowych łącznie. Ceny za 1 mln tokenów są aktualne i zmieniają się wraz z naszymi taryfami; kolumna OpenRouter pokazuje ceny referencyjne dla tego samego obciążenia.
Zobacz wszystkie ceny, dokumentację konfiguracji i utwórz klucz, aby wysłać pierwsze żądanie.
Jeśli nadal zawodzi#
- 429 przy pierwszym żądaniu. Przeczytaj typ i treść błędu w treści odpowiedzi: 429 związany z limitem wydatków lub konta będzie się powtarzać przy ponowieniu, dopóki limit nie zostanie podniesiony lub dostęp nie zostanie przywrócony, podczas gdy 429 związany z limitem szybkości ustępuje po przerwie.
- 429 powraca przy długiej pętli. Możesz nakładać ponowienia: ponowienia SDK razy Twoje ponowienia. Ustaw SDK na zero, jak w przykładach.
- Błędy przychodzą seriami na początku partii. Zwiększaj stopniowo zamiast uruchamiać wszystkich procesów roboczych naraz; OpenAI zgłasza
slow_downdla ruchu, który rośnie zbyt szybko. - Wywołanie strumieniowe nie powiodło się w połowie. Nie odtwarzaj go bezmyślnie po skonsumowaniu wyniku; zdecyduj, czy zrestartować całą odpowiedź, czy kontynuować od tego, co masz.
- Brak Retry-After w odpowiedzi. Kod korzysta z backoffu z jitterem, więc nie trzeba nic zmieniać.



