Khắc phục sự cốHướng dẫn
429 Too Many Requests từ một API AI: thử lại với backoff
429 từ một API AI có nghĩa là gì và cách xử lý: exponential backoff với jitter, Retry-After, và đồng thời của agent, với mã Python và JavaScript.

Trên trang này
Một 429 Too Many Requests từ API AI có nghĩa là yêu cầu đã bị từ chối vì bạn gửi quá nhiều quá nhanh, hoặc đã chạm giới hạn trên tài khoản của bạn. Cách khắc phục là chờ và thử lại với exponential backoff và jitter, dùng header Retry-After khi phản hồi có header này, và giới hạn số lượng yêu cầu mà agent của bạn gửi song song. Không thử lại một 429 thực chất là giới hạn chi tiêu hoặc số dư: chờ đợi sẽ không khắc phục được.
Hướng dẫn này dựa trên các hướng dẫn chính thức về rate limit của OpenAI và Anthropic, cả hai đều được kiểm tra vào ngày 22 tháng 10 năm 2026. Không trang nào hiển thị ngày cập nhật lần cuối.
429 có nghĩa là gì#
OpenAI mô tả 429 là yêu cầu bị từ chối do vượt quá rate limit (rate_limit_error, với mã slow_down khi lưu lượng tăng quá nhanh), hoặc do đã đạt giới hạn chi tiêu cứng. Anthropic cũng dùng rate_limit_error cho 429. Một 429 do giới hạn chi tiêu không có header retry-after và tiếp tục thất bại cho đến khi quyền truy cập được khôi phục.
Hai trường hợp lân cận dễ bị nhầm với nó. 503 server_ của OpenAI và 529 overloaded_ của Anthropic là tình trạng quá tải, không phải rate limit của bạn. Chúng thường được xử lý bằng cùng vòng lặp thử lại, nhưng chúng nói lên điều khác về nguyên nhân.
Vậy có ba trường hợp, và mỗi trường hợp cần một phản ứng khác nhau:
Cuộn bảng sang phải →
| Phản hồi | Nguyên nhân | Cần làm gì |
|---|---|---|
| 429 rate limit | Quá nhiều yêu cầu hoặc token mỗi phút | Chờ, thử lại với backoff |
| 429 giới hạn chi tiêu hoặc số dư | Đã đạt giới hạn tài khoản | Không thử lại; sửa giới hạn hoặc nạp thêm số dư |
| 503 / 529 quá tải | Phía nhà cung cấp đang bận | Thử lại với backoff, có giới hạn |
Nếu số dư của bạn đã hết, hãy đọc lỗi "không đủ token" thay vào đó. Đối với lỗi ở mức mạng như timeout và kết nối bị từ chối, xem các lỗi kết nối phổ biến.
Đọc các header trước khi đoán thời gian chờ#
OpenAI ghi nhận các header này trên phản hồi bị rate limit: Retry-After, và x-, x-, x- với các biến thể -tokens. Các API khác có thể gửi một tập con hoặc không gửi header nào, vì vậy hãy viết client để dùng Retry-After khi có và quay về lịch trình của riêng bạn khi không có.
Hướng dẫn của OpenAI về thử lại, tóm tắt:
- Coi
Retry-Afterlà thời gian chờ tối thiểu và thêm một độ trễ ngẫu nhiên nhỏ lên trên. - Nếu không có, dùng exponential backoff với jitter.
- Giới hạn cả số lần thử và tổng thời gian thử lại.
- Không chồng thêm các lần thử lại của bạn lên các lần thử lại của SDK.
- Không thử lại lỗi hạn mức hoặc thanh toán.
- Các yêu cầu thất bại vẫn tính vào giới hạn mỗi phút, nên một vòng lặp hung hăng sẽ làm mọi thứ tệ hơn.
- Với streaming, không phát lại một yêu cầu sau khi bạn đã tiêu thụ đầu ra từ nó.
Python: backoff với jitter#
Gói openai chính thức hoạt động với bất kỳ endpoint tương thích OpenAI nào. Tắt các lần thử lại của chính SDK (max_retries=0) để chúng không nhân lên với của bạn. Id của model đến từ tài liệu CheapTokens; id khác nhau giữa các nhà cung cấp.
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)Giới hạn trên của độ trễ khi không có header tăng 1, 2, 4, 8 giây (giới hạn ở 30), và random.uniform chọn một giá trị ngẫu nhiên bên dưới nó, để nhiều worker không cùng thức dậy vào một thời điểm. Retry-After cũng có thể là một ngày HTTP; đoạn mã trên xử lý dạng số và nếu không thì quay về backoff.
JavaScript: cùng một vòng lặp#
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);
}
}
}Khi nó hoạt động, một lệnh gọi bị rate limit chỉ đơn giản mất nhiều thời gian hơn rồi trả về một completion bình thường. Khi nó vẫn thất bại sau lần thử cuối, lỗi gốc được ném ra, để mã của bạn có thể ghi log hoặc đưa công việc vào hàng đợi cho sau này.
Agent nên xử lý 429 như thế nào#
Một vòng lặp agent gửi nhiều lệnh gọi ngắn, và nhiều agent hoặc lệnh gọi công cụ có thể chạy cùng lúc. Chỉ thử lại là không đủ; hãy giảm tốc độ yêu cầu tại nguồn:
- Giới hạn đồng thời. Một semaphore 3–5 lệnh gọi song song là điểm khởi đầu hợp lý; chỉ tăng nó khi lỗi vẫn hiếm.
- Chia sẻ một limiter. Nếu nhiều worker dùng cùng một key, chúng chia sẻ cùng giới hạn, nên một vòng lặp thử lại mỗi worker là không đủ: dùng một hàng đợi hoặc một semaphore cho tiến trình.
- Backoff toàn cục. Khi một lệnh gọi nhận 429 với một độ trễ, hãy tạm dừng toàn bộ pool trong khoảng thời gian đó thay vì chỉ lệnh gọi đang lỗi.
- Giữ yêu cầu nhỏ hơn. Ít token hơn mỗi yêu cầu nghĩa là ít áp lực hơn lên giới hạn token mỗi phút: cắt bớt lịch sử và đầu ra công cụ. Xem cách ước tính chi phí của một AI agent để biết token đi đâu.
- Dừng khi gặp lỗi không thể thử lại. 401, 400, hoặc lỗi số dư sẽ không tự khắc phục; hãy thất bại nhanh và báo cá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 aboveChạy vòng lặp agent trên CheapTokens#
Với các vòng lặp agent có nhiều lệnh gọi ngắn, CheapTokens cung cấp MiniMax-M2.7: một mức giá vào bất kỳ thời điểm nào trong ngày, ngữ cảnh 180K, tối đa 8.192 token mỗi câu trả lời, và một số dư cho tất cả model. Đầu ra có giá $0.15 mỗi 1M token, và tổng cộng, khi tính cả đầu vào và đầu ra, rẻ hơn OpenRouter. Nó hoạt động qua endpoint tương thích OpenAI https:/. Đoạn mã trên đã trỏ đến endpoint này; đặt id model từ tài liệu CheapTokens và chạy nó.
Giá trực tiếp cho khối lượng 500.000 đầu vào, 100.000 đầu ra:
| Mô hình | Đầu vào $/1M | Đầu ra $/1M | Chi phí | 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 |
Tổng cộng 500.000 token đầu vào và 100.000 token đầu ra. Giá trên 1 triệu token là giá hiện hành và thay đổi cùng với biểu phí của chúng tôi; cột OpenRouter hiển thị giá tham chiếu cho cùng khối lượng công việc.
Xem tất cả giá, tài liệu thiết lập, và tạo một key để gửi yêu cầu đầu tiên của bạn.
Nếu nó vẫn thất bại#
- 429 ngay ở yêu cầu đầu tiên. Đọc loại lỗi và thông điệp trong phần thân phản hồi: một 429 do chi tiêu hoặc giới hạn tài khoản tiếp tục thất bại khi thử lại cho đến khi giới hạn được nâng hoặc quyền truy cập được khôi phục, trong khi một 429 do rate limit sẽ hết sau một khoảng tạm dừng.
- 429 cứ tiếp tục với một vòng lặp dài. Bạn có thể đang chồng các lần thử lại: thử lại của SDK nhân với thử lại của bạn. Đặt SDK về không, như trong các ví dụ.
- Lỗi đến thành từng đợt ở đầu một lô. Hãy tăng dần thay vì bắn tất cả worker cùng lúc; OpenAI báo
slow_downcho lưu lượng tăng quá nhanh. - Lệnh gọi streaming thất bại giữa chừng. Không phát lại nó một cách mù quáng sau khi bạn đã tiêu thụ đầu ra; hãy quyết định xem nên khởi động lại toàn bộ câu trả lời hay tiếp tục từ những gì bạn đã có.
- Không có Retry-After trong phản hồi. Mã sẽ quay về backoff với jitter, nên không cần thay đổi gì.



