2.2 Structured Error Responses
Những gì cần nắm
Phần tiêu đề “Những gì cần nắm”Khi một MCP tool lỗi, thứ nó trả về quyết định agent phục hồi thông minh hay chết mù. Thông báo chung chung kiểu “Operation failed” là vô dụng với một LLM. Không tín hiệu nào về chuyện gì đã hỏng, có nên retry không, hay nên thử gì khác.
Giao thức MCP có sẵn cờ isError dành riêng cho việc báo lỗi tool ngược về agent. Bật nó lên thì model biết lần thực thi đã thất bại, nhờ đó suy luận về cách phục hồi thay vì coi đoạn text lỗi như một kết quả thành công bình thường.
Bốn nhóm lỗi
Phần tiêu đề “Bốn nhóm lỗi”Mọi lỗi tool đều rơi vào một trong bốn nhóm. Mỗi nhóm đòi một chiến lược phục hồi khác nhau, và agent cần metadata có cấu trúc mới phân biệt được.
Một lưu ý về hình dạng dữ liệu trước khi xem ví dụ. errorCategory, isRetryable và description là quy ước ở tầng ứng dụng, không thuộc envelope của MCP: CallToolResult trong giao thức chỉ định nghĩa content, structuredContent và isError. Các ví dụ dưới đây đặt metadata trong structuredContent, đúng chỗ dành cho dữ liệu có cấu trúc. Exam guide có gọi tên bốn nhóm này và boolean isRetryable, nên cứ nhớ theo tên; chỉ đừng trông đợi tìm thấy chúng trong đặc tả MCP.
1. Transient Errors Timeout, dịch vụ không sẵn sàng, rate limit. Hệ thống bên dưới tạm thời không với tới được nhưng bản thân request thì hợp lệ. Phục hồi: retry sau một khoảng chờ ngắn.
{ "isError": true, "content": [{ "type": "text", "text": "Service temporarily unavailable" }], "structuredContent": { "errorCategory": "transient", "isRetryable": true, "description": "The order database is experiencing high load. The request is valid and should succeed on retry." }}2. Validation Errors Định dạng input sai, thiếu field bắt buộc, giá trị ngoài khoảng. Bản thân request bị dị dạng. Phục hồi: sửa input rồi gửi một lệnh gọi đã chỉnh.
{ "isError": true, "content": [{ "type": "text", "text": "Invalid order ID format" }], "structuredContent": { "errorCategory": "validation", "isRetryable": false, "description": "Order ID must be in format #NNNNN (e.g. #12345). Received: 'order-abc'. Reformat the ID and call again." }}isRetryable: false ở đây không có nghĩa “bỏ cuộc”. Nó có nghĩa gửi lại đúng lệnh gọi này là vô ích: order-abc trượt cùng một kiểm tra định dạng mọi lần. Agent vẫn phục hồi được, chỉ là phải sửa input trước — và description nói rõ sửa thế nào. Boolean trả lời có gửi lại hay không; errorCategory trả lời không gửi lại thì làm gì.
3. Business Errors Vi phạm chính sách, vượt hạn mức, xung đột business rule. Request về mặt kỹ thuật là hợp lệ nhưng phạm một ràng buộc nghiệp vụ. Phục hồi: KHÔNG retry — cùng request đó sẽ luôn lỗi. Agent cần một luồng xử lý khác.
{ "isError": true, "content": [{ "type": "text", "text": "Refund exceeds policy limit" }], "structuredContent": { "errorCategory": "business", "isRetryable": false, "description": "Refund amount of £750 exceeds the £500 automatic refund limit. This requires manager approval. Please escalate to a human agent with the refund details." }}Để ý cờ isRetryable: false. Business error không bao giờ tự hết nhờ retry — cùng một vi phạm chính sách áp dụng ở mọi lần gọi. Agent phải đi một đường khác về bản chất, thường là escalate hoặc chuyển sang luồng thay thế, và một lời giải thích thân thiện với khách hàng trong description giúp nó truyền đạt chuyện đó tử tế.
4. Permission Errors Từ chối truy cập, thiếu credential, lỗi phân quyền. Tool không chạy được vì bên gọi không có quyền cần thiết. Phục hồi: escalate hoặc dùng credential khác.
{ "isError": true, "content": [{ "type": "text", "text": "Access denied" }], "structuredContent": { "errorCategory": "permission", "isRetryable": false, "description": "The current service account does not have permission to access financial records. Escalate to a senior agent with financial system access." }}isRetryable thực ra báo hiệu điều gì
Phần tiêu đề “isRetryable thực ra báo hiệu điều gì”isRetryable trả lời đúng một câu hỏi hẹp: gửi lại chính xác request này có ăn không? Chỉ transient error mới nhận true — lệnh gọi hợp lệ, hệ thống chỉ trục trặc trong chốc lát. Mọi nhóm còn lại là false, vì phải có gì đó thay đổi trước: input (validation), bản thân request (business), hoặc bên gọi (permission).
Đọc isRetryable để quyết định có gửi lại nguyên xi hay không, rồi đọc errorCategory để biết làm gì khi không gửi lại được:
| Nhóm | isRetryable |
Cách phục hồi |
|---|---|---|
transient |
true |
Gửi lại đúng lệnh gọi đó sau một khoảng chờ |
validation |
false |
Sửa input, gửi lệnh gọi mới |
business |
false |
Đi đường khác hoặc escalate |
permission |
false |
Thử lại với một principal có đúng quyền |
Khác biệt đáng chú ý nhất nằm giữa ba dòng false. Validation thì agent tự phục hồi được. Business và permission thì không — một hạn mức chính sách vẫn áp dụng dù request diễn đạt kiểu gì, và lỗi quyền cần một tài khoản khác chứ không phải một lệnh gọi hay hơn. false nghĩa là “đừng gọi lại đúng cái này”, không phải “dừng lại”.
Access failure và valid empty result
Phần tiêu đề “Access failure và valid empty result”Trong cả domain này, đây là phân biệt phải nắm chắc. Đề thi hỏi thẳng.
Access failure: tool không với tới được nguồn dữ liệu. Timeout, xác thực hỏng, hoặc dịch vụ chết. Dữ liệu có thể tồn tại, nhưng tool không kiểm tra được. Agent phải quyết định có retry hay không.
Valid empty result: tool truy vấn nguồn dữ liệu thành công và không thấy kết quả nào khớp. Truy vấn chạy đúng — chỉ là không có dữ liệu nào thỏa tiêu chí. Agent KHÔNG nên retry. Câu trả lời là “không tìm thấy kết quả”.
Lẫn hai thứ này là phá sạch logic phục hồi. Nó diễn ra thế này:
Một tool trả về mảng rỗng sau khi tra cứu khách hàng. Agent retry 3 lần rồi escalate cho người. Phân tích lại thì ra tài khoản khách hàng đó đơn giản là không tồn tại.
Tool đã thành công. Nó truy vấn database, không thấy khách hàng nào khớp, và trả về kết quả rỗng hoàn toàn đúng. Nhưng vì response không phân biệt “tôi không với tới database” với “tôi vào được database và chẳng thấy gì”, agent xử cả hai như nhau — như một thất bại đáng retry.
Cách sửa: cấu trúc response của tool sao cho một truy vấn thành công mà không có kết quả trông không giống chút nào với một truy vấn thất bại.
// Valid empty result — NOT an error{ "isError": false, "content": [{ "type": "text", "text": "No customer found matching email 'john@example.com'. The query executed successfully but returned no matches." }], "structuredContent": { "resultCount": 0 }}
// Access failure — IS an error{ "isError": true, "content": [{ "type": "text", "text": "Could not reach customer database" }], "structuredContent": { "errorCategory": "transient", "isRetryable": true, "description": "Connection to the customer database timed out after 5 seconds. The query did not execute." }}Lan truyền lỗi trong hệ multi-agent
Phần tiêu đề “Lan truyền lỗi trong hệ multi-agent”Trong kiến trúc multi-agent, xử lý lỗi theo nguyên tắc phục hồi tại chỗ, lan truyền có chọn lọc:
- Subagent tự phục hồi tại chỗ với lỗi transient. Nếu một lượt web search timeout, subagent tìm kiếm retry trước khi làm phiền coordinator.
- Chỉ đẩy lên những lỗi không giải quyết được tại chỗ. Nếu retry hết mà vẫn hỏng, subagent báo thất bại lên trên.
- Kèm theo kết quả từng phần và những gì đã thử. Coordinator cần ngữ cảnh: “Tôi tìm thành công 3 trong 5 nguồn. Nguồn 4 và 5 timeout. Đây là kết quả từng phần từ 3 nguồn thành công.”
Cách này chặn được hai anti-pattern: âm thầm nuốt lỗi (trả kết quả rỗng như thể thành công) và kết liễu cả workflow chỉ vì một thất bại. Cả hai đều khiến coordinator ra quyết định trong mù.
Bẫy thi
Phần tiêu đề “Bẫy thi”Tình huống luyện tập
Phần tiêu đề “Tình huống luyện tập”Một tool trả về mảng rỗng sau khi tra cứu khách hàng. Agent retry 3 lần rồi escalate cho người. Phân tích cho thấy tài khoản khách hàng đó đơn giản là không tồn tại. Gốc rễ của công sức lãng phí này là gì?
- A. Giới hạn retry quá thấp. Nâng lên 5 lần sẽ cho lượt tra cứu đủ cơ hội trả về tài khoản trước khi escalate kích hoạt
- B. System prompt nên bảo agent không bao giờ retry khi tra cứu khách hàng, để mọi lượt tìm hỏng đều escalate cho người ngay
- C. Ngưỡng escalate quá gắt. Agent nên dùng hết nhiều lượt retry hơn trước khi kéo người vào
- D. Tool không phân biệt access failure với valid empty result, nên agent coi “không khớp” là một thất bại đáng retry
Đáp án & giải thích
Đúng: D
- A — Thêm retry chỉ làm tệ hơn. Tool đã thành công — nó không tìm thấy khách hàng nào khớp. Retry một truy vấn thành công mà không có kết quả sẽ chẳng bao giờ cho ra thứ khác.
- B — Hard-code luật retry cho từng tool trong system prompt vừa giòn vừa không tổng quát được. Cách sửa đúng là metadata lỗi có cấu trúc nói cho agent biết kết quả có retry được hay không.
- C — Vấn đề không nằm ở ngưỡng escalate. Vấn đề là agent retry ngay từ đầu. Một valid empty result không cần retry cũng không cần escalate — nó chính là câu trả lời đúng.
- D — Tool đã truy vấn nguồn dữ liệu thành công và không thấy kết quả nào khớp. Đây là valid empty result, không phải access failure. Thiếu metadata có cấu trúc phân biệt hai ca này, agent coi cả hai là thất bại.
Nguồn
Phần tiêu đề “Nguồn”- Claude Certified Architect Foundations Exam Guide — Domain 2, Task Statement 2.2 — Anthropic
- MCP Specification — Tool Results — Model Context Protocol
- Building Effective Agents — Anthropic — Anthropic
Exam Simulator
Phần tiêu đề “Exam Simulator”Năm câu trắc nghiệm theo format đề thi về Structured Error Responses. Chọn đáp án trước, rồi mở phần giải thích.
Câu 1
Phần tiêu đề “Câu 1”Một tool trả về mảng rỗng sau khi tra cứu khách hàng. Agent retry 3 lần rồi escalate cho người. Phân tích cho thấy tài khoản khách hàng đó đơn giản là không tồn tại. Gốc rễ của công sức lãng phí này là gì?
- A. Tool không phân biệt access failure với valid empty result, nên agent retry một lần gọi đã thành công
- B. Giới hạn retry quá thấp, nâng lên 5 là xong
- C. Ngưỡng escalate quá gắt; agent nên dùng hết nhiều lượt retry hơn nữa trước khi kéo người vào
- D. System prompt nên bảo agent đừng retry các lượt tra cứu khách hàng
Đáp án & giải thích
Đúng: A
- A đúng vì tool đã truy vấn nguồn dữ liệu thành công và không thấy kết quả nào khớp. Đó là valid empty result chứ không phải access failure, nhưng thiếu metadata có cấu trúc tách hai ca, agent đọc cả hai thành thứ đáng retry.
- B sai vì thêm retry chỉ làm tệ hơn. Truy vấn vốn đã thành công, nên lặp lại chỉ trả về đúng mảng rỗng đó mọi lần.
- C sai vì ngưỡng escalate không phải vấn đề. Agent lẽ ra không nên retry chút nào, và một valid empty result chẳng cần retry cũng chẳng cần escalate.
- D sai vì hard-code luật retry theo từng tool trong system prompt vừa giòn vừa không áp được cho tool tiếp theo. Metadata lỗi có cấu trúc mới là cách sửa bền.
Câu 2
Phần tiêu đề “Câu 2”Một tool refund trả về lỗi: “Refund amount of 750 pounds exceeds the 500 pounds automatic refund limit.” Agent retry 3 lần. Vì sao lần retry nào cũng hỏng?
- A. Khoảng chờ giữa các lần retry quá ngắn để luật kịp cập nhật
- B. Tool không trả cờ isError, nên agent không hề nhận ra lệnh gọi đã thất bại
- C. Agent nên tự động giảm khoản refund xuống mức 500 pounds rồi gọi lại với số tiền thấp hơn
- D. Đây là business error, cùng chính sách đó áp dụng ở mọi lần thử, nên agent phải escalate
Đáp án & giải thích
Đúng: D
- D đúng vì business error như vi phạm chính sách hay vượt hạn mức về bản chất là non-retryable. Hạn mức 500 pounds áp dụng y hệt ở mọi lần thử, nên agent phải đi đường khác, thường là escalate lên quản lý.
- A sai vì business rule không thay đổi giữa các lần retry trong một session. Hạn mức là chính sách, không phải một trạng thái nhất thời.
- B sai vì cờ isError không phải chỗ thiếu. Metadata mới là thứ không nói isRetryable: false, khiến agent coi một lời từ chối vĩnh viễn là tạm thời.
- C sai vì agent không nên lẳng lặng giảm khoản refund. Khách hàng yêu cầu 750 pounds, và chỉ con người mới duyệt hay từ chối số tiền đó.
Câu 3
Phần tiêu đề “Câu 3”Tổ hợp field metadata lỗi nào cho phép agent ra quyết định phục hồi phù hợp với mọi kiểu lỗi tool?
- A. errorCode (integer), errorMessage (string), và timestamp (ngày giờ ISO)
- B. httpStatus (integer), retryAfter (giây), và errorBody (JSON) chuyển thẳng từ dịch vụ upstream xuống
- C. errorCategory (transient/validation/business/permission), isRetryable (boolean), và description
- D. severity (low, medium hoặc high), businessImpact (chuỗi tự do), và resolution (chuỗi tự do)
Đáp án & giải thích
Đúng: C
- C đúng vì ba field này phủ hết những gì agent phải quyết: errorCategory nói lỗi thuộc kiểu nào, isRetryable nói nên retry hay đi đường khác, và description mang chỉ dẫn người đọc hiểu được để phục hồi hoặc escalate.
- A sai vì một mã lỗi và một dấu thời gian chẳng nói gì về việc có nên retry hay phải làm gì thay thế.
- B sai vì metadata thiên về HTTP không ánh xạ gọn sang MCP tool response, và retryAfter chỉ nói được chuyện của lỗi transient. Business và permission bị bỏ trống.
- D sai vì severity không hàm ý retryability. Một transient error mức nghiêm trọng cao vẫn có thể retry được, còn business error mức thấp thì không.
Câu 4
Phần tiêu đề “Câu 4”Trong một hệ multi-agent, subagent web search gặp timeout ở 2 trong 5 nguồn. Nó có kết quả thành công từ 3 nguồn còn lại. Subagent nên làm gì?
- A. Chỉ trả 3 kết quả thành công, trình bày như thể cả 5 nguồn đều đã được tìm xong
- B. Báo cáo kết quả từng phần từ 3 nguồn thành công, ghi rõ nguồn 4 và 5 bị timeout
- C. Báo thất bại cho coordinator và vứt hết kết quả, kể cả những thứ đã thu được
- D. Retry cả 5 nguồn từ đầu để đảm bảo phủ hết
Đáp án & giải thích
Đúng: B
- B đúng vì coordinator cần cả phát hiện lẫn hình dung về những gì đã thử: ba trên năm nguồn đã tìm, nguồn bốn và năm timeout, đây là thứ thu được. Đó là cơ sở để nó quyết định đi tiếp, retry hai nguồn kia, hay mở rộng tìm kiếm.
- A sai vì âm thầm nuốt các lượt timeout là giấu thông tin thất bại. Coordinator không còn phân biệt được “hai nguồn đó không có gì” với “không với tới hai nguồn đó”.
- C sai vì vứt kết quả tốt là kết liễu cả workflow chỉ vì một thất bại từng phần. Phát hiện từ ba nguồn vẫn có giá trị.
- D sai vì retry cả năm là ném đi phần việc đã thành công. Chỉ nguồn bốn và năm cần thử lại.
Câu 5
Phần tiêu đề “Câu 5”Một tool nhận identifier “order-abc” trong khi định dạng mong đợi là #NNNNN (ví dụ #12345). Tool nên trả về:
- A. isError: true, errorCategory: “transient”, isRetryable: true, kèm thông báo bảo agent thử lại sau
- B. isError: false, với tập kết quả rỗng cho biết không tìm thấy đơn hàng nào khớp mã đó
- C. isError: true, errorCategory: “business”, isRetryable: false, kèm thông báo bảo agent escalate cho người
- D. isError: true, errorCategory: “validation”, isRetryable: false, kèm định dạng mong đợi trong thông báo
Đáp án & giải thích
Đúng: D
- D đúng vì định dạng sai, nên đây là lỗi validation. isRetryable là false bởi gửi lại “order-abc” sẽ trượt cùng kiểm tra đó mọi lần. Đó không phải ngõ cụt: nhóm lỗi bảo agent định dạng lại identifier theo #NNNNN rồi gọi lại, còn thông báo cung cấp đúng định dạng nó cần.
- A sai vì chẳng có gì tạm thời không sẵn sàng cả. Chờ rồi gửi lại đúng identifier dị dạng đó cho ra đúng lỗi đó, mà isRetryable: true lại đang mời gọi chính chuyện này.
- B sai vì một kết quả rỗng che mất vấn đề thật. Tool không phải tìm rồi không thấy gì; nó không tìm được chút nào, và đó đúng là phân biệt mà nhóm lỗi sinh ra để giữ.
- C sai vì không business rule nào bị vi phạm. Một identifier dị dạng là vấn đề input sửa được, không phải thứ cần tới con người.