Một buổi chiều tôi để agent “đọc toàn bộ repo để hiểu context” trước khi sửa một bug nhỏ. Nó làm đúng nghĩa đen: mở README, docs cũ, component không liên quan, vài file generated, rồi tóm tắt rất tự tin. Gần 20 phút sau, nó sửa đúng một dòng. Dòng đó vẫn phải review lại bằng tay.
Không phải model tệ. Lỗi nằm ở cách tôi giao ngân sách. Tôi không nói nó được tiêu bao nhiêu context, bao nhiêu tool call, bao nhiêu thời gian trước khi phải dừng lại và báo phát hiện. Khi không có budget, agent sẽ tối ưu theo hướng “đọc thêm cho chắc”. Với repo thật, “đọc thêm” có chi phí.
Trong AI coding, budget không chỉ là tiền token. Budget là context window, thời gian chờ tool, attention của reviewer, và rủi ro scope creep.
Context là tài nguyên có hạn
Context lớn tạo cảm giác an toàn. Nhưng context lớn không đồng nghĩa hiểu tốt hơn. Nếu nhồi 30 file vào prompt, model có thể bỏ sót chi tiết quan trọng trong file thứ 31, hoặc nhớ nhầm pattern từ module khác.
Tôi thường chia context thành ba lớp:
- task context: request, acceptance criteria, file ownership;
- local code context: file cần sửa, test gần đó, helper liên quan;
- background context: docs, architecture note, prior incident.
Task context luôn cần. Local code context gần như luôn cần. Background context chỉ lấy khi có lý do.
Ví dụ prompt tốt:
Fix disabled state in CheckoutForm.
Read CheckoutForm.tsx, its test file, and existing form helpers.
Do not scan unrelated features unless these files reference them.
Report if required API or hook is missing.
Prompt kém:
Read the repo and fix checkout.
Câu thứ hai mở cửa cho quá nhiều exploration. Agent có thể làm đúng, nhưng bạn không kiểm soát được cost.
Dùng search trước khi đọc sâu
Tôi muốn agent search hẹp trước, đọc sâu sau. Pattern cơ bản:
rg -n "CheckoutForm|useCheckout|country" src
rg --files src/features/checkout
Sau đó mới mở file cụ thể. Search cho biết bề mặt liên quan. Đọc sâu cho biết cách sửa.
Sai lầm là mở hàng chục file theo cảm giác. Với codebase lớn, cảm giác này tốn token rất nhanh. Search cũng giúp phát hiện naming thật của repo. Có thể bạn nghĩ hook tên useCheckout, nhưng repo dùng useCartCheckout. Agent đoán sai tên rồi tạo hook mới là một lỗi đắt.
Một heuristic tôi dùng:
- dưới 3 file liên quan: đọc hết;
- 4-10 file: đọc file chính và skim file còn lại bằng search;
- trên 10 file: dừng lại tóm tắt map trước khi edit.
Nếu task yêu cầu migration hàng loạt, lúc đó mới lập tracker hoặc script. Đừng cố nhồi mọi file vào một turn.
Time budget cho tool call
AI coding không chỉ tốn token. Nó tốn thời gian chờ command. npm test có thể 30 giây, cũng có thể 12 phút. npm run build có thể fail vì cache, network, hoặc type error không liên quan.
Tôi thích nói rõ validation budget:
After edits, run targeted test first.
If targeted test passes, run lint for changed files if available.
Do not run full build unless the change touches routing, config, or shared types.
If any command runs longer than 3 minutes, stop and report.
Không phải lúc nào cũng cần full build. Nhưng cũng không được lấy đó làm cớ bỏ validation. Quyết định dựa trên blast radius.
Thay đổi copy trong một Markdown file:
git diff --check -- src/content/blog/post.md
Thay đổi shared TypeScript type:
npm run typecheck
npm test -- --runInBand
Thay đổi Dockerfile:
docker build --platform linux/amd64 .
Budget tốt là budget gắn với rủi ro, không phải budget cố định cho mọi task.
Cost token: rẻ từng lượt, đắt cả ngày
Một turn AI có thể rẻ. Một ngày 80 turn với context lớn thì không còn rẻ. Nhưng tôi không tối ưu bằng cách làm prompt quá ngắn. Prompt quá ngắn làm agent đoán, và đoán sai cũng tốn tiền.
Tôi tối ưu bằng cách giảm context thừa:
- không paste file nếu agent có thể đọc local file;
- không paste log 5.000 dòng, search error trước;
- không yêu cầu giải thích dài khi chỉ cần patch;
- không để agent rewrite toàn bộ file nếu chỉ sửa một block;
- không chạy lại exploration sau khi đã có map.
Với log, tôi thường bắt đầu:
rg -n "ERROR|WARN|Exception|Traceback" logs/app.log
tail -200 logs/app.log
Nếu cần full log, lấy sau. Đừng đổ cả log vào context ngay.
Với repo, tôi thích agent tự đọc file bằng tool hơn là người paste nội dung vào chat. Tool output có thể được kiểm soát theo range, còn paste thủ công thường quá dài và không có đường dẫn rõ.
Context compaction và quyết định đã mất
Làm lâu sẽ có lúc context bị compact hoặc người khác resume session. Nếu quyết định quan trọng chỉ nằm trong chat, nó có thể bị mất hoặc bị tóm tắt sai.
Tôi ghi quyết định bền vào artifact:
- issue comment;
- PR description;
- tracker JSON;
- local note trong
.local/nếu nhạy cảm; - docs nhỏ nếu workflow sẽ lặp lại.
Ví dụ một decision note trong tracker:
{
"decision": "Do not migrate BillingPanel in this batch because it depends on the new invoice API.",
"madeAt": "2026-05-25T13:40:00+07:00",
"owner": "parent-session"
}
Khi agent khác resume, nó không cần hỏi lại vì sao BillingPanel bị bỏ qua. Nhưng note cũng không nằm trong source code production nếu không cần.
Đây là budget attention. Mỗi lần phải hỏi lại “vì sao mình không sửa file này?” là mất attention của người điều phối.
Khi agent nên dừng lại
Agent tốt không phải agent luôn tiếp tục. Có những điểm nên dừng:
- thiếu endpoint hoặc hook mà request nói “đã có”;
- file ownership bị conflict;
- test fail do lỗi ngoài scope;
- command cần credential chưa có;
- thay đổi cần migration dữ liệu;
- diff bắt đầu lan sang module không liên quan.
Tôi thích prompt có stop condition:
If you cannot find the existing API hook, stop and report the search terms and files checked. Do not create a new endpoint or mock data.
Stop condition tiết kiệm hơn nhiều so với việc agent tự chế một abstraction mới. Trong codebase thật, tự chế thường là nợ.
Budget review cũng quan trọng
Một PR 2.000 dòng có thể được AI tạo trong 15 phút, nhưng reviewer vẫn phải đọc bằng tốc độ con người. Nếu reviewer mất 2 giờ, bạn chưa tiết kiệm 2 giờ; bạn chỉ chuyển chi phí từ author sang reviewer.
Tôi đặt review budget trước:
- PR nhỏ: dưới 300 dòng diff, một behavior;
- PR vừa: 300-800 dòng, có test rõ, không chạm nhiều boundary;
- PR lớn: phải có plan, chia commit, hoặc chia PR.
Con số không tuyệt đối. Generated file có thể nhiều dòng nhưng ít review. Auth logic 80 dòng có thể rất khó review. Nhưng có budget giúp phát hiện PR đang phình.
Nếu diff vượt budget, tôi yêu cầu agent dừng và đề xuất split:
The diff is now over 700 lines and touches checkout, billing, and account settings. Stop editing. Propose a PR split with file ownership and dependency order.
Đây là lúc AI hữu ích: nó có thể tóm tắt split plan tốt. Nhưng nó không nên tự tiếp tục mở rộng diff.
Context reuse: summary có cấu trúc
Khi một task kéo dài, tôi yêu cầu agent tạo handoff summary ngắn:
## Current State
- Branch: fix/SCRUM-214-disable-submit
- Changed files: CheckoutForm.tsx, CheckoutForm.test.tsx
- Targeted test passes.
## Decisions
- Reused existing `useCheckoutState` hook.
- Did not change API client.
## Remaining
- Run lint.
- Open PR with checkout reviewer.
Summary này không thay diff, nhưng giúp turn sau không phải đọc lại mọi thứ. Nó cũng giúp người điều phối kiểm soát cost: thay vì reload toàn bộ chat, reload summary và file thật.
Chốt lại bằng nguyên tắc
AI coding có thể làm nhanh hơn, nhưng không miễn phí. Bạn trả bằng token, thời gian tool, attention review, và rủi ro context sai. Nếu không đặt budget, agent sẽ tiêu những thứ đó theo cách có vẻ hợp lý trong khoảnh khắc nhưng đắt về cuối ngày.
Tôi không muốn tiết kiệm token bằng mọi giá. Tôi muốn tiêu token vào đúng chỗ: đọc file liên quan, hiểu pattern thật, tạo diff nhỏ, chạy validation phù hợp. Còn phần không chắc, không có quyền, hoặc vượt scope thì dừng lại. Trong workflow hằng ngày, biết dừng đúng lúc thường tiết kiệm hơn một model cố tỏ ra tự chủ.