Một developer trong team của tôi đã yêu cầu AI coding agent “chuyển API sang dùng controller thay vì Minimal API.” Agent đã làm — hiệu quả, toàn diện, chạm vào mọi endpoint. Nó cũng xóa response caching middleware, loại bỏ các typed HttpClient registration, và cấu trúc lại exception handling theo cách tạo ra ba regression về latency.

Tại sao? Vì agent không biết tại sao chúng tôi chọn Minimal API ngay từ đầu. Nó không biết về các yêu cầu hiệu năng đã thúc đẩy quyết định đó. Nó không biết rằng cấu hình caching “bất thường” đang bù đắp cho rate limiting tích cực của vendor API. Không có lý do tại sao, nó đã tối ưu hóa cho cái gì mà nó có thể thấy — và phá vỡ những thứ nó không thể thấy.

Đây là vấn đề ADR trong kỷ nguyên AI. Và nó có giải pháp.

Điều Gì Đã Thay Đổi: ADR Như Bộ Nhớ Của Agent

Architecture Decision Records đã là best practice trong một thập kỷ. Michael Nygard đã viết format chuẩn vào năm 2011. Lý do cho chúng luôn là: các thành viên mới trong team cần hiểu tại sao các quyết định được đưa ra, không chỉ cái gì đã được quyết định. Không có context đó, họ đảo ngược các quyết định vì những lý do có vẻ hợp lý ở local nhưng bỏ qua các ràng buộc global.

Năm 2026, thành viên mới đó thường là một AI agent.

Điểm khác biệt là tốc độ và quy mô. Một kỹ sư người đọc ADR của bạn một lần và mang kiến thức đó về phía trước. Một AI agent đọc codebase của bạn mới mẻ trên mỗi task quan trọng — hoặc quên đi cuộc trò chuyện trước đó khi context window reset. Không có tài liệu machine-readable về lý luận kiến trúc của bạn, mỗi agent task bắt đầu với trang giấy trắng.

ADR bây giờ là cơ chế mà qua đó các quyết định kiến trúc của bạn tồn tại qua các tương tác agent. Nếu lý luận không được viết ra theo định dạng agent có thể tìm và phân tích, agent sẽ suy luận nó từ code — và suy luận từ code cho agent biết cái gì, không bao giờ là tại sao.

Những Gì Agent Thường Nhầm Lẫn (và ADR Khắc Phục)

Có ba loại kiến thức kiến trúc mà agent luôn sai khi thiếu tài liệu rõ ràng:

Quyết định dựa trên ràng buộc: “Chúng tôi dùng X vì vendor Y chỉ hỗ trợ X” hoặc “Chúng tôi tránh Z vì yêu cầu compliance.” Code cho thấy X được sử dụng; nó không cho thấy Z đã bị loại bỏ một cách có ý thức.

Quyết định đánh đổi: “Chúng tôi chọn approach đơn giản hơn biết rằng nó có chi phí hiệu năng 15% vì maintainability được ưu tiên cao hơn.” Agent thấy approach đơn giản hơn và tối ưu hóa nó đi, không biết về sự đánh đổi có chủ ý.

Quyết định theo thời gian: “Chúng tôi sẽ migrate cái này sang pattern mới sau Q3 khi việc migration vendor hoàn tất.” Agent thấy code legacy và hiện đại hóa nó vào thời điểm sai, theo thứ tự sai.

ADR tốt làm cho cả ba điều này hiện rõ.

Viết ADR Mà Agent Có Thể Đọc

Format ADR chuẩn (Title, Status, Context, Decision, Consequences) là bước khởi đầu tốt. ADR agent-readable thêm hai thứ: ràng buộc tường minh và phần “điều gì sẽ làm AI nhầm lẫn?”

ADR chuẩn (tối giản, tối ưu cho người):

# Dùng Minimal API thay vì Controller

## Status
Accepted

## Context
Chúng tôi cần xây dựng một internal API throughput cao.

## Decision
Chúng tôi chọn ASP.NET Core Minimal API.

## Consequences
- Khởi động nhanh hơn
- Ít boilerplate hơn
- Một số tính năng cần cấu hình thủ công nhiều hơn

ADR agent-readable (tường minh, nhận biết ràng buộc):

# ADR-007: Dùng Minimal API thay vì Controller cho OrderProcessing Service

## Status
Accepted (2025-11-14) — Không đảo ngược nếu chưa xem xét ADR-012

## Context
Service OrderProcessing xử lý 2.000-4.000 request/phút với P99 latency SLA 50ms.
Controller đã được đánh giá và từ chối vì:
- Thời gian khởi động với MVC pipeline đầy đủ thêm ~180ms (không chấp nhận được
  cho Lambda cold-start budget của chúng tôi)
- Filter pipeline overhead có thể đo lường ở volume request này
- Team đánh giá điều này trong 2 sprint; xem benchmark trong /docs/benchmarks/

## Decision
ASP.NET Core Minimal API cho tất cả endpoint OrderProcessing.

## Ràng Buộc Tường Minh (KHÔNG thay đổi mà không cập nhật ADR này)
- ResponseCaching middleware trong Program.cs KHÔNG phải dư thừa —
  nó bù đắp cho rate limit 100 req/phút của VendorX trên product lookup.
  Xóa nó sẽ gây lỗi 429 dưới load bình thường.
- Thứ tự đăng ký TypedHttpClient có vấn đề — xem comment trong
  ServiceExtensions.cs giải thích dependency chain.
- Chúng tôi CỐ TÌNH không dùng output caching trên endpoint POST /orders
  vì việc gửi order phải idempotent, không cached.

## Điều Gì Sẽ Làm AI Agent Nhầm Lẫn
- Class `LegacyAdapter` không phải code legacy cần xóa — nó bridge
  vendor SDK cũ mà chúng tôi không thể upgrade cho đến Q1 2026.
- Việc xử lý lỗi không nhất quán trong các endpoint `/webhook` là có chủ ý —
  chúng tôi trả về 200 trên tất cả webhook call theo yêu cầu PCI-DSS 6.4.2.
- Code được comment trong OrderValidator.cs là feature gate tương lai,
  không phải dead code. Xem ADR-015.

## Consequences
- Tích cực: P99 latency ổn định 28-35ms trong load test
- Tích cực: Cold-start dưới 800ms trên Lambda
- Tiêu cực: Một số authentication middleware cần đăng ký thủ công
- Tiêu cực: Cấu hình Swagger phức tạp hơn
- Đánh đổi: Chấp nhận code readability thấp hơn cho yêu cầu hiệu năng

## Quyết Định Liên Quan
- ADR-012: API versioning strategy (đọc trước khi thay đổi endpoint route)
- ADR-015: Feature flag implementation (giải thích validator được comment)

Sự khác biệt là đáng kể. ADR thứ hai nói với agent: đây là những thứ bạn có thể thay đổi một cách hợp lý, và đây chính xác là lý do tại sao bạn không nên. Các phần “Ràng Buộc Tường Minh” và “Điều Gì Sẽ Làm AI Agent Nhầm Lẫn” là những bổ sung mới quan trọng nhất.

Triển Khai: Ở Đâu và Như Thế Nào

Cấu trúc file:

docs/
└── decisions/
    ├── README.md          (index của tất cả ADR)
    ├── ADR-001-database-choice.md
    ├── ADR-007-minimal-api.md
    └── ADR-012-versioning.md

Quy ước đặt tên: ADR-NNN-short-description.md. Tiền tố số cho phép tham chiếu và sắp xếp dễ dàng. Mô tả ngắn cho phép grep và semantic search.

README index có vấn đề: agent thường bắt đầu với danh sách thư mục trước khi đi sâu vào file. Index rõ ràng giúp agent điều hướng đến ADR liên quan trước khi chỉnh sửa code mà nó quản lý.

# Architecture Decision Records

## Quick Reference
| ADR | Tiêu đề | Trạng thái | Phạm vi |
|-----|---------|------------|---------|
| 007 | Minimal API thay vì Controller | Active | src/OrderProcessing/ |
| 012 | API Versioning Strategy | Active | Tất cả public endpoint |
| 015 | Feature Flag Implementation | Active | Tất cả feature gate |

Liên kết ADR với code: thêm comment ngắn trong file liên quan trỏ đến ADR. Đây là cách đáng tin cậy nhất để đảm bảo agent gặp ADR liên quan khi nó đang xem code đó:

// Kiến trúc: Minimal API theo thiết kế. Xem docs/decisions/ADR-007-minimal-api.md
// trước khi sửa đổi pattern đăng ký này.
var builder = WebApplication.CreateBuilder(args);

Công Cụ

adr-tools là CLI tham chiếu cho quản lý ADR:

npm install -g adr-tools
adr init docs/decisions
adr new "Dùng Minimal API thay vì Controller"

Nó tạo file với naming pattern đúng và cập nhật README.md index tự động.

GitHub ADR template: thêm .github/DECISION_TEMPLATE.md với các phần mở rộng của tổ chức bạn (bao gồm “Ràng Buộc Tường Minh” và “Điều Gì Sẽ Làm AI Agent Nhầm Lẫn”) để ADR mới có cấu trúc đúng tự động.

Tích hợp ADR với agent context: trong thiết lập agent của bạn (Claude Code CLAUDE.md hoặc tương tự), thêm:

## Quyết Định Kiến Trúc
Trước khi sửa đổi bất kỳ service nào, hãy kiểm tra docs/decisions/ để tìm ADR liên quan.
ADR với phần "Ràng Buộc Tường Minh" ghi lại những thứ bạn KHÔNG ĐƯỢC
thay đổi mà không có hướng dẫn rõ ràng.

Điều này hướng dẫn agent tham khảo thư mục ADR như một phần của workflow chuẩn, không chỉ khi nó tình cờ gặp một comment.

Lợi Nhuận Trên Đầu Tư

Viết ADR tốt mất ba mươi phút cho mỗi quyết định. Sửa một production incident do agent không biết tại sao thứ gì đó lại như vậy mất… nhiều thời gian hơn đáng kể.

Phép tính thay đổi trong kỷ nguyên AI vì tần suất của các sự kiện “người tham gia mới gặp quyết định cũ” tăng mạnh. Một team người tám người có tám người có thể gặp một quyết định cũ. Một AI agent trong team đó có thể gặp nó năm mươi lần mỗi ngày trên các task khác nhau. Mỗi lần gặp mà không có context là một rủi ro.

ADR được viết cho AI agent không khác về bản chất so với ADR được viết cho người. Chúng chỉ rõ ràng hơn về ràng buộc, cụ thể hơn về những gì không thay đổi, và trung thực hơn về những gì có thể trông sai nhưng không phải vậy. Người thường suy luận những điều đó từ context xung quanh. Agent thường không.

ADR của bạn là bộ nhớ tổ chức của agent. Hãy viết chúng theo đó.


Công cụ được tham chiếu: adr-tools, MADR format, Claude Code context engineering.

Xuất nội dung

Bình luận