Khi production báo lỗi lúc 2 giờ sáng, thời gian quý giá nhất không phải lúc viết fix — mà là lúc tìm ra chính xác dòng code nào gây lỗi giữa stack trace dài, release notes, và một codebase vài trăm nghìn dòng. Kết hợp Sentry MCP server (nguồn error, stack trace, breadcrumb) với GitHub MCP server (nguồn code, blame, PR) cho AI agent khả năng tự nối hai đầu này lại: đọc lỗi thật từ Sentry, định vị chính xác đoạn code trong GitHub, sinh fix có targeted (đúng phạm vi, không sửa lan man), và mở PR có ghi chú root cause đầy đủ cho reviewer. Bài này đi qua toàn bộ chuỗi đó.
Tổng Quan Workflow: Từ Sentry Alert Đến Bug Fix Lên Production Qua AI
Luồng dữ liệu ở workflow này có một đặc điểm khác các cặp MCP khác: dữ liệu từ Sentry (stack trace, breadcrumb, tags) mang tính chẩn đoán — nó cho biết "lỗi gì, ở đâu, khi nào, ảnh hưởng release nào" nhưng không cho biết "sửa như thế nào". Việc suy luận từ triệu chứng (stack trace) sang nguyên nhân gốc (root cause trong code) là phần đòi hỏi agent phải kết hợp cả hai nguồn thông tin, không phải chỉ đọc tuần tự.
Sentry MCP server GitHub MCP server
────────────────── ──────────────────
Issue CHECKOUT-42 ──read──► agent đọc code tại đúng
"TypeError: Cannot read file:line từ stack trace
property 'total' of null"
stack trace: checkout.ts:87
release: v2.4.1
affected users: 340
first seen: 2 giờ trước
agent dùng git blame/history
để tìm commit nào đưa lỗi vào
(thường khớp với v2.4.1)
agent sinh fix có targeted
◄─write── branch fix/checkout-42-npe
agent mở PR
◄─write── PR có link Sentry issue +
giải thích root cause
Comment Sentry "linked PR #501" ◄──── (cập nhật lại Sentry issue)
Khác biệt lớn nhất so với workflow GitHub + Jira: ở đây thứ tự đọc dữ liệu quan trọng hơn — bạn phải đọc đủ context Sentry (không chỉ dòng lỗi cuối, mà cả breadcrumb dẫn tới lỗi và tags như release version, environment) trước khi để agent đọc code, nếu không agent dễ sửa nhầm chỗ (fix triệu chứng ở lớp UI trong khi lỗi gốc nằm ở lớp service phía dưới).
Mẹo: Trước khi giao agent tự sửa, luôn yêu cầu nó trình bày lại root cause bằng lời của chính nó (không copy nguyên văn error message) trước khi viết code fix — nếu agent không thể diễn giải rõ "vì sao" lỗi xảy ra, khả năng cao nó cũng chưa hiểu đúng, và fix sẽ chỉ che triệu chứng chứ không giải quyết gốc.
Bước 1: Lấy Thông Tin Lỗi, Stack Trace Và Release Bị Ảnh Hưởng Từ Sentry
Bắt đầu bằng việc lấy đầy đủ chi tiết issue, không chỉ title:
Lấy chi tiết Sentry issue CHECKOUT-42 trong project checkout-service.
Cần đầy đủ:
- Toàn bộ stack trace (không chỉ dòng đầu tiên)
- Breadcrumb (các bước xảy ra trước khi lỗi xuất hiện)
- Tags: release version, environment, browser/OS nếu có
- Số lượng user bị ảnh hưởng và thời điểm first seen / last seen
- Nếu có, lấy thêm 2-3 event mẫu (không chỉ 1) để so sánh có
pattern chung không
Kết quả trả về (rút gọn) thường có dạng:
{
"issueId": "CHECKOUT-42",
"title": "TypeError: Cannot read property 'total' of null",
"culprit": "checkout.ts in calculateOrderTotal",
"stacktrace": [
{ "filename": "src/checkout.ts", "lineno": 87, "function": "calculateOrderTotal" },
{ "filename": "src/cart/useCart.ts", "lineno": 34, "function": "getCartSummary" }
],
"tags": { "release": "v2.4.1", "environment": "production" },
"userCount": 340,
"firstSeen": "2026-08-22T00:14:00Z",
"breadcrumbs": [
{ "message": "User removed last item from cart" },
{ "message": "Navigated to /checkout" },
{ "message": "calculateOrderTotal called with cart=null" }
]
}
Breadcrumb ở đây chính là mảnh ghép quan trọng nhất — nó cho biết chuỗi hành động thật của user: xoá hết item trong cart → điều hướng sang trang checkout → hàm tính tổng bị gọi với cart = null. Nếu chỉ đọc dòng lỗi cuối (Cannot read property 'total' of null), agent dễ chỉ thêm ?. (optional chaining) một cách máy móc mà không hiểu tại sao cart lại null ở luồng này — dẫn tới fix kiểu che triệu chứng, lỗi tương tự sẽ tái xuất ở nơi khác gọi cùng hàm.
Với lỗi liên quan tới một release cụ thể (release: v2.4.1), luôn yêu cầu agent kiểm tra thêm: lỗi này có mới xuất hiện từ v2.4.1, hay đã tồn tại từ trước nhưng chỉ mới tăng tần suất? Sentry MCP server thường có tool xem lịch sử event theo thời gian — nếu first seen khớp đúng ngày release v2.4.1, khả năng cao đây là regression (lỗi hồi quy) do chính release đó gây ra, giúp agent khoanh vùng nhanh hơn trong bước tiếp theo.
Mẹo: Luôn lấy breadcrumb đầy đủ, không chỉ error message cuối cùng. Breadcrumb là dữ liệu "hành trình user" hiếm khi có trong bug report do người viết tay (họ thường chỉ note lại lỗi họ thấy, không note đủ các bước dẫn tới đó) — đây là lợi thế thực sự của việc dùng Sentry MCP server so với chỉ đọc bug report text thông thường.
Bước 2: Định Vị Bug Trong GitHub Và Sinh Fix Có Mục Tiêu Rõ Ràng
Có stack trace rồi, bước tiếp là dùng GitHub MCP server để đọc đúng đoạn code, đối chiếu với lịch sử commit để tìm commit gây lỗi (nếu là regression):
Đọc file src/checkout.ts từ dòng 70 đến 100 trong repo
acme/checkout-service, tag v2.4.1 (khớp với release trong Sentry issue).
Đọc thêm src/cart/useCart.ts dòng 25-45 (frame thứ 2 trong stack trace).
Nếu lỗi khớp với breadcrumb "User removed last item from cart", chạy
git log -p --follow trên đoạn code tính cartSummary để tìm commit nào
gần đây có thay đổi logic xử lý cart rỗng.
Sau khi đọc, agent thường tìm ra nguyên nhân dạng: hàm getCartSummary() trả về null khi cart rỗng (thay vì trả object với total: 0), và một commit gần đây đổi hành vi này từ "luôn trả object" sang "trả null khi rỗng" nhằm mục đích khác (có thể để tối ưu một luồng khác), vô tình phá vỡ giả định ở calculateOrderTotal.
Fix "targeted" (đúng phạm vi) nghĩa là sửa ở đúng lớp gây lỗi — trong trường hợp này có hai lựa chọn, và agent nên trình bày cả hai để bạn quyết định thay vì tự chọn:
Lựa chọn A (sửa tại nguồn — khuyến nghị nếu không ảnh hưởng nơi khác):
getCartSummary() luôn trả { items: [], total: 0 } khi cart rỗng,
không trả null. Cần kiểm tra toàn bộ nơi gọi getCartSummary()
xem có nơi nào đang dựa vào việc nó trả null không.
Lựa chọn B (guard tại điểm dùng — an toàn hơn khi không chắc các
điểm gọi khác):
calculateOrderTotal() thêm early return khi cartSummary null hoặc
undefined, trả về total mặc định 0 và log warning để theo dõi
tần suất xảy ra case này.
Yêu cầu agent tìm tất cả nơi gọi getCartSummary() trong codebase trước khi chọn lựa chọn A — đây chính là lý do cần GitHub MCP server thay vì chỉ đọc 1 file: khả năng search toàn repo (search_code hoặc tương đương) để đánh giá tác động lan tỏa của fix, tránh sửa xong bug này lại tạo ra bug khác ở một call site không ngờ tới.
Mẹo: Với bug xuất phát từ một hàm dùng chung (shared utility), luôn yêu cầu agent search toàn bộ call site trước khi quyết định sửa tại nguồn hay guard tại điểm dùng. Một fix "đúng về lý thuyết" tại nguồn có thể phá vỡ 2-3 nơi gọi khác đang (vô tình) dựa vào hành vi cũ — điều mà stack trace của riêng issue này không thể cho bạn biết.
Bước 3: Mở GitHub PR Gắn Liên Kết Với Sentry Issue Kèm Ghi Chú Root Cause
Mở PR với description không chỉ mô tả "đã sửa gì" mà quan trọng hơn là "vì sao lỗi xảy ra" — đây chính là phần giúp reviewer duyệt nhanh và giúp người xử lý case tương tự sau này (root cause note là tài liệu tra cứu lâu dài, không chỉ cho lần fix này):
Tạo branch fix/checkout-42-cart-null-guard từ main.
Commit fix (Lựa chọn B — guard tại điểm dùng, vì có 3 call site
khác đang dựa vào getCartSummary() có thể trả null).
Push branch, mở PR vào main với:
Title: "Fix: TypeError khi tính order total với cart rỗng (CHECKOUT-42)"
Description:
## Root cause
getCartSummary() trả null khi cart rỗng. calculateOrderTotal()
không handle case null này, gây TypeError khi user xoá hết item
trong cart rồi vào trang checkout. Regression từ commit <sha>
trong release v2.4.1.
## Fix
Thêm guard tại calculateOrderTotal() — trả total = 0 khi cartSummary
null/undefined, log warning để theo dõi tần suất.
Không sửa tại getCartSummary() vì có 3 call site khác (liệt kê ở
đây) đang dựa vào hành vi hiện tại — cần refactor riêng, ngoài
phạm vi fix khẩn cấp này.
## Liên kết
Sentry issue: https://acme.sentry.io/issues/CHECKOUT-42
Ảnh hưởng: 340 user, release v2.4.1
## Test
Đã thêm unit test: cart rỗng → checkout không throw, total = 0.
Sau khi PR được tạo, cập nhật ngược lại Sentry issue để mọi người theo dõi lỗi trên Sentry biết đã có fix đang chờ merge — đây là bước "khép vòng" quan trọng, tránh tình trạng 2 người cùng nhận issue và cùng bắt tay sửa trùng lặp:
Thêm comment vào Sentry issue CHECKOUT-42:
"Đã xác định root cause và mở PR #501 (acme/checkout-service).
Fix dạng guard tại calculateOrderTotal(), không thay đổi hành vi
getCartSummary(). Chờ review."
Đánh dấu issue trạng thái "In Progress" nếu Sentry project có
custom workflow status.
Ghi chú riêng cho case regression rõ ràng (first seen khớp ngày release): luôn nêu commit/SHA gây lỗi trong PR description như ví dụ trên. Thông tin này giúp phân biệt rõ đây là "sửa lỗi mới phát sinh do thay đổi gần đây" — mức độ ưu tiên và cách review sẽ khác với bug tồn tại lâu năm mới phát hiện.
Mẹo: Đừng để PR description chỉ nói "đã sửa lỗi X" — luôn buộc agent viết rõ phần "Root cause" tách biệt khỏi phần "Fix", kèm lý do tại sao chọn cách sửa này thay vì cách khác (như phần "Không sửa tại... vì..." trong ví dụ). Root cause note viết tốt là tài sản tra cứu về sau — 6 tháng sau có bug tương tự, người đọc lại PR này sẽ hiểu ngay bối cảnh mà không cần đọc lại Sentry issue gốc.
Vài Lưu Ý Thêm
- Luôn lấy đủ breadcrumb và nhiều event mẫu từ Sentry, không chỉ error message cuối — breadcrumb là dữ liệu hành trình user hiếm có trong bug report viết tay.
- Với lỗi khớp thời điểm release, luôn kiểm tra xem có phải regression từ commit cụ thể không, để phân loại đúng mức độ ưu tiên.
- Trước khi sửa tại nguồn một hàm dùng chung, luôn search toàn bộ call site để đánh giá tác động lan tỏa.
- Tách rõ "Root cause" và "Fix" trong PR description — đây là tài sản tra cứu lâu dài, không chỉ giải thích cho lần fix này.
- Luôn cập nhật ngược lại Sentry issue sau khi mở PR, để tránh trùng lặp công việc giữa nhiều người cùng xử lý một lỗi.
Mẹo: Với lỗi ảnh hưởng số lượng user lớn hoặc mức độ nghiêm trọng cao, đừng để agent tự merge PR dù nó tự tin vào fix — luôn giữ bước human review bắt buộc, đặc biệt khi agent phải chọn giữa "sửa tại nguồn" và "guard tại điểm dùng". Đây là loại quyết định ảnh hưởng kiến trúc lâu dài, không nên để hoàn toàn tự động.