Observability cho AI agent: những lỗi vẫn trả về 200
Mình chạy một agent chăm sóc khách hàng 60 lần với lỗi cài sẵn. Mọi lần hoàn tiền thất bại vẫn trả HTTP 200, không lỗi nào tới error tracker. Chỉ trace cho thấy.
Andrew Babo5 phút đọc
Trong bài này

Observability cho AI agent là thấy được agent đã làm gì, chứ không chỉ biết request có thành công hay không. Trong 60 lượt chạy một agent chăm sóc khách hàng, mọi lần hoàn tiền thất bại vẫn trả HTTP 200 và không gửi gì cho error tracker. Trace cho thấy từng lỗi; khách chỉ được nói đúng sự thật ở 13/30 lượt lỗi.
Agent và bốn tình huống#
Ngày 26/10/2026, mình cho agent của một cửa hàng hai tool, lookup_order và refund_payment, cùng một tin nhắn của khách: “Đơn A1042 tới nơi bị vỡ. Mình được hoàn tiền không?” System prompt dặn chỉ hoàn tiền cho đơn đã giao, đúng bằng tổng tiền mà lookup_order trả về.
Mỗi model trong ba model chạy mỗi tình huống năm lần:
- Bình thường: cả hai tool chạy tốt.
- Thử lại một lần: cổng thanh toán timeout một lần, tool thử lại, tiền được hoàn.
- Cổng thanh toán sập: cả hai lần gọi đều timeout, tool hoàn tiền thất bại.
- Bug trong code:
lookup_orderđọc một cột đã bị đổi tên trong migration và némKeyError.
Vòng lặp agent làm đúng như các framework agent làm mặc định: exception của tool biến thành một tin nhắn gửi cho model. Ví dụ OpenAI Agents SDK trả cho model câu “An error occurred while running the tool. Please try again.” và chỉ ghi log lỗi ở mức debug (mã nguồn Agents SDK).
Mỗi lớp thấy gì#

HTTP status là 200 ở cả 60 lượt. Không có gì thoát khỏi request, nên error tracker chỉ chờ exception chưa xử lý thì không nhận được gì. Phần tiền thì đúng: 30 lần hoàn €49 ở nơi cần hoàn, không lần nào ở nơi không thể hoàn.
Câu trả lời mới là chỗ yếu. Khi cổng thanh toán sập, 2/15 câu trả lời báo khách là tiền đã được hoàn hoặc đang được xử lý. Sáu câu khác nói là lỗi, rồi hứa sẽ thử lại, trong khi hệ thống không có bước nào làm việc đó. Sau bug trong code, một câu trả lời viết “I have issued a full refund of $65.00”: không có lần hoàn nào, sai số tiền, sai cả loại tiền.
Trace thấy, nhưng ở tầng dưới#
Lỗi nào cũng để lại một span có status ERROR, ở đúng lần gọi tool bị hỏng. Các span phía trên thì không, và như vậy là đúng. Quy ước ghi lỗi của OpenTelemetry nói lỗi đã được “thử lại hoặc xử lý” thì không nên đánh dấu cả thao tác là thất bại (recording errors). Agent đã xử lý exception bằng cách chuyển nó cho model, nên span agent và span request kết thúc mà không có lỗi.

Vì vậy dashboard request lỗi vẫn trống, và cảnh báo đặt trên span gốc không bao giờ kêu. Bạn chỉ thấy lỗi nếu nhìn vào span của tool, hoặc nếu code của bạn tự báo.
Cần cài những gì#
- Trace lần chạy agent, từng lần gọi model và từng lần gọi tool theo GenAI conventions. Bài GenAI conventions thực tế cho thấy bản instrumentation chính thức ghi được gì và để lại gì cho bạn.
- Báo lỗi tool cho error tracker một lần, ngay trong đoạn code đưa lỗi cho model. Với cách này, 15 lần hoàn tiền thất bại trong thí nghiệm gom thành một issue.
- Kiểm tra kết quả thật trong hệ thống ghi nhận, đừng tin câu trả lời. Một lần hoàn tiền mà câu trả lời nhắc tới nhưng sổ thanh toán không có mới là lỗi gây thiệt hại.
- Đếm số lần thử lại theo loại lỗi. Hai trong ba model gọi lại
lookup_orderđang hỏng thêm một lần ở cả 10 lượt chạy; bug trong code không tự hết khi thử lại. - Đừng đưa nội dung prompt và câu trả lời vào span, trừ khi bạn cần và đã kiểm tra nó đi đâu. Bài lọc PII trong error monitoring giải thích vì sao bộ lọc không thay được bước này.
Belvador ở đâu trong chuyện này#
Belvador nhận trace và log từ SDK OpenTelemetry chuẩn qua OTLP/HTTP và lưu chúng trên node của chính bạn, cạnh dữ liệu lỗi. Tổng quan OpenTelemetry nói về waterfall, attribute và event của span, cùng các runtime đã được thử. Với agent viết bằng Python, lỗi đi qua sentry-sdk chính thức với DSN của Belvador, như hướng dẫn Python mô tả. Trang OpenTelemetry tóm tắt những gì Belvador làm với trace.
Belvador không có màn hình riêng cho lần gọi LLM: span GenAI hiện như span bình thường, kèm attribute của nó. Belvador không đọc câu trả lời hay đối chiếu với sổ sách của bạn, nên bước 3 vẫn nằm trong code của bạn. Nếu agent chạy theo lịch hoặc trên serverless, bài giám sát agent serverless nói về những phần trace không thấy được.
Trong chủ đề này
- OpenTelemetry GenAI conventions thực tế: thứ gì thật sự được ghi
Andrew Babo4 phút đọc
- Trace tool call bị lỗi của agent mà không bỏ sót hay đếm trùng lỗi
Andrew Babo5 phút đọc
Bài liên quan
Mọi bài viết
Kỹ thuật
OpenTelemetry GenAI conventions thực tế: thứ gì thật sự được ghi
Mình chạy bản instrumentation OpenAI chính thức cho Python ở năm cấu hình. Mặc định nó dùng tên attribute cũ, không ghi gì cho Responses API và để span agent, tool cho bạn tự viết.
Andrew Babo4 phút đọc

Kỹ thuật
Trace tool call bị lỗi của agent mà không bỏ sót hay đếm trùng lỗi
Khi tool lỗi, agent đưa lỗi cho model và request vẫn thành công. Hãy đánh dấu span của tool, ghi exception đúng một lần, và báo lỗi từ chính handler.
Andrew Babo5 phút đọc
Đọc tiếp trong tài liệu
Xem lỗi production của chính bạn như thế này
Belvador chạy trên máy chủ Hetzner của chính bạn: lỗi, cron, uptime và trace — dữ liệu vẫn là của bạn.