Đến nội dung chính
Tools & MCP

Xử lý lỗi MCP tool: isError, retry và kết quả rỗng

Xử lý lỗi MCP tool cho CCAR-F: cấu trúc isError, bốn loại lỗi, khi nào nên retry, và vì sao tra cứu thất bại không được trông giống kết quả rỗng hợp lệ.

Đội ngũ CertGrove · 7 phút đọc

Agent hỗ trợ khách hàng gọi lookup_order, dịch vụ đơn hàng bị timeout, và MCP tool trả về đúng một câu "Operation failed." Agent gọi lại y hệt thêm bốn lần, rồi báo khách là đơn hàng không tồn tại. Xử lý lỗi MCP tool đúng cách ngăn được cả hai sai lầm này. Bài viết nói về các loại lỗi mà đề CCAR-F yêu cầu nắm, cấu trúc kết quả có isError, cách phân biệt tra cứu thất bại với kết quả rỗng, và chỗ nào nên tự phục hồi trong hệ thống multi-agent.

Nội dung bám theo task statement 2.2 (structured error response cho MCP tool) thuộc Domain 2, và task statement 5.3 (lan truyền lỗi trong hệ thống multi-agent) thuộc Domain 5. Chủ đề này hay xuất hiện ở Scenario 1, agent hỗ trợ khách hàng truy cập backend qua MCP tool, và Scenario 3, hệ thống research multi-agent.

isError trong kết quả MCP tool nghĩa là gì?

isError: true báo cho client biết tool đã chạy nhưng thao tác bên trong thất bại. Đặc tả MCP gọi đây là tool execution error, gồm lỗi API, lỗi validate input và lỗi business logic. Chúng nằm trong một result bình thường, và đặc tả nói client SHOULD chuyển chúng cho model để model tự sửa.

Đặc tả tách loại này khỏi protocol error: tool không tồn tại, request sai cấu trúc, lỗi server. Protocol error trả về dưới dạng JSON-RPC error chuẩn có code, và model ít khi tự sửa được.

Đây là một tool execution error khi tra cứu đơn hàng bị timeout. MCP quy định content và isError. Phần JSON bên trong text block là quy ước của riêng bạn:

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"errorCategory\": \"transient\", \"isRetryable\": true, \"description\": \"Order service timed out after 5s. A retry in a few seconds may succeed.\", \"attempted\": {\"order_id\": \"ORD-99172\"}}"
      }
    ],
    "isError": true
  }
}

⚠ Bản đặc tả MCP mới nhất (2026-07-28) thêm trường "resultType": "complete" vào kết quả. Exam guide không nhắc tới trường này, và cách dùng isError ở hai phiên bản là như nhau.

Khi ứng dụng chuyển kết quả này sang Claude Messages API, cờ đổi tên thành is_error trên block tool_result. Nhớ giữ cờ này, nếu không Claude sẽ đọc lỗi như output bình thường.

Xử lý lỗi MCP tool: transient, validation, business, permission

Exam guide liệt kê bốn loại lỗi, mỗi loại cần một bước xử lý khác nhau. Timeout có thể hết khi thử lại; lỗi quyền thì thử bao nhiêu lần cũng không hết.

Loại lỗiVí dụGọi lại y hệt?Agent làm gì
TransientDịch vụ đơn hàng timeout, 503Có, số lần giới hạnRetry tại chỗ, rồi báo lên kèm những gì đã thử
Validationdate: "last Tuesday-ish"Không gọi lại nguyên xiSửa input hoặc hỏi người dùng, rồi gọi lại
Business ruleYêu cầu hoàn tiền sau 45 ngày, chính sách cho 30 ngàyKhôngGiải thích quy định cho khách và đưa phương án được phép
PermissionTài khoản không được đọc dữ liệu billingKhôngDừng gọi; escalate hoặc báo thiếu quyền
Kết quả rỗng hợp lệTìm kiếm chạy xong, không đơn nào khớpKhông phải lỗiBáo "không có kết quả" như một phát hiện

Một chi tiết nhỏ: phần kỹ năng trong guide liệt kê giá trị errorCategory là transient, validation và permission, còn lỗi nghiệp vụ thì xử lý bằng cờ retriable: false kèm lời giải thích thân thiện cho khách. Thêm category business vẫn ổn. Đề kiểm tra hành vi, không kiểm tra enum.

Vì sao "Operation failed" là cái bẫy

Thông báo chung chung khiến timeout và ngày sai định dạng trông giống hệt nhau, nên agent hoặc retry cả hai, hoặc bỏ cả hai. Exam guide nói error response đồng nhất khiến agent không ra được quyết định phục hồi phù hợp. Giữ cấu trúc response thống nhất, còn nội dung phải cụ thể.

Cách trả structured error response từ tool

Trả về errorCategory, boolean isRetryable và mô tả dễ đọc cho người, đúng ba trường exam guide nêu tên. Với lỗi nghiệp vụ, thêm câu giải thích để agent nói lại với khách. Một hàm helper nhỏ giúp mọi tool trả lỗi giống nhau:

import json

def tool_error(category, retryable, description, **details):
    payload = {"errorCategory": category, "isRetryable": retryable,
               "description": description, **details}
    return {"content": [{"type": "text", "text": json.dumps(payload)}],
            "isError": True}

refund_refused = tool_error(
    "business", False,
    "Refund window closed: order delivered 2026-09-01, policy allows 30 days.",
    customer_message="This order is outside our 30-day refund window, "
                     "but it is still eligible for store credit.",
)

isRetryable: false nghĩa là "đừng lặp lại đúng lời gọi này". Gọi mới sau khi sửa input thì vẫn được. Bản thân cờ này không chặn được gì; prompt hoặc code của bạn phải tuân theo nó.

Tra cứu thất bại và kết quả rỗng: vì sao phải tách riêng

Truy vấn đã chạy và không khớp gì là một câu trả lời thành công: "khách này không có đơn nào trong tháng Ba". Truy vấn chưa tới được database thì không cho biết điều gì. Nếu cả hai cùng trả về danh sách rỗng với trạng thái thành công, agent sẽ tự tin khẳng định một thứ không tồn tại trong khi chưa ai kiểm tra.

Exam guide nhắc sự khác biệt này hai lần, ở 2.2 và ở 5.3. Kết quả rỗng hợp lệ thì trả về thành công với danh sách rỗng. Lỗi truy cập thì trả isError: true kèm quyết định retry. Đừng bao giờ bắt timeout rồi trả [] như thành công. Task 5.3 gọi đó là giấu lỗi (silent suppression), một anti-pattern.

Subagent tự phục hồi hay đẩy lỗi lên coordinator

Subagent nên tự retry lỗi transient trong giới hạn cho phép, và chỉ đẩy lên những lỗi nó không tự xử lý được. Khi đẩy lên, nó kèm loại lỗi, những gì đã thử, kết quả một phần và phương án thay thế, để coordinator quyết định bước tiếp theo.

flowchart TD
    A[Tool returns isError true] --> B{errorCategory}
    B -- transient --> C{Retries left?}
    C -- yes --> D[Retry locally]
    C -- no --> E[Propagate: type, attempts, partial results, alternatives]
    B -- validation --> F[Fix input or ask user]
    B -- business --> G[Explain rule to customer]
    B -- permission --> E
    E --> H[Coordinator: re-delegate, use another source, or annotate the gap]

Trong Agent SDK, coordinator chỉ thấy báo cáo cuối của subagent, không thấy các lời gọi tool trung gian. Một trạng thái trống trơn như "search unavailable" sẽ che mất context mà coordinator cần.

Sai lầm ngược lại là dừng cả workflow chỉ vì một subagent lỗi, và đó cũng là anti-pattern trong 5.3. Giữ lại phần đã thành công, và cho bản tổng hợp ghi rõ mảng nào còn thiếu vì nguồn không truy cập được.

Thử sức

Một coordinator research giao cho bốn subagent tìm ở bốn kho dữ liệu khác nhau. Nguồn của subagent tìm bằng sáng chế trả HTTP 503 cả ba lần thử. Ba subagent còn lại hoàn tất. Subagent bằng sáng chế nên trả về gì?

A) Danh sách kết quả rỗng với trạng thái thành công, để coordinator hoàn thành báo cáo. B) Structured error với loại lỗi transient, truy vấn đã chạy, ba lần đã thử, kết quả một phần nếu có và một nguồn thay thế nên thử. C) Thông báo "patent search unavailable" để coordinator biết mà bỏ qua. D) Tín hiệu yêu cầu huỷ lượt chạy, vì báo cáo sẽ không đầy đủ.

Đáp án: B. Subagent đã thử phục hồi tại chỗ. Giờ nó đưa cho coordinator đủ thông tin để chọn bước tiếp.

  • A là giấu lỗi. Báo cáo sẽ khẳng định không có bằng sáng chế liên quan trong khi kho đó chưa hề được tìm.
  • C là trạng thái chung chung. Coordinator không phân biệt được sự cố ngắn với API key bị thu hồi, cũng không biết đã thử những gì.
  • D vứt bỏ ba lượt tìm thành công vì một lỗi, đúng anti-pattern còn lại mà task 5.3 nêu.

Ghi nhớ

  • isError: true đánh dấu tool execution error bên trong một result bình thường; protocol error dùng JSON-RPC error.
  • Phân loại mọi lỗi thành transient, validation, business hoặc permission, và trả về errorCategory, isRetryable cùng mô tả dễ đọc.
  • Từ chối theo nghiệp vụ là không retry được, và nên kèm lời giải thích để agent nói lại với khách.
  • Kết quả rỗng từ truy vấn thành công là một phát hiện. Truy vấn thất bại là điều chưa biết. Đừng để hai thứ trông giống nhau.
  • Subagent tự retry lỗi transient, phần còn lại đẩy lên kèm số lần thử, kết quả một phần và phương án thay thế.

Câu hỏi thường gặp

Đội ngũ CertGroveViết ghi chú ôn thi song ngữ cho developer Việt Nam chuẩn bị Claude Certified Architect — Foundations.