Tấm bản đồ không có ổ gà
Giả sử bạn gọi điện cho một người bạn sáu tuổi và nói:
Đi từ nhà đến tiệm tạp hóa, mua giúp mình một chai nước.
Nghe thì có vẻ đơn giản.
Đứa trẻ biết căn nhà. Nó biết tiệm tạp hóa. Nó biết chai nước trông như thế nào. Trong đầu nó hiện lên một đường thẳng rất đẹp: mở cửa, bước ra đường, đi tới cửa hàng, mua nước, đi về.
Nhưng ngoài đường có một con chó đang nằm ngủ.
Hôm nay tiệm tạp hóa đóng cửa trước để cô chủ đi đám cưới.
Con đường quen thuộc đang bị đào lên để thay ống nước.
Trong túi đứa trẻ không có tiền.
Và “một chai nước” là nước lọc, nước ngọt, nước mắm hay một chai nước thần kỳ giúp con người bay lên Mặt Trăng thì không ai nói rõ.
Tấm bản đồ trong đầu rất sạch sẽ.
Thế giới thật thì có chó, có ổ gà, có đám cưới và đôi khi có cả một chiếc xe xúc đang nằm ngang giữa đường như con khủng long màu vàng bị hết pin.
Đó cũng là chuyện đang xảy ra khi chúng ta giao việc cho AI Agent.
Prompt là bản đồ.
Codebase, dữ liệu, người dùng, hệ thống cũ, deadline, quy định nội bộ và những dòng code được viết từ thời một anh lập trình viên nào đó còn chưa lấy vợ mới là lãnh thổ thật.
Trong bài viết A field guide to Claude Fable 5: Finding your unknowns, Thariq Shihipar, thành viên kỹ thuật tại Anthropic, gọi khoảng cách giữa bản đồ và lãnh thổ là những điều chưa biết, hay unknowns. Khi Agent gặp một khoảng trống như vậy, nó buộc phải đoán xem con người muốn gì. Công việc càng dài, nó càng phải đoán nhiều lần. (Claude)
AI không làm sai hoàn toàn, nó chỉ đi đúng trên một tấm bản đồ sai
Giả sử chúng ta yêu cầu Claude Code:
1Thêm chức năng đăng nhập bằng Google vào hệ thống.
Xong prompt, quá dễ.
Agent có thể lập tức tạo route callback, thêm thư viện OAuth, sinh nút đăng nhập, thêm biến môi trường và viết vài bài test.
Nhưng một lúc sau, vấn đề bắt đầu xuất hiện.
Hệ thống đang dùng Keycloak hay tự quản lý tài khoản?
Một email đã tồn tại thì ghép vào tài khoản cũ hay tạo tài khoản mới?
Người dùng bị khóa trong hệ thống nhưng tài khoản Google vẫn hoạt động thì xử lý thế nào?
Nhân viên nghỉ việc nhưng còn đăng nhập được bằng tài khoản Google cá nhân thì sao?
Có cần lưu access token không?
Secret nằm trong file .env, Vault, KMS hay một nơi thiêng liêng nào đó chỉ có hai người trong công ty biết?
Agent không được cung cấp những thông tin này, nhưng nó vẫn phải viết code. Nó sẽ chọn một phương án có vẻ hợp lý dựa trên codebase, tài liệu, kinh nghiệm phổ biến và những gì nó suy đoán về ý định của chúng ta.
Và đây là điểm nguy hiểm.
Một Agent yếu có thể đứng lại và nói rằng nó không hiểu.
Một Agent mạnh có thể chạy rất xa.
Nó xây đủ controller, migration, interface, test và tài liệu. Nó chạy test xanh lè như cánh đồng lúa sau cơn mưa. Ba giờ sau, chúng ta phát hiện kiến trúc tài khoản mà nó chọn không phù hợp với nghiệp vụ.
AI không nhất thiết viết code dở.
Nó chỉ giải một bài toán hơi khác bài toán mà chúng ta đang có.
Bốn căn phòng của sự không biết
Thariq chia những điều chưa biết thành bốn nhóm. Cách chia này không phải để làm cho prompt nghe sang hơn, mà để biết mỗi loại khoảng trống nên được xử lý bằng một cách khác nhau. (Claude)
Known knowns: những điều mình biết và đã nói ra
Đây là phần thường nằm trong prompt, spec hoặc tài liệu yêu cầu.
Ví dụ:
- Hệ thống viết bằng Go.
- Đang sử dụng PostgreSQL.
- Người dùng đăng nhập bằng Google Workspace.
- Tài khoản chỉ được phép thuộc tên miền công ty.
- Không lưu access token của Google.
Những thông tin này giống như những con đường đã được vẽ rõ trên bản đồ.
Agent không cần đoán quá nhiều.
Known unknowns: những điều mình biết là chưa rõ
Ví dụ, chúng ta biết mình chưa quyết định:
- Có tự động liên kết tài khoản cùng email hay không?
- Có cho phép nhiều nhà cung cấp đăng nhập cùng một tài khoản hay không?
- Khi Google bị lỗi thì có cho đăng nhập bằng mật khẩu cũ không?
- Thời gian sống của phiên đăng nhập là bao lâu?
Ta chưa có câu trả lời, nhưng ít nhất ta biết mình cần đặt câu hỏi.
Đây là những ô trống có dấu hỏi trên bản đồ.
Unknown knowns: những điều mình biết nhưng chưa từng viết xuống
Đây là nhóm vui nhất.
Chúng ta thường nói:
Giao diện này nhìn chưa đúng.
Nhưng hỏi “chưa đúng chỗ nào” thì cả phòng im lặng như vừa bị gọi lên bảng kiểm tra bài cũ.
Có thể chúng ta biết nút đăng nhập phải nằm ở đâu.
Biết khoảng cách nào trông cân đối.
Biết cách hệ thống hiện tại thông báo lỗi.
Biết khách hàng của mình không thích bị chuyển qua ba màn hình.
Nhưng các tiêu chuẩn đó nằm trong kinh nghiệm, thói quen và cảm giác. Ta nhận ra khi nhìn thấy, nhưng chưa chắc mô tả được ngay từ đầu.
AI không thể đọc ký ức nằm trong đầu chúng ta bằng sóng Wi-Fi.
Muốn lấy những điều này ra, ta thường phải xem prototype, so sánh nhiều phương án rồi phản hồi.
Unknown unknowns: những cái hố mình không biết con đường có thể có
Đây là loại nguy hiểm nhất.
Ta không biết một vấn đề tồn tại, nên cũng không biết phải hỏi.
Ví dụ, khi thêm Google OAuth, ta có thể chưa từng nghĩ tới:
- Người dùng thay đổi email trên Google Workspace.
- Hai tenant có cùng địa chỉ email hiển thị.
- Callback bị khai thác bằng OAuth account linking attack.
- Đồng hồ giữa các máy chủ lệch nhau làm token bị đánh giá hết hạn.
- Một tài khoản đã bị xóa nhưng dữ liệu audit vẫn phải giữ lại.
- Hệ thống cũ dùng email làm khóa chính ở mười bảy bảng khác nhau.
Không ai cố tình giấu các thông tin này.
Chúng đơn giản đang nằm dưới mặt nước.
Kỹ năng thật sự không còn là viết prompt dài
Khi mô hình còn yếu, người ta thường cố làm prompt dài hơn.
Thêm vai trò.
Thêm quy tắc.
Thêm năm mươi dòng “phải”, “tuyệt đối”, “không bao giờ”.
Prompt dần trở thành một bản hiến pháp được viết trong lúc hoảng loạn.
Nhưng một prompt dài không tự động làm cho bản đồ giống lãnh thổ hơn.
Ta có thể viết rất chi tiết về con đường mình tưởng tượng, trong khi cái cầu thật ngoài kia đã bị nước cuốn đi từ tuần trước.
Theo Thariq, hướng dẫn Agent là một bài toán cân bằng. Quá chi tiết, Agent có thể bám chặt vào phương án ban đầu ngay cả khi thực tế cho thấy nên đổi hướng. Quá mơ hồ, nó sẽ tự lấp khoảng trống bằng các “best practices” phổ biến, dù những thực hành đó chưa chắc phù hợp với hệ thống cụ thể. (Claude)
Vì vậy, kỹ năng quan trọng của agentic coding không chỉ là ra lệnh.
Đó là khả năng liên tục phát hiện:
- Mình đang biết gì?
- Mình chưa quyết định gì?
- Có tiêu chuẩn nào chỉ nằm trong đầu mình?
- Có điều gì cả mình lẫn Agent chưa nghĩ tới?
- Khi thực tế khác kế hoạch, ai được quyền đổi hướng?
- Sau khi Agent làm xong, mình có thật sự hiểu thay đổi đó không?
Trước khi viết code: đào những cái hố lên trước
Bài viết của Thariq đưa ra năm kỹ thuật nên dùng trước khi triển khai: quét điểm mù, brainstorm và prototype, phỏng vấn, cung cấp tài liệu tham chiếu và lập kế hoạch triển khai. (Claude)
Quét điểm mù — Blind spot pass
Khi bước vào một khu vực codebase chưa quen, đừng vội yêu cầu Agent sửa code.
Hãy yêu cầu nó đi quanh khu đất trước.
Ví dụ:
1Tôi cần thêm Google OAuth nhưng chưa quen module authentication
2trong repository này.
3
4Hãy thực hiện một blind spot pass.
5
6Tìm những unknown unknowns quan trọng, các luồng đăng nhập hiện có,
7quy tắc liên kết tài khoản, vị trí lưu secret, các bài test liên quan
8và những rủi ro có thể làm thay đổi kiến trúc.
9
10Chưa viết code. Trước tiên hãy giúp tôi viết lại một yêu cầu tốt hơn.
Agent lúc này không còn đóng vai thợ xây đang cầm búa.
Nó đóng vai người đi khảo sát đất, xem bên dưới có đường ống nước, dây điện hay một bộ xương khủng long hay không.
Kết quả tốt của bước này không phải là code.
Kết quả tốt là một danh sách câu hỏi mà trước đó ta chưa biết cần phải hỏi.
Brainstorm trước khi khóa mình vào một phương án
Có những bài toán mà chúng ta chỉ biết mình thích gì sau khi nhìn thấy nó.
Giao diện là một ví dụ.
Thay vì nói:
1Làm một dashboard đẹp, hiện đại, chuyên nghiệp.
Ta có thể yêu cầu:
1Dùng dữ liệu giả để tạo một file HTML gồm bốn hướng thiết kế
2dashboard hoàn toàn khác nhau:
3
41. Dashboard điều hành tối giản.
52. Giao diện giống trung tâm vận hành.
63. Dạng bảng dành cho chuyên viên phân tích.
74. Dạng thẻ phù hợp màn hình lớn.
8
9Chưa kết nối API và chưa sửa ứng dụng thật.
10Mục tiêu là giúp tôi nhìn thấy các khả năng để chọn hướng.
Lúc này, prototype không phải sản phẩm.
Nó là một chiếc đèn pin rọi vào phần kiến thức đang nằm trong đầu mà ta chưa diễn đạt được.
Một buổi prototype rẻ hơn nhiều so với việc để Agent xây xong cả căn nhà rồi mới phát hiện cửa chính đang mở thẳng vào nhà vệ sinh.
Để Agent phỏng vấn ngược con người
Sau khi brainstorm, vẫn sẽ còn những điểm mơ hồ.
Đừng cố nhét tất cả vào một prompt dài bằng trí nhớ.
Hãy để Agent hỏi.
1Hãy phỏng vấn tôi từng câu một về những điểm còn mơ hồ.
2
3Ưu tiên các câu hỏi mà câu trả lời có thể làm thay đổi:
4
5- kiến trúc,
6- mô hình dữ liệu,
7- quyền truy cập,
8- luồng người dùng,
9- khả năng rollback.
10
11Sau mỗi câu trả lời, cập nhật bảng quyết định.
12Chỉ chuyển sang lập kế hoạch khi các quyết định quan trọng đã rõ.
Cụm “từng câu một” khá quan trọng.
Nếu Agent ném ra ba mươi câu hỏi cùng lúc, con người thường trả lời câu 1, câu 2, lướt câu 3 rồi bỏ cuộc ở câu 7 để đi uống cà phê.
Một câu hỏi đúng lúc tốt hơn một bảng khảo sát trông như hồ sơ xin cấp phép xây sân bay.
Đưa cho Agent vật mẫu, đừng chỉ dùng tính từ
Đôi khi chúng ta nói:
Làm giống hệ thống cũ, nhưng tốt hơn.
Đây là một câu đủ mơ hồ để làm cả con người lẫn máy móc đau đầu.
Tài liệu tham chiếu tốt nhất thường không phải là ảnh chụp màn hình, mà là code đang chạy.
Ví dụ:
1Module vendor/rate-limiter có đúng cơ chế retry và backoff
2mà tôi cần.
3
4Hãy đọc implementation đó, xác định rõ semantics, edge cases
5và các test quan trọng.
6
7Sau đó triển khai hành vi tương đương cho TypeScript API client.
8Không sao chép cú pháp máy móc vì hai ngôn ngữ khác nhau.
Ảnh chụp cho Agent biết một thành phần trông như thế nào.
Source code còn cho nó biết thành phần đó được ghép ra sao, nhận dữ liệu gì, xử lý lỗi thế nào và đang sống cùng những thành phần khác bằng những sợi dây vô hình nào.
Lập kế hoạch theo thứ dễ thay đổi nhất
Kế hoạch triển khai thông thường hay đi theo thứ tự làm việc:
- Tạo bảng.
- Tạo model.
- Tạo API.
- Tạo giao diện.
- Viết test.
Nhưng khi review cùng Agent, thứ tự này chưa chắc có ích.
Ta nên đưa những quyết định dễ thay đổi và có ảnh hưởng lớn lên trước.
1Viết implementation plan.
2
3Đưa các phần có khả năng cần tôi điều chỉnh lên đầu:
4
5- thay đổi data model,
6- interface mới,
7- luồng người dùng,
8- quyền truy cập,
9- chiến lược migration và rollback.
10
11Các phần refactor máy móc có thể để phía cuối.
12Chưa triển khai cho đến khi kế hoạch được duyệt.
Đừng dành ba mươi phút review tên của một hàm helper trong khi phía dưới Agent đang âm thầm đề xuất đổi khóa chính của bảng khách hàng.
Trong khi viết code: đừng giả vờ kế hoạch là lời tiên tri
Kế hoạch không phải lời sấm được khắc trên đá.
Khi Agent bước vào codebase thật, nó có thể phát hiện một constraint chưa từng xuất hiện trong tài liệu.
Có một bảng cũ không được phép migration.
Có một service khác đang phụ thuộc vào hành vi tưởng như vô nghĩa.
Có một bài test kỳ lạ nhưng thật ra đang bảo vệ lỗi production từng xảy ra ba năm trước.
Theo phương pháp của Thariq, trong lúc triển khai nên yêu cầu Agent duy trì một file ghi chú tạm thời, chẳng hạn implementation-notes.md. Mỗi lần thực tế buộc nó đi lệch kế hoạch, Agent chọn phương án thận trọng, ghi lại quyết định rồi tiếp tục. (Claude)
1Trong quá trình triển khai, hãy duy trì file implementation-notes.md.
2
3Khi gặp edge case khiến phải lệch khỏi kế hoạch:
4
51. Không âm thầm thay đổi kiến trúc.
62. Chọn phương án bảo thủ nhất có thể rollback.
73. Ghi rõ phát hiện, quyết định tạm thời và tác động.
84. Tiếp tục nếu thay đổi nằm trong phạm vi an toàn.
95. Dừng và hỏi tôi nếu liên quan đến dữ liệu, bảo mật hoặc API contract.
File này giống cuốn nhật ký của một người đi rừng.
Ngày đầu bản đồ nói có con suối.
Ngày thứ hai người đi rừng phát hiện con suối đã đổi dòng.
Nếu không ghi lại, lần sau một đoàn khác lại cầm đúng tấm bản đồ cũ và tiếp tục đi xuống nước.
Sau khi viết code: người duyệt cũng có những điều chưa biết
Agent hoàn thành công việc không có nghĩa là con người đã hiểu công việc.
Một pull request có thể thay đổi mười bốn file.
Ta đọc diff.
Ta thấy dấu cộng màu xanh.
Ta thấy test chạy qua.
Ta thấy Agent viết một đoạn tổng kết rất tự tin.
Rồi ta nhấn merge bằng niềm tin trong sáng của một người đang băng qua đường mà chỉ nhìn đèn giao thông chứ không nhìn chiếc xe tải mất phanh.
Thariq đề xuất hai bước sau triển khai: tạo tài liệu giải thích để nhận được sự đồng thuận và yêu cầu Agent kiểm tra lại hiểu biết của chính người duyệt. (Claude)
Tạo một tài liệu giải thích cho người chưa đi cùng chuyến
Người review thường bắt đầu với đúng những unknowns mà chúng ta từng có.
Họ không tham gia buổi brainstorm.
Không đọc prototype.
Không biết vì sao phương án A bị bỏ.
Không biết edge case nào khiến kế hoạch phải đổi.
Hãy yêu cầu Agent đóng gói toàn bộ hành trình:
1Tổng hợp prototype, specification, implementation plan,
2implementation notes và kết quả test thành một tài liệu review.
3
4Tài liệu cần trả lời:
5
6- Bài toán ban đầu là gì?
7- Những phương án nào đã được cân nhắc?
8- Vì sao chọn phương án hiện tại?
9- Đã lệch kế hoạch ở đâu?
10- Rủi ro còn lại là gì?
11- Ai cần phê duyệt phần nào?
12- Có thể rollback bằng cách nào?
13
14Đưa demo và thay đổi người dùng nhìn thấy lên đầu.
Tài liệu này không chỉ dùng để “trình bày cho đẹp”.
Nó là cây cầu giúp một người chưa đi qua khu rừng hiểu vì sao đoàn thám hiểm lại quay về với đôi giày dính bùn và một cái xẻng bị gãy.
Bắt con người làm bài kiểm tra trước khi merge
Đây là ý tưởng nghe hơi ngáo nhưng rất hợp lý.
Sau một phiên làm việc dài, Agent có thể sửa nhiều thứ hơn ta tưởng. Chỉ đọc diff chưa chắc giúp ta hiểu toàn bộ hành vi, vì code mới còn phụ thuộc vào luồng cũ, cấu hình cũ và dữ liệu cũ.
Thay vì chỉ hỏi Agent:
Có chắc không?
Hãy bảo nó kiểm tra ngược lại mình.
1Tạo một báo cáo giúp tôi hiểu toàn bộ thay đổi trong pull request này.
2
3Giải thích bằng trực giác trước, sau đó mới đi vào từng module.
4
5Cuối báo cáo, tạo một bài kiểm tra gồm các câu hỏi về:
6
7- luồng dữ liệu,
8- hành vi khi lỗi,
9- quyền truy cập,
10- migration,
11- rollback,
12- những điểm lệch khỏi kế hoạch.
13
14Không đưa đáp án ngay.
15
16Tôi chỉ merge sau khi trả lời đúng toàn bộ.
17Nếu tôi trả lời sai, chỉ ra phần tài liệu cần đọc lại.
Code review từ đây không còn là nghi thức nhìn vài dòng màu xanh rồi cầu nguyện.
Nó trở thành một phép kiểm tra xem con người có thật sự đủ hiểu biết để chịu trách nhiệm cho đoạn code sắp đi vào production hay không.
Một quy trình hoàn chỉnh cho công việc cùng AI Agent
Từ những ý tưởng trên, chúng ta có thể tạo một quy trình tương đối gọn.
Giai đoạn 1: khám phá
- Nói rõ mình đang biết gì và chưa quen phần nào.
- Yêu cầu Agent quét codebase.
- Thực hiện blind spot pass.
- Brainstorm nhiều hướng.
- Tạo prototype rẻ bằng dữ liệu giả.
- Để Agent phỏng vấn từng câu một.
Đầu ra của giai đoạn này chưa phải code.
Đó là một bài toán được mô tả tốt hơn.
Giai đoạn 2: thống nhất
- Cung cấp code, tài liệu hoặc sản phẩm tham chiếu.
- Chốt các quyết định kiến trúc quan trọng.
- Lập implementation plan.
- Review phần dễ thay đổi trước.
- Xác định những việc Agent được tự quyết và những việc phải dừng lại hỏi.
Đầu ra là một tấm bản đồ đủ tốt để bắt đầu chuyến đi, chứ không phải một tấm bản đồ giả vờ biết mọi cục đá ngoài đời.
Giai đoạn 3: triển khai
- Mở một phiên làm việc sạch.
- Đưa spec, prototype và kế hoạch vào context.
- Yêu cầu Agent ghi implementation notes.
- Ghi lại mọi chỗ lệch kế hoạch.
- Dừng ở các thay đổi có tác động lớn.
- Chạy test, kiểm tra dữ liệu và xác minh hành vi thực tế.
Đầu ra không chỉ là code, mà còn là lịch sử quyết định.
Giai đoạn 4: hiểu và phê duyệt
- Tạo tài liệu giải thích.
- Tổng hợp rủi ro và cách rollback.
- Yêu cầu Agent tạo bài kiểm tra.
- Chỉ merge khi người chịu trách nhiệm hiểu thay đổi.
- Đưa các bài học mới trở lại tài liệu, skill hoặc
CLAUDE.md.
Điều ta học được trong chuyến đi hôm nay sẽ trở thành bản đồ tốt hơn cho ngày mai.
Trang ví dụ đi kèm của tác giả cung cấp 11 HTML artifact cho các giai đoạn trước, trong và sau triển khai, từ blind spot pass, prototype, phỏng vấn cho đến implementation notes và bài kiểm tra trước khi merge. (Thariq’s GitHub Pages)
Khi Agent làm sai, có thể lỗi không nằm ở câu lệnh
Một tác vụ dài thất bại thường khiến chúng ta phản ứng theo ba cách:
- Đổi sang model mạnh hơn.
- Viết prompt dài hơn.
- Chạy lại và hy vọng lần này electron trong GPU có tâm trạng tốt.
Cả ba cách đôi khi có tác dụng.
Nhưng chúng không giải quyết một vấn đề căn bản: Agent có thể đang bước vào một vùng đất mà cả nó lẫn chúng ta đều không hiểu đủ rõ.
Mô hình càng mạnh, nó càng có khả năng tự nối những khoảng trống lại với nhau.
Đó vừa là sức mạnh, vừa là rủi ro.
Một chiếc xe đạp đi sai đường chỉ đưa ta sang đầu hẻm.
Một chiếc máy bay phản lực đi sai hướng có thể đưa ta sang một quốc gia khác trước khi ta kịp nhận ra dưới chân không còn là ruộng lúa quê mình nữa.
Vì vậy, làm việc tốt với AI Agent không phải là loại bỏ toàn bộ sự không chắc chắn. Điều đó gần như không thể.
Mục tiêu là làm cho sự không chắc chắn trở nên nhìn thấy được.
Ta muốn biết chỗ nào trên bản đồ là con đường đã khảo sát.
Chỗ nào chỉ là nét bút chì.
Chỗ nào có dấu hỏi.
Và chỗ nào nên cắm một tấm biển lớn:
Đừng tự đi tiếp. Hỏi con người.
Tổng kết
Ý tưởng chính của phương pháp này khá đơn giản: prompt không phải là công việc thật.
Prompt chỉ là bản mô tả của công việc.
Giữa bản mô tả và thế giới thật luôn tồn tại những khoảng trống. Có khoảng trống ta biết, có khoảng trống chỉ nhận ra khi nhìn thấy và có cả những cái hố mà trước đó ta không biết con đường có thể có.
Thay vì chỉ bảo AI viết code, hãy dùng nó để tìm những điều chưa biết:
- Quét điểm mù trước khi làm.
- Prototype trước khi xây thật.
- Để Agent phỏng vấn ngược lại mình.
- Dùng code và sản phẩm thật làm vật tham chiếu.
- Ghi lại những chỗ thực tế buộc kế hoạch thay đổi.
- Tạo tài liệu giải thích sau khi hoàn thành.
- Kiểm tra xem con người có thật sự hiểu trước khi merge.
AI càng thông minh, nút thắt càng ít nằm ở khả năng gõ code của nó.
Nút thắt dần chuyển sang khả năng của con người trong việc nhìn vào bóng tối và nói:
Khoan đã. Ở đây còn thứ gì mà cả hai chúng ta chưa nhìn thấy?
Cảm ơn các bạn đã quan tâm và theo dõi bài viết, hẹn gặp lại ở các bài viết tiếp theo.
Bình luận