Agent của bạn gọi một API. API trả về lỗi 429. Agent của bạn thử lại ngay lập tức, nhận thêm một lỗi 429 nữa, thử lại lần nữa, và bây giờ bạn có một vòng lặp liên tục tấn công một dịch vụ bị giới hạn cho đến khi quá trình chạy bị dừng hoặc hóa đơn tăng vọt. Không ai cố ý viết vòng lặp đó. Nó xuất hiện từ phiên bản đơn giản của việc "xử lý lỗi", và đó là vấn đề phổ biến nhất mà các nhà phát triển hỏi trên diễn đàn thảo luận Anthropic SDK.
Khôi phục lỗi là phần trong việc xây dựng agent giúp phân biệt một bản demo sạch với một thứ mà bạn có thể cần nhờ người khác giúp đỡ. Mô hình không phải là vấn đề. Vấn đề là những gì mã của bạn thực hiện khi một lệnh gọi công cụ trả về chậm, bị giới hạn hoặc bị hỏng. Nếu khôi phục đúng cách, một phụ thuộc không ổn định sẽ trở thành một tạm dừng ngắn mà người dùng không bao giờ nhận thấy. Nếu làm sai, một lỗi 500 duy nhất sẽ biến thành một sự cố. Hướng dẫn này bao gồm bốn mô hình chịu tải chính: thử lại với backoff, timeouts, circuit breakers và idempotency keys. Sau đó, nó chỉ ra cách kiểm tra chúng với một bản giả lập (mock), trước khi người dùng phát hiện ra các lỗ hổng. Để có cái nhìn rộng hơn về cách các agent thất bại, hãy bắt đầu với lý do các agent AI bị lỗi trong môi trường production.
Bạn không thể kiểm tra khả năng khôi phục với một API khỏe mạnh
Đây là cái bẫy. Phụ thuộc của bạn hoạt động tốt trong quá trình phát triển. Bạn viết agent của mình, các lệnh gọi thành công, bản demo sạch sẽ, và bạn triển khai. Mã khôi phục chưa bao giờ chạy một lần nào, bởi vì một API khỏe mạnh không bao giờ trả về các lỗi mà nó phải xử lý. Lần đầu tiên logic backoff của bạn chạy là trong môi trường production, chống lại một sự cố thực tế, với người dùng thực đang theo dõi. Đó là nơi tồi tệ nhất để phát hiện ra lỗi đánh máy trong vòng lặp thử lại.
Vì vậy, quy tắc rất đơn giản. Để kiểm tra khả năng khôi phục, bạn cố ý tạo ra các lỗi. Tạo một bản giả lập (mock) của API mà agent gọi, lập trình nó để trả về lỗi 429, 500, timeout hoặc một phần thân (body) không đúng định dạng, trỏ agent đến đó và quan sát những gì nó làm. Lỗi sẽ trở thành thứ bạn kích hoạt trong một bài kiểm tra thay vì thứ khiến bạn phải thức dậy lúc 3 giờ sáng. Apidog tạo ra bản giả lập đó và viết script cho các phản hồi, và nó sẽ chạy qua phần kiểm thử ở cuối.
Thử lại với backoff lũy thừa và jitter
Thử lại là tuyến phòng thủ đầu tiên, và phiên bản đơn giản là một cái bẫy. Bắt lỗi, gọi lại ngay lập tức. Đối với một sự cố tạm thời, nó hoạt động. Đối với một dịch vụ đang quá tải, nó làm mọi thứ tồi tệ hơn, vì mỗi client thất bại đều thử lại cùng một lúc và sự bùng nổ này khiến dịch vụ ngừng hoạt động.
Hai cách khắc phục kết hợp với nhau. Backoff lũy thừa giãn cách các lần thử: đợi 1 giây, sau đó 2, sau đó 4, sau đó 8, gấp đôi lên đến một giới hạn. Dịch vụ có không gian để phục hồi thay vì bị bao vây bởi các lần thử lại ngay lập tức. Jitter thêm một độ lệch ngẫu nhiên vào mỗi lần chờ đợi để hàng nghìn client cùng thất bại tại cùng một thời điểm cũng không thử lại cùng một lúc. Nếu không có nó, backoff vẫn tạo ra các làn sóng đồng bộ.
Giới hạn hai điều: độ trễ, để bạn không phải đợi hàng phút giữa các lần thử, và số lần thử, để một lỗi vĩnh viễn từ bỏ thay vì thử lại mãi mãi. Ba đến năm lần thử khắc phục hầu hết mọi lỗi tạm thời. Ngoài ra, bạn thường thử lại một thứ sẽ không thành công. Anthropic SDK thực hiện một phần việc này cho các lệnh gọi của chính nó: nó thử lại các lỗi kết nối và các mã trạng thái cụ thể với backoff lũy thừa, và bạn đặt giới hạn với tùy chọn max-retries. Nó không bao gồm các API khác mà công cụ của agent của bạn truy cập, vì vậy bạn phải tự xử lý. Các nhóm kiếm tiền thông qua việc thử lại sớm học được điều này, và phân tích của chúng tôi về logic thử lại cho các API có độ rủi ro cao cho thấy một lần thử lại bất cẩn gây ra thiệt hại thực sự như thế nào.
Đặt một timeout cho mọi lệnh gọi
Thử lại chỉ hữu ích nếu yêu cầu thất bại. Trường hợp tồi tệ hơn là một yêu cầu không bao giờ trả về: một phụ thuộc chấp nhận kết nối của bạn, sau đó bị treo. Không có timeout, lệnh gọi công cụ bị chặn và toàn bộ quá trình chạy bị đình trệ phía sau một socket chết. Không có lỗi, không có khôi phục, chỉ có một agent bị kẹt đốt thời gian và ngân sách token một cách vô ích.
Mỗi lệnh gọi ra bên ngoài đều cần một timeout. Đặt một connect timeout để thiết lập kết nối và một read timeout để chờ phản hồi, sau đó là một ngân sách tổng thể cho toàn bộ quá trình chạy của agent để một chuỗi các lệnh gọi chậm-nhưng-hợp lệ không thể vượt quá sự kiên nhẫn của người dùng. Khi một timeout kích hoạt, hãy xử lý nó như bất kỳ lỗi nào có thể thử lại khác: thực hiện backoff và thử lại, cho đến giới hạn của bạn.
Chọn các con số từ độ trễ thực tế, không phải là phỏng đoán. Đặt mỗi timeout cao hơn p99 của phụ thuộc với một khoảng an toàn. Quá chặt chẽ và bạn hủy bỏ các lệnh gọi lẽ ra đã thành công. Quá lỏng lẻo và một phụ thuộc bị treo sẽ giữ agent lâu hơn điểm hữu ích. Cấp ngân sách riêng cho các phản hồi streaming, vì một quá trình hoàn thành dài là chậm một cách hợp lệ và một timeout cố định ngắn sẽ hủy bỏ nó giữa chừng.
Kích hoạt circuit breaker khi một phụ thuộc bị lỗi
Backoff xử lý một dịch vụ bận rộn trong thời gian ngắn. Nó là công cụ sai cho một dịch vụ hoàn toàn ngừng hoạt động. Nếu một phụ thuộc đã bị lỗi trong một phút, yêu cầu tiếp theo gần như chắc chắn cũng sẽ thất bại, và việc thử lại nó sẽ chất thêm tải lên một thứ đã bị hỏng trong khi người dùng chờ đợi một lỗi mà bạn có thể dự đoán.
Một circuit breaker khắc phục điều này với ba trạng thái. Closed là bình thường: các yêu cầu luân chuyển và breaker đếm số lỗi. Khi số lỗi vượt qua một ngưỡng, nó chuyển sang open: nó ngừng gửi yêu cầu và thất bại nhanh chóng trong một khoảng thời gian chờ (cool-down window), vì vậy bạn không phải chịu chi phí timeout trên mỗi lệnh gọi đến một dịch vụ đã chết. Sau khoảng thời gian chờ, nó chuyển sang half-open và cho phép một thăm dò duy nhất đi qua. Nếu thăm dò thành công, breaker đóng và lưu lượng truy cập tiếp tục; nếu nó thất bại, nó lại mở và chờ đợi.
Đối với một agent, breaker biến "API thanh toán bị lỗi" thành một lỗi nhanh, rõ ràng mà agent có thể xử lý, thay vì bốn mươi timeout chậm làm cạn kiệt ngân sách token và thời gian. Kết nối nó cho mỗi phụ thuộc, không phải toàn cầu, để một API tìm kiếm bị lỗi không ngăn agent sử dụng một API thanh toán khỏe mạnh.
Giúp việc thử lại an toàn với idempotency keys
Mọi mô hình cho đến nay đều giả định việc thử lại là an toàn. Thường thì không phải vậy. Agent của bạn gửi POST /charge, máy chủ xử lý nó, và phản hồi bị timeout trên đường trở về. Agent không bao giờ thấy thành công, vì vậy nó thử lại, và bây giờ khách hàng bị tính phí hai lần. Lần thử lại đã làm chính xác những gì bạn yêu cầu. Thiết kế là lỗi.
Một idempotency key thu hẹp khoảng cách này. Client tạo ra một khóa duy nhất cho mỗi hành động logic và gửi nó cùng với yêu cầu, thường là dưới dạng header Idempotency-Key. Máy chủ ghi lại khóa khi nhận lần đầu tiên và, nếu nó thấy cùng một khóa lần nữa, sẽ trả về kết quả ban đầu thay vì thực hiện công việc hai lần. Bây giờ, việc thử lại là an toàn theo cấu trúc: lần POST /charge thứ hai với cùng một khóa là một thao tác không làm gì (no-op) mà trả về kết quả của lần tính phí đầu tiên.
Khóa phải duy trì ổn định qua các lần thử lại cùng một hành động và thay đổi giữa các hành động khác nhau. Tạo nó một lần khi bạn xây dựng yêu cầu, không phải bên trong vòng lặp thử lại, nếu không mỗi lần thử sẽ nhận được một khóa mới và việc loại bỏ trùng lặp sẽ không bao giờ diễn ra. Bất kỳ lệnh gọi công cụ nào tạo hoặc thay đổi trạng thái (tính phí, đơn hàng, email, bản ghi) đều cần một khóa. Hướng dẫn của chúng tôi về idempotency keys bao gồm việc tạo và xử lý phía máy chủ một cách đầy đủ.
Vượt qua giới hạn tỷ lệ và vòng lặp RateLimitError
Giới hạn tỷ lệ xứng đáng được xử lý riêng vì chúng đi kèm với hướng dẫn. Một phản hồi vượt quá giới hạn tỷ lệ thường đến dưới dạng lỗi 429 mang theo header Retry-After cho bạn biết chính xác cần đợi bao lâu, theo giây hoặc dưới dạng ngày tháng. Hãy tôn trọng điều đó. Nếu máy chủ nói đợi 30 giây và bạn thử lại trong 2 giây, bạn sẽ nhận thêm một lỗi 429 nữa, và bạn đã xây dựng vòng lặp RateLimitError lấp đầy diễn đàn thảo luận SDK: bắt giới hạn, thử lại quá sớm, bị giới hạn nặng hơn, lặp lại cho đến khi quá trình chạy bị dừng. Một chủ đề SDK riêng biệt đề cập đến cùng một rào cản mà các nhà phát triển gặp phải ở đây.
Cách khắc phục là để máy chủ đặt tốc độ. Khi bạn nhận được lỗi 429, hãy đọc Retry-After và đợi ít nhất thời gian đó trước khi thử lại. Nếu header bị thiếu, hãy quay lại sử dụng backoff lũy thừa với jitter. Giới hạn số lần thử để một giới hạn kéo dài kết thúc bằng một lỗi rõ ràng thay vì đợi vô hạn. Anthropic SDK đã tuân thủ Retry-After cho các lệnh gọi của chính nó; công việc của bạn là áp dụng cùng quy tắc cho các API bị giới hạn tỷ lệ khác mà agent của bạn chạm tới.
Cũng có một khía cạnh chủ động. Nếu nhà cung cấp cho phép một số lượng yêu cầu nhất định mỗi phút, hãy đo lường các lệnh gọi của riêng bạn bằng token bucket để bạn duy trì dưới giới hạn thay vì phát hiện ra nó bằng cách bị giới hạn. Khôi phục xử lý các giới hạn bạn gặp phải; việc điều chỉnh tốc độ giúp bạn tránh gặp chúng.
Cách kiểm tra đường dẫn khôi phục
Bây giờ hãy ghép nối chúng lại. Các mô hình trên chỉ tốt khi bạn có bằng chứng rằng chúng hoạt động, và bằng chứng là một bài kiểm tra buộc các lỗi mà một API khỏe mạnh sẽ không cung cấp cho bạn. Hình dạng này được sử dụng lại trong mọi kịch bản:
- Giả lập (Mock) phụ thuộc. Tạo một bản giả lập API mà công cụ của agent của bạn gọi, để bạn kiểm soát mọi mã trạng thái, header, body và độ trễ, và không có phí hoặc email thực nào được gửi trong quá trình kiểm tra.
- Lập trình một chuỗi. Lập script cho bản giả lập để trả lời một loạt các lệnh gọi theo thứ tự: đầu tiên là 429 với
Retry-After: 2, sau đó là 500, sau đó là 200 với một body hợp lệ. Một điểm cuối, ba phản hồi đã được script, một vòng lặp khôi phục hoàn chỉnh trong một lần chạy duy nhất. - Điều khiển agent đến bản giả lập. Trỏ công cụ của agent đến URL giả lập thay vì dịch vụ thực và chạy kịch bản từ đầu đến cuối.
- Xác nhận hành vi. Kiểm tra những gì quan trọng: agent đã đợi ít nhất 2 giây sau lỗi 429 trước khi thử lại, đã thử lại sau lỗi 500, thành công trong lệnh gọi thứ ba và không bao giờ vượt quá giới hạn số lần thử của bạn.
Kịch bản đó chứng minh backoff và Retry-After chỉ trong một lần chạy. Thêm kịch bản thứ hai cho đường dẫn từ bỏ: lập script cho bản giả lập để thất bại mọi lúc và xác nhận agent dừng lại ở giới hạn và trả về một lỗi rõ ràng thay vì lặp lại. Thêm kịch bản thứ ba cho circuit breaker: làm thất bại đủ các lệnh gọi liên tiếp và xác nhận agent kích hoạt và thất bại nhanh chóng thay vì phải trả phí timeout cho mỗi lần thử.
Kiểm tra tính không thay đổi (idempotency) là thứ mà mọi người thường bỏ qua, và đó là thứ giúp tiết kiệm tiền. Lập script cho bản giả lập để chấp nhận một lệnh gọi thay đổi trạng thái, bỏ qua phản hồi để agent nghĩ rằng nó đã thất bại, sau đó chấp nhận thử lại. Bây giờ, hãy xác nhận hình dạng yêu cầu: cả hai yêu cầu đều mang cùng Idempotency-Key, và bản giả lập thấy một hành động logic, không phải hai. Một khóa mới trong lần thử lại, hoặc một lệnh gọi trùng lặp, có nghĩa là bạn đã tìm thấy lỗi gửi hai lần trước khi khách hàng phát hiện ra. Phương pháp rộng hơn để kiểm tra các agent gọi API của bạn thiết lập toàn bộ hệ thống kiểm thử.
Danh sách kiểm tra khôi phục lỗi
Trước khi một agent đi vào môi trường production, hãy xem xét danh sách này:
- Mọi lệnh gọi ra bên ngoài đều có connect timeout, read timeout và tổng ngân sách chạy.
- Các lần thử lại sử dụng backoff lũy thừa với jitter, giới hạn cả về độ trễ và số lần thử.
- Phản hồi 429 đọc và tuân thủ
Retry-After, với backoff làm phương án dự phòng. - Một circuit breaker kích hoạt cho mỗi phụ thuộc để một dịch vụ chết nhanh chóng thất bại thay vì lặp lại.
- Mọi lệnh gọi thay đổi trạng thái đều mang một khóa idempotency ổn định tồn tại qua các lần thử lại.
- Đường dẫn từ bỏ trả về một lỗi rõ ràng, không phải đợi vô hạn.
- Mỗi điều này được chứng minh bằng một bài kiểm tra buộc thất bại chống lại một bản giả lập, chứ không phải là giả định.
Đánh dấu tất cả bảy mục và agent của bạn sẽ phục hồi một cách có chủ đích chứ không phải do may mắn.
Apidog phù hợp ở đâu (và không phù hợp ở đâu)
Giữ cho công việc của công cụ trung thực. Apidog không phải là một framework agent, một máy chủ mô hình hay một runtime. Nó không xây dựng, chạy hay điều phối agent của bạn, và nó không đánh giá đầu ra của mô hình. Những gì nó sở hữu là lớp API mà agent của bạn gọi, chính xác là nơi khả năng phục hồi được thắng hoặc thua.

Điều đó mang lại cho nó ba nhiệm vụ. Nó giả lập các phụ thuộc mà agent của bạn truy cập, vì vậy bạn có một bản thay thế có thể kiểm soát thay vì dịch vụ trực tiếp. Nó lập trình các phản hồi lỗi (429 với Retry-After, 500, timeout, body không đúng định dạng) mà một API thực sẽ không tạo ra theo lệnh, vì vậy bạn có thể diễn tập khôi phục. Và nó xác thực các yêu cầu mà bản giả lập nhận được (khóa idempotency hiện diện và ổn định, hình dạng chính xác, số lượng lệnh gọi dự kiến) để một lần gửi hai lần hoặc một header bị mất sẽ làm thất bại một bài kiểm tra thay vì một khách hàng. Đó là sự phù hợp trung thực: Apidog giả lập các lỗi mà agent của bạn phải sống sót và kiểm tra những gì nó gửi lại.
Các câu hỏi thường gặp
Anthropic SDK có xử lý việc thử lại cho tôi không? Đối với các lệnh gọi của chính nó, có. SDK thử lại các lỗi nhất định với backoff lũy thừa và tuân thủ Retry-After, và bạn đặt giới hạn với tùy chọn max-retries. Nó không bao gồm các API khác mà công cụ của agent của bạn gọi. Những API đó cần bạn áp dụng các mô hình tương tự.
Khi nào tôi cần một idempotency key? Trên bất kỳ lệnh gọi nào tạo hoặc thay đổi trạng thái: tính phí, đơn hàng, tin nhắn đã gửi, bản ghi mới. Các lệnh gọi chỉ đọc an toàn để thử lại mà không cần khóa. Tạo khóa một lần cho mỗi hành động để nó duy trì ổn định qua các lần thử lại.
Diễn tập một lỗi trong tuần này
Bạn không cần phải xây dựng tất cả bốn mô hình cùng một lúc. Chọn một mô hình gây thiệt hại lớn nhất, thường là vòng lặp giới hạn tỷ lệ hoặc một lần thử lại không có tính không thay đổi, và diễn tập nó với một bản giả lập. Lập trình lỗi 429, bỏ qua một phản hồi và quan sát những gì agent gửi. Lần đầu tiên bạn thấy backoff sạch sẽ và một idempotency key duy nhất nơi bạn lo sợ bị tính phí hai lần, bạn sẽ tin tưởng agent vì một lý do tốt hơn là một bản demo màu xanh.
Tải xuống Apidog để giả lập các lỗi, lập script chuỗi và xác nhận những gì agent của bạn làm khi API gặp vấn đề.
