Lúc viết bài này mình có lật lại bài viết cũ trên blog. Damn it, thời gian trôi nhanh thật kể từ bài viết đầu tiên mình viết về vibe coding trên cái blog này Mình thử vibe coding... đến bây giờ đã gần 1 năm rồi. Một năm trước với một năm sau, workflow - cách làm sử dụng AI của mình cũng đã thay đổi rất nhiều.
Từng là một AI-denier đến một thằng giờ "cụt tay" nếu ko có AI. Mình nghĩ lại thì ban đầu mình phủ nhận AI là vì... tui đã custom cái editor của mình sâu đến tận control cả màu sắc, ngồi chọn từng plugin cho từng chức năng cụ thể. Xong đùng một cái AI coding thành trend và được quảng cáo dev sẽ ko cần viết code nữa. Trời ơi, bao nhiêu công sức tuỳ biến cái editor của mình sẽ công cốc sao, thế là ban đầu mình hơi "out of the loop" ko muốn cập nhật thông tin về AI, nhưng giờ thì sao chứ. Mình đã đốt cả 1 tỷ token (tính cả cached =)) trong 2 tháng gần đây, damn it mình đã đánh mất bản thân rồi sao?
Thống kê lượng token theo tháng
Anyways, let's see mình đã "đánh mất bản thân" như thế nào sau một năm sử dụng AI, và xem hiện tại thì mình đang sử AI như thế nào, đặc biệt là cho coding, mà mọi người vẫn gọi là vibecoding ấy.
Before we start
Trước khi chia sẻ thì mình phải nói trước là hiện tại ko có cái workflow nào là tốt nhất, áp dụng cho mọi trường hợp. Cái workflow (đúng hơn là tips & tricks) mà mình chia sẻ sau đây, mình cũng tham khảo từ nhiều nguồn và cá nhân mình thấy kết quả mà nó tạo ra cũng ngang với kỳ vọng của mình nên mới mang ra chia sẻ với mọi người. Còn nếu bạn mang workflow này về mà thấy nó ko phù hợp với bản thân thì ... "build your damn workflow"
Thêm nữa là những cái mình chia sẻ sau đó có thể có nhiều người biết, nhiều người chưa biết. Những ai biết rồi thì ngồi im cho người chưa biết nghe, chứ đừng có kêu mình "múa rìu qua mắt thợ" rồi gạch đá mình, mà những ai có ý định gạch đá mình thì cân nhắc lại nhé... mình cầm rìu đấy. 🪓
Ai kêu tui múa rìu qua mắt thợ hả??
Alright, đấy trước khi mỗi lần chia sẻ ý kiến cá nhân thì mình cứ phải Trịnh Trần Phương Tuấn à nhầm tuyên bố từ bỏ trách nhiệm cái đã, ko sau này lại bị phốt.
Ok vui vậy thôi nhưng mình bảo các bạn này: giờ mình bắt đầu thôi, mình bắt đầu với step quan trọng nhất mà nhiều người thường bỏ qua.
Luôn luôn có plan
Trong công việc coding hàng ngày, cơ bản chúng ta có 2 trường hợp sau đây:
-
Bạn nhận được một yêu cầu, 1 ý tưởng xây dựng 1 ứng dụng từ đầu, từ khi chưa có gì cả (from scratch đấy)
-
Là bạn nhận được 1 source-code rồi maintain nó (add thêm features mới, upgrade hoặc bỏ đi những cái outdate)
Trường hợp 1 thì chắc chắn bạn phải có plan rồi thì mới làm được. Thế còn trường hợp 2 thì sao, trường hợp maintain thì cần plan gì? Ở đây mình đang nói đến các features to như: thêm một module mới hay upgrade hoặc migrate đến môi trường hoặc version mới mà có thể break cái hệ thống hiện tại.
Trong 2 trường hợp trên thì trước khi cắm đầu vào bảo AI agent coding thì please make a plan.
Còn tại sao phải lập plan thì?
- Để chia nhỏ vấn đề ra. Chắc hẳn các bạn đã nghe đến khái niệm chia để trị (divide and conquer), khái niệm này có từ thời thực dân rồi, nhưng trong lập trình nó được phát biểu như sau: "Khi giải quyết một bài toán lớn, phức tạp. ta chia bài toán đó ra thành các bài toán nhỏ hơn, giải quyết các bài toán nhỏ đó rồi tổng hợp lại kết quả -> suy ra kết quả của bài toán lớn."
Cái việc chia để trị này thực ra nó lại rất phù hợp với cái limit hiện tại của AI model, đó là các bạn biết đấy cái context window của con AI nó có giới hạn (thường là 256k, to thì 1 triệu). Nên nếu bạn ko chia nhỏ vấn đề ra, mà cắm đầu giải quyết nó từ đầu thì khả năng cao bạn sẽ bị vỡ context, khi mà vỡ context thì con AI sẽ bị ảo giác dẫn đến kết quả đầu ra rất tệ.
-
Để cho bạn có cái nhìn tổng quan về cái ứng dụng hoặc cái features mình sẽ làm. Cũng như là nhìn được rõ các cái bước để mà hoàn thành nó. Khi mà biết được các bước phải đi rồi thì bạn có thể sắp xếp các cái steps mà bất hợp lí. Ví dụ trong FE thì những cái features như darkmode hay support multiple languagues thì phải làm lúc đầu, nếu làm những features này lúc sau thì sẽ phải sửa rất nhiều.
-
Nó giúp bạn có thể làm việc song song, tối ưu hoá AI. Khi bạn chia nhỏ ra các steps, các modules nhỏ hơn rồi thì bạn có thể mở nhiều AI agents, hoặc sessions lên. Mỗi session làm một module cùng lúc.
Thật ra công dụng của việc lập plan ko cần phải chứng mình từ trước đến nay nó luôn tỏ ra hiệu quả rồi.
Ví dụ chúng ta có định luật Kidlin, ở đây chúng ta có ai biết định luật Kidlin ko ạ? Thì định luật Kidlin phát biểu rằng: "Nếu bạn viết vấn đề ra một cách rõ ràng và cụ thể, bạn đã giải quyết được một nửa vấn đề rồi."
Hay có một câu nói nổi tiếng của Abram Lincoln: "Nếu cho tôi 6 tiếng để chặt cây, tôi sẽ dùng 4 tiếng để mài rìu."
Một ví dụ trực quan hơn liên quan đến AI luôn đó là LLM.
LLM (Large Language Model) là mô hình ngôn ngữ lớn — nói đơn giản thì nó là “bộ não” của các AI tools như ChatGPT, Gemini hay Claude.
Các LLM này hoạt động dựa trên một nguyên lý khá cơ bản: dự đoán token tiếp theo (next-token prediction). Tức là khi bạn đưa vào một đoạn text, model sẽ dự đoán từ tiếp theo có xác suất cao nhất dựa trên context hiện tại.
Trong research về LLM có một kỹ thuật khá nổi tiếng gọi là Chain-of-Thought prompting, được giới thiệu trong paper:
"Chain-of-Thought Prompting Elicits Reasoning in Large Language Models" (Google Research, 2022).
Ý tưởng của kỹ thuật này rất đơn giản: thay vì yêu cầu model trả lời ngay lập tức, ta yêu cầu nó viết ra các bước suy luận trước khi đưa ra kết quả.
Ví dụ:
| Mode | Prompt | AI xử lý |
|---|---|---|
| Bình thường | "A có 1 quả táo, B cho A thêm 1 quả táo. Hỏi A có bao nhiêu quả táo?" | AI dự đoán token tiếp theo và kết quả có xác suất cao nhất là "2" |
| Chain-of-thought | "Hãy suy luận từng bước trước khi trả lời: A có 1 quả táo, B cho A thêm 1 quả táo. Hỏi A có bao nhiêu quả táo?" | AI sẽ tạo các bước reasoning như: "Ban đầu A có 1 quả táo, sau đó được cho thêm 1 quả → 1 + 1 = 2" |
Các bước suy luận trung gian này giúp model giảm sai sót trong các bài toán reasoning.
Và nếu để ý thì bạn sẽ thấy một điều thú vị: Chain-of-Thought thực chất chính là một dạng “planning” ở mức reasoning.
Thay vì nhảy thẳng tới câu trả lời, model viết ra plan giải quyết vấn đề trước, sau đó mới thực hiện từng bước.
Vì vậy khi chúng ta làm việc với AI agent, việc lập plan cho task trước khi code cũng hoạt động theo logic tương tự:
- chia nhỏ vấn đề
- xác định các bước cần làm
- rồi mới thực thi từng bước
Điều này không chỉ giúp con người suy nghĩ rõ ràng hơn, mà còn giúp AI agent tạo ra kết quả ổn định và chính xác hơn.
Lập plan thế nào?
Với dự án mà bắt đầu từ đầu thì bạn có thể dùng ChatGPT, Gemini để research, để lập project development plan (chia phases, milestones). Khi mà bạn research xong rồi thì ném cái đống docs vào con AI agent rồi bật "plan mode" để viết technical plan, lúc này bạn sẽ phải trả lời các câu hỏi mà con AI agent đưa ra kiểu như: techstack bạn muốn dùng là gì? bạn muốn sử dụng database nào?...etc
Với dự án maintain thì bạn có thể vào thẳng AI agent bật "plan mode" và prompt thẳng luôn ví dụ như: "I want to migrate this project from Node.js 18 to Node.js 22. Help me create a plan for that." Thì AI agent cũng sẽ hỏi bạn một số câu hỏi để nó có thể viết được 1 cái plan: "Bạn có muốn migrate từ từ từng bước từ 18 lên 20 rồi từ 20 lên 22 ko?" hay "bạn có muốn thay thế các packages đã deprecated ko?"... etc. Trả lời xong đống này thì nó sẽ đưa cho bạn một cái plan cụ thể. Nếu bạn thấy ko ưng cái plan đấy có thể chat trực tiếp với nó "I think we should use a different approach for this task...". Sau đó lại tiếp tục trả lời đống câu hỏi mà nó đưa ra ==)
Setup an AI agent friendly environment
Khi mà có plan rồi, ta cũng chưa vội nhảy ngay vào code. mà ta cần setup một môi trường dev thân thiện với AI agent.
1. Viết file AGENTS.md (or CLAUDE.md),
Cái file này sẽ được inject vào AI model mỗi khi bắt đầu 1 session mới. Nó như là long-term memory của AI agent vậy. File này nên được cả team viết vào (contributing), cơ bản nó sẽ bao gồm: tổng quan dự án, các câu lệnh sử dụng hay những business logic đặc thù.
Tips: File này bạn ko nên viết quá dài, gần đây có một nhiều bài báo nói rằng việc viết AGENTS.md quá dài sẽ làm giảm chất lượng output của model (vì nó chiếm context window, cộng nếu các cái nội dung mà bạn viết trong file AGENTS.md mà nó có thể suy ra từ code thì nó sẽ làm duplicate context)
Trước mình cũng hay để file AGENTS.md khá dài, cho đến khi mình thấy cái tweet của ông Boris (là cái ông tạo ra Claude Code đó). Ông ấy để cái file CLAUDE.md có mấy dòng như bên dưới, mình cũng bị shock luôn vì trước đó mình cũng hay viết (hoặc AI gen) cái file này rất dài.
Boris simple CLAUDE.md
2. Setup Agent Skills
AGENTS.md thì là long-term memory của AI agents, còn Agent skills là short-term memory. Những cái skills ko được inject vào AI model từ đầu, mà chỉ khi nào AI agent quyết định sẽ dùng skill nào thì nó mới được load vào (load on demand) nên bạn có thể add nhiều skills vào mà ko lo chúng sẽ chiếm nhiều context như AGENTS.md (hay CLAUDE.md).
Dưới đây là demo nhỏ để mọi người thấy được output của AI agent khác nhau thế nào khi có và ko có skills. Link repo cho phần demo
Thề quả demo này ảo vãi chưởng, mình đã test đi test lại mấy lần rồi. Làm thành repo cho lên git, đến lúc present thì ... fail desperately =(( Ngay khi mình vừa tắt share màn hình, mình chạy lại thì ... nó lại ăn. WTF! May có nói rằng tỉ lệ tự động "pick up" skills của AI agent là 60% (coi như mình đen rơi vào 40% còn lại). Còn bạn có thể tự trải nghiệm với cái repo trên của mình, xem có khác biệt ko nhé!
3. Setup linter, formatter và precommit
Thường thì step này khi chưa có AI mình cũng hay làm rồi. Nó đảm bảo trước khi commit code thì coding style sẽ được enforce: tabs vs space, double quote vs single quote,...
Mấy cái tech mà mình thích dùng (từng thử nghiệm) lần trước tự nhiên giờ đây thấy nó hợp với làm việc với AI thật.
- Bun: Mình dùng thằng này cho dự án cá nhân từ khi nó mới tương thích 85% mới Node.js API, còn gần đây thì đa phần dự án mới mình đều bắt đầu với nó.
- Biome: Really fast linter and formatter. Thằng này có thể check lint với format hàng chục files trong ms, max nhanh luôn.
- tsgo: Thằng này chủ yếu mình để bật LSP hook vào cái OpenCode của mình cho nó check types
Lý do mình sử dụng 3 thằng trên thì ai cũng có thể nhìn ra... nó nhanh v~~~~ Setup xong mấy cái này rồi thì giờ đến với một cái tip khá là "chất lượng" trong khi sử dụng AI.
Chỉ cho AI agent cách để nó verify kết quả
Nó như cái Definition of Done của 1 Jira ticket vậy. Cơ bản thì bạn phải cung cấp cái cách mà AI agent có thể dùng để verify cái code mà nó gen ra, ở phần trước mà mình có nó về setup linters và formatter ấy. Thì bạn có thể bảo AI dùng các linters để check xem có lỗi syntax gì hay ko, hay dùng câu lệnh build để xem nó có build thành công hay ko...
Ông Boris cũng có nói rằng việc chỉ cho AI agent cách để verify kết quả có thể làm tăng gấp 3 chất lượng output.
Bonus
- Git worktree để làm việc song song, nhiều features một lúc.
- Use MCPs để tự động hoá công việc (nếu được)
- Commands (predefined prompts) để đỡ phải gõ lại 1 prompt over and over again.
Mệt quá thôi mình end ở đây thôi, bây giờ là 01:00 2026-03-07 🥱!

