Vì sao hầu hết hệ thống đa tác tử (Multi-Agent) thất bại ngay cả khi bài kiểm tra đánh giá vẫn đạt?

Công nghệ07 tháng 9, 2026·13 phút đọc

Hầu hết các hệ thống đa tác tử AI thất bại trong thực tế không phải vì lỗi 500 mà vì các phản hồi 200 trả về dữ liệu sai nhưng có cấu trúc hợp lệ. Bài viết đề xuất kiến trúc 'Intermediate State Eval' với một 'watchdog' nhỏ đánh giá dữ liệu tại từng điểm chuyển tiếp giữa các tác tử thay vì chỉ chấm điểm văn bản cuối cùng, kèm theo mã Python cụ thể để triển khai.

Vì sao hầu hết hệ thống đa tác tử (Multi-Agent) thất bại ngay cả khi bài kiểm tra đánh giá vẫn đạt?

Vì sao hầu hết hệ thống đa tác tử thất bại ngay cả khi bài kiểm tra đánh giá vẫn đạt?

Hầu hết các hệ thống đa tác tử AI khi đưa vào vận hành thực tế không gặp lỗi nghiêm trọng (500) mà chết dần vì những phản hồi "thành công" (200) nhưng chứa dữ liệu sai. Việc chỉ chấm điểm kết quả văn bản cuối cùng khiến ta mù về các bước trung gian sai sót. Giải pháp là đặt một "watchdog" – một bộ đánh giá nhẹ – tại các điểm kết nối giữa các tác tử để kiểm tra độ hợp lý của dữ liệu trước khi chúng được chuyển tiếp.

Tôi liên tục gặp phải kiểu thất bại này ở các hệ thống đa tác tử, dù dưới hình thức này hay hình thức khác. Hãy thử tưởng tượng một hệ phân loại vé hỗ trợ khách hàng có ba bước: một bước phân loại vé đến, một bước lấy lịch sử tài khoản của khách từ một API nội bộ, và một bước cuối soạn email giải quyết hoặc chuyển tiếp vấn đề. Hệ thống hoạt động tốt trong bản demo, nhưng demo thì hiếm khi nói lên điều gì. Nó cũng hoạt động tốt trong vài ngày đầu ở môi trường thực tế — nhưng vậy vẫn là chưa đủ.

Rồi một ngày, một khách hàng khiếu nại về việc hoàn tiền cho đăng ký đã hủy. Bước lấy lịch sử tài khoản gọi API thanh toán, nhận mã 200, và chuyển tiếp dữ liệu xuống phía dưới như không có chuyện gì xảy ra. Nhưng dữ liệu đó lại rỗng. Không có dữ liệu sai cấu trúc, không có lỗi timeout, không điều gì có thể hiện thành lỗi 500. Chỉ là một kết quả rỗng, nhưng được định dạng chính xác như một phản hồi hợp lệ, bởi vì ID tài khoản đã bị lỗi ở hai bước trên và dịch vụ thanh toán âm thầm trả về dữ liệu rỗng cho một tài khoản không thể khớp được. Bước soạn email không hề thấy lỗi. Nó thấy một JSON hợp lệ nhưng không có bản ghi nào và kết luận rằng khách hàng này "không có lịch sử thanh toán", sau đó viết một email rất lịch sự giải thích rằng chẳng có gì để hoàn tiền. Email được gửi đi với quyết định hoàn tiền sai lầm. Không ai phát hiện ra, vì quy trình không hề sụp đổ. Với hệ thống, nó đã hoàn thành nhiệm vụ.

Tôi không nghĩ bạn cần phải trải qua chính xác tình huống này thì mới thấy nó đáng quan tâm. Nếu bạn đã làm việc với các hệ đa tác tử ở môi trường sản xuất một thời gian, bạn sẽ thấy một phiên bản của lỗi này, hoặc là sắp tới bạn sẽ thấy.

Đây không phải là chuyện cá biệt. Báo cáo State of AI Engineering 2026 của Datadog cho thấy tỷ lệ thất bại của các yêu cầu AI khoảng 5%, nhưng chỉ 60% trong số đó đến từ các lỗi "ồn ào" do quá tải mà bạn nhận biết qua mã lỗi. Phần còn lại giống với tình huống trên: yêu cầu được hoàn thành nhưng kết quả lại sai.

Vì sao không có gì phát hiện ra vấn đề?

Chạy quy trình trên qua một bộ kiểm thử đánh giá tiêu chuẩn, nó sẽ vượt qua một cách dễ dàng. Kết quả đầu ra cuối cùng được viết khá hay, đúng ngữ pháp và chuyên nghiệp. Người đọc rà soát giọng văn sẽ không có lý do gì để gắn cờ, trừ khi họ tình cờ đối chiếu lại với tài khoản thực — mà việc đó lại phá vỡ mục đích của việc tự động hóa kiểm tra. Nếu bạn chấm điểm dựa trên tiêu chí chất lượng giải quyết, nó cũng sẽ đạt điểm cao: rõ ràng, lịch sự và đúng chủ đề.

Nó đạt là vì mỗi bài kiểm tra đó đều nhìn vào cùng một lớp: văn bản cuối cùng. Không bài nào đặt câu hỏi về những gì xảy ra giữa bước hai và bước ba. Bước lấy lịch sử tài khoản không hề thất bại một cách ồn ào; nó thất bại bằng cách trả về một thứ sai nhưng lại thành công, và "thành công" chính là điều mà các hệ thống chấm điểm ở mức đầu ra được xây dựng để khen thưởng.

Đây là phần tôi nghĩ chúng ta nên dành thời gian tìm hiểu kỹ hơn trước khi tìm cách sửa chữa. Việc chỉ chấm điểm kết quả đầu ra đã được biên dịch khiến bạn mù về các trạng thái trung gian. Chúng trông có vẻ đúng nhưng thực tế lại sai. Đó là một lỗ hổng không thể vá bằng cách thêm một câu lệnh hay ho cho bước cuối. Đó là một điểm mù đã được đóng đinh ngay từ khi bạn quyết định nơi để mắt tới.

Chấm điểm giao diện người dùng thay vì ứng dụng bên dưới

Có một phép so sánh cũ mà tôi vẫn thường nhớ lại. Không ai giao một ứng dụng đã biên dịch và gọi nó là đã được kiểm thử chỉ vì màn hình đăng nhập hiển thị. Bạn kiểm thử lớp bên dưới nó: câu lệnh truy vấn hỗ trợ đăng nhập, token nó cấp, và cả kiểm tra quyền truy cập mà nó kích hoạt. Giao diện người dùng là nơi cuối cùng lỗi bộc lộ, chứ không phải là nơi đầu tiên bạn nghĩ đến để tìm lỗi.

Hầu hết việc đánh giá tác tử AI trong sản xuất hiện nay chỉ là kiểm thử trên "giao diện người dùng" — với các hệ thống không truyền thống, đó là văn bản phản hồi cuối cùng. Đây là thứ duy nhất được chấm điểm, thường là vì nó là thứ dễ chấm điểm nhất. Bạn có thể chạy nó qua một tiêu chí, so sánh từng dòng với một câu trả lời đúng đã biết, hoặc để ai đó đọc lướt qua trong lúc uống cà phê.

Các lệnh gọi công cụ, việc chuyển giao JSON giữa các bước, thông tin suy luận một phần được chuyển tiếp: không thứ nào trong đó được giám sát trừ khi có sự cố nghiêm trọng đến mức để lại dấu vết trong nhật ký (log).

Chế độ thất bại đắt đỏ nhất chưa bao giờ là lỗi gây tiếng ồn. Mã lỗi 500 — máy chủ trực tiếp thừa nhận có gì đó hỏng — sẽ được phát hiện và xử lý, vì hệ thống đã lường trước được dạng lỗi đó và có kế hoạch cho nó. Thứ làm bạn tổn thất là mã 200, phản hồi nói rằng mọi thứ vẫn ổn, nhưng kèm theo một payload sai về mặt ngữ nghĩa dù cấu trúc vẫn đúng.

Watchdog đánh giá từng bước chuyển giaoWatchdog đánh giá từng bước chuyển giao

Kiến trúc giám sát phần giữa quy trình

Vậy giải pháp không phải là thêm một hệ thống tiêu chí nữa ở cuối quy trình. Mà là chuyển một phần việc đánh giá vào trong chính pipeline, ngay tại các điểm nối mà đầu ra của tác tử này trở thành đầu vào của tác tử kia. Tôi gọi kiến trúc này là Intermediate State Eval (Đánh giá trạng thái trung gian). Ý tưởng là một bộ chấm điểm nhẹ đặt giữa các nút tác tử, không chờ đợi toàn bộ chuỗi hoàn thành.

Trong trường hợp phân loại vé hỗ trợ ở trên, đây là một điểm kiểm tra giữa bước lấy lịch sử tài khoản và bước soạn email. Nhiệm vụ duy nhất của nó là tự hỏi liệu phần chuyển giao có hợp lý hay không. ID tài khoản trong dữ liệu có khớp với ID được yêu cầu ban đầu không? Đây có phải là một kết quả tra cứu thực sự, hay giống kiểu giá trị mặc định mà hệ thống âm thầm rơi vào khi không tìm thấy thứ nó cần?

Bạn không cần một mô hình lớn và thông minh để thực hiện phán đoán này. Một mô hình nhỏ chạy cục bộ, hoạt động như một "người canh gác", là đủ để phát hiện các vấn đề về cấu trúc và độ hợp lý. Giữ mô hình này ở mức cục bộ giúp tránh việc tăng độ trễ và chi phí — vốn sẽ tạo ra một phiên bản thứ hai của chính vấn đề bạn đang cố giải quyết. Phán quyết của nó không cần phải thông minh. Nó chỉ cần nhanh và có tính phân loại nhị phân: phần chuyển giao này có đủ "bình thường" để chuyển tiếp hay cần được gắn cờ và dừng lại trước khi bước tiếp theo xây dựng trên nó?

Dưới đây là đoạn mã Python cho thấy cách triển khai ý tưởng này.

Xác định cấu trúc dữ liệu chuyển giao

Đầu tiên, hãy định nghĩa cấu trúc dữ liệu chuyển giao bằng Pydantic. Điều này rất quan trọng vì nó cho "người canh gác" một thứ cụ thể để kiểm tra.

from pydantic import BaseModel, Field
import logging

logger = logging.getLogger("pipeline.handoff")

# Ngưỡng tự tin tối thiểu cho phán đoán "hợp lý"
# Bắt đầu từ 0.5, gặp nhiều cảnh báo sai, hạ xuống 0.35 để giảm tỷ lệ dừng oan.  
CONFIDENCE_FLOOR = 0.35

class AccountHistoryPayload(BaseModel):
    account_id: str
    subscription_status: str
    billing_records: list[dict] = Field(default_factory=list)
    lookup_source: str  # Nguồn dữ liệu thực tế đã trả lời

class HandoffVerdict(BaseModel):
    is_plausible: bool
    reason: str
    confidence: float

Xây dựng bộ kiểm tra (Watchdog)

Hàm kiểm tra chỉ là một hàm nhỏ và nhanh. Nó nhận dữ liệu chuyển giao, yêu cầu ban đầu và hỏi mô hình cục bộ một câu hỏi hẹp thay vì một câu hỏi mở.

import textwrap

GRADER_PROMPT = textwrap.dedent("""\
    Một tác tử ở phía sau sẽ nhận được dữ liệu lịch sử tài khoản này:
    {payload}

    Nó được yêu cầu cho account_id: {account_id}

    Chỉ trả lời bằng JSON: {{"is_plausible": bool, "reason": str, "confidence": float}}
    Hãy đánh dấu là không hợp lý nếu account_id không khớp, nếu billing_records rỗng
    mà subscription có trạng thái active, hoặc dữ liệu trông giống như một giá trị 
    mặc định (default/fallback) hơn là kết quả tra cứu thực.
""")

def grade_handoff(request_account_id: str, payload: AccountHistoryPayload, local_grader) -> HandoffVerdict:
    prompt = GRADER_PROMPT.format(payload=payload.model_dump_json(), account_id=request_account_id)
    raw_response = local_grader(prompt)

    try:
        verdict = HandoffVerdict.model_validate_json(raw_response)
    except ValueError:
        # Nếu "người canh gác" trả về thứ không đọc được, hãy chặn chuyển giao
        logger.error("Người canh gác trả về định dạng lỗi, dừng chuyển giao: %r", raw_response[:200])
        return HandoffVerdict(is_plausible=False, reason="Đầu ra của người canh gác không đọc được", confidence=0.0)

    if not verdict.is_plausible or verdict.confidence < CONFIDENCE_FLOOR:
        return HandoffVerdict(is_plausible=False, reason=verdict.reason, confidence=verdict.confidence)
    return verdict

Kết nối vào quy trình chính

Cuối cùng, bạn thêm bước kiểm tra này vào giữa quy trình. Nếu dữ liệu không được chấp nhận, một ngoại lệ sẽ được đưa ra thay vì một email sai được gửi đi.

# Trong bước xử lý lịch sử tài khoản
def get_account_history(account_id: str, local_grader, billing_api) -> AccountHistoryPayload:
    account_data = billing_api.get_history(account_id)
    payload = AccountHistoryPayload(**account_data)

    verdict = grade_handoff(account_id, payload, local_grader)
    if not verdict.is_plausible:
        # Trước đây, quy trình này sẽ khiến một email sai được gửi đi một cách im lặng.
        # Giờ đây, một ngoại lệ được đưa ra ở đây giúp ngăn chặn điều đó.
        raise HandoffRejectedError(f"account_id={account_id}: {verdict.reason}")

    return payload

Không có gì phức tạp trong số này. Đó chỉ là một cấu trúc dữ liệu, một lần gọi đánh giá duy nhất và một ngoại lệ thay cho việc chuyển tiếp im lặng. Giá trị của ý tưởng không nằm ở việc nó có công nghệ cao siêu hay không. Nó nằm hoàn toàn ở vị trí bạn quyết định đặt watchdog. Kết quả là các thất bại không còn xảy ra trong im lặng. Thay vì một email sai được gửi đi ba bước sau vấn đề thực sự, quy trình sẽ dừng lại ngay tại điểm của lỗi, cùng với dữ liệu hỏng được đính kèm vào cảnh báo. Điều này biến một sự cố khiến bạn mất lòng tin thành một buổi gỡ lỗi chỉ mất vài phút.

Chi phí của phương pháp này là gì?

Không có gì là miễn phí ở đây. Có ba chi phí chính:

  • Độ trễ: Với một quy trình ba bước, bạn phải thêm hai lần gọi suy luận (inference) ngay trên đường đi quan trọng của hệ thống. Điều này có thể gây khó khăn nếu sản phẩm của bạn yêu cầu thời gian phản hồi thật nhanh.

  • Bề mặt lỗi mới: Một "người canh gác" được cấu hình không tốt có thể bắt đầu từ chối những dữ liệu chuyển giao hoàn toàn hợp lệ. Điều này biến rủi ro "hỏng thầm lặng" thành một nỗi phiền toái mới: các lần dừng sai lệch do ai đó phải tự xử lý. Việc tinh chỉnh ngưỡng này đòi hỏi phải lặp đi lặp lại nhiều lần.

  • Sự phán đoán trong thiết kế: Việc quyết định vị trí nào nên đặt "người canh gác" và vị trí nào chỉ thêm phiền phức phụ thuộc hoàn toàn vào mức độ tổn thất nếu hệ thống xử lý sai tại điểm đó. Không phải nút nào cũng cần một "người canh gác". Những nút đứng ngay trước một hành động hướng ra bên ngoài (như gửi email hoặc thực hiện hoàn tiền) là nơi chi phí xử lý lỗi rõ ràng cao hơn chi phí của một bước kiểm tra thêm. Còn ở những vị trí khác, bạn có thể chỉ đang thêm độ trễ để cảm thấy an toàn hơn.

Kết luận

Nếu bạn đang vận hành một quy trình đa tác tử và muốn thử cách tiếp cận này mà không phải sửa sang lại tất cả, đừng bắt đầu từ đầu quy trình. Hãy bắt đầu từ khâu chuyển giao nội bộ cuối cùng trước khi một hành động ra bên ngoài được thực hiện — ngay trước khi email được gửi, một bản ghi được lưu hoặc một quyết định được đưa vào thực thi. Đó là ranh giới duy nhất đáng để thêm thiết bị theo dõi đầu tiên. Hãy chạy thử trong một hoặc hai tuần, xem watchdog bắt được những gì, và để kết quả đó quyết định xem có nên đưa phương pháp này đi sâu hơn vào quy trình của bạn hay không.

Bạn không cần toàn bộ kiến trúc ngay từ ngày đầu để thu được kết quả từ ý tưởng này. Lần tới khi một thứ gì đó hỏng hóc trong quy trình bạn quản lý, hãy tự hỏi: liệu các bài kiểm tra đánh giá của bạn có phát hiện ra lỗi trước khi văn bản đầu ra trông có vẻ sai không? Hầu hết thời gian, nếu thành thật với chính mình, câu trả lời là không. Khoảng trống đó chính là nơi rủi ro chuyển giao lớn nhất của hệ thống bạn đã nằm ở đó suốt thời gian qua, chờ đợi một ai đó chú ý.

Đầu ra cuối cùng có thể nói dối bạn. Quỹ đạo tạo ra nó thì không.

Hình minh họa hệ thống đa tác tửHình minh họa hệ thống đa tác tử

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗