Insight Hub
Failure Recovery: Checkpoint, Retry, Rollback Cho Agent Nhiều Bước

Failure Recovery: Checkpoint, Retry, Rollback Cho Agent Nhiều Bước

Khi một bước giữa chuỗi thất bại, những bước trước đó có thể đã charge tiền, giữ chỗ tài nguyên, hoặc báo cho ai đó. Failure recovery là kỷ luật quyết định khi nào retry, khi nào rollback, để một thất bại một phần không biến thành một side effect mồ côi tốn kém.

Thuộc chuỗi bài: Agentic Workflow Design: 4 Quyết Định Giữ Cho AI Agent An Toàn Khi Chạy Thật

Một chatbot single-turn trả lời sai có cách sửa rất đơn giản: người dùng bấm regenerate. Một agent nhiều bước thất bại giữa chừng không có được cái xa xỉ đó - khi bước ba đổ vỡ, bước một và bước hai có thể đã charge thẻ, giữ chỗ một tài nguyên, hoặc báo cho ai đó ở phía sau. Thất bại lúc này không còn là "tác vụ chưa xong." Nó là "tác vụ đã xảy ra một phần, và giờ có thứ đang ở trạng thái không nhất quán."

Khi Một Bước Thất Bại: Retry Hay Rollback

Checkpoint Đã Lưu
Bước Thất Bại
Retry Có Backoff
Rollback + Escalate

Recovery Triad: Checkpoint, Retry, Rollback

Ba nguyên lý làm nên phần việc thật sự của failure recovery. Checkpoint là một bản snapshot trạng thái và tiến độ được lưu tại một mốc cụ thể - nếu có sự cố sau đó, hệ thống resume từ checkpoint gần nhất thay vì làm lại từ đầu. Retry thử lại chính bước bị lỗi, nhưng chỉ hợp lý khi bước đó idempotent - an toàn để chạy hai lần mà không tạo side effect trùng lặp - và nên giãn cách các lần thử bằng exponential backoff thay vì dội liên tục vào một service đang gặp sự cố. Rollback, còn gọi là compensating action, là một chuỗi hành động có chủ đích để huỷ hoặc đảo ngược tác động của các bước đã thành công trước đó, khi một bước sau đó thất bại theo cách không thể phục hồi tiếp về phía trước.

Ví dụ xuyên suốt: WarehouseRestockBot - một agent tự động hoá việc bổ sung hàng cho cửa hàng: đặt đơn hàng (PO) với nhà cung cấp, đặt chỗ tại bến bốc dỡ (loading dock) cho lô hàng, và báo cho cửa hàng đích về lô hàng sắp tới.

Không Phải Lỗi Nào Cũng Cần Cùng Một Phản Ứng

Sai lầm phá vỡ mọi thứ nhanh nhất là xử lý mọi loại lỗi giống hệt nhau - "cứ retry 3 lần" - bất kể lý do vì sao nó lỗi. Một request timeout vì kết nối mạng chập chờn là một tình huống hoàn toàn khác với một request thất bại vì bến bốc dỡ của kho không còn slot trống cho tuần được yêu cầu. Cái đầu là tạm thời và rất có thể sẽ thành công ở lần thử tiếp theo. Cái sau là một sự từ chối mang tính xác định (deterministic), sẽ thất bại y hệt dù retry bao nhiêu lần - bến bốc dỡ sẽ không tự nhiên có slot trống ở lần thử thứ tư mà nó không có ở lần thử đầu tiên.

Sự phân biệt đó chính là thứ quyết định một lỗi nên retry hay rollback: bước đó có idempotent không và còn retry budget hay không, hay đây là một sự từ chối theo business logic mà retry bao nhiêu cũng không sửa được? Hiểu sai theo hướng ngây thơ khiến hệ thống đốt compute retry một kết quả không bao giờ đổi, trong khi những phần của workflow đã thành công - một đơn hàng đã đặt thật với nhà cung cấp - vẫn nằm đó chưa được giải quyết suốt thời gian đó.

Đưa Các Lỗi Của WarehouseRestockBot Qua Decision Tree

Cùng một chuỗi 3 bước - đặt PO, đặt chỗ bến bốc dỡ, báo cửa hàng - ba cách khác nhau nó có thể đổ vỡ.

Chọn một kịch bản lỗi
Đặt PO bị timeout

API đặt hàng của nhà cung cấp bị timeout vì mạng chập chờn khi đang đặt đơn hàng. Một idempotency key đã được tạo sẵn cho request này.

Bước này có idempotent không?Có - idempotency key ngăn tạo đơn hàng trùng
Còn retry budget không?Có - lần thử đầu tiên, budget còn nguyên
Hành Động RecoveryRETRY CÓ BACKOFF

An toàn để retry. Idempotency key đảm bảo lần thử thứ hai không thể tạo ra một đơn hàng trùng. Chờ, rồi retry với exponential backoff - 1s, rồi 2s, rồi 4s.

Vì Sao Dừng Lại Không Phải Một Lựa Chọn An Toàn Mặc Định

Đoạn code xử lý lỗi dễ viết nhất cũng chính là đoạn nguy hiểm nhất để ship: bắt lỗi, log lại, dừng. Nó trông an toàn vì không có gì crash thêm. Nhưng nó không an toàn, vì việc dừng lại không đảo ngược những gì đã xảy ra - nó chỉ đóng băng workflow ở trạng thái dở dang và hy vọng ai đó sẽ nhận ra. Nếu WarehouseRestockBot đặt một đơn hàng, sau đó thất bại khi đặt chỗ bến bốc dỡ, rồi hệ thống chỉ dừng lại ở đó, kết quả không phải là "không có đợt bổ sung hàng nào xảy ra." Nó là "một nhà cung cấp giờ đang có một đơn hàng thật cho lượng hàng chẳng có nơi nào để nhận" - một side effect mồ côi tốn tiền thật và tốn cả vốn quan hệ với nhà cung cấp để gỡ bằng tay, và sẽ chẳng ai để ý cho tới khi xe tải tới nơi mà không có chỗ để dỡ hàng.

Dừng Ngây Thơ Càng Tốn Kém Khi Xảy Ra Càng Muộn

Vị trí của bước lỗi trong chuỗi × side effect đã cam kết = chi phí của việc chỉ dừng lại

Lỗi ở Bước 1 (Đặt PO)
Không có gì mồ côi

Chưa bước nào trước đó thành công. Dừng ở đây không tốn gì ngoài đúng một lần thử thất bại - không có gì cần gỡ.

Lỗi ở Bước 2 (Đặt Chỗ Bến Bốc Dỡ)
Một cam kết mồ côi

Đơn hàng đã được đặt thật với nhà cung cấp. Dừng ở đây để lại lượng hàng đã đặt mà không có bến bốc dỡ nào được lên lịch để nhận.

Lỗi ở Bước 3 (Báo Cửa Hàng)
Hai cam kết mồ côi

Cả đơn hàng và chỗ bến bốc dỡ đều đã được đặt thật. Dừng ở đây để lại một lô hàng đã lên lịch tới một cửa hàng không hề biết nó sắp tới.

Điểm chốt: bước hầu hết đội checkpoint đầu tiên không phải bước cần nó nhất

Bước một dễ test nhất nên thường là bước có kế hoạch rollback đầu tiên. Nhưng đó lại là bước cuối trong chuỗi mới là nơi có nhiều cam kết đã thực hiện nhất đứng phía sau -độ phủ rollback quan trọng nhất đúng ở chỗ được build sau cùng

Các tầng này mô tả số lượng cam kết phía trước bị bỏ mồ côi bởi một lần dừng ngây thơ, không phải một con số chi phí đo được bằng tiền - chi phí thật của một đơn hàng mồ côi hay một chỗ bến bốc dỡ không dùng tới phụ thuộc vào điều khoản cụ thể với nhà cung cấp và vận hành kho, nên cần ước tính riêng cho workflow của bạn thay vì suy ra từ thứ tự này.

Thiết Kế Recovery Phải Xảy Ra Trước Khi Lỗi Xảy Ra, Không Phải Lúc Đó

Không có cái nào trong số này - checkpoint ở đâu, bước nào idempotent, một rollback thật sự đảo ngược cái gì - có thể ứng biến ngay lúc lỗi xảy ra. Nó phải được quyết định ở thời điểm thiết kế, từng bước một, trước khi workflow chạy lần nào: bước nào có checkpoint, bước nào an toàn để retry và theo lịch backoff nào, và chính xác compensating action nào đảo ngược từng bước nếu có sự cố ở phía sau. Một workflow lần đầu đối mặt với quyết định này ngay lúc đang thất bại thật trên production sẽ ứng biến ra một thứ tệ hơn cả một retry sạch lẫn một rollback sạch - thường là một thứ nửa vời, không nhất quán.

Đây cũng là chỗ failure recovery dựa vào tool scoping nhiều hơn vẻ ngoài của nó: một rollback chỉ rẻ để thực thi nếu agent đã có sẵn một tool được scope rõ ràng để đảo ngược đúng hành động đó - một endpoint huỷ, một API compensating - thay vì cần một quyền truy cập rộng, ứng biến sau khi sự cố xảy ra để dọn một mớ hỗn độn mà chẳng ai thiết kế sẵn cho nó.

Cạm Bẫy Thường Gặp Trong Failure Recovery

Một nhóm sai lầm lặp lại khi các đội build workflow agentic nhiều bước đầu tiên: retry một hành động không idempotent và tạo ra một side effect trùng lặp (một lần charge thứ hai, một đơn hàng thứ hai) thay vì một bản sửa; retry một sự từ chối theo business logic mang tính xác định như thể nó là lỗi tạm thời, đốt thời gian và compute cho một kết quả không bao giờ thay đổi; coi "retry budget đã hết" như một điểm dừng thay vì một tín hiệu để rollback và escalate; và chỉ thiết kế recovery cho đúng lỗi đã gặp lúc test, để mọi bước khác trong chuỗi không có kế hoạch rollback nào cả.

Làm đúng failure recovery giúp một workflow thất bại ồn ào và an toàn thay vì âm thầm và tốn kém - mọi thất bại một phần đều tự giải quyết qua một retry được scope đúng, hoặc được gỡ sạch qua một rollback, thay vì để lại một side effect mồ côi cho ai đó phát hiện ra sau nhiều ngày.