Nội dung
Bài giảng 01. Mô hình mạnh không đồng nghĩa chạy việc đáng tin cậy 12,186 ký tự
English Version → | 中文版本 →
Ví dụ mã nguồn: code/ Dự án thực hành: Dự án 01. Chỉ Prompt vs. Ưu tiên Quy tắc
Bài 01. Mô hình Mạnh Không có nghĩa là Thực thi Đáng tin cậy
Bạn tự coi mình là người có kinh nghiệm trong thế giới AI — đăng ký Claude Pro, có API key GPT-4o, thuộc lòng các con số trên bảng xếp hạng SWE-bench. Một ngày nào đó bạn cuối cùng giao một dự án thực sự cho một AI agent, đầy tự tin. Kết quả? Nó thêm một tính năng nhưng làm hỏng các bài test, sửa một lỗi nhưng gây ra thêm hai lỗi khác, chạy 20 phút và tự hào tuyên bố "xong" — nhưng khi bạn nhìn vào mã nguồn, nó hoàn toàn không phải là thứ bạn yêu cầu.
Phản ứng đầu tiên của bạn? "Mô hình này không đủ tốt. Thời điểm nâng cấp." Khoan đã. Trước khi bạn mở ví, hãy cân nhắc rằng vấn đề có thể hoàn toàn không phải là mô hình.
Hãy nhìn vào một vài con số. Tính đến cuối năm 2025, các coding agent mạnh nhất trên SWE-bench Verified đạt khoảng 50-60%. Và đó là trên các tác vụ được lựa chọn cẩn thận với mô tả vấn đề rõ ràng và các bài test hiện có. Chuyển sang môi trường phát triển hàng ngày của bạn — yêu cầu mơ hồ, không có test, các quy tắc kinh doanh ẩn rải rác khắp nơi — và con số đó chỉ giảm xuống.
Nhưng đằng sau những con số này ẩn chứa một sự thật phản trực giác.
Cùng Con Ngựa, Số Phận Khác Nhau
Anthropic đã thực hiện một thí nghiệm có kiểm soát. Cùng một prompt ("xây dựng một trình tạo trò chơi retro 2D"), cùng một mô hình (Opus 4.5). Lần chạy đầu tiên: trần trụi, không có hỗ trợ — 20 phút, $9, các tính năng cốt lõi của trò chơi hoàn toàn không hoạt động. Lần chạy thứ hai: harness đầy đủ (kiến trúc ba agent: planner + generator + evaluator) — 6 giờ, $200, trò chơi có thể chơi được.
Họ không thay đổi mô hình. Opus 4.5 vẫn là Opus 4.5. Những gì thay đổi là cái yên ngựa.
Bài viết về harness engineering năm 2025 của OpenAI nói thẳng: Codex trong một kho lưu trữ được trang bị harness tốt đi từ "không đáng tin cậy" đến "đáng tin cậy." Lưu ý cách diễn đạt của họ — không phải "tốt hơn một chút," mà là một sự thay đổi về chất. Giống như một con ngựa thuần chủng: bạn có thể cưỡi nó không có yên, nhưng bạn sẽ không đi xa, không nhanh, và việc ngã ngựa không có gì là ngạc nhiên. Harness là cái yên ngựa đó — tất cả mọi thứ trong cơ sở hạ tầng kỹ thuật bên ngoài trọng số mô hình.
Agent Thực sự Bị Kẹt Ở Đâu
Vậy cụ thể điều gì đi sai?
Phổ biến nhất: bạn không bao giờ xác định rõ ràng tác vụ. Bạn nói "thêm tính năng tìm kiếm," và sự hiểu biết của agent hoàn toàn khác với của bạn — tìm kiếm cái gì? Full-text hay có cấu trúc? Phân trang? Tô sáng? Bạn không chỉ định, vì vậy agent đoán. Đoán đúng là may mắn; đoán sai tốn nhiều chi phí để sửa hơn là cụ thể hóa ngay từ đầu. Giống như đi vào nhà hàng và bảo với đầu bếp "tôi muốn cá" — liệu bạn có cá kho, cá hấp hay cá lẩu là hoàn toàn phụ thuộc vào may rủi.
Ngay cả khi bạn đã chỉ định, dự án có các quy ước kiến trúc ẩn mà agent không biết. Nhóm của bạn đã chuẩn hóa cú pháp SQLAlchemy 2.0, nhưng agent mặc định viết mã 1.x. Tất cả các API endpoint phải sử dụng xác thực OAuth 2.0, nhưng quy tắc đó chỉ tồn tại trong đầu bạn và một tin nhắn Slack từ ba tháng trước. Agent không thể nhìn thấy những điều này — không phải vì nó không muốn tuân thủ, mà là vì nó thực sự không biết những quy tắc này tồn tại.
Môi trường cũng là một cái bẫy. Dev environment không đầy đủ, thiếu dependencies, phiên bản công cụ sai. Agent đốt cháy cửa sổ ngữ cảnh quý báu vào lỗi pip install và xung đột phiên bản Node thay vì giải quyết tác vụ thực tế của bạn. Giống như thuê một thợ mộc lành nghề nhưng quên cung cấp búa, đinh hoặc bàn làm việc bằng phẳng — dù tài năng đến đâu, họ cũng không thể làm được việc.
Thậm chí còn phổ biến hơn: đơn giản là không có cách nào để xác minh. Không có test, không có lint, hoặc các lệnh xác minh không bao giờ được truyền đạt cho agent. Agent viết mã, nhìn vào nó, quyết định nó ổn, nói "xong." Giống như yêu cầu học sinh nộp bài tập mà không có đáp án — họ nghĩ họ làm đúng, nhưng khi bạn chấm điểm có hàng đống lỗi. Anthropic cũng quan sát thấy một hiện tượng thú vị: khi các agent cảm thấy ngữ cảnh đang cạn kiệt, họ vội vàng hoàn thành, bỏ qua xác minh, và chọn một giải pháp đơn giản hơn giải pháp tối ưu. Họ gọi đây là "lo lắng ngữ cảnh" — điều tương tự xảy ra khi bạn nhận ra thời gian gần hết trong bài kiểm tra và bắt đầu đoán ngẫu nhiên các câu hỏi trắc nghiệm còn lại.
Các tác vụ dài trải dài qua nhiều phiên còn tệ hơn — tất cả những phát hiện từ phiên trước đều bị mất, và mọi phiên mới phải khám phá lại cấu trúc dự án và hiểu lại cách tổ chức mã. Các agent không có trạng thái liên tục thấy tỷ lệ thất bại tăng vọt trên các tác vụ vượt quá 30 phút.
Giải thích thuật ngữ chính
Với những tình huống này, các khái niệm sau không còn chỉ là thuật ngữ nữa:
Khoảng cách Năng lực (Capability Gap) : Khoảng cách lớn giữa hiệu suất mô hình trên các điểm chuẩn và hiệu suất trên các tác vụ thực tế. Tỷ lệ vượt qua 50-60% trên SWE-bench Verified có nghĩa là gần một nửa số vấn đề thực tế không thể được giải quyết.
Harness : Mọi thứ bên ngoài mô hình — hướng dẫn, công cụ, môi trường, quản lý trạng thái, phản hồi xác minh. Nếu không phải trọng số mô hình, thì đó là harness. Đó là cái chúng ta gọi là "yên ngựa."
Lỗi Do Harness (Harness-Induced Failure) : Mô hình có đủ năng lực, nhưng môi trường thực thi có khiếm khuyết cấu trúc. Thí nghiệm có kiểm soát của Anthropic đã chứng minh điều này.
Khoảng cách Xác minh (Verification Gap) : Khoảng cách giữa sự tự tin của agent vào kết quả của nó và tính đúng đắn thực tế. Agent nói "tôi đã xong" khi chưa xong — đây là chế độ lỗi phổ biến nhất.
Vòng lặp Chẩn đoán (Diagnostic Loop) : Thực thi, quan sát lỗi, quy cho một lớp harness cụ thể, sửa lớp đó, thực thi lại. Đây là phương pháp luận cốt lõi của harness engineering.
Định nghĩa Hoàn thành (Definition of Done) : Một tập hợp các điều kiện có thể xác minh bằng máy — test qua, lint sạch, type check qua. Không có định nghĩa hoàn thành rõ ràng, agent sẽ tự bịa ra định nghĩa của mình.
Khi Sự Cố Xảy ra, Sửa Harness Trước
Nguyên tắc cốt lõi: Khi sự cố xảy ra, đừng đổi mô hình trước — kiểm tra harness. Nếu cùng một mô hình thành công trên các tác vụ tương tự, có cấu trúc tốt, hãy giả định đó là vấn đề harness. Giống như xe hơi bị hỏng — bạn không ngay lập tức nghi ngờ động cơ. Bạn kiểm tra xăng trước.
Các bước cụ thể:
Quy mọi lỗi cho một lớp cụ thể. Đừng chỉ nói "mô hình không tốt." Hãy hỏi: tác vụ có mơ hồ không? Ngữ cảnh có không đủ không? Không có phương pháp xác minh không? Ánh xạ mỗi lỗi vào một trong năm lớp phòng thủ (đặc tả tác vụ, cung cấp ngữ cảnh, môi trường thực thi, phản hồi xác minh, quản lý trạng thái). Xây dựng thói quen này, và bạn sẽ thấy "mô hình không đủ tốt" xuất hiện ngày càng ít hơn trong nhật ký của bạn.
Viết Định nghĩa Hoàn thành rõ ràng cho mỗi tác vụ. Đừng nói "thêm tính năng tìm kiếm." Hãy nói:
Tiêu chí hoàn thành:
- Endpoint GET /api/search?q=xxx mới
- Hỗ trợ phân trang, mặc định 20 mục
- Kết quả bao gồm đoạn trích được tô sáng
- Tất cả mã mới vượt qua pytest
- Type checking vượt qua (mypy --strict)
Tạo tệp AGENTS.md. Đặt nó trong thư mục gốc của repo để cho agent biết tech stack của dự án, các quy ước kiến trúc, và các lệnh xác minh. Đây là bước đầu tiên trong harness engineering và bước có ROI cao nhất bạn có thể thực hiện. Một tệp AGENTS.md có thể hiệu quả hơn việc nâng cấp lên mô hình đắt tiền hơn — tôi không nói đùa.
Xây dựng vòng lặp chẩn đoán. Đừng coi lỗi là "mô hình lại ngốc rồi." Coi chúng là tín hiệu rằng harness của bạn có khiếm khuyết. Mỗi lỗi, xác định lớp, sửa nó, không bao giờ thất bại theo cách đó nữa. Sau vài vòng, harness của bạn mạnh hơn và hiệu suất agent ổn định hơn. Giống như vá đường — mỗi ổ gà bạn lấp đầy làm cho đoạn đường tiếp theo êm hơn.
Định lượng cải tiến. Giữ một nhật ký đơn giản: mỗi tác vụ có thành công hay thất bại, và lớp nào gây ra lỗi. Sau vài vòng, bạn sẽ thấy lớp nào là điểm nghẽn cổ chai — tập trung năng lượng của bạn ở đó.
Thí nghiệm Triệu Dòng Mã
OpenAI đã thực hiện một thí nghiệm táo bạo vào năm 2025: sử dụng Codex để xây dựng một sản phẩm nội bộ hoàn chỉnh từ một kho git trống. Năm tháng sau, kho có khoảng một triệu dòng mã — logic ứng dụng, cơ sở hạ tầng, công cụ, tài liệu, công cụ dev nội bộ — tất cả được tạo bởi agent. Ba kỹ sư điều khiển Codex, mở và hợp nhất khoảng 1,500 PR. Trung bình 3.5 PR mỗi người mỗi ngày.
Ràng buộc chính: con người không bao giờ viết mã trực tiếp. Đây không phải là trò gimmick — nó được thiết kế để buộc nhóm phải tìm ra điều gì thay đổi khi công việc chính của kỹ sư không còn là viết mã, mà là thiết kế môi trường, diễn đạt ý định, và xây dựng các vòng phản hồi.
Tiến độ ban đầu chậm hơn dự kiến. Không phải vì Codex không đủ năng lực, mà vì môi trường chưa đủ hoàn chỉnh — agent thiếu các công cụ, trừu tượng và cấu trúc nội bộ cần thiết để tiến lên các mục tiêu cấp cao. Công việc của các kỹ sư trở thành: chia nhỏ các mục tiêu lớn thành các khối xây dựng nhỏ (thiết kế, mã hóa, đánh giá, kiểm tra), để agent lắp ráp chúng, rồi sử dụng những khối đó để mở khóa các tác vụ phức tạp hơn. Khi có sự cố, câu trả lời gần như không bao giờ là "cố gắng hơn" — mà là "agent đang thiếu năng lực gì, và làm thế nào để chúng ta làm cho nó có thể hiểu và thực thi được?"
Thí nghiệm này trực tiếp chứng minh luận điểm cốt lõi của bài giảng này: cùng một mô hình tạo ra kết quả về cơ bản khác nhau trong môi trường trần trụi so với môi trường có harness đầy đủ. Mô hình không thay đổi. Môi trường thay đổi.
Nguồn: OpenAI: Harness engineering: leveraging Codex in an agent-first world
Một Ví dụ Thực tế Hơn
Một nhóm sử dụng Claude Sonnet để thêm một API endpoint mới vào ứng dụng web Python cỡ trung (FastAPI + PostgreSQL + Redis, ~15,000 dòng mã).
Ban đầu họ chỉ đưa ra một câu: "thêm các endpoint tùy chọn người dùng dưới /api/v2/users ." Kết quả? Agent dành 40% cửa sổ ngữ cảnh để khám phá cấu trúc repo, tạo ra mã trông có vẻ hợp lý nhưng không theo các mẫu xử lý lỗi của dự án, sử dụng cú pháp SQLAlchemy cũ, và tuyên bố hoàn thành trong khi endpoint có lỗi runtime. Phiên tiếp theo phải làm lại toàn bộ công việc khám phá.
Sau đó họ thêm AGENTS.md (mô tả kiến trúc dự án và phiên bản tech stack), các lệnh xác minh rõ ràng ( pytest tests/api/v2/ && python -m mypy src/ ), và các bản ghi quyết định kiến trúc. Cùng một mô hình đã thành công trong cả ba lần chạy độc lập, với hiệu quả ngữ cảnh tốt hơn khoảng 60%.
Họ không thay đổi mô hình. Họ thay đổi harness.
Những Điểm chính cần Nhớ
Năng lực mô hình và độ tin cậy thực thi là hai điều khác nhau. Một con ngựa thuần chủng vẫn cần một cái yên tốt.
Khi sự cố xảy ra, kiểm tra harness trước, rồi mới đến mô hình. Đổi mô hình là lựa chọn tốn kém nhất — và thường thậm chí không phải là vấn đề mô hình.
Mỗi lỗi là một tín hiệu: harness của bạn có khiếm khuyết cấu trúc. Tìm nó, sửa nó.
Năm lớp phòng thủ: đặc tả tác vụ, cung cấp ngữ cảnh, môi trường thực thi, phản hồi xác minh, quản lý trạng thái. Kiểm tra chúng có hệ thống, như bác sĩ loại trừ các nguyên nhân phổ biến nhất trước.
Một tệp AGENTS.md có thể hiệu quả hơn việc nâng cấp lên mô hình đắt tiền hơn. Thực sự vậy.
Đọc thêm
OpenAI: Harness Engineering — Leveraging Codex in an Agent-First World
Anthropic: Effective Harnesses for Long-Running Agents
HumanLayer: Skill Issue — Harness Engineering for Coding Agents
SWE-bench Leaderboard
Thoughtworks Technology Radar: Harness Engineering
Bài tập
Thí nghiệm so sánh : Chọn một codebase bạn biết rõ và một tác vụ sửa đổi không tầm thường. Đầu tiên, chạy agent mà không có hỗ trợ harness và ghi lại các lỗi. Sau đó thêm AGENTS.md với các lệnh xác minh rõ ràng và chạy lại với cùng agent. So sánh kết quả, quy mỗi lỗi vào một trong năm lớp phòng thủ.
Đo lường khoảng cách xác minh : Chọn 5 tác vụ lập trình. Sau mỗi tác vụ, ghi lại xem agent có tuyên bố hoàn thành không, sau đó xác minh tính đúng đắn thực tế bằng các bài test độc lập. Tính tỷ lệ lần agent tuyên bố xong khi thực tế chưa xong — đó là khoảng cách xác minh của bạn. Sau đó suy nghĩ: những lệnh xác minh nào sẽ giảm tỷ lệ này?
Thực hành vòng lặp chẩn đoán : Tìm một tác vụ mà agent liên tục thất bại trong dự án của bạn. Chạy một lần, ghi lại lỗi. Quy nó cho một trong năm lớp. Sửa lớp đó. Chạy lại. Lặp lại ba đến năm vòng, ghi lại cải tiến mỗi lần.
Bài giảng 02. Harness thực sự là gì 9,526 ký tự
Bài giảng này cho bạn một định nghĩa harness chính xác, có thể hành động được. Không phải sự trừu tượng học thuật, mà là một khung bạn có thể sử dụng ngay hôm nay: một harness bao gồm năm hệ thống phụ, mỗi hệ thống có trách nhiệm và tiêu chí đánh giá rõ ràng.
Bắt đầu Bằng một Phép loại suy
Hãy tưởng tượng bạn là một kỹ sư mới được tuyển, được thả vào một dự án không có tài liệu. Không có README, không có chú thích trong mã, không ai cho bạn biết cách chạy test, cấu hình CI bị chôn vùi đâu đó. Bạn có thể viết mã tốt không? Có thể — nếu bạn đủ thông minh và kiên nhẫn. Nhưng bạn sẽ dành rất nhiều thời gian để "tìm hiểu dự án này là về cái gì" thay vì "giải quyết vấn đề."
Một AI agent đối mặt với chính xác tình huống tương tự. Và còn tệ hơn — ít nhất bạn có thể hỏi đồng nghiệp. Agent chỉ có thể nhìn thấy các tệp bạn đặt trước mặt nó và các lệnh nó có thể thực thi. Nó không thể vỗ vai ai đó và hỏi "này, phiên bản ORM nào dự án này sử dụng vậy?"
OpenAI đóng khung nguyên tắc cốt lõi là "repo LÀ spec" — tất cả ngữ cảnh cần thiết phải có trong kho lưu trữ, được truyền qua các tệp hướng dẫn có cấu trúc, lệnh xác minh rõ ràng và tổ chức thư mục rõ ràng. Tài liệu về agent chạy lâu của Anthropic nhấn mạnh tính liên tục của trạng thái, các đường phục hồi rõ ràng và theo dõi tiến độ có cấu trúc. Hai công ty tập trung vào các khía cạnh khác nhau, nhưng họ đang nói cùng một điều: tất cả mọi thứ trong cơ sở hạ tầng kỹ thuật bên ngoài mô hình xác định mức độ năng lực của mô hình thực sự được hiện thực hóa bao nhiêu.
Nhìn vào một số công cụ bạn đã biết:
Claude Code thể hiện tư duy harness. Nó đọc CLAUDE.md từ repo của bạn (kệ công thức), có thể chạy lệnh shell (giá dao), thực thi trong môi trường cục bộ của bạn (bếp), duy trì lịch sử phiên (bàn chuẩn bị), và có thể chạy test và xem kết quả (cửa sổ kiểm tra chất lượng). Nhưng nếu bạn không nói cho nó biết cách chạy test, cửa sổ kiểm tra chất lượng bị hỏng — không ai biết liệu món ăn đã chín chưa.
Cursor theo logic tương tự. Tệp .cursorrules của nó là kệ công thức, terminal là giá dao, nó đọc cấu trúc dự án và cấu hình lint cho bếp. Nhưng quản lý trạng thái của Cursor tương đối yếu — đóng IDE và mở lại, ngữ cảnh trước đó biến mất.
Codex (coding agent của OpenAI) sử dụng git worktrees để cô lập môi trường runtime của mỗi tác vụ, kết hợp với ngăn xếp quan sát cục bộ (logs, metrics, traces), vì vậy mỗi thay đổi được xác minh trong môi trường độc lập. Trong các repo có AGENTS.md và lệnh xác minh rõ ràng, nó hoạt động tốt hơn nhiều so với các repo "trần trụi".
AutoGPT là câu chuyện cảnh báo — thiếu quản lý trạng thái có cấu trúc dẫn đến tích lũy ngữ cảnh trong các tác vụ dài, và thiếu cơ chế phản hồi chính xác khiến agent lặp vòng. Nhiều người nói AutoGPT "không hoạt động," nhưng thực ra là harness của AutoGPT không hoạt động — đưa cho đầu bếp một cái bếp hỏng và ngay cả nguyên liệu tốt nhất cũng không tạo ra bữa ăn.
Các Khái niệm Cốt lõi
Harness là gì : Mọi thứ trong cơ sở hạ tầng kỹ thuật bên ngoài trọng số mô hình. OpenAI chắt lọc công việc cốt lõi của kỹ sư thành ba thứ: thiết kế môi trường, diễn đạt ý định, và xây dựng vòng phản hồi. Anthropic gọi Claude Agent SDK của họ là "harness agent đa năng."
Repo là nguồn sự thật duy nhất : Bất cứ thứ gì agent không thể nhìn thấy, theo mọi nghĩa thực tế, không tồn tại. OpenAI coi repo là "hệ thống ghi chép" — tất cả ngữ cảnh cần thiết phải sống ở đó, qua các tệp có cấu trúc và tổ chức thư mục rõ ràng.
Đưa bản đồ, không phải cẩm nang : Kinh nghiệm của OpenAI — AGENTS.md nên là một trang thư mục, không phải bách khoa toàn thư. Khoảng 100 dòng là đủ. Nếu không vừa, chia vào thư mục docs/ và để agent đọc theo yêu cầu.
Ràng buộc, không vi quản lý : Một harness tốt sử dụng các quy tắc có thể thực thi để ràng buộc agent, thay vì liệt kê hướng dẫn từng cái một. OpenAI nói "thực thi các bất biến, không vi quản lý triển khai"; Anthropic phát hiện rằng các agent tự tin khen ngợi công việc của chính mình, và giải pháp là tách "người làm việc" khỏi "người kiểm tra công việc."
Xóa từng thành phần một : Để định lượng giá trị của từng thành phần harness, hãy xóa chúng từng cái một và xem cái nào bị xóa gây ra giảm hiệu suất lớn nhất. Anthropic đã sử dụng phương pháp này và phát hiện ra rằng khi các mô hình trở nên mạnh hơn, một số thành phần không còn quan trọng — nhưng các thành phần mới luôn xuất hiện.
Mô hình Harness Năm Hệ thống Phụ
Trở lại phép loại suy nhà bếp. Một nhà bếp hoàn chỉnh có năm khu vực chức năng, và một harness có năm hệ thống phụ:
Hệ thống phụ Hướng dẫn (kệ công thức) : Tạo AGENTS.md (hoặc CLAUDE.md ) chứa tổng quan và mục đích dự án (một câu), tech stack và phiên bản (Python 3.11, FastAPI 0.100+, PostgreSQL 15), lệnh chạy đầu tiên ( make setup , make test ), các ràng buộc cứng không thể thương lượng ("Tất cả API phải sử dụng OAuth 2.0"), và các liên kết đến tài liệu chi tiết hơn.
Hệ thống phụ Công cụ (giá dao) : Đảm bảo agent có đủ quyền truy cập công cụ. Đừng vô hiệu hóa shell vì "bảo mật" — nếu agent thậm chí không thể chạy pip install , làm sao nó được cho là hoạt động? Nhưng cũng đừng mở tất cả — tuân theo nguyên tắc ít đặc quyền nhất.
Hệ thống phụ Môi trường (bếp) : Làm cho trạng thái môi trường tự mô tả. Sử dụng pyproject.toml hoặc package.json để khóa dependencies, .nvmrc hoặc .python-version cho các phiên bản runtime, Docker hoặc devcontainers để tái tạo.
Hệ thống phụ Trạng thái (bàn chuẩn bị) : Các tác vụ dài cần theo dõi tiến độ. Sử dụng tệp PROGRESS.md đơn giản ghi lại: những gì đã xong, những gì đang tiến hành, những gì bị chặn. Cập nhật trước khi mỗi phiên kết thúc, đọc khi phiên tiếp theo bắt đầu.
Hệ thống phụ Phản hồi (cửa sổ kiểm tra chất lượng) : Đây là hệ thống phụ có ROI cao nhất. Liệt kê rõ ràng các lệnh xác minh trong AGENTS.md :
Lệnh xác minh:
- Test: pytest tests/ -x
- Type check: mypy src/ --strict
- Lint: ruff check src/
- Xác minh đầy đủ: make check (bao gồm tất cả những trên)
Thiếu bất kỳ hệ thống phụ nào cũng giống như thiếu một khu vực chức năng trong nhà bếp — bạn vẫn có thể nấu ăn, nhưng luôn gượng gạo.
Chẩn đoán chất lượng harness : Sử dụng "kiểm soát mô hình đẳng áp." Giữ nguyên mô hình, xóa từng hệ thống phụ một, đo xem cái nào bị xóa gây ra giảm hiệu suất lớn nhất. Đó là điểm nghẽn cổ chai của bạn — tập trung nỗ lực ở đó. Giống như tìm điểm nghẽn cổ chai trong nhà bếp: lấy kệ công thức đi và xem mọi thứ chậm lại bao nhiêu, tắt bếp và xem tác động.
Câu chuyện Thực tế của Một Nhóm
Một nhóm sử dụng GPT-4o trên ứng dụng frontend TypeScript + React (~20,000 dòng mã). Họ trải qua bốn giai đoạn — về cơ bản là thêm thiết bị nhà bếp từng cái một:
Giai đoạn 1 — Nhà bếp trống : Chỉ có mô tả dự án cơ bản trong README. 1 trong 5 lần chạy thành công (20%). Lỗi chính: chọn sai package manager (npm vs yarn), không tuân theo quy ước đặt tên component, không thể chạy test.
Giai đoạn 2 — Kệ công thức được cài đặt : Thêm AGENTS.md với phiên bản tech stack, quy ước đặt tên, các quyết định kiến trúc chính. Tỷ lệ thành công tăng lên 60%. Các lỗi còn lại chủ yếu là vấn đề môi trường và thiếu xác minh.
Giai đoạn 3 — Cửa sổ kiểm tra chất lượng được mở : Liệt kê các lệnh xác minh trong AGENTS.md : yarn test && yarn lint && yarn build . Tỷ lệ thành công tăng lên 80%.
Giai đoạn 4 — Bàn chuẩn bị sẵn sàng : Giới thiệu các mẫu tệp tiến độ nơi các agent ghi lại công việc đã hoàn thành và chưa hoàn thành mỗi lần chạy. Tỷ lệ thành công ổn định ở 80-100%.
Bốn lần lặp, mô hình hoàn toàn không thay đổi, tỷ lệ thành công từ 20% lên gần 100%. Đó là sức mạnh của harness engineering. Bạn không mua nguyên liệu đắt tiền hơn — bạn chỉ tổ chức lại nhà bếp đúng cách.
Những Điểm chính cần Nhớ
Harness = Hướng dẫn + Công cụ + Môi trường + Trạng thái + Phản hồi. Năm hệ thống phụ, như năm khu vực chức năng của nhà bếp — tất cả đều cần thiết.
Nếu không phải trọng số mô hình, thì đó là harness. Harness của bạn xác định mức độ năng lực mô hình được hiện thực hóa bao nhiêu.
Trong số năm hệ thống phụ, hệ thống phụ phản hồi thường có đầu tư thấp nhất và lợi nhuận cao nhất. Đặt đúng các lệnh xác minh trước — cửa sổ kiểm tra chất lượng là bản nâng cấp đáng giá nhất.
Sử dụng "kiểm soát mô hình đẳng áp" để định lượng đóng góp biên của mỗi hệ thống phụ — đừng dựa vào trực giác.
Harness mục nát như mã nguồn. Kiểm tra thường xuyên, trả nợ harness như bạn trả nợ kỹ thuật.
Đọc thêm
OpenAI: Harness Engineering
Anthropic: Effective Harnesses for Long-Running Agents
HumanLayer: Harness Engineering for Coding Agents
SWE-agent: Agent-Computer Interfaces
Thoughtworks: Harness Engineering on Technology Radar
Bài tập
Kiểm toán harness năm tuple : Lấy một dự án nơi bạn sử dụng AI agent và thực hiện kiểm toán đầy đủ bằng khung năm tuple. Chấm điểm mỗi hệ thống phụ từ 1-5. Tìm hệ thống phụ có điểm thấp nhất, dành 30 phút cải thiện nó, sau đó quan sát sự thay đổi về hiệu suất agent.
Thí nghiệm kiểm soát mô hình đẳng áp : Chọn một mô hình và một tác vụ đầy thách thức. Lần lượt xóa hướng dẫn (xóa AGENTS.md), xóa phản hồi (không cung cấp lệnh xác minh), xóa trạng thái (không có tệp tiến độ) — xóa chỉ một cái mỗi lần và đo lường giảm hiệu suất. Dựa trên kết quả, xếp hạng tầm quan trọng của hệ thống phụ cho dự án của bạn.
Phân tích affordance : Tìm một tình huống mà agent trong dự án của bạn "muốn làm gì đó nhưng không thể" (ví dụ: biết nó nên sử dụng các truy vấn được tham số hóa nhưng không biết các mẫu ORM của dự án của bạn). Phân tích liệu đây là Gulf of Execution (không biết làm thế nào) hay Gulf of Evaluation (không biết có đúng không), sau đó thiết kế một cải tiến harness để thu hẹp khoảng cách đó.
Bài giảng 03. Biến repo thành nguồn sự thật duy nhất (system of record) 10,901 ký tự
English Version → | 中文版本 →
Ví dụ mã nguồn: code/ Dự án thực hành: Dự án 02. Không gian làm việc Agent đọc được
Bài 03. Biến Kho lưu trữ Thành Nguồn Sự thật Duy nhất
Các quyết định kiến trúc của nhóm bạn rải rác khắp Confluence, Slack, Jira, và một vài cái đầu của các kỹ sư cấp cao. Đối với con người, điều này hoạt động gượng gạo — bạn có thể hỏi đồng nghiệp, tìm kiếm lịch sử chat, đào qua tài liệu. Nếu thất bại, bạn có thể chặn ai đó ở căng tin. Nhưng đối với AI agent, thông tin không có trong kho lưu trữ đơn giản là không tồn tại.
Đây không phải phóng đại. Hãy nghĩ về các đầu vào thực sự của agent là gì: system prompt và mô tả tác vụ, nội dung tệp từ kho lưu trữ, và kết quả thực thi công cụ. Chỉ vậy thôi. Lịch sử Slack, ticket Jira, trang Confluence, và quyết định kiến trúc bạn thảo luận với đồng nghiệp qua cà phê vào chiều thứ Sáu — agent không thể thấy bất cứ điều nào trong số này. Nó không thể "đi hỏi ai đó" hoặc "tìm kiếm lịch sử chat." Nó là một kỹ sư bị nhốt bên trong kho lưu trữ — tất cả những gì bên ngoài, nó không biết gì cả.
Vậy câu hỏi trở thành: bạn có định đưa cho kỹ sư này một bản đồ tốt không?
Những Gì Thuộc Về Bản Đồ
OpenAI nói thẳng: thông tin không tồn tại trong repo, không tồn tại với agent. Họ gọi đây là nguyên tắc "repo là spec" — bản thân kho lưu trữ là tài liệu đặc tả có thẩm quyền cao nhất.
Tài liệu về agent chạy lâu của Anthropic phản ánh điều này: trạng thái liên tục là điều kiện cần thiết cho tính liên tục của tác vụ dài. Khả năng phục hồi kiến thức xuyên phiên trực tiếp xác định tỷ lệ thành công của tác vụ. Và trạng thái này phải tồn tại trong kho lưu trữ — vì đó là bộ lưu trữ ổn định, có thể truy cập duy nhất mà agent có.
Bạn có thể nghĩ: "Nhóm chúng tôi nhỏ, kiến thức nằm trong đầu mọi người, và nó vẫn hoạt động tốt." Chắc chắn, đối với con người. Nhưng nếu bạn đang sử dụng agent, hãy chấp nhận sự thật này: agent không thể hỏi người. Mọi thứ nó cần biết phải được viết xuống và đặt ở nơi nó có thể tìm thấy.
Đây không phải về "viết nhiều tài liệu hơn." Mà là về "đặt thông tin quyết định vào đúng chỗ." Một ARCHITECTURE.md 50 dòng trong thư mục src/api/ hữu ích hơn mười nghìn lần so với một tài liệu thiết kế 500 trang trong Confluence mà không ai bảo trì. Giống như bản đồ văn phòng vẽ tay dán trên bàn làm việc của bạn so với bản vẽ kiến trúc đẹp bị khóa trong tủ hồ sơ — cái trước có sẵn ngay khi bạn cần; cái sau về mặt kỹ thuật ưu việt hơn nhưng vô dụng trong thời điểm đó.
Khả năng Hiển thị Kiến thức
Làm thế nào để kiểm tra xem bản đồ của bạn có đủ tốt không? Chạy "bài kiểm tra khởi động lạnh (cold-start test)": mở một phiên agent hoàn toàn mới chỉ sử dụng nội dung repo, và xem nó có thể trả lời năm câu hỏi cơ bản không:
Nếu nó không thể trả lời, bản đồ có những chỗ trống. Nơi bản đồ trống, agent đoán — đoán sai trở thành lỗi, đoán quá nhiều lãng phí ngữ cảnh. Và mỗi phiên mới lại đoán lại. Chi phí đoán luôn cao hơn chi phí vẽ bản đồ đúng cách ngay từ đầu.
Các Khái niệm Cốt lõi
Khoảng cách Hiển thị Kiến thức (Knowledge Visibility Gap) : Tỷ lệ tổng kiến thức dự án KHÔNG có trong kho lưu trữ. Khoảng cách càng lớn, tỷ lệ thất bại của agent càng cao. Bao nhiêu kiến thức ẩn về dự án này sống trong đầu bạn? Đếm tất cả, sau đó xem bao nhiêu đã vào repo — sự khác biệt là khoảng cách hiển thị của bạn.
Hệ thống Ghi chép (System of Record) : Kho lưu trữ mã là nguồn có thẩm quyền cho các quyết định dự án, ràng buộc kiến trúc, trạng thái thực thi và tiêu chuẩn xác minh. Repo có tiếng nói cuối cùng, không nơi nào khác có giá trị. Giống như bản đồ có ghi "đường đóng cửa" — bạn sẽ không đi theo con đường đó. Nhưng nếu thông tin đó chỉ tồn tại trong đầu của Anh Nam, bạn phải hỏi Anh Nam mỗi lần.
Bài kiểm tra Khởi động Lạnh (Cold-Start Test) : Năm câu hỏi ở trên. Nó có thể trả lời bao nhiêu thì bản đồ của bạn hoàn chỉnh bấy nhiêu.
Chi phí Khám phá (Discovery Cost) : Ngân sách ngữ cảnh agent đốt cháy để tìm một thông tin quan trọng trong repo. Thông tin càng ẩn, chi phí khám phá càng cao, và ngân sách còn lại cho tác vụ thực tế càng ít. Ẩn thông tin quan trọng trong README sâu mười cấp thư mục giống như khóa bình chữa cháy trong két an toàn tầng hầm — nó tồn tại, nhưng bạn không thể tìm thấy khi cần.
Tốc độ Suy giảm Kiến thức (Knowledge Decay Rate) : Tỷ lệ các mục kiến thức trở nên lỗi thời theo đơn vị thời gian. Tài liệu không đồng bộ với mã là kẻ thù lớn nhất — tệ hơn không có tài liệu nào cả.
Phép loại suy ACID : Áp dụng các nguyên tắc giao dịch cơ sở dữ liệu (Tính nguyên tử, Nhất quán, Cô lập, Bền vững) vào quản lý trạng thái agent. Chúng ta sẽ mở rộng điều này dưới đây.
Cách Vẽ Bản Đồ Tốt
Nguyên tắc 1: Kiến thức sống gần mã. Một quy tắc về xác thực API endpoint thuộc về gần mã API, không bị chôn vùi trong một tài liệu toàn cục khổng lồ. Đặt một tài liệu ngắn trong mỗi thư mục module giải thích trách nhiệm, giao diện và các ràng buộc đặc biệt của module đó. Giống như nhãn kệ thư viện — bạn muốn sách lịch sử, đi thẳng đến kệ ghi nhãn "Lịch sử." Không cần tìm kiếm toàn bộ thư viện.
Nguyên tắc 2: Sử dụng tệp đầu vào được chuẩn hóa. AGENTS.md (hoặc CLAUDE.md ) là "trang đích" của agent. Nó không cần chứa tất cả thông tin, nhưng phải để agent nhanh chóng trả lời ba câu hỏi: "Dự án này là gì," "Làm thế nào để chạy nó," và "Làm thế nào để xác minh nó." 50-100 dòng là đủ.
Nguyên tắc 3: Tối giản nhưng đầy đủ. Mỗi mảnh kiến thức nên có trường hợp sử dụng rõ ràng. Nếu xóa một quy tắc không ảnh hưởng đến chất lượng quyết định của agent, quy tắc đó không nên tồn tại. Nhưng mỗi câu hỏi từ bài kiểm tra khởi động lạnh phải có câu trả lời. Đây là sự cân bằng tế nhị — không quá nhiều, không quá ít, vừa đủ.
Nguyên tắc 4: Cập nhật cùng mã. Ràng buộc cập nhật kiến thức với thay đổi mã. Cách tiếp cận đơn giản nhất: đặt tài liệu kiến trúc trong thư mục module tương ứng. Khi bạn sửa đổi mã, bạn tự nhiên nhìn thấy tài liệu. Sau khi thay đổi mã, CI có thể nhắc nhở bạn kiểm tra xem tài liệu có cần cập nhật không.
Cấu trúc repo cụ thể :
project/
├── AGENTS.md # Đầu vào: tổng quan dự án, lệnh chạy, ràng buộc cứng
├── src/
│ ├── api/
│ │ ├── ARCHITECTURE.md # Quyết định kiến trúc lớp API
│ │ └── ...
│ ├── db/
│ │ ├── CONSTRAINTS.md # Ràng buộc cứng của hoạt động cơ sở dữ liệu
│ │ └── ...
│ └── ...
├── PROGRESS.md # Tiến độ hiện tại: xong, đang thực hiện, bị chặn
└── Makefile # Lệnh chuẩn hóa: setup, test, lint, check
Quản lý Trạng thái Agent với Nguyên tắc ACID
Phép loại suy này đến từ quản lý giao dịch cơ sở dữ liệu — bạn có thể nghĩ nó đang phức tạp hóa quá mức, nhưng nó thực sự cung cấp cho bạn một khung rất thực tế:
Tính nguyên tử (Atomicity) : Mỗi "hoạt động logic" (ví dụ: "thêm endpoint mới và cập nhật test") nhận một git commit. Nếu thất bại giữa chừng, git stash để khôi phục. Tất cả hoặc không có gì — không có "làm được một nửa."
Nhất quán (Consistency) : Xác định các vị từ xác minh "trạng thái nhất quán" — tất cả test qua, lint báo cáo không có lỗi. Agent chạy xác minh sau mỗi hoạt động; các trạng thái trung gian không nhất quán không được commit. Giống như chuyển khoản ngân hàng — bạn không thể ghi nợ mà không ghi có.
Cô lập (Isolation) : Khi nhiều agent hoạt động đồng thời, thiết kế các tệp trạng thái để tránh race condition. Cách tiếp cận đơn giản: mỗi agent sử dụng tệp tiến độ riêng, hoặc sử dụng git branch để cô lập. Hai đầu bếp không thể nêm cùng một nồi đồng thời — ai chịu trách nhiệm khi bị mặn quá?
Bền vững (Durability) : Kiến thức dự án quan trọng sống trong các tệp được theo dõi bởi git. Trạng thái tạm thời có thể ở lại trong bộ nhớ phiên, nhưng kiến thức xuyên phiên phải được lưu trữ vào tệp. Những gì trong đầu bạn không tính — chỉ những gì trên giấy mới tính.
Câu chuyện Chuyển đổi Thực tế
Một nhóm duy trì một nền tảng thương mại điện tử với ~30 microservices. Các quyết định kiến trúc (giao thức giao tiếp giữa các dịch vụ, chiến lược nhất quán dữ liệu, quy tắc phiên bản API) bị rải rác khắp: Confluence (một phần lỗi thời), Slack (khó tìm kiếm), một vài đầu của các kỹ sư cấp cao (không có khả năng mở rộng), và các chú thích mã rải rác (không có hệ thống).
Sau khi giới thiệu AI agent, 70% tác vụ yêu cầu can thiệp của con người. Gần như mọi lỗi đều liên quan đến agent vi phạm một số ràng buộc ẩn "mọi người biết nhưng không ai viết xuống." Giống như nhân viên mới mà không ai nói với họ "bạn cần đăng lệnh ăn trưa trong nhóm chat" — họ đoán sai, bị mắng, nhưng sau khi bị mắng vẫn không ai nói với họ quy tắc.
Nhóm đã thực hiện một cuộc chuyển đổi:
Tạo AGENTS.md trong thư mục gốc repo với tổng quan dự án, phiên bản tech stack và các ràng buộc cứng toàn cục
Thêm ARCHITECTURE.md trong mỗi thư mục microservice mô tả trách nhiệm, giao diện và phụ thuộc
Tạo CONSTRAINTS.md tập trung với các ràng buộc cứng bằng ngôn ngữ "PHẢI/KHÔNG ĐƯỢC" rõ ràng
Thêm PROGRESS.md trong mỗi thư mục dịch vụ theo dõi trạng thái công việc hiện tại
Sau chuyển đổi: cùng agent có thể trả lời tất cả các câu hỏi dự án quan trọng khi khởi động lạnh, và chất lượng hoàn thành tác vụ cải thiện đáng kể.
Những Điểm chính cần Nhớ
Kiến thức không có trong repo không tồn tại với agent. Đặt các quyết định quan trọng vào repo là đầu tư harness cơ bản nhất — vẽ bản đồ tốt để không bị lạc.
Sử dụng "bài kiểm tra khởi động lạnh" để đánh giá chất lượng repo: một phiên mới có thể trả lời năm câu hỏi cơ bản chỉ sử dụng nội dung repo không?
Kiến thức phải ở gần mã, tối giản nhưng đầy đủ, và cập nhật cùng mã. Không phải về viết nhiều tài liệu hơn — mà là đặt thông tin vào đúng chỗ.
Sử dụng nguyên tắc ACID cho trạng thái agent: commit nguyên tử, xác minh nhất quán, cô lập đồng thời, kiến thức quan trọng bền vững.
Suy giảm kiến thức là kẻ thù lớn nhất. Tài liệu không đồng bộ với mã nguy hiểm hơn không có tài liệu — nó đưa agent đi theo hướng sai trong khi nghĩ rằng mình đúng.
Đọc thêm
OpenAI: Harness Engineering
Anthropic: Effective Harnesses for Long-Running Agents
Infrastructure as Code — Martin Fowler
ADR: Architecture Decision Records
The Twelve-Factor App
Bài tập
Bài kiểm tra khởi động lạnh : Mở một phiên agent hoàn toàn mới trong dự án của bạn (không có ngữ cảnh lời nói, chỉ nội dung repo). Hỏi nó năm câu hỏi: Hệ thống này là gì? Nó được tổ chức như thế nào? Làm thế nào để chạy nó? Làm thế nào để xác minh nó? Tiến độ hiện tại là gì? Ghi lại những gì nó không thể trả lời, sau đó cải thiện repo cho đến khi nó có thể.
Định lượng ngoại hóa kiến thức : Liệt kê tất cả các quyết định và ràng buộc quan trọng cho công việc phát triển trong dự án của bạn. Đánh dấu mỗi cái là có trong hoặc ngoài repo. Tính khoảng cách hiển thị kiến thức của bạn (tỷ lệ ngoài repo). Lập kế hoạch để đưa nó xuống dưới 10%.
Đánh giá ACID : Đánh giá quản lý trạng thái dự án của bạn bằng phép loại suy ACID của bài giảng này. Tính nguyên tử — các hoạt động agent có thể được khôi phục sạch không? Nhất quán — có xác minh "trạng thái nhất quán" không? Cô lập — các agent đồng thời có giẫm lên nhau không? Bền vững — tất cả kiến thức xuyên phiên có được lưu trữ không?
Bài giảng 04. Tách hướng dẫn thành nhiều tệp (đừng dồn 1 file khổng lồ) 10,903 ký tự
English Version → | 中文版本 →
Ví dụ mã nguồn: code/ Dự án thực hành: Dự án 02. Không gian làm việc Agent đọc được
Bài 04. Chia Hướng dẫn Ra Thành Nhiều Tệp
Bạn đã nghiêm túc với harness engineering — tốt lắm. Bạn đã tạo AGENTS.md và nhét mọi quy tắc, ràng buộc và bài học kinh nghiệm mà bạn có thể nghĩ ra vào đó. Một tháng sau, tệp phình lên 300 dòng, hai tháng 450 dòng, ba tháng 600 dòng. Rồi bạn nhận ra hiệu suất của agent thực sự đang kém hơn — trên một sửa lỗi đơn giản, agent đốt cháy rất nhiều ngữ cảnh để xử lý các hướng dẫn triển khai không liên quan; một ràng buộc bảo mật quan trọng bị chôn ở dòng 300 bị bỏ qua hoàn toàn; ba quy tắc phong cách mã mâu thuẫn có nghĩa là agent chọn một cái ngẫu nhiên mỗi lần.
Đây là bẫy "tệp hướng dẫn khổng lồ." Giống như nhồi quá nhiều vào vali — mọi thứ có vẻ hữu ích, vì vậy bạn nhét tất cả vào cho đến khi khóa kéo sắp nổ tung. Tìm đồ lót của bạn có nghĩa là đổ toàn bộ túi. Bạn mang một chiếc vali đầy, nhưng thực ra bạn chỉ dùng khoảng một phần ba những gì bên trong.
Vòng lặp Vicious Tại Gốc rễ
Vòng lặp vicious phổ biến nhất diễn ra như thế này: agent mắc lỗi, bạn nói "thêm quy tắc để ngăn điều này," thêm nó vào AGENTS.md, nó hoạt động tạm thời, agent mắc lỗi khác, thêm quy tắc khác, lặp lại, tệp phình ra ngoài tầm kiểm soát.
Đây không phải lỗi của bạn. Đây là một phản ứng rất tự nhiên — "thêm quy tắc" mỗi khi có sự cố cảm thấy hợp lý, giống như tống thêm thứ gì đó vào túi mỗi khi bạn ra khỏi nhà "đề phòng bất trắc." Nhưng hiệu ứng tích lũy là thảm khốc. Hãy xem cụ thể những gì đi sai.
Ngân sách ngữ cảnh bị ăn mòn. Cửa sổ ngữ cảnh của agent là hữu hạn. Giả sử agent của bạn có cửa sổ 200K token (tiêu chuẩn của Claude). Một tệp hướng dẫn phình to có thể ăn 10-20K token. Có vẻ vẫn còn nhiều chỗ? Nhưng một tác vụ phức tạp có thể cần đọc hàng chục tệp nguồn, kết quả thực thi công cụ cũng chiếm ngữ cảnh, và lịch sử hội thoại tích lũy. Đến khi agent cần hiểu mã, ngân sách đã chật chội — giống như một chiếc vali quá đầy đến mức không còn chỗ cho laptop của bạn.
Lạc giữa đường. Bài báo "Lost in the Middle" (Liu et al., 2023) đã chứng minh rõ ràng rằng LLM sử dụng thông tin ở giữa các văn bản dài kém hiệu quả hơn đáng kể so với đầu hoặc cuối. AGENTS.md của bạn có 600 dòng, và dòng 300 nói "tất cả các truy vấn cơ sở dữ liệu phải sử dụng truy vấn được tham số hóa" — đó là ràng buộc cứng bảo mật. Nhưng nó bị chôn ở giữa, và agent gần như chắc chắn sẽ bỏ qua nó. Giống như chai kem chống nắng ở đáy chiếc vali quá đầy của bạn — bạn biết nó ở đó, bạn đào ba lần, không tìm thấy, cuối cùng mua cái khác.
Xung đột ưu tiên. Tệp trộn lẫn các ràng buộc cứng không thể thương lượng ("không bao giờ sử dụng eval()"), các hướng dẫn thiết kế quan trọng ("ưu tiên phong cách hàm"), và một bài học lịch sử cụ thể ("đã sửa rò rỉ bộ nhớ WebSocket tuần trước, chú ý đến các mẫu tương tự"). Ba quy tắc này có mức độ quan trọng hoàn toàn khác nhau, nhưng chúng trông giống hệt nhau trong tệp. Agent không có tín hiệu đáng tin cậy để phân biệt — giống như hộ chiếu và dây sạc bị lẫn lộn trong vali, không cách nào biết cái nào cấp bách hơn.
Suy giảm bảo trì. Các tệp lớn vốn dĩ khó bảo trì. Các hướng dẫn lỗi thời hiếm khi bị xóa — vì hậu quả của việc xóa là không chắc chắn ("có lẽ thứ gì đó khác phụ thuộc vào quy tắc này?"), trong khi thêm hướng dẫn mới có vẻ miễn phí. Kết quả: tệp chỉ tăng, không bao giờ giảm, và tỷ lệ tín hiệu/nhiễu liên tục giảm. Đây chính xác giống như tích lũy nợ kỹ thuật trong phần mềm.
Tích lũy mâu thuẫn. Các hướng dẫn được thêm vào các thời điểm khác nhau bắt đầu mâu thuẫn nhau — một cái nói "sử dụng TypeScript strict mode," một cái khác nói "một số tệp legacy cho phép any types." Agent chọn ngẫu nhiên một cái để tuân theo mỗi lần. Giống như mẹ bạn nói "mặc thêm ấm" và bố bạn nói "đừng mặc quá nhiều," và bạn đứng ở cửa không biết lắng nghe ai.
Các Khái niệm Cốt lõi
Phình Hướng dẫn (Instruction Bloat) : Khi một tệp hướng dẫn chiếm hơn 10-15% cửa sổ ngữ cảnh, nó bắt đầu lấn át ngân sách để đọc mã và lý luận tác vụ. Một AGENTS.md 600 dòng có thể tiêu thụ 10,000-20,000 token — đó là 8-15% cửa sổ 128K bị ăn hết trước khi agent thậm chí bắt đầu.
Hiệu ứng Lạc Giữa Đường (Lost in the Middle Effect) : Nghiên cứu năm 2023 của Liu et al. đã chứng minh rằng LLM sử dụng thông tin ở giữa các văn bản dài kém hiệu quả hơn đáng kể so với thông tin ở đầu hoặc cuối. Một ràng buộc quan trọng bị chôn ở dòng 300 của tệp 600 dòng có xác suất rất cao bị bỏ qua thực tế.
Tỷ lệ Tín hiệu/Nhiễu Hướng dẫn (Instruction SNR) : Tỷ lệ hướng dẫn trong một tệp liên quan đến tác vụ hiện tại. Bị buộc phải đọc 50 dòng hướng dẫn triển khai trong khi sửa lỗi — đó là SNR thấp.
Tệp Định tuyến (Routing File) : Một tệp đầu vào ngắn có chức năng cốt lõi là chỉ agent đến các tài liệu chi tiết hơn, không chứa tất cả mọi thứ trong chính nó. 50-200 dòng là đủ.
Tiết lộ Tiến triển (Progressive Disclosure) : Đưa thông tin tổng quan trước, thông tin chi tiết khi cần. Thiết kế harness tốt giống như thiết kế UI tốt — đừng đổ tất cả các tùy chọn lên người dùng cùng một lúc.
Mơ hồ Ưu tiên (Priority Ambiguity) : Khi tất cả hướng dẫn xuất hiện ở cùng định dạng và vị trí, agent không thể phân biệt các ràng buộc cứng không thể thương lượng với các hướng dẫn mềm mang tính gợi ý.
Kiến trúc Hướng dẫn
Cách Chia
Nguyên tắc cốt lõi: giữ thông tin thường cần ở tầm tay, cất thông tin thỉnh thoảng cần, và bỏ lại những gì bạn sẽ không bao giờ dùng.
Tệp đầu vào AGENTS.md duy trì ở 50-200 dòng, chỉ chứa các mục được sử dụng thường xuyên nhất — tổng quan dự án (một hoặc hai câu), lệnh chạy đầu tiên ( make setup && make test ), các ràng buộc cứng toàn cục (không quá 15 quy tắc không thể thương lượng), và liên kết đến các tài liệu chủ đề (mô tả một dòng + điều kiện áp dụng).
markdown # AGENTS.md
## Tổng quan Dự án
Backend FastAPI Python 3.11, cơ sở dữ liệu PostgreSQL 15.
## Khởi động Nhanh
- Cài đặt: `make setup`
- Test: `make test`
- Xác minh đầy đủ: `make check`
## Ràng buộc Cứng
- Tất cả API phải sử dụng xác thực OAuth 2.0
- Tất cả truy vấn cơ sở dữ liệu phải sử dụng cú pháp SQLAlchemy 2.0
- Tất cả PR phải vượt qua pytest + mypy --strict + ruff check
## Tài liệu Chủ đề
- [ Mẫu Thiết kế API ]( docs/api-patterns.md ) — Đọc bắt buộc khi thêm endpoint
- [ Quy tắc Cơ sở dữ liệu ]( docs/database-rules.md ) — Bắt buộc khi sửa đổi hoạt động cơ sở dữ liệu
- [ Tiêu chuẩn Testing ]( docs/testing-standards.md ) — Tham khảo khi viết test
Mỗi tài liệu chủ đề có 50-150 dòng, được tổ chức theo chủ đề trong thư mục docs/ hoặc cạnh module tương ứng. Agent chỉ đọc chúng khi cần. Giống như túi đựng đồ trong vali — đồ lót một túi, đồ vệ sinh một túi, dây sạc một túi. Tìm đồ không cần đổ toàn bộ túi.
Một số thông tin được đặt tốt hơn trực tiếp trong mã — định nghĩa type, chú thích giao diện, giải thích trong tệp cấu hình. Agent tự nhiên thấy những điều này khi đọc mã, không cần sao chép trong hướng dẫn.
Mỗi hướng dẫn nên có nguồn gốc ("tại sao quy tắc này được thêm?"), điều kiện áp dụng ("khi nào quy tắc này cần?"), và điều kiện hết hạn ("trong hoàn cảnh nào quy tắc này có thể được xóa?"). Kiểm tra thường xuyên, xóa các mục lỗi thời, dư thừa và mâu thuẫn. Quản lý hướng dẫn của bạn như bạn quản lý các phụ thuộc mã — các phụ thuộc không dùng nên được xóa, nếu không chúng chỉ làm chậm hệ thống.
Nếu một hướng dẫn phải có trong tệp đầu vào, hãy đặt nó ở đầu hoặc cuối — không bao giờ ở giữa. Hiệu ứng "lạc giữa đường" cho chúng ta biết rằng LLM sử dụng thông tin ở các cực đoan tốt hơn đáng kể so với trung tâm. Nhưng cách tiếp cận tốt hơn là di chuyển hướng dẫn sang các tài liệu chủ đề để tải theo yêu cầu.
Cả OpenAI và Anthropic đều ngầm hỗ trợ cách tiếp cận chia nhỏ. OpenAI nói các tệp đầu vào nên "ngắn và hướng định tuyến," Anthropic nói thông tin kiểm soát agent chạy lâu nên "súc tích và ưu tiên cao." Cả hai đều nói cùng một điều: đừng nhồi nhét mọi thứ vào một tệp. Vali cần được tổ chức, không phải nhồi nhét thô bạo.
Ví dụ Thực tế
Một nhóm SaaS có AGENTS.md phình từ 50 dòng lên 600. Nội dung trộn lẫn phiên bản tech stack, tiêu chuẩn mã hóa, ghi chú sửa lỗi lịch sử, hướng dẫn sử dụng API, quy trình triển khai và sở thích cá nhân của các thành viên nhóm — toàn bộ chiếc vali sắp nổ tung.
Hiệu suất agent bắt đầu giảm rõ rệt: trong khi sửa lỗi đơn giản, agent dành nhiều ngữ cảnh để xử lý các hướng dẫn triển khai không liên quan; ràng buộc bảo mật "tất cả truy vấn cơ sở dữ liệu phải sử dụng truy vấn được tham số hóa" bị chôn ở dòng 300 và thường xuyên bị bỏ qua; ba quy tắc phong cách mã mâu thuẫn gây ra hành vi agent ngẫu nhiên.
Nhóm đã thực hiện "tái tổ chức vali":
AGENTS.md được cắt xuống còn 80 dòng: chỉ tổng quan dự án, lệnh chạy và 15 ràng buộc cứng toàn cục
Tạo các tài liệu chủ đề: docs/api-patterns.md (120 dòng), docs/database-rules.md (60 dòng), docs/testing-standards.md (80 dòng)
Thêm liên kết tài liệu chủ đề trong tệp định tuyến
Các ghi chú lịch sử được chuyển đổi thành test case hoặc bị xóa
Sau tái cấu trúc: tỷ lệ thành công cùng bộ tác vụ tăng từ 45% lên 72%. Tuân thủ ràng buộc bảo mật tăng từ 60% lên 95% — vì nó di chuyển từ giữa tệp lên đầu tệp định tuyến, không còn "lạc giữa đường" nữa.
Những Điểm chính cần Nhớ
"Thêm quy tắc" là giảm đau ngắn hạn, thuốc độc dài hạn. Trước khi thêm quy tắc, hãy hỏi: quy tắc này có tốt hơn trong một tài liệu chủ đề không? Đừng cứ tiếp tục nhồi nhét vào vali.
Tệp đầu vào là bộ định tuyến, không phải bách khoa toàn thư. 50-200 dòng chỉ với tổng quan, ràng buộc cứng và liên kết.
Tận dụng hiệu ứng "lạc giữa đường": thông tin quan trọng đặt ở đầu hoặc cuối; thông tin không quan trọng di chuyển sang tài liệu chủ đề.
Quản lý phình hướng dẫn như nợ kỹ thuật. Kiểm tra thường xuyên, mỗi hướng dẫn cần nguồn gốc, điều kiện áp dụng và điều kiện hết hạn.
Sau khi chia, SNR cải thiện và agent dành nhiều ngân sách ngữ cảnh hơn cho các tác vụ thực tế thay vì xử lý các hướng dẫn không liên quan.
Đọc thêm
OpenAI: Harness Engineering
Anthropic: Effective Harnesses for Long-Running Agents
Lost in the Middle: How Language Models Use Long Contexts
HumanLayer: Harness Engineering for Coding Agents
Nielsen Norman Group: Progressive Disclosure
Bài tập
Kiểm toán SNR : Lấy tệp hướng dẫn đầu vào hiện tại của bạn và liệt kê tất cả các mục hướng dẫn. Chọn 5 loại tác vụ thông thường khác nhau và đánh dấu liệu mỗi hướng dẫn có liên quan đến tác vụ đó không. Tính SNR cho mỗi loại tác vụ. Các hướng dẫn là nhiễu cho hầu hết các tác vụ nên di chuyển sang tài liệu chủ đề.
Tái cấu trúc tiết lộ tiến triển : Nếu bạn có tệp hướng dẫn trên 300 dòng, hãy chia nó thành: (a) tệp định tuyến dưới 100 dòng, (b) 3-5 tài liệu chủ đề. Chạy cùng bộ tác vụ (ít nhất 5) trước và sau, so sánh tỷ lệ thành công.
Xác minh lạc giữa đường : Trong một tệp hướng dẫn dài, đặt một ràng buộc quan trọng ở đầu, giữa và cuối lần lượt, chạy cùng bộ tác vụ mỗi lần (ít nhất 5 lần mỗi vị trí). Xem có sự khác biệt về tỷ lệ tuân thủ không. Bạn có thể ngạc nhiên về mức độ mạnh của hiệu ứng vị trí.
Bài giảng 05. Giữ ngữ cảnh xuyên phiên làm việc (continuity) 13,619 ký tự
English Version → | 中文版本 →
Ví dụ mã nguồn: code/ Dự án thực hành: Dự án 03. Tính liên tục đa phiên
Bài 05. Duy trì Ngữ cảnh Qua Các Phiên
Bạn yêu cầu Claude Code triển khai một tính năng hoàn chỉnh. Nó chạy 30 phút, thực hiện hầu hết công việc, nhưng ngữ cảnh đang cạn kiệt. Bạn bắt đầu một phiên mới để tiếp tục — và khám phá rằng nó không nhớ những quyết định nào đã được đưa ra lần trước, tại sao lại chọn phương án A thay vì phương án B, những tệp nào đã được sửa đổi, hay trạng thái của các bài test là gì. Nó dành 15 phút để khám phá lại dự án, và có thể không nhất quán với cách tiếp cận trước.
Hãy tưởng tượng bạn là một thợ thủ công quên hết mọi thứ mỗi buổi sáng khi thức dậy. Bạn phải làm quen lại với toàn bộ công trường — bức tường nào đang xây dở, tại sao lại chọn gạch đỏ thay vì gạch xanh, đường ống nước đã chạy đến đâu. Tệ hơn nữa, bạn có thể tháo ra một cửa sổ đã được lắp vào ngày hôm qua, đơn giản vì bạn không nhớ nó đã xong.
Đây chính xác là tình huống khó khăn mà các AI coding agent phải đối mặt trong các tác vụ xuyên phiên. Bài giảng này giải thích tại sao các agent "mất ký ức" trong các tác vụ dài, và cách lưu trữ trạng thái có cấu trúc có thể làm cho chúng giống như một thợ thủ công giữ nhật ký đáng tin cậy hàng ngày — vẫn bị mất ký ức, nhưng nhật ký nhớ mọi thứ.
Cửa sổ Ngữ cảnh: Không Vô hạn
Cửa sổ ngữ cảnh là hữu hạn. Điều này không thể giải quyết bằng nâng cấp mô hình — ngay cả khi kích thước cửa sổ tăng lên 1M token, các tác vụ phức tạp vẫn sẽ tiêu hao chúng. Vì các agent không chỉ tạo ra mã; họ hiểu codebase, theo dõi lịch sử quyết định của chính mình, xử lý kết quả công cụ và duy trì ngữ cảnh hội thoại. Tất cả thông tin này tăng trưởng nhanh hơn sự mở rộng cửa sổ.
Một vấn đề sâu hơn: thông tin mà agent tạo ra không đồng đều về mức độ quan trọng. Các bước lý luận trung gian chứa "tại sao" của các quyết định — tại sao chọn phương án B thay vì A, tại sao thư viện này thay vì kia, tại sao một tối ưu hóa cụ thể bị bỏ qua. Kết quả cuối cùng chỉ chứa "cái gì" — bản thân mã. Các chiến lược nén thường bảo tồn cái sau nhưng mất cái trước. Phiên tiếp theo thấy mã nhưng không biết tại sao nó được viết như vậy, và có thể "tối ưu hóa" đi một quyết định thiết kế cố ý.
Anthropic đã phát hiện ra điều hấp dẫn trong nghiên cứu về agent chạy lâu của họ: khi các agent cảm thấy ngữ cảnh đang cạn kiệt, chúng thể hiện hành vi "hội tụ sớm" — vội vàng hoàn thành công việc hiện tại, bỏ qua các bước xác minh, hoặc chọn giải pháp đơn giản thay vì giải pháp tối ưu. Giống như nhận ra thời gian sắp hết trong bài thi và nhanh chóng đoán các câu hỏi trắc nghiệm còn lại. Anthropic gọi đây là "lo lắng ngữ cảnh."
Luồng Tính Liên tục Phiên
Không có các artifact tính liên tục, mọi phiên mới là một thảm họa:
Với các artifact tính liên tục, các phiên mới có thể tiếp tục nhanh chóng:
Các Khái niệm Cốt lõi
Cửa sổ ngữ cảnh là hữu hạn : Bất kể kích thước cửa sổ nào được tuyên bố (128K, 200K, 1M), các tác vụ dài cuối cùng sẽ tiêu hao chúng. Sau khi tiêu hao, cần phải nén (mất thông tin) hoặc đặt lại (phiên mới). Cả hai đều mất điều gì đó.
Artifact tính liên tục (Continuity Artifacts) : Các tệp trạng thái được lưu trữ cho phép phiên mới tiếp tục không mơ hồ từ nơi phiên cuối kết thúc. Dạng cơ bản: nhật ký tiến độ + bản ghi xác minh + các hành động tiếp theo. Nhật ký của thợ thủ công đó.
Chi phí Tái xây dựng (Rebuild Cost) : Thời gian phiên mới cần để đạt đến trạng thái có thể thực thi. Harness tốt có thể nén chi phí tái xây dựng từ 15 phút xuống còn 3 phút.
Trôi dạt (Drift) : Khoảng cách giữa sự hiểu biết của agent và trạng thái thực tế của kho lưu trữ mã. Mỗi ranh giới phiên tạo ra trôi dạt; nếu không kiểm soát, nó sẽ tích lũy.
Lo lắng ngữ cảnh (Context Anxiety) : Hiện tượng được Anthropic quan sát — các agent thể hiện hành vi hội tụ sớm khi tiếp cận giới hạn ngữ cảnh nhận thức, kết thúc tác vụ sớm để tránh mất thông tin. Đó là sự lo lắng tài nguyên phi lý.
Nén vs. Đặt lại (Compaction vs. Reset) : Nén tóm tắt ngữ cảnh trong cùng phiên (giữ "cái gì," có thể mất "tại sao"); đặt lại mở phiên mới tái xây dựng từ trạng thái được lưu trữ (sạch nhưng phụ thuộc vào tính hoàn chỉnh của artifact).
Điều Gì Xảy ra Khi Tính Liên tục Bị Phá vỡ
Phiên trước đã dành ngân sách ngữ cảnh đáng kể để phân tích ba cách tiếp cận và chọn phương án B. Phiên này của agent không biết về phân tích đó và có thể quyết định lại dựa trên thông tin không đầy đủ — có thể chọn phương án A. Giống như thợ thủ công mất ký ức không nhớ tại sao gạch đỏ được chọn, nhìn vào gạch xanh ngày hôm nay và nghĩ chúng đẹp hơn, và tháo bức tường của ngày hôm qua để xây lại.
Thậm chí còn tệ hơn là công việc trùng lặp. Agent không chắc chắn liệu một số công việc đã hoàn thành chưa và làm lại. Hoặc tệ hơn — làm một nửa, phát hiện ra xung đột với triển khai hiện có, và phải làm lại. Trên công trường, hai đội không thể xây cùng một bức tường đồng thời — nhưng không có bản ghi tiến độ, đội mới không biết có ai đó đang làm việc đó rồi.
Qua nhiều phiên, hướng triển khai có thể đã âm thầm trôi xa khỏi yêu cầu ban đầu. Mỗi phiên mới có sự hiểu biết hơi khác nhau về mục tiêu dự án. Giống như trò chơi truyền tin — sau mười người truyền tin, "đón tôi một ly cà phê" có thể trở thành "mua cho tôi máy pha cà phê."
Cũng có khoảng cách xác minh. Kết quả xác minh của phiên trước (test nào vượt qua, test nào thất bại, tại sao thất bại) không được ghi lại. Phiên mới phải chạy lại tất cả xác minh để hiểu trạng thái hiện tại. Mỗi phiên chẩn đoán lại từ đầu, mỗi lần lãng phí ngữ cảnh quý báu.
Cả OpenAI và Anthropic đều nhấn mạnh lưu trữ trạng thái có cấu trúc trong tài liệu của họ. Bài viết về harness engineering của OpenAI coi kho lưu trữ là "bản ghi hoạt động" — kết quả của mỗi hoạt động phải để lại bằng chứng có thể truy vết trong repo. Tài liệu về agent chạy lâu của Anthropic đặc biệt khuyến nghị "tệp bàn giao" — các tài liệu có cấu trúc chứa trạng thái hiện tại, các vấn đề đã biết và các hành động tiếp theo.
Nhật ký Cho Thợ thủ công Mất Ký ức
Cách tiếp cận cốt lõi: Đối xử với agent như một kỹ sư tài giỏi bị mất ký ức. Trước khi nó "tan ca," nó phải ghi lại thông tin quan trọng để agent "ca tiếp theo" có thể tiếp tục nhanh chóng.
Công cụ 1: Tệp tiến độ (PROGRESS.md). Artifact tính liên tục cơ bản nhất — cốt lõi của nhật ký:
markdown # Tiến độ Dự án
## Trạng thái Hiện tại
- Commit mới nhất: abc1234 (feat: add user preferences endpoint)
- Trạng thái test: 42/43 vượt qua (test_pagination_edge_case thất bại)
- Lint: vượt qua
## Đã Hoàn thành
- [ x ] User model và database migration
- [ x ] Các endpoint CRUD cơ bản
- [ x ] Tích hợp auth middleware
## Đang Thực hiện
- [ ] Tính năng phân trang (90% - edge case test thất bại)
## Vấn đề Đã biết
- test_pagination_edge_case trả về 500 trên result sets trống
- Cần xác nhận liệu người dùng đã xóa có nên xuất hiện trong danh sách không
## Các Bước Tiếp theo
1. Sửa lỗi edge case phân trang
2. Thêm tham số truy vấn "include deleted users"
3. Cập nhật tài liệu API
Công cụ 2: Nhật ký quyết định (DECISIONS.md). Ghi lại các quyết định thiết kế quan trọng và lý do. Không cần tài liệu thiết kế chi tiết — chỉ cần "quyết định gì, tại sao, khi nào" — các ghi chú trong nhật ký:
markdown # Các Quyết định Thiết kế
## 2024-01-15: Sử dụng Redis để cache tùy chọn người dùng
- Lý do: Tần suất đọc cao (mỗi lần gọi API), kích thước dữ liệu nhỏ
- Phương án bị từ chối: PostgreSQL materialized view (tần suất thay đổi cao làm chi phí bảo trì không xứng đáng)
- Ràng buộc: Cache TTL 5 phút, vô hiệu hóa chủ động khi ghi
Công cụ 3: Git commit như checkpoint. Commit sau khi hoàn thành mỗi đơn vị công việc nguyên tử. Commit message phải giải thích những gì đã được thực hiện và tại sao. Đây là các snapshot trạng thái miễn phí, được phiên bản hóa tự động.
Công cụ 4: init.sh hoặc luồng khởi tạo harness. Chỉ định trong AGENTS.md các thói quen "bắt đầu ca" và "kết thúc ca":
markdown ## Khi bắt đầu phiên (bắt đầu ca)
1. Đọc PROGRESS.md để biết trạng thái hiện tại
2. Đọc DECISIONS.md để biết các quyết định quan trọng
3. Chạy make check để xác nhận repo ở trạng thái nhất quán
4. Tiếp tục từ phần "Các Bước Tiếp theo" của PROGRESS.md
## Trước khi kết thúc phiên (kết thúc ca)
1. Cập nhật PROGRESS.md
2. Chạy make check để xác nhận trạng thái nhất quán
3. Commit tất cả công việc đã hoàn thành
Chiến lược hỗn hợp : Không phải mọi tác vụ đều cần đặt lại ngữ cảnh. Các tác vụ ngắn (dưới 30 phút) có thể hoàn thành trong một phiên. Các tác vụ dài (trải dài qua các phiên) phải sử dụng tệp tiến độ và nhật ký quyết định để tính liên tục. Tiêu chí quyết định: nếu một tác vụ cần hơn 60% cửa sổ, hãy bắt đầu chuẩn bị bàn giao.
Tìm hiểu Sâu hơn về Lo lắng Ngữ cảnh
Nghiên cứu tháng 3 năm 2026 của Anthropic tiếp tục tiết lộ các biểu hiện cụ thể của lo lắng ngữ cảnh: trên Sonnet 4.5, khi ngữ cảnh tiếp cận giới hạn cửa sổ, agent thể hiện hành vi "hội tụ sớm" mạnh. Giống như nhận ra thời gian gần hết trong bài thi và nhanh chóng điền câu trả lời ngẫu nhiên vào các câu trắc nghiệm.
Hai chiến lược giải quyết điều này:
Nén (Compaction) : Tóm tắt hội thoại đầu trong cùng phiên. Ưu điểm: duy trì tính liên tục, agent có thể thấy "cái gì." Nhược điểm: "tại sao" thường bị mất trong các bản tóm tắt — tại sao phương án B được chọn thay vì A, tại sao một tối ưu hóa cụ thể bị bỏ qua. Quan trọng hơn, nén không loại bỏ lo lắng ngữ cảnh — agent biết ngữ cảnh từng lớn, và về mặt tâm lý vẫn có xu hướng vội vàng kết thúc.
Đặt lại ngữ cảnh (Context Reset) : Xóa hoàn toàn ngữ cảnh, mở phiên mới, tái xây dựng từ các artifact được lưu trữ. Ưu điểm: trạng thái tâm trí sạch — phiên mới không có lo lắng "tôi sắp hết thời gian." Nhược điểm: phụ thuộc vào tính hoàn chỉnh của artifact bàn giao. Nếu nhật ký thiếu thông tin quan trọng, phiên mới có thể lãng phí thời gian đi theo hướng sai.
Dữ liệu thực tế của Anthropic: đối với Sonnet 4.5, lo lắng ngữ cảnh đủ nghiêm trọng đến mức nén một mình không đủ — đặt lại ngữ cảnh trở thành thành phần quan trọng của thiết kế harness. Nhưng đối với Opus 4.5, hành vi này giảm đáng kể, và nén có thể quản lý ngữ cảnh mà không cần dựa vào đặt lại. Điều này có nghĩa là: thiết kế harness cần sự hiểu biết cụ thể về mô hình mục tiêu, không phải một mẫu chung cho tất cả.
Nguồn: Anthropic: Harness design for long-running application development
Ví dụ Thực tế
Một agent được giao nhiệm vụ triển khai hệ thống blog với xác thực người dùng — 12 điểm tính năng, ước tính cần 5 phiên.
Không có nhật ký : Phiên 1 triển khai user model và các route cơ bản. Phiên 2 bắt đầu mà agent không nhớ hợp đồng giao diện của auth middleware, dành ~15 phút để suy ra ý định thiết kế trước. Đến phiên 3, trôi dạt tích lũy khiến agent bắt đầu triển khai lại các tính năng đã hoàn thành. Đến phiên 5, repo chứa nhiều mã dư thừa nhưng tính năng auth cốt lõi vẫn chưa vượt qua test end-to-end. Chỉ 7 trong 12 điểm tính năng hoàn thành, 3 có vấn đề tính đúng đắn ẩn. Giống như thợ thủ công không bao giờ ghi nhật ký — đến ngày thứ năm, công trường là hỗn loạn, một số bức tường được xây hai lần, một số lẽ ra phải được xây nhưng chưa bao giờ bắt đầu.
Với nhật ký : Sử dụng tệp tiến độ, nhật ký quyết định, bản ghi xác minh và git checkpoint. Báo cáo trạng thái được cập nhật tự động ở cuối mỗi phiên. Chi phí tái xây dựng của phiên 2 giảm xuống còn ~3 phút. Đến phiên 5, tất cả 12 điểm tính năng hoàn thành và được xác minh.
So sánh định lượng: thời gian tái xây dựng giảm ~78%, tỷ lệ hoàn thành tính năng từ 58% lên 100%, tỷ lệ lỗi ẩn từ 43% xuống còn 8%. Thợ thủ công vẫn mất ký ức, nhưng với nhật ký, mỗi ngày bắt đầu từ nơi ngày hôm qua dừng lại, không phải từ đầu.
Những Điểm chính cần Nhớ
Cửa sổ ngữ cảnh là tài nguyên hữu hạn. Các tác vụ dài sẽ trải dài qua nhiều phiên, và các phiên sẽ mất thông tin — giống như thợ thủ công quên mỗi ngày, đây là thực tế khách quan.
Giải pháp không phải là cửa sổ lớn hơn — mà là lưu trữ trạng thái tốt hơn. Tệp tiến độ + nhật ký quyết định + git checkpoint — đưa cho thợ thủ công mất ký ức một cuốn nhật ký đáng tin cậy.
Đối xử với agent như kỹ sư bị mất ký ức: trước khi "tan ca," hãy ghi lại những gì đã làm, tại sao, và tiếp theo là gì.
Chi phí tái xây dựng là chỉ số chính. Harness tốt phải đưa các phiên mới đến trạng thái có thể thực thi trong vòng 3 phút.
Chiến lược hỗn hợp: các tác vụ ngắn trong phiên, các tác vụ dài với artifact có cấu trúc để tính liên tục.
Đọc thêm
Anthropic: Effective Harnesses for Long-Running Agents
OpenAI: Harness Engineering
Lost in the Middle: How Language Models Use Long Contexts
Claude Code Documentation
HumanLayer: Harness Engineering for Coding Agents
Bài tập
Đo lường mất tính liên tục : Chọn một tác vụ phát triển cần ít nhất 3 phiên. Không cung cấp bất kỳ artifact tính liên tục nào, ghi lại ở mỗi lần bắt đầu phiên xem agent dành bao nhiêu ngữ cảnh để "tìm hiểu chuyện gì đã xảy ra lần trước." Sau mỗi phiên, tạo một tệp tiến độ và để phiên tiếp theo bắt đầu từ đó. So sánh chi phí tái xây dựng có và không có tệp tiến độ.
Thiết kế mẫu bàn giao : Thiết kế một mẫu bàn giao tối giản với bốn trường: trạng thái repo (hash commit), trạng thái runtime (tỷ lệ vượt qua test), các chướng ngại vật, các hành động tiếp theo. Để một phiên agent hoàn toàn mới phục hồi trạng thái dự án chỉ sử dụng mẫu này. Ghi lại các điểm mơ hồ gặp phải trong quá trình phục hồi, cải tiến mẫu lặp đi lặp lại.
Thí nghiệm chiến lược hỗn hợp : Trong một tác vụ phát triển 5 phiên, so sánh ba chiến lược: (a) luôn bắt đầu phiên mới + tệp tiến độ, (b) làm càng nhiều càng tốt trong một phiên (nén ngữ cảnh), (c) chiến lược hỗn hợp (tác vụ ngắn trong phiên, tác vụ dài xuyên phiên + tệp tiến độ). So sánh thời gian tái xây dựng, tỷ lệ hoàn thành tính năng và tính nhất quán của quyết định.
Bài giảng 06. Khởi tạo (init) phải là một pha riêng 10,689 ký tự
Bài giảng này giải thích tại sao khởi tạo phải là một giai đoạn riêng, không được trộn lẫn với triển khai.
Móng và Tường: Hai Công việc Khác Nhau Về Bản chất
Khởi tạo và triển khai có mục tiêu tối ưu hóa hoàn toàn khác nhau. Giai đoạn triển khai tối ưu hóa cho: tối đa hóa số lượng và chất lượng của các tính năng được xác minh. Giai đoạn khởi tạo tối ưu hóa cho: tối đa hóa độ tin cậy và hiệu quả của tất cả các triển khai tiếp theo.
Khi bạn trộn khởi tạo và triển khai, agent đối mặt với bài toán tối ưu hóa đa mục tiêu — đồng thời xây dựng cơ sở hạ tầng và viết mã tính năng. Không có cài đặt ưu tiên rõ ràng, agent tự nhiên nghiêng về viết mã (vì đó là kết quả có thể nhìn thấy trực tiếp) trong khi hy sinh cơ sở hạ tầng (vì giá trị của nó chỉ hiện ra trong các phiên sau). Giống như nói với đội xây dựng đồng thời đổ móng và xây tường — họ có thể sẽ vội vàng xây tường vì tường có thể nhìn thấy và trình diễn được. Nhưng một ngôi nhà có móng tệ có vấn đề hệ thống về sau.
Vòng đời Khởi tạo
Điều Gì Xảy ra Khi Bạn Trộn Chúng
Vấn đề trực tiếp nhất: móng không đông cứng đúng cách. Agent dành 80% công sức cho mã tính năng và 20% tùy tiện thiết lập một số cơ sở hạ tầng. Khung test được cấu hình nhưng không bao giờ được xác minh, quy tắc lint được thiết lập nhưng quá lỏng, không có tệp tiến độ được tạo. Những khiếm khuyết này không rõ ràng trong phiên đầu tiên (vì agent vẫn nhớ những gì nó đã làm), nhưng chúng nổi lên trong phiên thứ hai — agent mới không biết cách chạy, test, hoặc mọi thứ đang ở đâu. Móng cẩu thả, tòa nhà lung lay.
Một chi phí ẩn hơn là "tích lũy chưa xác minh" — mã tính năng được viết trước khi khung test được cấu hình là mã không có xác minh. Khi bạn cuối cùng quay lại thêm test cho mã đó, bạn có thể phát hiện ra thiết kế ngay từ đầu đã sai — nếu biết trước, bạn đã triển khai khác đi. Giống như lát gạch lên bê tông ướt — khi bạn phát hiện ra sàn không phẳng, tất cả gạch phải được cạy lên và làm lại.
Ngân sách phiên cũng đang bị lãng phí. Công việc khởi tạo (cấu hình môi trường, thiết lập test, hiểu cấu trúc dự án) tiêu thụ ngân sách đáng kể, để lại ít hơn cho việc triển khai tính năng thực tế. Kết quả: phiên đầu chỉ hoàn thành một nửa tính năng, và phiên thứ hai phải bắt đầu lại hiểu dự án. Ngân sách dành cho móng, nhưng móng cũng không vững — không mục tiêu nào đạt được.
Vấn đề dễ bị bỏ qua nhất là bẫy giả định ẩn. Các quyết định mà agent đưa ra trong quá trình khởi tạo (khung test nào, cách tổ chức thư mục, quản lý phụ thuộc) — nếu không được ghi lại rõ ràng, các phiên sau không thể hiểu những lựa chọn này. Tệ hơn, các phiên sau có thể đưa ra các lựa chọn mâu thuẫn. Đội xây dựng đầu tiên dùng móng bê tông, đội thứ hai không biết và đóng cọc gỗ vào đó — móng nứt.
Nghiên cứu phát triển ứng dụng chạy lâu của Anthropic đặc biệt khuyến nghị tách khởi tạo khỏi triển khai. Dữ liệu thực nghiệm của họ: các dự án sử dụng giai đoạn khởi tạo riêng biệt cho thấy tỷ lệ hoàn thành tính năng cao hơn 31% trong các kịch bản đa phiên so với các cách tiếp cận hỗn hợp. Hiểu biết chính — thời gian đầu tư vào giai đoạn khởi tạo được thu hồi hoàn toàn trong 3-4 phiên tiếp theo. Móng càng vững, tường xây càng nhanh.
Hướng dẫn harness engineering Codex của OpenAI cũng nhấn mạnh nguyên tắc "kho lưu trữ là bản ghi hoạt động" — thiết lập cấu trúc hoạt động rõ ràng từ lần chạy đầu tiên, hoặc mọi phiên mới phải suy ra lại các quy ước dự án.
Các Khái niệm Cốt lõi
Giai đoạn Khởi tạo : Giai đoạn đầu tiên trong vòng đời của agent — không triển khai tính năng, chỉ thiết lập các điều kiện tiên quyết cho tất cả các giai đoạn triển khai tiếp theo. Kết quả không phải là mã, mà là cơ sở hạ tầng.
Bootstrap Contract : Các điều kiện mà một dự án có thể được vận hành không mơ hồ bởi một phiên agent mới — có thể bắt đầu, có thể test, có thể thấy tiến độ, có thể chọn bước tiếp theo. Bốn điều kiện, tất cả đều cần thiết.
Khởi động Lạnh vs. Khởi động Ấm (Cold Start vs. Warm Start) : Khởi động lạnh là từ một thư mục trống nơi agent phải đoán cấu trúc dự án; khởi động ấm là từ một mẫu hoặc dự án hiện có nơi cơ sở hạ tầng đã có sẵn. Khởi động ấm vượt trội hơn nhiều so với khởi động lạnh — giống như bắt đầu làm việc trên công trường có nước chạy và điện so với bắt đầu từ vùng đất hoang.
Sẵn sàng Bàn giao (Handoff Readiness) : Dự án ở trạng thái tại bất kỳ thời điểm nào mà một agent mới có thể tiếp quản. Không cần giải thích bằng lời — chỉ cần nội dung repo.
Thời gian Đến Xác minh Đầu tiên (Time to First Verification) : Thời gian từ khi bắt đầu dự án đến khi điểm tính năng đầu tiên vượt qua xác minh. Đây là chỉ số cốt lõi để đo hiệu quả khởi tạo.
Khả năng Sử dụng Downstream : Thước đo tốt nhất về chất lượng khởi tạo — tỷ lệ các phiên tiếp theo có thể thực thi thành công các tác vụ mà không cần dựa vào kiến thức ẩn.
Cách Khởi tạo Đúng
Coi khởi tạo là một giai đoạn riêng biệt. Phiên đầu tiên chỉ làm khởi tạo — hoàn toàn không có mã tính năng kinh doanh. Khởi tạo tạo ra:
1. Môi trường có thể chạy. Dự án khởi động, dependencies được cài đặt, không có vấn đề môi trường. Móng được đổ, không có vết nứt.
2. Khung test có thể xác minh. Ít nhất một test mẫu vượt qua. Điều này chứng minh bản thân khung test được cấu hình đúng — giống như đứng một cột trên móng để chứng minh nó có thể chịu được trọng lượng.
3. Tài liệu bootstrap contract. Một tài liệu rõ ràng cho các phiên sau:
markdown # Khởi tạo Contract
## Lệnh Khởi động
- Cài đặt dependencies: `make setup`
- Khởi động dev server: `make dev`
- Chạy test: `make test`
- Xác minh đầy đủ: `make check`
## Trạng thái Hiện tại
- Tất cả dependencies đã được cài đặt và khóa
- Khung test được cấu hình (Vitest + React Testing Library)
- Test mẫu vượt qua (1/1)
- Quy tắc lint được cấu hình (ESLint + Prettier)
## Cấu trúc Dự án
- src/ — Mã nguồn
- src/components/ — React components
- src/api/ — API client
- tests/ — Tệp test
4. Phân chia tác vụ. Chia toàn bộ dự án thành danh sách tác vụ có thứ tự, mỗi tác vụ có tiêu chí chấp nhận rõ ràng:
markdown # Phân chia Tác vụ
## Tác vụ 1: Xác thực Người dùng Cơ bản
- Triển khai JWT auth middleware
- Thêm endpoint đăng nhập/đăng ký
- Chấp nhận: pytest tests/test_auth.py tất cả vượt qua
## Tác vụ 2: Trang Hồ sơ Người dùng
- Triển khai CRUD hồ sơ người dùng
- Thêm form chỉnh sửa hồ sơ
- Chấp nhận: pytest tests/test_profile.py tất cả vượt qua
## Tác vụ 3: Tính năng Tìm kiếm
- ...
5. Git commit như checkpoint. Sau khi khởi tạo hoàn thành, commit một checkpoint sạch. Tất cả công việc tiếp theo bắt đầu từ checkpoint này.
Chiến lược khởi động ấm : Đừng bắt đầu từ một thư mục trống. Sử dụng mẫu dự án (create-react-app, fastapi-template, v.v.) để đặt trước cấu trúc thư mục chuẩn, cấu hình phụ thuộc và khung test. Nướng các bước khởi tạo thông thường vào mẫu, chỉ để lại công việc khởi tạo cụ thể cho dự án. Giống như bắt đầu làm việc trên công trường có nước chạy và điện — tốt hơn mười nghìn lần so với bắt đầu từ vùng đất hoang.
Tiêu chí hoàn thành khởi tạo : Không phải "bao nhiêu mã đã được viết," mà là liệu bốn điều kiện của bootstrap contract có được đáp ứng không — có thể bắt đầu, có thể test, có thể thấy tiến độ, có thể chọn bước tiếp theo. Sử dụng danh sách kiểm tra này để xác nhận khởi tạo:
markdown ## Danh sách Kiểm tra Chấp nhận Khởi tạo
- [ ] `make setup` thành công từ đầu
- [ ] `make test` có ít nhất một test vượt qua
- [ ] Một phiên agent mới có thể trả lời "làm thế nào để chạy" và "làm thế nào để test" chỉ từ nội dung repo
- [ ] Tệp phân chia tác vụ tồn tại với ít nhất 3 tác vụ
- [ ] Mọi thứ đã được commit vào git
Ví dụ Thực tế
Hai cách tiếp cận khởi tạo cho một dự án frontend React:
Cách tiếp cận hỗn hợp (đồng thời đổ móng và xây tường) : Agent đồng thời tạo scaffolding dự án và triển khai tính năng đầu tiên trong phiên 1. Ở cuối phiên, repo có mã có thể chạy nhưng: không có tài liệu lệnh bắt đầu/test rõ ràng, không có tệp theo dõi tiến độ, không có phân chia tác vụ. Phiên 2 dành ~20 phút để suy ra cấu trúc dự án, khung test và quy trình build — giống như đội xây dựng mới đến công trường, không biết móng đã chạy đến đâu hoặc đường ống nước ở đâu, phải đào lỗ từng chỗ để tìm ra.
Khởi tạo riêng biệt (móng trước) : Phiên 1 chỉ làm khởi tạo — tạo cấu trúc thư mục từ mẫu, cấu hình khung test (Vitest + React Testing Library), viết và xác minh một test mẫu, tạo tài liệu bootstrap contract và tệp phân chia tác vụ, commit checkpoint ban đầu. Chi phí tái xây dựng của phiên 2 dưới 3 phút, và nó bắt đầu làm việc trực tiếp từ danh sách tác vụ — đội đến, nhìn vào bản vẽ, và biết chính xác nơi cần tiếp tục.
So sánh chu kỳ dự án đầy đủ: tổng thời gian tái xây dựng (qua tất cả các phiên) của cách tiếp cận hỗn hợp cao hơn ~60% so với cách tiếp cận khởi tạo riêng biệt. 20 phút thêm dành cho khởi tạo được thu hồi nhiều lần trong các phiên tiếp theo. Giống như móng vững giúp tường xây nhanh hơn — chậm là nhanh.
Những Điểm chính cần Nhớ
Khởi tạo và triển khai có mục tiêu tối ưu hóa khác nhau — trộn lẫn chúng chỉ kéo cả hai xuống. Đổ móng trước, rồi xây tường.
Kết quả của khởi tạo không phải là mã, mà là cơ sở hạ tầng: môi trường có thể chạy, test có thể xác minh, bootstrap contract, phân chia tác vụ.
Xác nhận khởi tạo bằng bốn điều kiện của bootstrap contract: có thể bắt đầu, có thể test, có thể thấy tiến độ, có thể chọn bước tiếp theo.
Khởi động ấm tốt hơn khởi động lạnh. Sử dụng mẫu dự án để đặt trước cơ sở hạ tầng chuẩn hóa.
Thời gian đầu tư vào khởi tạo được thu hồi hoàn toàn trong 3-4 phiên tiếp theo. Đây không phải chi phí thêm — đó là đầu tư trước. Móng càng vững, tòa nhà xây càng nhanh.
Đọc thêm
Anthropic: Effective Harnesses for Long-Running Agents
OpenAI: Harness Engineering
HumanLayer: Harness Engineering for Coding Agents
Infrastructure as Code — Martin Fowler
SWE-agent: Agent-Computer Interfaces
Bài tập
Thiết kế bootstrap contract : Viết một bootstrap contract hoàn chỉnh cho một dự án bạn đang phát triển. Sau đó mở một phiên agent hoàn toàn mới, chỉ hiển thị nội dung repo (không có ngữ cảnh lời nói), và để nó thử bắt đầu dự án, chạy test và hiểu tiến độ hiện tại. Ghi lại mọi vấn đề gặp phải — mỗi vấn đề tương ứng với một điều khoản còn thiếu trong bootstrap contract của bạn.
Thí nghiệm so sánh : Chọn một dự án mới cỡ vừa. Cách A: để agent đồng thời khởi tạo và thực hiện triển khai đầu tiên. Cách B: dành một phiên cho khởi tạo riêng biệt, bắt đầu triển khai trong phiên 2. Sau 4 phiên, so sánh: thời gian đến xác minh đầu tiên, chi phí tái xây dựng, tỷ lệ hoàn thành tính năng.
Danh sách kiểm tra chấp nhận khởi tạo : Thiết kế một danh sách kiểm tra chấp nhận khởi tạo cho dự án của bạn. Để một phiên agent mới thực thi từng mục trong danh sách kiểm tra và ghi lại cái nào vượt qua và cái nào thất bại. Các mục thất bại là nơi harness của bạn cần được tăng cường.
Bài giảng 07. Vẽ ranh giới nhiệm vụ rõ ràng (WIP=1) 9,612 ký tự
English Version → | 中文版本 →
Ví dụ mã nguồn: code/ Dự án thực hành: Dự án 04. Phản hồi Runtime và Kiểm soát Phạm vi
Bài 07. Vạch Ranh giới Tác vụ Rõ ràng cho Agent
Bạn nói với Claude Code "thêm xác thực người dùng vào dự án này," và nó bắt đầu sửa đổi database schema, viết route, thay đổi frontend component, và — nhân tiện — tái cấu trúc error-handling middleware. Hai giờ sau bạn kiểm tra: 12 tệp được sửa đổi, 800 dòng mã mới, và không có một tính năng nào hoạt động end-to-end.
Bạn không thể ăn vội nuốt tươi — câu nói này áp dụng đặc biệt cho AI agent. Agent vốn có xung lực "làm thêm một chút" — chúng thấy những thứ liên quan và chỉ xử lý chúng luôn, giống như người đi siêu thị mua một chai nước tương mà ra về đẩy cả xe hàng đầy. Vấn đề là, con người mua quá nhiều chỉ lãng phí tiền; agent làm quá nhiều thứ đồng thời có nghĩa là không cái nào được làm đúng.
Blog kỹ thuật "Effective harnesses for long-running agents" của Anthropic nói rõ ràng: khi các prompt quá rộng, các agent có xu hướng "bắt đầu nhiều thứ cùng một lúc" thay vì "hoàn thành một thứ trước." Các thực hành kỹ thuật Codex của OpenAI cũng thấy điều tương tự — các tác vụ không có kiểm soát phạm vi rõ ràng thấy tỷ lệ hoàn thành giảm mạnh. Đây không phải vấn đề mô hình — đây là vấn đề harness. Bạn chưa vạch ranh giới.
Sự Chú ý là Tài nguyên Hữu hạn
Đây không phải phép ẩn dụ — đây là toán học. Giả sử năng lực ngữ cảnh của agent là C và nó kích hoạt k tác vụ đồng thời. Mỗi tác vụ nhận được trung bình C/k tài nguyên lý luận. Khi C/k giảm xuống dưới ngưỡng tối thiểu cần thiết để hoàn thành một tác vụ duy nhất, không cái nào trong số chúng được hoàn thành. Bụng bạn chỉ có giới hạn — nhét mười cái bánh bao cùng một lúc và bạn sẽ không tiêu hóa hết tất cả, bạn chỉ bị khó tiêu mười lần.
Hành vi thực tế của Claude Code rất rõ ràng. Yêu cầu nó "thêm đăng ký người dùng" và nó có thể:
Tạo User model
Viết route đăng ký
Nhận thấy cần xác minh email, vậy thêm mail service
Thấy mật khẩu cần được hash, vậy mang vào bcrypt
Nhận thấy error handling không nhất quán, vậy tái cấu trúc global error middleware
Thấy cấu trúc tệp test lộn xộn, vậy sắp xếp lại thư mục
Sau sáu bước, mỗi cái đang làm dở. Không có xác minh end-to-end, mã nửa vời phức tạp cộng lẫn nhau, và phiên tiếp theo để dọn dẹp sẽ hoàn toàn bị lạc. Giống như ai đó đang nấu sáu món đồng thời — mỗi món đều đang trong chảo nhưng chưa cái nào được bày ra đĩa. Tất cả đều cháy.
Dữ liệu thực nghiệm của Anthropic trực tiếp hỗ trợ điều này: các agent sử dụng chiến lược "bước tiếp theo nhỏ" (tương đương WIP=1) cho thấy tỷ lệ hoàn thành tác vụ cao hơn 37% so với các agent sử dụng các prompt rộng. Thú vị hơn, số dòng mã được tạo ra bởi agent tương quan âm yếu với tỷ lệ hoàn thành tính năng thực tế — viết nhiều mã hơn, hoàn thành ít tính năng hơn. Không thể ăn vội nuốt tươi, được chứng minh bằng dữ liệu.
Luồng Công việc WIP=1
Các Khái niệm Cốt lõi
Vượt phạm vi (Overreach) : Agent kích hoạt nhiều tác vụ hơn mức tối ưu trong một phiên. Có thể định lượng được — làm 5 tính năng với 0 cái vượt qua end-to-end là vượt phạm vi.
Dưới mức hoàn thành (Under-finish) : Tỷ lệ tác vụ vượt qua xác minh end-to-end, trong tổng số tác vụ được kích hoạt, giảm xuống dưới ngưỡng. Mã được viết nhưng test không vượt qua là dưới mức hoàn thành.
Giới hạn WIP (Work-in-Progress Limit) : Từ phương pháp Kanban. Ý tưởng cốt lõi: giới hạn số lượng tác vụ đang tiến hành cùng một lúc. Đối với agent, WIP=1 là giá trị mặc định an toàn nhất — hoàn thành một cái trước khi bắt đầu cái tiếp theo. Giống như buffet — đừng chồng đĩa, hoàn thành một đĩa rồi quay lại lấy thêm.
Bằng chứng Hoàn thành (Completion Evidence) : Điều kiện có thể xác minh mà một tác vụ phải thỏa mãn để chuyển từ "đang thực hiện" sang "xong." Không có điều này, agent thay thế "mã trông có vẻ ổn" cho "hành vi vượt qua test."
Bề mặt Phạm vi (Scope Surface) : Cấu trúc DAG nơi mỗi nút là một đơn vị công việc và cạnh là các phụ thuộc. Trạng thái giới hạn ở bốn: not_started, active, blocked, passing.
Áp lực Hoàn thành (Completion Pressure) : Lực ràng buộc mà harness tác dụng thông qua giới hạn WIP và yêu cầu bằng chứng hoàn thành, buộc agent hoàn thành tác vụ hiện tại trước khi bắt đầu một cái mới.
Vượt Phạm vi và Dưới mức Hoàn thành là Cộng sinh
Hai vấn đề này không độc lập — chúng khuếch đại lẫn nhau. Vượt phạm vi làm loãng sự chú ý, sự chú ý bị loãng gây dưới mức hoàn thành, và mã nửa vời còn lại tăng độ phức tạp hệ thống, điều này tiếp tục thúc đẩy vượt phạm vi trong tác vụ tiếp theo. Một vòng lặp vicious.
Theo thuật ngữ Kanban: Định luật Little cho chúng ta biết L = lambda * W. Nếu công việc đang tiến hành L quá cao (làm quá nhiều thứ cùng một lúc), thời gian thực hiện W cho mỗi tác vụ tất yếu tăng lên. Đối với agent, điều này có nghĩa là mỗi tính năng mất nhiều thời gian hơn từ bắt đầu đến hoàn thành đã xác minh, và xác suất thất bại tăng lên.
Đây cũng là một vấn đề cũ trong thế giới con người — Steve McConnell đã ghi lại trong Rapid Development rằng scope creep là nguyên nhân hàng đầu gây thất bại dự án. Nhưng con người ít nhất có trực giác "tôi đã làm đủ rồi." Agent thì không. Tạo ra ý tưởng tiếp theo tốn mô hình gần như không có token thêm — viết "để tôi sửa cái này luôn" hầu như không đáng kể — nhưng mỗi sửa đổi bổ sung làm loãng sự chú ý của agent. Giống như buffet nơi mỗi đĩa thêm có chi phí biên gần bằng không, nhưng bụng bạn chỉ có giới hạn.
Cách Làm Đúng
1. Thực thi WIP=1
Đây là phương pháp trực tiếp và hiệu quả nhất. Trong harness của bạn, hãy nói rõ ràng với agent: chỉ một tác vụ được phép ở trạng thái "active" tại bất kỳ thời điểm nào. Trong CLAUDE.md của Claude Code hoặc AGENTS.md của Codex, hãy viết:
## Quy tắc Làm việc
- Làm việc trên một tính năng tại một thời điểm
- Chỉ bắt đầu tính năng tiếp theo sau khi tính năng hiện tại vượt qua xác minh end-to-end
- Đừng "cũng tái cấu trúc" tính năng B trong khi triển khai tính năng A
Giống như ăn buffet — một đĩa mỗi lần, hoàn thành nó trước khi quay lại lấy thêm.
2. Định nghĩa Bằng chứng Hoàn thành Rõ ràng cho Mỗi Tác vụ
Xong không phải là "mã được viết" — mà là "xác minh hành vi vượt qua." Trong feature list của bạn, mỗi mục cần một lệnh xác minh:
F01: Đăng ký Người dùng
Xác minh: curl -X POST /api/register -d '{"email":"test@example.com","password":"123456"}' | jq .status == 201
Trạng thái: passing
3. Ngoại hóa Bề mặt Phạm vi
Sử dụng tệp có thể đọc bởi máy (JSON hoặc Markdown) để ghi lại tất cả trạng thái tác vụ. Bất kỳ phiên mới nào cũng có thể đọc tệp này và biết ngay: tác vụ nào đang hoạt động? Hành vi nào được coi là xong? Xác minh nào đã vượt qua?
4. Theo dõi Tỷ lệ Hoàn thành Đã xác minh
Harness nên liên tục theo dõi VCR (Verified Completion Rate) = tác vụ đã xác minh / tác vụ được kích hoạt. Chặn kích hoạt tác vụ mới khi VCR < 1.0.
Trường hợp Thực tế
Một dự án REST API với 8 tính năng, hai chiến lược được so sánh:
Chế độ buffet (không có ràng buộc) : Agent kích hoạt 5 tính năng đồng thời trong phiên 1. Tạo ra ~800 dòng trên 12 tệp. Tỷ lệ vượt qua test end-to-end: 20% — chỉ đăng ký người dùng hoạt động. 4 tính năng còn lại: database schema được tạo nhưng thiếu logic xác thực, route được định nghĩa nhưng trả về định dạng phản hồi sai. Giống như ai đó nấu sáu món cùng một lúc, chỉ có một món tạm ăn được. Đến cuối phiên 3, chỉ 3 trong 8 tính năng hoàn thành.
Chế độ một đĩa (WIP=1) : Agent chỉ làm việc trên đăng ký người dùng trong phiên 1. Tạo ra ~200 dòng trên 4 tệp. Test end-to-end: 100% vượt qua. Commit một triển khai sạch, đã xác minh. Đến cuối phiên 4, 7 trong 8 tính năng hoàn thành (cái thứ 8 bị chặn bởi phụ thuộc bên ngoài).
Kết quả: tổng mã ít hơn (800 vs 1200 dòng) nhưng mã hiệu quả hơn. Tỷ lệ hoàn thành: 87.5% vs 37.5%. Ăn từng miếng một, và bạn thực sự ăn được nhiều hơn.
Những Điểm chính cần Nhớ
WIP=1 là cài đặt an toàn mặc định cho harness agent — hoàn thành một cái, rồi bắt đầu cái tiếp theo; đừng cố song song hóa. Bạn không thể béo lên trong một bữa ăn.
Bằng chứng hoàn thành phải có thể thực thi — "mã trông có vẻ ổn" không tính; "curl trả về 201" mới tính.
Bề mặt phạm vi phải được ngoại hóa như một tệp — không chỉ đề cập trong hội thoại, mà được ghi lại ở định dạng có thể đọc bởi máy trong repo.
Vượt phạm vi và dưới mức hoàn thành là cộng sinh — giải quyết một cái giải quyết cái kia.
"Làm ít nhưng hoàn thành" luôn tốt hơn "làm nhiều nhưng để lại một nửa" — dòng mã agent và tỷ lệ hoàn thành tính năng tương quan âm. Chất lượng luôn tốt hơn số lượng.
Đọc thêm
Effective harnesses for long-running agents - Anthropic — Blog kỹ thuật của Anthropic, thảo luận chi tiết về chiến lược "bước tiếp theo nhỏ"
Harness Engineering - OpenAI — Xử lý đầy đủ về harness engineering của OpenAI
Kanban: Successful Evolutionary Change - David Anderson — Nguồn kinh điển về giới hạn WIP
Rapid Development - Steve McConnell — Dữ liệu thực nghiệm về scope creep là nguyên nhân hàng đầu gây thất bại dự án
Bài tập
Nguyên tử hóa tác vụ : Chọn một yêu cầu rộng (ví dụ: "triển khai hệ thống quản lý người dùng") và chia thành ít nhất 5 đơn vị công việc nguyên tử. Cho mỗi đơn vị, chỉ định: (a) mô tả hành vi đơn, (b) lệnh xác minh có thể thực thi, (c) các phụ thuộc. Kiểm tra liệu việc phân chia có thỏa mãn ràng buộc WIP=1 không.
Thí nghiệm So sánh : Chạy cùng dự án hai lần — một lần không có ràng buộc, một lần với WIP=1 được thực thi. So sánh: tỷ lệ hoàn thành đã xác minh, tổng số dòng mã, tỷ lệ mã hiệu quả.
Kiểm toán Bằng chứng Hoàn thành : Xem xét kết quả của một lần chạy agent gần đây, phân loại từng thay đổi mã là "hành vi đã hoàn thành," "hành vi chưa hoàn thành" hoặc "scaffolding." Thêm các lệnh xác minh còn thiếu cho mỗi hành vi chưa hoàn thành.
Bài giảng 08. Feature list là primitive của harness 8,986 ký tự
English Version → | 中文版本 →
Ví dụ mã nguồn: code/ Dự án thực hành: Dự án 04. Phản hồi Runtime và Kiểm soát Phạm vi
Bài 08. Sử dụng Feature List để Ràng buộc những gì Agent Làm
Bạn yêu cầu một agent xây dựng một trang web thương mại điện tử. Sau khi nó hoàn thành, nó nói với bạn "xong." Bạn nhìn vào mã — xác thực người dùng hoạt động, nhưng nút thanh toán trong giỏ hàng không làm gì cả, và luồng thanh toán hoàn toàn không được kết nối. Vấn đề: bạn không bao giờ nói với nó "xong" có nghĩa là gì, vì vậy nó đã sử dụng tiêu chuẩn của riêng mình — "tôi đã viết nhiều mã và nó trông khá đầy đủ."
Feature list, theo mắt nhiều người, chỉ là một ghi chú nhắc nhở — viết mọi thứ xuống để không quên, sau đó để sang một bên. Nhưng trong thế giới harness, feature list không phải là ghi chú cho con người — nó là xương sống của toàn bộ harness. Bộ lập lịch phụ thuộc vào nó để chọn tác vụ, bộ xác minh phụ thuộc vào nó để đánh giá hoàn thành, trình báo cáo bàn giao phụ thuộc vào nó để tạo tóm tắt. Phá vỡ xương sống và toàn bộ cơ thể bị tê liệt.
Cả Anthropic và OpenAI đều nhấn mạnh: các artifact phải được ngoại hóa. Trạng thái tính năng phải sống trong một tệp có thể đọc bởi máy trong repo, không phải trong văn bản hội thoại không có cấu trúc.
Agent Không Biết "Xong" Có nghĩa là Gì
Cả Claude Code lẫn Codex đều không tự động biết ý bạn là gì khi nói "xong." Bạn nói "thêm tính năng giỏ hàng," và sự diễn giải của mô hình có thể là "viết một Cart component và một addToCart method." Nhưng ý bạn là "người dùng có thể duyệt sản phẩm, thêm vào giỏ hàng, và hoàn thành thanh toán end-to-end." Khoảng cách hiểu biết này tồn tại mãi mà không có feature list. Agent sử dụng tiêu chuẩn ẩn của riêng mình — thường là "mã không có lỗi cú pháp rõ ràng." Những gì bạn cần là xác minh hành vi end-to-end. Giống như nhờ bạn mua hoa quả — bạn nói "lấy vài thứ hoa quả" và họ về với chanh. Hoa quả của họ và hoa quả của bạn không phải là cùng loại hoa quả.
Nhìn vào ghi chú tiến độ phổ biến này:
Đã làm xác thực người dùng, giỏ hàng hầu như xong, vẫn cần thanh toán
Một phiên agent mới có thể trả lời những câu hỏi này từ ghi chú này không? "Hầu như xong" có nghĩa là gì? Test nào giỏ hàng đã vượt qua? Điều gì đang chặn thanh toán? Câu trả lời cho tất cả là "không ai biết." Giống như nói với bác sĩ "bụng tôi đau, gần đây ổn hơn" — họ có thể kê thuốc gì?
Kết quả: phiên mới dành 20 phút để suy ra trạng thái dự án, và có thể triển khai lại các tính năng đã hoàn thành. Dữ liệu kỹ thuật của Anthropic cho thấy bản ghi tiến độ tốt giảm thời gian chẩn đoán khởi động phiên 60-80%.
Máy trạng thái Tính năng
Các Khái niệm Cốt lõi
Feature list là nguyên lý cơ bản của harness : Không phải "công cụ lập kế hoạch tùy chọn," mà là cấu trúc dữ liệu nền tảng mà tất cả các thành phần harness khác phụ thuộc vào. Giống như cấu trúc bảng cơ sở dữ liệu — bạn không thể nói "hãy bỏ qua khóa chính."
Cấu trúc ba yếu tố : Mỗi mục tính năng là một bộ ba (mô tả hành vi, lệnh xác minh, trạng thái hiện tại) . Thiếu bất kỳ yếu tố nào làm cho mục không đầy đủ.
Mô hình máy trạng thái : Mỗi mục tính năng có bốn trạng thái — not_started , active , blocked , passing . Chuyển đổi trạng thái được kiểm soát bởi harness, không được thay đổi tự do bởi agent.
Gating trạng thái vượt qua (Pass-state gating) : Cách duy nhất một tính năng chuyển từ active sang passing là thực thi thành công lệnh xác minh. Điều này không thể đảo ngược — một khi passing , nó không thể quay lại. Giống như vượt qua bài thi có nghĩa là bạn đã qua, bạn không thể hồi tố thay đổi điểm.
Nguồn sự thật duy nhất : Tất cả thông tin về "những gì cần làm" phải bắt nguồn từ một feature list. Không có mâu thuẫn giữa feature list và lịch sử hội thoại.
Áp lực ngược (Back-pressure) : Số lượng tính năng chưa vượt qua là áp lực mà harness tác dụng lên agent. Áp lực bằng không = dự án hoàn thành.
Tại sao Feature List Phải là "Nguyên lý Cơ bản"
Tài liệu là để con người đọc; nguyên lý cơ bản là để hệ thống thực thi. Tài liệu có thể bị bỏ qua; nguyên lý cơ bản không thể bị vượt qua.
Nghĩ về nó như ràng buộc trigger cơ sở dữ liệu vs. kiểm tra lớp ứng dụng: cái trước được thực thi bởi engine cơ sở dữ liệu, không có SQL nào có thể bỏ qua nó; cái sau phụ thuộc vào tính đúng đắn của mã ứng dụng và có thể vô tình bị vượt qua. Feature list như nguyên lý cơ bản harness phục vụ bốn thành phần harness cụ thể:
Bộ lập lịch (Scheduler) : Đọc trạng thái, chọn tính năng not_started tiếp theo. Giống như hệ thống lập kế hoạch sản xuất nhà máy.
Bộ xác minh (Verifier) : Thực thi lệnh xác minh, quyết định có cho phép chuyển đổi trạng thái không. Giống như kiểm tra chất lượng.
Trình báo cáo bàn giao (Handoff Reporter) : Tự động tạo tóm tắt bàn giao phiên từ feature list. Giống như báo cáo ca tự động.
Trình theo dõi tiến độ (Progress Tracker) : Đếm phân phối trạng thái, cung cấp số liệu sức khỏe dự án. Giống như dashboard.
Cách Làm Đúng
1. Định nghĩa Định dạng Feature List Tối giản
Bạn không cần một hệ thống phức tạp — một tệp Markdown hoặc JSON có cấu trúc là đủ. Điều quan trọng là mỗi mục phải có bộ ba:
json {
"id" : "F03" ,
"behavior" : "POST /cart/items với {product_id, quantity} trả về 201" ,
"verification" : "curl -X POST http://localhost:3000/api/cart/items -H 'Content-Type: application/json' -d '{ \" product_id \" :1, \" quantity \" :2}' | jq .status == 201" ,
"state" : "passing" ,
"evidence" : "commit abc123, test output log"
}
2. Để Harness Kiểm soát Chuyển đổi Trạng thái
Agent không thể trực tiếp thay đổi trạng thái của tính năng thành passing . Nó chỉ có thể gửi yêu cầu xác minh; harness thực thi lệnh xác minh và quyết định có cho phép chuyển đổi không. Đây là "pass-state gating."
3. Viết Quy tắc trong CLAUDE.md
## Quy tắc Feature List
- Tệp feature list: /docs/features.md
- Chỉ một tính năng active tại một thời điểm
- Lệnh xác minh phải vượt qua trước khi đánh dấu là passing
- Đừng tự mình sửa đổi trạng thái feature list — script xác minh cập nhật chúng tự động
4. Hiệu chỉnh Độ hạt
Mỗi mục tính năng phải có phạm vi "có thể hoàn thành trong một phiên." Quá rộng thì không xong; quá hẹp thì overhead quản lý tăng lên. "Người dùng có thể thêm mục vào giỏ hàng" là độ hạt tốt. "Triển khai giỏ hàng" là quá rộng. "Tạo trường tên trên Cart model" là quá hẹp. Giống như cắt bít tết — không phải cả miếng, và cũng không phải thịt băm.
Trường hợp Thực tế
Một nền tảng thương mại điện tử với 10 tính năng. Hai cách tiếp cận theo dõi được so sánh:
Chế độ ghi chú nhắc nhở : Agent sử dụng ghi chú không có cấu trúc. Sau 3 phiên, ghi chú trở thành "đã làm xác thực người dùng và danh sách sản phẩm, giỏ hàng hầu như xong nhưng có lỗi, thanh toán chưa bắt đầu." Phiên mới cần 20 phút để suy ra trạng thái, cuối cùng triển khai lại các tính năng đã hoàn thành. Giống như danh sách mua sắm của bạn nói "sữa, bánh mì và cái đó" — ở cửa hàng, bạn vẫn không biết mua gì.
Chế độ xương sống : Mỗi tính năng có trạng thái và lệnh xác minh rõ ràng. Phiên mới đọc feature list và trong 3 phút biết: F01-F05 là passing , F06 là active , F07-F10 là not_started . Tiếp tục từ F06 trực tiếp, không có làm lại nào.
Kết quả định lượng: các dự án sử dụng feature list có cấu trúc cho thấy tỷ lệ hoàn thành tính năng cao hơn 45% so với theo dõi tự do, với zero triển khai trùng lặp.
Những Điểm chính cần Nhớ
Feature list là xương sống của harness , không phải ghi chú cho con người. Bộ lập lịch, bộ xác minh và trình báo cáo bàn giao đều phụ thuộc vào chúng.
Mỗi mục tính năng phải có bộ ba : mô tả hành vi + lệnh xác minh + trạng thái hiện tại. Thiếu một yếu tố thì không đầy đủ — giống như ghế ba chân thiếu một chân.
Chuyển đổi trạng thái được kiểm soát bởi harness — agent không thể tự mình thay đổi trạng thái. Vượt qua xác minh = con đường nâng cấp duy nhất.
Feature list là nguồn sự thật duy nhất của dự án — tất cả thông tin "phải làm gì" đều bắt nguồn từ một danh sách.
Hiệu chỉnh độ hạt thành "có thể hoàn thành trong một phiên."
Đọc thêm
Building Effective Agents - Anthropic — Xác định rõ ràng feature list là "cấu trúc dữ liệu cốt lõi" để kiểm soát phạm vi agent
Harness Engineering - OpenAI — Nhấn mạnh nguyên tắc "ngoại hóa artifact"
Design by Contract - Bertrand Meyer — Nguyên tắc thiết kế hợp đồng, nền tảng lý thuyết của feature list
How Google Tests Software — Tháp kiểm thử và thực hành kỹ thuật đặc tả hành vi
Bài tập
Thiết kế Feature List : Định nghĩa một JSON schema feature list tối giản. Bao gồm: id, mô tả hành vi, lệnh xác minh, trạng thái hiện tại, tham chiếu bằng chứng. Sử dụng nó để mô tả một dự án thực tế với 5 tính năng.
So sánh Độ khắt khe Xác minh : Chọn 3 tính năng và thiết kế cả xác minh "lỏng" (ví dụ: "mã không có lỗi cú pháp") và xác minh "nghiêm" (ví dụ: "test end-to-end vượt qua"). So sánh tỷ lệ dương tính giả dưới mỗi cách tiếp cận.
Kiểm toán Nguyên tắc Nguồn duy nhất : Xem xét một dự án agent hiện có và kiểm tra thông tin phạm vi mâu thuẫn với feature list (yêu cầu ẩn trong hội thoại, chú thích TODO trong mã, v.v.). Thiết kế kế hoạch để hợp nhất tất cả thông tin vào feature list.
Bài giảng 09. Chặn agent “tuyên bố xong quá sớm” 13,119 ký tự
English Version → | 中文版本 →
Mã nguồn ví dụ cho bài giảng này: code/ Thực hành: Dự án 05. Để agent tự xác minh công việc của mình
Bài 9. Ngăn chặn Agent Tuyên bố Thành công Quá sớm
Bạn yêu cầu một agent thực hiện tính năng "đặt lại mật khẩu". Nó sửa đổi cấu trúc cơ sở dữ liệu, viết API endpoint, thêm mẫu email, chạy unit test (tất cả đều qua), và sau đó tự tin nói với bạn rằng "đã xong." Nhưng khi bạn thực sự thử chạy nó—liên kết đặt lại mật khẩu không thể gửi được (thiếu cấu hình dịch vụ email), quá trình di chuyển cơ sở dữ liệu bị lỗi giữa chừng (không nhất quán cấu trúc), và toàn bộ quy trình chưa được thực thi thực tế dù chỉ một lần.
Cảm giác này không có gì lạ—giống như việc điền kín toàn bộ bài thi, tự tin nộp bài đầu tiên, chỉ để trượt khi có điểm. Chỉ vì bài thi được viết kín không có nghĩa là các câu trả lời đều đúng.
Đây không phải là một sự cố cá biệt. Bài báo ICML kinh điển năm 2017 của Guo và cộng sự đã chứng minh: các mạng nơ-ron hiện đại thường quá tự tin một cách có hệ thống —độ tự tin mà các mô hình báo cáo cao hơn đáng kể so với độ chính xác thực tế của chúng. Điều này cũng đúng với các AI coding agent: chúng "cảm thấy" chúng đã xong, nhưng thực tế, chúng còn lâu mới xong. Harness của bạn phải thay thế "cảm giác" của agent bằng sự xác minh dựa trên thực thi bên ngoài.
Con dốc trơn trượt
Các tuyên bố hoàn thành sớm hầu như luôn theo cùng một khuôn mẫu: mã trông có vẻ ổn—cú pháp đúng, logic có vẻ hợp lý và phân tích tĩnh không cho thấy lỗi rõ ràng. Nhưng harness không bắt buộc xác minh thực thi toàn diện, do đó agent bỏ qua việc thực sự chạy mã hoặc chỉ chạy các bài kiểm thử một phần. Nó chạy unit test nhưng bỏ qua integration test; nó chạy test nhưng không kiểm tra độ phủ (coverage). Cuối cùng, "mã trông có vẻ ổn" được coi là bằng chứng cho "tính năng đã hoàn thành." Và bài thi được nộp.
Thông tin bị mất đi ở mỗi bước. Từ thông số kỹ thuật tác vụ đến triển khai mã rồi đến hành vi runtime, mọi sự chuyển đổi đều có thể đưa vào sự sai lệch, và mỗi bước xác minh bị bỏ qua đều làm trầm trọng thêm sự bất đối xứng thông tin.
Kiểm tra Kết thúc Ba Lớp
Các Khái niệm Cốt lõi
Tuyên bố Hoàn thành Sớm : Agent khẳng định tác vụ đã hoàn thành, nhưng vẫn tồn tại các thông số kỹ thuật chưa được đáp ứng. Vấn đề cốt lõi: agent đánh giá dựa trên sự tự tin cục bộ ở cấp độ mã nguồn, trong khi tính đúng đắn ở cấp độ hệ thống đòi hỏi xác minh tổng thể.
Sai lệch Hiệu chuẩn Độ Tự tin : Khoảng cách có hệ thống giữa độ tự tin hoàn thành tự báo cáo của agent và chất lượng hoàn thành thực tế. Đối với các tác vụ đa tệp phức tạp, độ lệch này rất dương—agent luôn tự tin hơn so với khả năng thực hiện thực tế. Giống như một học sinh luôn đánh giá quá cao điểm số của mình sau kỳ thi.
Tiêu chí Kết thúc : Một tập hợp các điều kiện đánh giá rõ ràng, có thể thực thi được xác định trong harness. Agent phải thỏa mãn tất cả các điều kiện trước khi tuyên bố hoàn thành. "Đã xong" chuyển từ một đánh giá chủ quan sang một xác định khách quan.
Cổng Kép Xác minh-Xác nhận (Verification-Validation) : Lớp xác minh đầu tiên kiểm tra "mã có triển khai chính xác hành vi được chỉ định không"; lớp xác nhận thứ hai kiểm tra "hành vi cấp hệ thống có đáp ứng các yêu cầu end-to-end không". Cả hai đều phải qua để được coi là hoàn thành.
Tín hiệu Phản hồi Runtime : Nhật ký (logs), trạng thái tiến trình và kiểm tra tình trạng (health checks) từ việc thực thi chương trình. Đây là cơ sở khách quan để harness đánh giá chất lượng hoàn thành.
Ràng buộc Ưu tiên Hoàn thành : Đầu tiên xác minh tính đúng đắn của chức năng, sau đó xử lý hiệu suất, và cuối cùng giải quyết phong cách. Việc tái cấu trúc (refactoring) bị cấm cho đến khi chức năng cốt lõi được xác minh.
Vượt qua Unit Test ≠ Tác vụ Hoàn thành
Đây là cạm bẫy phổ biến nhất và cũng nguy hiểm nhất. Agent đã viết mã, chạy unit test, tất cả đều xanh và nói "đã xong." Nhưng triết lý thiết kế của unit test—cô lập đơn vị được kiểm tra và giả lập (mocking) các phụ thuộc—chính xác là điều làm cho chúng không có khả năng phát hiện các vấn đề xuyên thành phần:
Không khớp Giao diện (Interface Mismatch) : Đường dẫn tệp được chuyển bởi quá trình render cho preload script là đường dẫn tương đối, nhưng preload script mong đợi đường dẫn tuyệt đối. Cả hai bài kiểm tra đơn vị tương ứng của chúng đều sử dụng mock và đã vượt qua. Vấn đề chỉ được phát hiện trong quá trình kiểm tra end-to-end. Giống như mỗi nhạc công trong một ban nhạc thực hành hoàn hảo khi chơi một mình, nhưng lại nhận ra họ đang chơi ở các tông khác nhau khi chơi cùng nhau.
Lỗi Truyền Trạng thái (State Propagation Errors) : Một quá trình migration cơ sở dữ liệu thay đổi cấu trúc bảng, nhưng lớp bộ nhớ cache ORM vẫn giữ các mục cache cho cấu trúc cũ. Unit test cung cấp một môi trường mock mới mỗi lần, điều này sẽ không để lộ sự không nhất quán trạng thái xuyên lớp này.
Phụ thuộc Môi trường (Environment Dependency) : Mã hoạt động chính xác trong môi trường test (nơi mọi thứ được mock) nhưng thất bại trong môi trường thực do sự khác biệt về cấu hình, độ trễ mạng hoặc dịch vụ không khả dụng. Giống như hát hoàn hảo trong phòng tập, nhưng gặp sự cố thiết bị âm thanh trên sân khấu.
"Nhân tiện Tái cấu trúc luôn" là Thuốc độc đối với việc Đánh giá Hoàn thành
Claude Code có một kiểu hành vi phổ biến: nó bắt đầu tái cấu trúc mã, tối ưu hóa hiệu suất và cải thiện phong cách trước khi chức năng cốt lõi vượt qua xác minh. Câu nói của Knuth, "Tối ưu hóa sớm là nguồn gốc của mọi tội lỗi," có một ý nghĩa mới trong kịch bản agent—việc tái cấu trúc làm thay đổi ranh giới giữa mã đã được xác minh và chưa được xác minh, có khả năng phá vỡ các luồng mã trước đó đã ngầm định là đúng. Giống như việc bạn chép lại các câu trả lời trắc nghiệm của mình để có định dạng đẹp hơn trước khi bạn hoàn thành các câu hỏi tự luận toán—không chỉ lãng phí thời gian mà bạn còn có thể chép sai.
Sự Sai lệch có Hệ thống trong Tự đánh giá
Anthropic đã phát hiện ra một mô hình lỗi sâu sắc hơn trong nghiên cứu năm 2026 của họ: khi một agent được yêu cầu đánh giá công việc của chính nó, nó sẽ đưa ra các đánh giá quá tích cực một cách có hệ thống—ngay cả khi một người quan sát con người sẽ coi chất lượng rõ ràng là dưới tiêu chuẩn. Điều này giống như yêu cầu một học sinh tự chấm điểm bài thi của mình—họ sẽ luôn đặc biệt khoan dung với câu trả lời của chính họ.
Vấn đề này đặc biệt nghiêm trọng trong các tác vụ mang tính chủ quan (chẳng hạn như thẩm mỹ thiết kế)—việc liệu một "bố cục có tinh tế hay không" là một cuộc gọi phán đoán, và agent có xu hướng đáng tin cậy về phía tích cực. Ngay cả đối với các tác vụ có thể xác minh kết quả, hiệu suất của agent cũng có thể bị cản trở bởi khả năng phán đoán kém.
Giải pháp không phải là làm cho agent "khách quan hơn"—cùng một mô hình tạo ra và đánh giá vốn có xu hướng hào phóng với chính nó. Giải pháp là tách "người làm" khỏi "người kiểm tra". Giống như một học sinh không nên tự chấm bài thi của mình—bạn cần một người chấm điểm độc lập.
Một agent đánh giá độc lập, được tinh chỉnh đặc biệt để "kén chọn", hiệu quả hơn nhiều so với việc để agent tạo tự đánh giá. Dữ liệu thực nghiệm từ Anthropic:
Kiến trúc Thời gian chạy Chi phí Chức năng Cốt lõi Hoạt động? Agent Đơn lẻ (chạy trần) 20 phút $9 Không (các thực thể trò chơi không phản hồi với đầu vào) Ba Agent (planner + generator + evaluator) 6 giờ $200 Có (trò chơi có thể chơi hoàn toàn) Đây là cùng một mô hình (Opus 4.5) với cùng một prompt ("xây dựng một trình chỉnh sửa trò chơi retro 2D"). Sự khác biệt duy nhất là harness—từ "chạy trần" đến "planner mở rộng yêu cầu → generator thực hiện từng tính năng → evaluator thực hiện kiểm tra nhấp chuột thực tế bằng Playwright".
Nguồn: Anthropic: Harness design for long-running application development
Cách Ngăn chặn Việc Nộp bài Sớm
1. Ngoại hóa việc Đánh giá Kết thúc
Việc đánh giá hoàn thành không nên do chính agent thực hiện. Harness phải thực hiện xác nhận kết thúc một cách độc lập, sử dụng các tín hiệu runtime làm đầu vào chứ không phải sự tự tin của agent. Viết rõ điều này trong CLAUDE.md :
## Định nghĩa Hoàn thành (Definition of Done)
- Tính năng hoàn thành = xác minh end-to-end đã qua, không phải "mã đã được viết"
- Các cấp độ xác minh bắt buộc:
1. Unit tests pass
2. Integration tests pass
3. End-to-end flow verification passes
- Không chuyển sang cấp độ 2 nếu cấp độ 1 thất bại
- Không chuyển sang cấp độ 3 nếu cấp độ 2 thất bại
2. Xây dựng Xác nhận Kết thúc Ba Lớp
Lớp 1: Cú pháp và Phân tích Tĩnh . Chi phí thấp nhất, ít thông tin nhất, nhưng phải vượt qua. Đây là mức kiểm tra tối thiểu—bạn phải đánh vần đúng các từ trước khi chúng ta xem xét bất cứ thứ gì khác.
Lớp 2: Xác minh Hành vi Runtime . Thực thi test, kiểm tra khởi động ứng dụng, xác nhận đường dẫn quan trọng. Đây là bằng chứng cốt lõi của sự hoàn thành. Chỉ viết ra thôi là chưa đủ; nó phải chạy được.
Lớp 3: Xác nhận Cấp Hệ thống . Kiểm thử end-to-end, xác nhận tích hợp, mô phỏng kịch bản người dùng. Tuyến phòng thủ cuối cùng chống lại các tuyên bố sớm. Nó không chỉ phải chạy; nó phải chạy chính xác.
3. Thiết kế "Bút đỏ Đánh dấu" Tốt cho Agents
OpenAI đã giới thiệu một mẫu đặc biệt hiệu quả trong quá trình thực hành Codex của họ: các thông báo lỗi cho agent phải bao gồm các hướng dẫn sửa chữa . Đừng chỉ vẽ một dấu chéo đỏ lớn như một người chấm điểm lười biếng; hãy giống như một giáo viên giỏi và viết "đây là cách bạn nên thay đổi điều này" ở lề. Đừng sử dụng "Test failed" , mà hãy sử dụng "Test failed: POST /api/reset-password returned 500. Check that the email service config exists in environment variables. The template file should be at templates/reset-email.html." Phản hồi cụ thể, có thể hành động này cho phép agent tự sửa lỗi mà không cần sự can thiệp của con người.
4. Nắm bắt các Tín hiệu Runtime
Các tín hiệu runtime hiệu quả bao gồm:
Ứng dụng có khởi động thành công và đạt đến trạng thái sẵn sàng không?
Các đường dẫn tính năng quan trọng có thực thi thành công trong runtime không?
Các thao tác ghi cơ sở dữ liệu, hoạt động tệp và các hiệu ứng phụ khác có chính xác không?
Các tài nguyên tạm thời có được dọn dẹp không?
Trường hợp Thực tế
Tác vụ : Triển khai chức năng đặt lại mật khẩu người dùng. Bao gồm hoạt động cơ sở dữ liệu, gửi email và sửa đổi API endpoint.
Đường dẫn nộp bài sớm : Agent sửa đổi cấu trúc cơ sở dữ liệu, viết API endpoint, thêm mẫu email, chạy unit test (qua) và tuyên bố hoàn thành. Bài kiểm tra đã được điền đầy đủ.
Các điểm trừ thực tế : (1) Luồng end-to-end chưa được kiểm tra—việc gửi và xác minh thực tế liên kết đặt lại chưa bao giờ được xác nhận. (2) Quá trình migration cơ sở dữ liệu thất bại sau khi thực thi một phần, gây ra sự không nhất quán cấu trúc. (3) Cấu hình dịch vụ email bị thiếu trong môi trường đích.
Sự can thiệp của Harness : Xác nhận kết thúc bị bắt buộc—(1) Khởi động toàn bộ ứng dụng để xác minh khả năng truy cập endpoint đặt lại; (2) Thực thi toàn bộ quy trình đặt lại; (3) Xác minh tính nhất quán của trạng thái cơ sở dữ liệu. Tất cả các khiếm khuyết đã được tìm thấy trong phiên, tiết kiệm 5-10 lần chi phí của các bản sửa lỗi sau này. Người chấm điểm độc lập đã tìm ra các vấn đề thực sự.
Những Điểm chính cần Nhớ
Các Agent thường quá tự tin một cách có hệ thống —sai lệch hiệu chuẩn độ tự tin là một thực tế khách quan. Điền kín bài kiểm tra không có nghĩa là bạn đã làm đúng.
Đánh giá hoàn thành phải được ngoại hóa —harness tự xác minh một cách độc lập; đừng tin vào "cảm giác" của agent. Học sinh không thể tự chấm bài thi của mình.
Cả ba lớp xác nhận đều rất cần thiết —qua được cú pháp, qua được hành vi, qua được hệ thống, tiến triển từng lớp một.
Các thông báo lỗi nên giống như việc dùng bút đỏ đánh dấu của một giáo viên giỏi —bao gồm các bước sửa chữa cụ thể để agent có thể tự sửa đổi.
Không tái cấu trúc (refactoring) cho đến khi chức năng cốt lõi được xác minh —ràng buộc ưu tiên hoàn thành là chìa khóa để ngăn chặn tối ưu hóa sớm.
Đọc thêm
On Calibration of Modern Neural Networks - Guo et al. — Chứng minh các mạng sâu hiện đại thường quá tự tin một cách có hệ thống
Building Effective Agents - Anthropic — Vai trò quan trọng của bằng chứng runtime trong việc đánh giá hoàn thành
Harness Engineering - OpenAI — Tuyên bố hoàn thành sớm là một trong những chế độ lỗi chính của các agent
The Art of Software Testing - Myers — Tài liệu tham khảo kinh điển về phân cấp và hiệu quả của phương pháp kiểm thử
Bài tập
Thiết kế Hàm Xác nhận Kết thúc : Thiết kế một quy trình xác nhận kết thúc hoàn chỉnh cho một tác vụ liên quan đến việc di chuyển cơ sở dữ liệu và sửa đổi API. Liệt kê các tín hiệu runtime cần thiết và các tiêu chí đạt/trượt (pass/fail) cho từng tín hiệu. Chạy nó trên một tác vụ thực tế và ghi lại những vấn đề tiềm ẩn mà nó tìm thấy.
Đo lường Sai lệch Hiệu chuẩn : Chọn 10 loại tác vụ lập trình khác nhau và ghi lại độ tự tin hoàn thành tự báo cáo của agent so với chất lượng hoàn thành thực tế. Tính toán giá trị sai lệch và phân tích mối quan hệ của nó với độ phức tạp của tác vụ.
Thử nghiệm Phòng thủ Đa Lớp : Chạy ba cấu hình trên cùng một bộ tác vụ—(a) chỉ phân tích tĩnh, (b) thêm unit testing, (c) xác nhận đầy đủ ba lớp. So sánh tỷ lệ các tuyên bố hoàn thành sớm và số lượng các khiếm khuyết không bị phát hiện.
Bài giảng 10. End-to-end mới là kiểm chứng thật 11,900 ký tự
English Version → | 中文版本 →
Ví dụ mã nguồn cho bài giảng này: code/ Thực hành: Dự án 05. Để agent xác minh công việc của chính nó
Bài 10. Chỉ Testing End-to-End mới là Xác minh Thực sự
Bạn yêu cầu agent thêm tính năng xuất tệp vào ứng dụng Electron. Nó viết component render process, preload script và logic lớp service. Unit test cho từng component vượt qua hoàn hảo. Agent nói, "Xong rồi." Khi bạn thực sự nhấp vào nút xuất — định dạng đường dẫn tệp sai, thanh tiến trình không cập nhật, và xuất tệp lớn gây rò rỉ bộ nhớ. Năm lỗi ranh giới component, và unit test không bắt được một cái nào.
Giống như buổi tập hợp xướng — từng bè tiếng nghe hoàn hảo khi hát riêng, nhưng khi hát cùng nhau, bè soprano nhanh hơn nửa nhịp so với bè bass, và phần đệm lạc một nửa cung so với giai điệu chính. Từng phần "đúng" riêng lẻ, nhưng tổng thể lại không đồng điệu.
Tháp kiểm thử của Google cho chúng ta biết: số lượng lớn unit test là nền tảng, nhưng nếu dừng lại ở đó, bạn sẽ bỏ lỡ có hệ thống các vấn đề tương tác component. Đối với AI coding agent, vấn đề này còn nghiêm trọng hơn — các agent có xu hướng chỉ chạy các test nhanh nhất và sau đó tuyên bố hoàn thành. Chỉ testing end-to-end mới có thể chứng minh rằng các lỗi cấp hệ thống không tồn tại.
Điểm Mù của Unit Testing
Triết lý thiết kế của unit testing là cô lập — mock các phụ thuộc và chỉ tập trung vào đơn vị đang được test. Triết lý này làm cho unit testing nhanh và chính xác, nhưng nó cũng tạo ra các điểm mù có hệ thống. Giống như từng bè tiếng tập với tai nghe trong buổi tập hợp xướng — nghe ổn với họ, nhưng các vấn đề chỉ xuất hiện khi họ hát cùng nhau:
Không khớp giao diện : Đường dẫn tệp được truyền bởi render process cho preload script là đường dẫn tương đối, nhưng preload script mong đợi đường dẫn tuyệt đối. Unit test tương ứng của chúng đều sử dụng mock và vượt qua. Vấn đề chỉ được phát hiện khi luồng end-to-end được thực thi — giống như hai bè tiếng tập độc lập và cảm thấy ổn, chỉ để nhận ra trong buổi hòa tấu rằng một bè đang hát nhịp 4/4 và cái kia nhịp 3/4.
Lỗi Truyền trạng thái : Một database migration thay đổi schema bảng, nhưng lớp caching ORM vẫn giữ các cache entry cho schema cũ. Unit test cung cấp một môi trường mock hoàn toàn mới mỗi lần, điều này sẽ không làm lộ ra sự không nhất quán trạng thái xuyên lớp này. Giống như thay lời bài hát, nhưng ai đó vẫn đang hát phiên bản cũ.
Vấn đề Vòng đời Tài nguyên : Việc thu thập và giải phóng file handle, database connection và network socket trải dài trên nhiều component. Unit test tạo và hủy tài nguyên độc lập cho mỗi test, không thể làm lộ ra tranh chấp hoặc rò rỉ tài nguyên. Giống như từng bè tiếng lần lượt sử dụng microphone trong buổi tập, nhưng khi tất cả lên sân khấu cùng nhau, không đủ mic cho tất cả.
Phụ thuộc Môi trường : Mã hoạt động đúng trong môi trường test (nơi mọi thứ được mock) nhưng thất bại trong môi trường thực do sự khác biệt cấu hình, độ trễ mạng, hoặc dịch vụ không khả dụng. Giống như hát hoàn hảo trong phòng tập, nhưng gặp phản hồi âm thanh và can thiệp gió ở một lễ hội ngoài trời.
Testing End-to-End Không Chỉ Thay đổi Kết quả, Nó Thay đổi Hành vi
Đây là điều mà nhiều người không nhận ra: khi một agent biết công việc của nó sẽ được đưa qua testing end-to-end, hành vi lập trình của nó thay đổi.
Cân nhắc Tương tác Component : Trong khi viết mã, nó sẽ nghĩ về "cách giao diện này kết nối với upstream," thay vì chỉ tập trung vào một hàm duy nhất. Giống như biết cuối cùng bạn sẽ hát cùng nhau, bạn sẽ chú ý đến các bè khác trong khi tập.
Tôn trọng Ranh giới Kiến trúc : Trong các hệ thống có ràng buộc kiến trúc, testing end-to-end buộc agent phải tuân thủ các quy tắc ranh giới. Giống như bản nhạc được ghi chú "tăng âm lượng ở đây," bạn phải tuân theo.
Xử lý Đường dẫn Lỗi : Test end-to-end thường bao gồm các kịch bản thất bại, buộc agent phải xem xét xử lý ngoại lệ. Giống như mô phỏng "điều gì sẽ xảy ra nếu mic đột nhiên tắt" trong buổi tập, để bạn biết phải làm gì.
Tháp Kiểm thử và Đẩy Phản hồi Review Lên Cấp cao hơn
Trong các thực hành kỹ thuật Codex, OpenAI nhấn mạnh: các thông báo lỗi được viết cho agent phải bao gồm hướng dẫn sửa chữa. Đừng chỉ viết "Direct filesystem access in renderer" ; viết "Direct filesystem access in renderer. All file operations must go through the preload bridge. Move this call to preload/file-ops.ts and invoke it via window.api." Điều này biến các quy tắc kiến trúc thành một vòng lặp tự sửa chữa. Giống như người chỉ huy hợp xướng không chỉ nói "bạn hát sai rồi," mà còn nói "bạn nhanh hơn nửa nhịp ở đây, hãy nghe nhịp của bè alto, và vào ở nhịp 32."
Các Khái niệm Cốt lõi
Lỗi Ranh giới Component : Component A và B đều vượt qua unit test của chúng, nhưng tương tác của chúng tạo ra hành vi không đúng. Đây là loại vấn đề mà testing end-to-end giỏi bắt nhất — giống như các bè hợp xướng đúng riêng lẻ nhưng không đồng điệu cùng nhau.
Gradient Đủ kiểm thử (Testing Adequacy Gradient) : Lỗi được bắt bởi unit test <= lỗi được bắt bởi integration test <= lỗi được bắt bởi test end-to-end. Mỗi lớp lên cao hơn tăng khả năng phát hiện.
Quy tắc Thực thi Ranh giới Kiến trúc : Biến các quy tắc từ tài liệu kiến trúc (như "render process không thể truy cập trực tiếp hệ thống tệp") thành các kiểm tra tự động có thể thực thi. Từ "viết trên giấy" thành "chạy trong CI."
Đẩy Phản hồi Review (Review Feedback Promotion) : Chuyển đổi các nhận xét review mã lặp đi lặp lại thành test tự động. Mỗi lần một vấn đề lặp lại được tìm thấy, thêm một quy tắc, và harness tự động trở nên mạnh hơn. Giống như người chỉ huy biến các lỗi tập phổ biến thành bài tập khởi động — lần sau khi mắc cùng lỗi, bài tập tự nó làm lộ ra mà người chỉ huy không cần nói gì.
Thông báo Lỗi Hướng Agent : Thông báo lỗi không chỉ nên nêu "điều gì đã sai," mà còn nói với agent chính xác cách sửa nó. Điều này biến lỗi test thành vòng phản hồi tự sửa chữa.
Cách Thực hiện
0. Định nghĩa Ranh giới Kiến trúc Trước, Sau đó Viết Test E2E
Điều kiện tiên quyết để testing end-to-end là ranh giới hệ thống rõ ràng. Nếu kiến trúc là một đĩa mì spaghetti, testing end-to-end chỉ chứng minh "đĩa mì spaghetti này chạy được," nó sẽ không nói cho bạn biết ý định thiết kế ở đâu bị vi phạm. Giống như hợp xướng chưa thậm chí chia thành các bè — không có lượng tập nào sẽ làm cho nó nghe hay.
Kinh nghiệm của OpenAI: đối với các codebase được tạo bởi agent, ràng buộc kiến trúc phải là điều kiện tiên quyết ban đầu được thiết lập từ ngày đầu tiên, không phải điều gì đó cần xem xét khi nhóm lớn lên. Lý do rất đơn giản — các agent sẽ sao chép các mẫu hiện có trong kho lưu trữ, ngay cả khi các mẫu đó không đồng đều hoặc tối ưu. Không có ràng buộc kiến trúc, agent sẽ giới thiệu thêm sai lệch trong mỗi phiên.
OpenAI đã áp dụng "Kiến trúc Miền Phân lớp" — mỗi domain kinh doanh được chia thành các lớp cố định: Types → Config → Repo → Service → Runtime → UI. Các phụ thuộc chảy nghiêm ngặt theo hướng tiến, và các mối quan tâm xuyên domain đi vào qua các giao diện Provider rõ ràng. Bất kỳ phụ thuộc nào khác đều bị cấm và được thực thi cơ học qua linting tùy chỉnh.
Nguyên tắc quan trọng: Thực thi các bất biến, không vi quản lý triển khai. Ví dụ, yêu cầu "dữ liệu được parse tại ranh giới," nhưng không chỉ định nên sử dụng thư viện nào. Thông báo lỗi phải bao gồm hướng dẫn sửa chữa — không chỉ nói "vi phạm," mà nói với agent chính xác cách thay đổi.
Nguồn: OpenAI: Harness engineering: leveraging Codex in an agent-first world
1. Harness Phải Bao gồm Một Lớp End-to-End
Làm rõ ràng trong luồng xác minh của bạn: đối với các tác vụ liên quan đến thay đổi xuyên component, vượt qua test end-to-end là điều kiện tiên quyết cho hoàn thành:
## Thứ bậc Xác minh
- Mức 1: Unit test (Bắt buộc vượt qua)
- Mức 2: Integration test (Bắt buộc vượt qua)
- Mức 3: Test End-to-end (Bắt buộc vượt qua khi có thay đổi xuyên component)
- Bỏ qua bất kỳ mức nào bắt buộc = Chưa Hoàn thành
2. Biến Quy tắc Kiến trúc Thành Kiểm tra Có thể Thực thi
Mỗi ràng buộc kiến trúc nên có test hoặc quy tắc lint tương ứng:
bash # Kiểm tra xem render process có gọi trực tiếp Node.js API không
grep -r "require('fs')" src/renderer/ && exit 1 || echo "OK: no direct fs access in renderer"
3. Thiết kế Thông báo Lỗi Hướng Agent
Thông báo lỗi nên chứa ba yếu tố: điều gì đã sai, tại sao, và cách sửa:
LỖI: Tìm thấy import trực tiếp 'fs' trong src/renderer/App.tsx:12
TẠI SAO: Render process không có quyền truy cập Node.js API vì lý do bảo mật
CÁCH SỬA: Di chuyển các hoạt động tệp sang src/preload/file-ops.ts và gọi qua window.api.readFile()
4. Thiết lập Quy trình Đẩy Phản hồi Review
Mỗi khi tìm thấy một loại lỗi agent mới trong code review, biến nó thành kiểm tra tự động. Một tháng sau, harness của bạn sẽ mạnh hơn đáng kể so với lúc đầu tháng. Giống như ghi chú buổi tập cho hợp xướng — ghi lại các vấn đề được tìm thấy trong mỗi buổi tập để có thể kiểm tra trước buổi tiếp theo. Theo thời gian, các lỗi phổ biến giảm đi, và âm nhạc trở nên hài hòa hơn.
Trường hợp Thực tế
Tác vụ : Triển khai tính năng xuất tệp trong ứng dụng Electron. Liên quan đến UI render process, proxy hệ thống tệp preload script, và chuyển đổi dữ liệu lớp service.
Hát từng bè riêng (Unit test vượt qua) : Test component Render (vượt qua, file operations được mock), test preload script (vượt qua, filesystem được mock), test lớp service (vượt qua, data source được mock). Agent tuyên bố hoàn thành.
Hát cùng nhau (Lỗi được Test End-to-End tiết lộ) :
Lỗi Mô tả Unit Test E2E Không khớp giao diện Định dạng đường dẫn tệp không nhất quán Bỏ qua Bắt được Truyền trạng thái Tiến trình xuất không được gửi trở lại UI qua IPC Bỏ qua Bắt được Rò rỉ tài nguyên File handle xuất tệp lớn không được giải phóng Bỏ qua Bắt được Vấn đề quyền Quyền khác nhau trong môi trường đóng gói Bỏ qua Bắt được Truyền lỗi Ngoại lệ lớp service không đến được lớp UI Bỏ qua Bắt được Tất cả 5 lỗi đều được test end-to-end bắt được, trong khi unit test không bắt được cái nào. Chi phí là tăng thời gian test từ 2 giây lên 15 giây — hoàn toàn chấp nhận được trong quy trình agent. Dù từng bè hát tốt đến đâu, không thể so với một buổi tập hòa tấu đầy đủ.
Những Điểm chính cần Nhớ
Unit test mù có hệ thống với các lỗi ranh giới component — thiết kế cô lập của chúng chính xác là điều ngăn chúng phát hiện các vấn đề tương tác. Mọi người đều hát đúng không có nghĩa là hợp xướng không lạc nhịp.
Testing end-to-end không chỉ phát hiện lỗi, nó thay đổi hành vi lập trình của agent — làm cho nó tập trung hơn vào tích hợp và ranh giới.
Các quy tắc kiến trúc phải có thể thực thi — không viết trong tài liệu để được đọc, mà được kiểm tra tự động trên mỗi commit.
Thông báo lỗi phải được thiết kế cho agent — bao gồm các bước cụ thể về "cách sửa nó" để tạo thành vòng lặp tự sửa chữa.
Đẩy phản hồi review làm cho harness tự động mạnh hơn — mỗi danh mục lỗi được bắt trở thành một tuyến phòng thủ vĩnh viễn.
Đọc thêm
How Google Tests Software - Whittaker et al. — Nguồn kinh điển của mô hình Tháp Kiểm thử
Harness Engineering - OpenAI — Thực hành kỹ thuật để thực thi tự động các ràng buộc kiến trúc
Chaos Engineering - Netflix (Basiri et al.) — Chủ động đưa vào lỗi để xác minh độ bền hệ thống
QuickCheck - Claessen & Hughes — Phương pháp property testing, nằm giữa example testing và kiểm chứng hình thức
Bài tập
Phát hiện Lỗi Xuyên Component : Chọn một tác vụ sửa đổi liên quan đến ít nhất ba component. Đầu tiên, chỉ chạy unit test và ghi lại kết quả, sau đó chạy test end-to-end. Phân tích mỗi lỗi được phát hiện thêm thuộc loại vấn đề tương tác xuyên lớp nào.
Tự động hóa Quy tắc Kiến trúc : Chọn một ràng buộc kiến trúc từ dự án của bạn và biến nó thành kiểm tra có thể thực thi (với thông báo lỗi hướng agent). Tích hợp nó vào harness và xác minh hiệu quả của nó với một tác vụ baseline.
Đẩy Phản hồi Review : Tìm một loại nhận xét lặp lại từ lịch sử code review của bạn và chuyển đổi nó thành kiểm tra tự động bằng quy trình năm bước. So sánh tần suất của vấn đề trước và sau khi đẩy.
Bài giảng 11. Observability phải nằm trong harness 9,076 ký tự
Bài giảng này Giải quyết Vấn đề Gì?
Bạn yêu cầu một agent triển khai một tính năng. Nó chạy 20 phút, sửa đổi một loạt tệp, sau đó nói với bạn "xong, nhưng hai test đang thất bại." Bạn hỏi tại sao chúng thất bại — "không chắc, có thể là vấn đề timing." Bạn hỏi nó đã thay đổi những đường dẫn quan trọng nào — "để tôi nhìn vào mã..."
Đây không phải về việc agent thiếu năng lực. Đó là về việc harness của bạn không cung cấp đủ khả năng quan sát. Không có khả năng quan sát, agent đưa ra quyết định trong sự không chắc chắn, đánh giá trở thành phán xét chủ quan, và thử lại trở thành lang thang mù quáng. Cả OpenAI và Anthropic đều định nghĩa độ tin cậy là một vấn đề bằng chứng — harness phải phơi bày hành vi runtime và các tín hiệu đánh giá ở dạng có thể hướng dẫn quyết định tiếp theo.
Các Khái niệm Cốt lõi
Quan sát runtime : Các tín hiệu cấp hệ thống — log, trace, sự kiện process, health check. Trả lời "hệ thống đã làm gì."
Quan sát quá trình : Khả năng hiển thị vào các artifact quyết định harness — kế hoạch, rubric tính điểm, tiêu chí chấp nhận. Trả lời "tại sao thay đổi này nên được chấp nhận."
Task trace : Bản ghi đường dẫn quyết định hoàn chỉnh từ khi bắt đầu tác vụ đến khi hoàn thành, tương tự như request tracing trong hệ thống phân tán. Mỗi bước agent thực hiện, với ngữ cảnh, được ghi lại.
Sprint contract : Thỏa thuận ngắn hạn được thương lượng trước khi bắt đầu lập trình — chỉ định phạm vi tác vụ, tiêu chuẩn xác minh và các ngoại lệ. Công cụ cốt lõi cho quan sát quá trình.
Evaluator rubric : Biến đánh giá chất lượng từ phán xét chủ quan thành tính điểm có cấu trúc dựa trên bằng chứng. Làm cho các evaluator khác nhau tạo ra kết quả tương tự cho cùng một kết quả đầu ra.
Quan sát phân lớp : Quan sát lớp hệ thống và lớp quá trình được thiết kế đồng thời và củng cố lẫn nhau. Tín hiệu runtime giải thích hành vi; artifact quá trình giải thích ý định.
Quan sát Phân lớp
Tại sao Điều này Xảy ra
Chi phí Thực sự của Thiếu Quan sát
Khi một harness thiếu khả năng quan sát, bốn loại vấn đề xuất hiện có hệ thống:
Không thể phân biệt "đúng" với "trông có vẻ đúng" : Một hàm trông hoàn hảo trong code review — cú pháp đúng, logic hợp lý. Nhưng ở runtime, một lỗi xử lý edge case tạo ra kết quả không đúng với các đầu vào cụ thể. Chỉ có runtime trace mới có thể tiết lộ rằng đường dẫn thực thi thực tế lệch khỏi kỳ vọng.
Đánh giá trở thành huyền bí : Không có rubric tính điểm và tiêu chí chấp nhận, các evaluator (con người hoặc agent) dựa vào các giả định ẩn. Cùng một kết quả đầu ra có thể nhận được đánh giá hoàn toàn khác nhau từ các người đánh giá khác nhau. Đánh giá chất lượng trở thành không thể tái tạo.
Thử lại trở thành đoán mù : Khi agent không biết tại sao thứ gì đó thất bại, hướng thử lại là ngẫu nhiên. Nó có thể thử lặp đi lặp lại theo hướng sai — sửa các đường dẫn mã không liên quan trong khi bỏ qua nguyên nhân thất bại thực sự. Mỗi lần thử lại mù quáng tốn token và thời gian.
Vách đá thông tin bàn giao phiên : Khi công việc chưa hoàn thành được bàn giao cho phiên tiếp theo, thiếu khả năng quan sát có nghĩa là phiên mới phải chẩn đoán trạng thái hệ thống từ đầu. Quan sát của Anthropic về agent chạy lâu cho thấy việc chẩn đoán thừa này có thể tiêu thụ 30-50% tổng thời gian phiên.
Kịch bản Claude Code Thực tế
Hãy tưởng tượng một harness sử dụng luồng công việc ba vai "planner-generator-evaluator," thực thi tác vụ "thêm dark mode vào ứng dụng."
Không có khả năng quan sát : Planner đưa ra mô tả mơ hồ. Generator triển khai dark mode dựa trên sự mơ hồ đó, nhưng nó không khớp với kỳ vọng ẩn của planner. Evaluator từ chối dựa trên tiêu chuẩn ẩn của riêng họ nhưng không thể nói cụ thể điều gì sai. Generator thử lại mù quáng dựa trên lý do từ chối mơ hồ. Chu kỳ lặp lại 3-4 lần, mất khoảng 45 phút, tạo ra kết quả vừa tạm chấp nhận.
Với đầy đủ khả năng quan sát : Planner đưa ra sprint contract — liệt kê các component cần sửa đổi, tiêu chuẩn xác minh cho mỗi cái, và các ngoại lệ (không xử lý print styles). Generator triển khai theo contract. Quan sát runtime ghi lại quá trình tải và áp dụng style của mỗi component. Evaluator sử dụng rubric tính điểm để đánh giá từng chiều một, với các trích dẫn bằng chứng cụ thể. Một lần lặp tạo ra kết quả chất lượng cao, trong khoảng 15 phút.
Khác biệt hiệu quả 3x. Thay đổi duy nhất là khả năng quan sát.
Tại sao Agent Không thể Tự Giải quyết Điều này
Bạn có thể đang nghĩ: "Agent không thể tự in log của nó sao?" Các vấn đề là:
Agent không biết những gì nó không biết — nó sẽ không chủ động ghi lại các tín hiệu mà nó không nhận ra là cần thiết.
Các định dạng log không nhất quán — các phiên khác nhau sử dụng các định dạng log khác nhau, làm cho phân tích có hệ thống không thể thực hiện.
Quan sát quá trình không thể được giải quyết bằng log — sprint contract và rubric tính điểm là artifact có cấu trúc cần hỗ trợ cấp harness.
Cách Làm Đúng
1. Xây dựng Thu thập Tín hiệu Runtime vào Harness
Đừng dựa vào agent để tự in log của nó. Harness nên tự động thu thập các tín hiệu này:
Vòng đời ứng dụng : Các trạng thái giai đoạn Startup, ready, running, shutdown
Thực thi đường dẫn tính năng : Bản ghi thực thi đường dẫn quan trọng, bao gồm điểm vào, điểm kiểm tra và điểm thoát
Luồng dữ liệu : Bản ghi dữ liệu chảy giữa các component
Sử dụng tài nguyên : Các mẫu sử dụng tài nguyên bất thường (ví dụ: bộ nhớ liên tục tăng)
Lỗi và ngoại lệ : Đầy đủ ngữ cảnh lỗi, không chỉ thông báo lỗi
2. Triển khai Sprint Contract
Trước khi mỗi tác vụ bắt đầu, generator và evaluator (có thể là các lần gọi khác nhau của cùng một agent) thương lượng một contract:
markdown # Sprint Contract: Hỗ trợ Dark Mode
## Phạm vi
- Sửa đổi component chuyển đổi theme
- Cập nhật biến CSS toàn cục
- Thêm test dark mode
## Tiêu chuẩn Xác minh
- Test hồi quy trực quan vượt qua cho mỗi component
- Test end-to-end luồng chính vượt qua
- Không có flash of unstyled content (FOUC)
## Ngoại lệ
- Không xử lý print styles
- Không xử lý dark mode cho component bên thứ ba
3. Thiết lập Evaluator Rubric
Biến "tốt hay không" thành tính điểm có thể định lượng:
markdown # Rubric Tính điểm
| Chiều | A | B | C | D |
|-------|---|---|---|---|
| Tính đúng đắn mã | Tất cả test vượt qua | Luồng chính vượt qua | Vượt qua một phần | Build thất bại |
| Tuân thủ kiến trúc | Hoàn toàn tuân thủ | Sai lệch nhỏ | Sai lệch rõ ràng | Vi phạm nghiêm trọng |
| Phạm vi test | Luồng chính + edge case | Chỉ luồng chính | Chỉ skeleton | Không có test |
4. Chuẩn hóa với OpenTelemetry
Tạo một trace cho mỗi phiên harness, một span cho mỗi tác vụ, và sub-span cho mỗi bước xác minh. Sử dụng các thuộc tính chuẩn để chú thích thông tin quan trọng. Theo cách này, dữ liệu quan sát tích hợp với các công cụ chuẩn (Jaeger, Zipkin).
Trường hợp Thực tế
Một harness sử dụng luồng công việc planner-generator-evaluator, thực thi "thêm hỗ trợ dark mode":
Phiên bản không quan sát được : 3-4 vòng thử lại mù quáng, 45 phút, kết quả vừa tạm chấp nhận. Evaluator nói "nó không cảm thấy đúng" nhưng không thể nói cụ thể điều gì. Generator lãng phí nhiều thời gian theo hướng sai.
Phiên bản quan sát đầy đủ :
Sprint contract làm rõ phạm vi, tiêu chuẩn và ngoại lệ
Runtime trace ghi lại quá trình tải style của mỗi component
Rubric tính điểm cung cấp đánh giá có cấu trúc từng chiều một
Một lần lặp tạo ra kết quả chất lượng cao, 15 phút
Cải thiện hiệu quả 3x, chất lượng ổn định hơn, đánh giá có thể tái tạo.
Những Điểm chính cần Nhớ
Khả năng quan sát là thuộc tính kiến trúc harness — không phải tính năng được thêm vào sau, mà là khả năng cốt lõi phải được xem xét trong quá trình thiết kế.
Cả hai lớp quan sát đều cần thiết — tín hiệu runtime giải thích "điều gì đã xảy ra," artifact quá trình giải thích "tại sao nó được thực hiện theo cách đó."
Sprint contract front-load alignment — ngăn "generator xây dựng thứ gì đó mà evaluator ngay lập tức từ chối vì lý do có thể dự đoán trước."
Rubric tính điểm làm cho đánh giá có thể tái tạo — các evaluator khác nhau tạo ra điểm tương tự cho cùng một kết quả đầu ra.
Thiếu khả năng quan sát lãng phí 30-50% thời gian phiên vào chẩn đoán thừa.
Đọc thêm
Observability Engineering - Charity Majors — Khung lý thuyết và thực hành cho kỹ thuật quan sát hiện đại
Dapper - Google (Sigelman et al.) — Thực hành đột phá trong distributed tracing quy mô lớn
Harness Design - Anthropic — Giới thiệu sprint contract và evaluator rubric
Site Reliability Engineering - Google — Ứng dụng có hệ thống của khả năng quan sát trong hệ thống production
Bài tập
Phân tích Khoảng cách Quan sát : Kiểm toán harness hiện tại của bạn để tìm quan sát lớp hệ thống và lớp quá trình. Tìm các trạng thái hệ thống không thể phân biệt từ các tín hiệu hiện có, và đề xuất bổ sung.
Thực hành Sprint Contract : Viết một sprint contract cho một tác vụ thực tế. Để agent thực thi theo contract, và so sánh hiệu quả và chất lượng có và không có contract.
Xây dựng Task Trace : Ghi lại mỗi bước trong các hoạt động của agent trong một tác vụ lập trình hoàn chỉnh. Chú thích với các quy ước ngữ nghĩa OpenTelemetry. Phân tích các điểm nghẽn thông tin trong trace — bước nào thiếu hỗ trợ tín hiệu đủ cho các quyết định.
Bài giảng 12. Mỗi phiên phải để lại trạng thái sạch 9,741 ký tự
Bài giảng này Giải quyết Vấn đề Gì?
Agent của bạn chạy cả buổi chiều, sửa đổi 20 tệp, commit mã, phiên kết thúc. Phiên agent tiếp theo bắt đầu và ngay lập tức phát hiện: build bị hỏng, test đang đỏ, các tệp debug tạm thời ở khắp nơi, feature list không được cập nhật, và tiến độ hoàn toàn không rõ ràng. Phiên mới dành 30 phút đầu tiên chỉ để tìm hiểu "phiên cuối thực sự đã làm gì."
Cả OpenAI và Anthropic đều nói rõ ràng: độ tin cậy dài hạn phụ thuộc vào kỷ luật vận hành, không chỉ là thành công một lần chạy. Chất lượng trạng thái khi thoát phiên trực tiếp xác định hiệu quả của phiên tiếp theo. Hãy nghĩ về nó giống như các thực hành tốt nhất của Git — mỗi commit nên là một thay đổi nguyên tử, có thể biên dịch, không phải một đống mã làm dở.
Các Khái niệm Cốt lõi
Trạng thái sạch (Clean state) : Hệ thống thỏa mãn năm điều kiện khi thoát phiên — build vượt qua, test vượt qua, tiến độ được ghi lại, không có artifact lỗi thời, đường dẫn khởi động khả dụng. Thiếu bất kỳ cái nào có nghĩa là phiên không "xong."
Tính toàn vẹn phiên (Session Integrity) : Tương tự như giao dịch cơ sở dữ liệu — hoặc commit đầy đủ và để lại trạng thái sạch, hoặc rollback về trạng thái nhất quán cuối cùng. Không có lựa chọn trung gian.
Tài liệu chất lượng (Quality Document) : Một artifact đang hoạt động liên tục ghi lại xếp loại chất lượng cho mỗi module. Không phải đánh giá một lần, mà là tracker cho thấy liệu codebase có đang trở nên mạnh hơn hay yếu hơn theo thời gian.
Vòng lặp dọn dẹp (Cleanup Loop) : Một phiên bảo trì thường xuyên nhằm giảm entropy có hệ thống trong codebase. Không phải sửa chữa khẩn cấp, mà là vận hành thường xuyên.
Đơn giản hóa harness (Harness Simplification) : Khi năng lực mô hình cải thiện, định kỳ xóa các thành phần harness không còn cần thiết. Một ràng buộc cần thiết ngày hôm nay có thể là overhead không cần thiết ba tháng sau.
Dọn dẹp Idempotent : Các hoạt động dọn dẹp tạo ra cùng kết quả bất kể chúng chạy bao nhiêu lần. Đảm bảo dọn dẹp vẫn an toàn ngay cả trong các kịch bản thất bại-thử lại.
Năm Chiều của Trạng thái Sạch
Tại sao Điều này Xảy ra
Tăng trưởng Entropy là Trạng thái Mặc định
Các quy luật tiến hóa phần mềm của Lehman cho chúng ta biết: các hệ thống trải qua thay đổi liên tục sẽ không thể tránh khỏi tăng độ phức tạp trừ khi được quản lý chủ động. Điều này đặc biệt đúng với AI coding agent — mỗi phiên giới thiệu các thay đổi, và nếu không dọn dẹp khi thoát, nợ kỹ thuật tích lũy theo cấp số nhân.
Dữ liệu thực tế rất rõ ràng. Một dự án được phát triển với agent trong 12 tuần, không có chiến lược dọn dẹp:
Tuần 1: Tỷ lệ vượt qua build 100%, tỷ lệ vượt qua test 100%, khởi động phiên mới 5 phút
Tuần 4: Build 95%, test 92%, khởi động 15 phút
Tuần 8: Build 82%, test 78%, khởi động 35 phút
Tuần 12: Build 68%, test 61%, khởi động 60+ phút
Cùng dự án với chiến lược dọn dẹp:
Tuần 1: 100%, 100%, 5 phút
Tuần 12: 97%, 95%, 9 phút
Sau 12 tuần: tỷ lệ vượt qua build khác nhau 29 điểm phần trăm, thời gian khởi động phiên mới khác nhau 85%. Đây không phải lý thuyết — đây là sự khác biệt được quan sát.
Năm Chiều của Trạng thái Sạch
Trạng thái sạch không chỉ là "mã được biên dịch." Đó là năm chiều được đánh giá cùng nhau:
Chiều Build : Mã có build không có lỗi không? Đây là cơ bản nhất — phiên tiếp theo không nên phải sửa lỗi build trước tiên.
Chiều Test : Tất cả test có vượt qua không? Bao gồm cả test tồn tại trước phiên — phiên có trách nhiệm không làm hỏng chức năng hiện có. Và nó phải được xác minh trong CI, không chỉ "hoạt động trên máy của tôi."
Chiều Tiến độ : Tiến độ hiện tại có được ghi lại trong một artifact có thể đọc bởi máy không? Các subtask đã hoàn thành với tiêu chí vượt qua của chúng, các subtask đang tiến hành nhưng chưa hoàn thành với trạng thái hiện tại, các subtask chưa bắt đầu. Bản ghi tiến độ tốt giảm 60-80% thời gian chẩn đoán khởi động phiên.
Chiều Artifact : Có các artifact tạm thời hoặc mơ hồ lỗi thời không? Debug log, tệp tạm, mã bị comment out, marker TODO — tất cả những thứ này tăng tải nhận thức cho phiên tiếp theo.
Chiều Khởi động : Đường dẫn khởi động chuẩn có khả dụng không? Phiên tiếp theo có thể bắt đầu làm việc mà không cần can thiệp thủ công không? Khởi tạo môi trường, tải codebase, thu thập ngữ cảnh, lựa chọn tác vụ — các đường dẫn này không được bị hỏng.
"Dọn dẹp sau" Có nghĩa là Không bao giờ Dọn dẹp
Cái bẫy tâm lý phổ biến nhất là "không có thời gian dọn dẹp trong phiên này, tôi sẽ làm lần sau." Nhưng phiên agent tiếp theo không biết bạn đã để lại gì — nó thấy một mớ mã và trạng thái không chắc chắn. Nó sẽ dành nhiều thời gian để suy ra "phần nào của mã này là có chủ ý và phần nào là tạm thời."
Tệ hơn, mỗi phiên có mục tiêu tác vụ riêng của mình. Phiên mới ở đó để làm công việc mới, không phải dọn dẹp mớ bòng bong của phiên trước. Nó sẽ bỏ qua sự hỗn loạn và bắt đầu công việc mới trên đó, giới thiệu thêm hỗn loạn trên đỉnh hỗn loạn. Đây là vòng phản hồi tích cực của entropy.
Cách Làm Đúng
1. Trạng thái Sạch như Yêu cầu Hoàn thành
Định nghĩa rõ ràng trong harness: hoàn thành phiên = tác vụ vượt qua xác minh VÀ kiểm tra trạng thái sạch vượt qua. Thiếu bất kỳ cái nào có nghĩa là phiên không hoàn thành. Viết trong CLAUDE.md:
## Danh sách Kiểm tra Thoát Phiên
- [ ] Build vượt qua (npm run build)
- [ ] Tất cả test vượt qua (npm test)
- [ ] Feature list đã được cập nhật
- [ ] Không có mã debug còn lại (console.log, debugger, TODO)
- [ ] Đường dẫn khởi động chuẩn khả dụng (npm run dev)
2. Chiến lược Dọn dẹp Hai Chế độ
Kết hợp hai chế độ dọn dẹp:
Dọn dẹp tức thì (ở cuối mỗi phiên) : Dọn dẹp các artifact tạm thời được tạo trong phiên, cập nhật trạng thái feature list, đảm bảo build và test vượt qua. Đây là dọn dẹp "tính tham chiếu."
Dọn dẹp định kỳ (hàng tuần) : Quét toàn hệ thống — xử lý các vấn đề cấu trúc tích lũy, cập nhật tài liệu chất lượng, chạy test benchmark để phát hiện trôi dạt. Đây là dọn dẹp "tracing."
3. Duy trì Tài liệu Chất lượng
Tài liệu chất lượng là một artifact đang hoạt động liên tục tính điểm mỗi module:
markdown # Tài liệu Chất lượng
## Module Xác thực Người dùng (Chất lượng: A)
- Xác minh vượt qua: Có
- Agent có thể hiểu: Có
- Độ ổn định test: Ổn định
- Ranh giới kiến trúc: Tuân thủ
- Quy ước mã: Được tuân theo
## Module Thanh toán (Chất lượng: C)
- Xác minh vượt qua: Một phần (payment callback chưa được test)
- Agent có thể hiểu: Khó (logic trải rộng trên 3 tệp)
- Độ ổn định test: Không ổn định (2 test flaky)
- Ranh giới kiến trúc: Có vi phạm
- Quy ước mã: Được tuân theo một phần
Các phiên mới đọc tài liệu này và biết ngay nơi ưu tiên. Sửa module có điểm thấp nhất trước.
4. Định kỳ Đơn giản hóa Harness
Một hiểu biết quan trọng từ Anthropic: mỗi thành phần harness tồn tại vì mô hình không thể thực hiện điều gì đó một cách đáng tin cậy. Nhưng khi các mô hình cải thiện, các giả định này trở nên lỗi thời. Một ràng buộc cần thiết ba tháng trước có thể là overhead không cần thiết ngày hôm nay.
Thực hành được khuyến nghị: Mỗi tháng, chọn một thành phần harness, tạm thời vô hiệu hóa nó, và chạy các tác vụ benchmark. Nếu kết quả không giảm sút, hãy xóa vĩnh viễn. Nếu có, hãy khôi phục hoặc thay thế bằng một thay thế nhẹ hơn.
5. Các Hoạt động Dọn dẹp Phải là Idempotent
Script dọn dẹp phải an toàn để chạy lặp đi lặp lại:
bash # Các hoạt động dọn dẹp idempotent
rm -f /tmp/debug- * .log # -f đảm bảo không có lỗi khi tệp không tồn tại
git checkout -- .env.local # Khôi phục về trạng thái đã biết
npm run test # Xác minh dọn dẹp không làm hỏng gì
Trường hợp Thực tế
Một ứng dụng Electron được phát triển với agent trong 12 tuần, so sánh hai cách tiếp cận:
Không có chiến lược dọn dẹp (nhóm kiểm soát): Tuần 12, tỷ lệ vượt qua build 68%, tỷ lệ vượt qua test 61%, khởi động phiên mới 60+ phút, artifact lỗi thời 103.
Với chiến lược dọn dẹp (nhóm thực nghiệm): Kiểm tra trạng thái sạch đầy đủ ở cuối mỗi phiên + vòng lặp dọn dẹp hàng tuần. Tuần 12, tỷ lệ vượt qua build 97%, tỷ lệ vượt qua test 95%, khởi động phiên mới 9 phút, artifact lỗi thời 11.
Đến tuần 12, tỷ lệ vượt qua build của nhóm thực nghiệm cao hơn 29 điểm phần trăm, tỷ lệ vượt qua test cao hơn 34 điểm, và thời gian khởi động phiên mới thấp hơn 85%.
Những Điểm chính cần Nhớ
Trạng thái sạch là điều kiện cần thiết cho hoàn thành phiên — không phải dọn dẹp tùy chọn, mà là một phần của "định nghĩa hoàn thành."
Tất cả năm chiều đều bắt buộc — build, test, tiến độ, artifact, khởi động — mỗi cái phải được kiểm tra rõ ràng.
Tài liệu chất lượng làm cho sức khỏe codebase có thể theo dõi — bạn chỉ có thể sửa những gì bạn biết đang suy giảm.
Định kỳ đơn giản hóa harness — khi năng lực mô hình cải thiện, hãy xóa các ràng buộc không còn cần thiết.
"Dọn dẹp sau" bằng với không bao giờ dọn dẹp — tăng trưởng entropy là mặc định; chỉ có dọn dẹp chủ động mới chống lại nó.
Đọc thêm
Clean Code - Robert C. Martin — Các nguyên tắc có hệ thống về sự sạch sẽ của mã
Harness Engineering - OpenAI — Khả năng tái tạo như một yêu cầu thiết kế harness cốt lõi
Effective Harnesses - Anthropic — Vai trò quan trọng của thoát phiên sạch cho độ tin cậy dài hạn
Programs, Life Cycles, and Laws of Software Evolution - Lehman — Các quy luật tiến hóa phần mềm chứng minh độ phức tạp hệ thống tất yếu tăng mà không có bảo trì chủ động
Bài tập
Danh sách Kiểm tra Trạng thái Sạch : Thiết kế một danh sách kiểm tra thoát phiên cho codebase của bạn bao phủ tất cả năm chiều. Áp dụng nó qua 5 phiên liên tiếp và ghi lại vi phạm theo từng chiều.
So sánh Benchmark : Sử dụng một bộ tác vụ cố định với hai biến thể harness (có/không có yêu cầu trạng thái sạch). So sánh tỷ lệ hoàn thành, số lần thử lại và tỷ lệ thoát lỗi.
Thực hành Đơn giản hóa Harness : Chọn một thành phần harness, tạm thời vô hiệu hóa nó, và chạy các tác vụ benchmark. So sánh kết quả có và không có nó. Quyết định có giữ, xóa hay thay thế.