+2

Agentic Engineering (Phần 1): Từ “vibe coding” đến cách làm phần mềm một cách bài bản

Xin chào các bạn, lâu rồi không cập nhật gì cả, hôm nay mình lại ngoi lên đây. Dạo này thấy mọi người bàn tán chủ đề "AI đá dev ra chuồng gà - Lập trình viên chuẩn bị thất nghiệp, về nuôi cá và trồng thêm rau" nhiều quá, lại tiện hưởng ứng mỗi năm Viblo Mayfest 1 lần, lấy tinh thần săn áo làm động lực để tìm hiểu và chia sẻ thêm điều gì đó hữu ích, bài viết này được ra đời!

Nội dung của bài viết được tham khảo và truyền cảm hứng cực lớn từ series: Agentic Engineering Patterns của Simon Willison - người đồng sáng tạo ra Django, một trong những web framework bằng ngôn ngữ Python phổ biến nhất hiện nay. Cực kì recommend mọi người nên đọc chi tiết series này:

1. Vì sao có cái tên "Agentic Engineering"?

Nếu đã dùng AI để code một thời gian, chắc các bạn cũng từng thực hiện thao tác này: ban đầu chỉ định nhờ nó viết hộ vài đoạn boilerplate, một lúc sau nó đã đọc repo, sửa file, chạy test, báo lỗi, sửa tiếp, rồi thậm chí mở browser để kiểm tra UI.

Đến đoạn này, thao tác không thể gọi là “autocomplete” như Github Copilot ngày trước nữa.

Các công cụ như Claude Code, OpenAI Codex, Gemini CLI hay những coding agents tương tự không chỉ trả lời bằng text. Chúng có thể động vào môi trường làm việc thật: đọc file, ghi file, chạy lệnh, chạy test, xem stack trace, đọc log, mở trình duyệt, tạo tài liệu. Quan trọng hơn, chúng có thể lặp lại: sai thì nhìn lỗi, sửa tiếp; thiếu context thì đọc thêm; test fail thì thử hướng khác.

Simon Willison gọi cách làm việc với các công cụ như vậy là Agentic Engineering. Và chúng ta sẽ cần phân biệt 1 chút để xem nó giống và khác gì với "vibe coding" đang được nhắc đến rầm rộ hiên nay.

  • dùng AI để thử nhanh một prototype ==> vibe coding.
  • dùng coding agent như một phần nghiêm túc trong quy trình engineering ==> agentic engineering.

“Vibe coding”, hiểu theo nghĩa phổ biến, là kiểu làm bằng cảm giác. Mô tả ý tưởng, để AI viết, chạy thử, thấy được thì đi tiếp, lỗi thì bảo AI sửa. Không nhất thiết đọc kỹ code. Không nhất thiết hiểu hết kiến trúc. Cách này không xấu. Với demo, hackathon, tool cá nhân hoặc PoC nhỏ, nó cực kỳ tiện.

Nhưng đem cùng logic đó vào production thì hơi nhiều vấn đề.

Ở production, code chạy được mới là bước đầu. Nó còn cần được hiểu, test, review, deploy, rollback, bảo trì, và đôi khi bị gọi dậy lúc 2 giờ sáng để debug. Agentic engineering nằm ở chỗ đó.

Tóm gọn lại:

Cách sử dụng Mục tiêu Rủi ro chính Khi nào phù hợp?
AI-assisted coding Tăng tốc viết code Context thiếu, code rời rạc Hàm nhỏ, snippet, refactor đơn giản
Vibe coding Có bản demo nhanh Không hiểu code, prototype đội lốt production Demo, hackathon, tool cá nhân
Agentic engineering Xây phần mềm thực tế, có action, có kiểm thử Sửa quá rộng, tạo bug kỹ thuật nếu thiếu quy trình Task kỹ thuật có Git, test, review, QA

Điểm quan trọng ở đây là: Với Agentic Engineering , AI không thay thế hay làm mất đi vai trò của 1 kỹ sư. Ngược lại, AI bắt kỹ sư phải biết cách nâng cấp bản thân, rõ hơn về cách giao việc, cách kiểm chứng và cách chịu trách nhiệm với công việc của mình.

2. Agent thực ra là gì?

Từ “agent” bây giờ bị dùng khá loạn. Chatbot cũng gọi là agent. Workflow automation cũng gọi là agent. Một cái script gọi API cũng có lúc được marketing thành agent.

Trong phạm vi bài này, chúng ta thống nhất theo định nghĩa dưới đây:

Agent là phần mềm dùng LLM để chọn bước tiếp theo, gọi công cụ, quan sát kết quả, rồi lặp lại để đạt mục tiêu.

Coding agent là agent có công cụ phục vụ lập trình. Các công cụ đó có thể gồm:

  • đọc và sửa file trong repo;
  • tìm kiếm code bằng rg;
  • chạy shell command;
  • chạy test, lint, typecheck;
  • đọc log, stack trace, screenshot;
  • mở browser hoặc dùng browser automation;
  • dùng Git để xem status, diff, history;
  • tạo tài liệu, walkthrough hoặc artifact phụ trợ.

Khác biệt lớn nhất nằm ở vòng lặp. Một chatbot bình thường trả lời một lần. Coding agent có thể làm kiểu này:

Vòng lặp này làm thay đổi cách ta giao việc.

  • Nếu chúng ta hỏi chatbot “viết hàm sort này”, nó chỉ trả ra code (và chúng ta Ctrl+C/Ctrl+V).
  • Nếu chúng ta giao cho coding agent “sửa bug này, thêm regression test, chạy test liên quan, báo cáo diff”, nó "có thể" tự đi qua nhiều bước và hoàn thành công việc.

Tất nhiên, “có thể” không có nghĩa là “luôn đúng”. Agent vẫn có thể sửa sai file, chạy nhầm test, hiểu nhầm yêu cầu hoặc tự tin bịa ra kết quả (Hallucination). Nhưng nó có một lợi thế rất đáng giá: khả năng nhận feedback từ con người.

Test fail là fail. Stack trace là stack trace. Browser không hiển thị đúng thì không thể nói miệng là đúng được.

Vì vậy, trong agentic engineering, prompt vẫn quan trọng, nhưng prompt không còn đứng một mình. Prompt phải đi cùng tools, test, Git, docs, convention, review và feedback loop.

Đừng chỉ học cách hỏi AI. Hãy học cách dựng môi trường để AI không phải đoán mò quá nhiều - từ khóa Harness mà chắc hẳn mọi người cũng nghe nhiều gần đây.

3. Kỹ sư có bị AI đá ra chuồng gà?

Cứ mỗi lần có công cụ AI mới (OpenAI, Anthropic, Google, ... thay nhau ra liên tục), câu hỏi “kỹ sư còn cần làm gì?” lại quay lại. Nghe cũng hợp lý. Nếu agent đọc được code, sửa được code, chạy được test, vậy phần của con người còn lại là gì?

Câu trả lời thực tế là: vẫn còn nhiều việc lắm.

Viết code chưa bao giờ là toàn bộ quá trình của việc làm phần mềm. Phần khó thường nằm ở:

  • hiểu vấn đề thật sự cần giải quyết;
  • nhận ra yêu cầu mơ hồ hoặc mâu thuẫn;
  • chọn giữa nhiều hướng thiết kế có trade-off khác nhau;
  • giữ kiến trúc không phình to;
  • bảo vệ dữ liệu, quyền truy cập và trải nghiệm người dùng;
  • tạo test đủ mạnh;
  • đọc diff và phát hiện rủi ro;
  • quyết định cái gì nên làm ngay và cái gì nên hoãn;
  • chịu trách nhiệm khi production có sự cố.

Agent có thể hỗ trợ từng phần, nhưng nó không tự biết bối cảnh tổ chức. Nó không biết khách hàng nào đang dùng một API cũ mà team chưa dám bỏ. Nó không biết vì sao 2 năm trước team tránh một dependency. Nó không biết “đừng động vào billing trước kỳ chốt doanh thu”.

Mô hình hợp tác hợp lý không phải là “agent thay thế kỹ sư”, mà phải là:

  • Kỹ sư đặt mục tiêu, ràng buộc, trade-off, tiêu chí kiểm chứng.
  • Agent đọc code, tạo diff, chạy tool, thu thập bằng chứng.
  • Kỹ sư review, quyết định, merge và chịu trách nhiệm.

Đây là điểm khác biệt rất lớn giữa agentic engineering và vibe coding. Với vibe coding, đôi khi ta chấp nhận “nó chạy được là được”. Với agentic engineering, “nó chạy được” chỉ là một phần evidence, không phải giấy phép bỏ qua engineering.

4. Viết code đang trở nên "rẻ" hơn

Trước đây, muốn thử một hướng giải pháp, chúng ta có thể mất vài giờ hoặc vài ngày. Bây giờ, chúng ta có thể bảo agent tạo spike, viết test mẫu, dựng demo, thậm chí thử vài hướng khác nhau.

Tuy nhiên, chi phí viết code rẻ hơn không đồng nghĩa phần mềm rẻ hơn. Good code vẫn đắt vì điểm đáng giá thật sự nằm ở nhiều quy trình khác:

  • hiểu code và bảo trì sau này.
  • test và review.
  • xử lý edge cases.
  • vận hành production.
  • debug sự cố.
  • cập nhật khi yêu cầu đổi.
  • xóa bỏ hướng sai.
  • giữ niềm tin trong team.

Khi chi phí viết code giảm, nút thắt chuyển từ “ai viết code?” sang “ai chọn, kiểm chứng và review output?”. Nếu team không đổi thói quen, agent chỉ giúp tạo nhiều code hơn mức team có thể hiểu.

Và đây là điểm khá nguy hiểm: code do agent viết thường nhìn rất “hợp lý”. Nó có tên hàm đẹp, comment tử tế, structure có vẻ sạch. Nhưng “trông hợp lý” không đồng nghĩa với “đúng domain”, “an toàn”, hay “maintainable”.

Một cách dùng agent tốt hơn là xem nhiều output ban đầu như exploration:

  • sinh ra để học nhanh
  • so sánh vài hướng
  • giữ lại phần tốt
  • xóa phần thừa
  • rồi implement lại qua quy trình tử tế hơn.

Prototype là prototype. Đừng để nó lặng lẽ được merge vào main branch chỉ vì “thấy cũng chạy được”.

5. Hoard: tích lũy kho tri thức

Nghe hơi đơn giản, nhưng với coding agent thì cực kỳ quan trọng. LLM rất giỏi tái tổ hợp pattern. Đưa cho nó một test mẫu đúng style repo, nó viết test mới tốt hơn. Đưa cho nó script migration cũ, nó bám convention hơn. Đưa cho nó checklist release, nó ít bịa quy trình hơn.

Còn nếu mọi tri thức nằm trong đầu senior engineer, agent chỉ còn cách đoán.

Kho tri thức hữu ích có thể gồm:

  • AGENTS.md hoặc instruction file cho repo
  • CONTRIBUTING.md
  • thư mục docs/engineering/
  • runbooks vận hành
  • prompt library
  • scripts debug hoặc migration
  • test fixtures và factories
  • ADRs
  • PR templates
  • examples về API payload
  • checklist QA

Một cách nghĩ đơn giản thế này: Agent cũng như một thành viên mới onboard trong team, thứ gì giúp người mới onboard dễ hơn thì cũng giúp agent làm tốt hơn.

Ví dụ, thay vì prompt:

Viết test cho refund API.

hãy prompt:

Dựa trên style test trong tests/api/test_orders.py,
hãy viết test cho refund API.
Giữ naming, fixture và assertion style giống file đó.
Chạy pytest tests/api/test_refunds.py nếu có,
hoặc test file mới nếu tạo.

Đây không phải chuyện viết prompt cho dài và chi tiết (như những lý thuyết prompt engineering). Đây là cách đưa tri thức thật của repo vào vòng lặp agent.

Nếu phải nhắc agent cùng một điều ba lần, nhiều khả năng điều đó nên nằm trong docs, instruction file hoặc prompt library.

6. AI nên giúp chúng ta viết code tốt hơn, không chỉ nhanh hơn

Nếu chỉ dùng agent để tăng tốc độ code, team có thể tạo thêm rác kỹ thuật nhanh hơn. Mục tiêu phù hợp hơn là dùng agent để làm những việc mà trước đây ta hay bỏ qua vì thiếu thời gian:

  • viết regression test
  • tạo context map trước khi sửa
  • cập nhật docs
  • refactor nhỏ nhưng đều đặn
  • kiểm edge cases
  • tạo manual QA note
  • review diff lần đầu
  • tạo walkthrough cho module khó hiểu

Ví dụ một prompt tốt nên sử dụng để tăng chất lượng của output từ agent:

Trước khi implement, hãy nêu 2-3 hướng giải quyết và trade-off.
Ưu tiên diff nhỏ, maintainability và reuse pattern hiện có.
Không thêm dependency mới nếu chưa giải thích lý do.
Nếu thấy cơ hội refactor ngoài scope, ghi vào Follow-up, không làm ngay.

Như vậy agent không còn là máy gõ code. Nó trở thành công cụ để mở rộng số phương án mình có thể cân nhắc.

Code rẻ giúp chúng ta thử nhiều hơn. Review đắt bắt chúng ta phải biết dừng.

7. Git: lớp bảo vệ căn bản

Trong khi agent có thể sửa nhiều file rất nhanh, chúng ta có thể coi Git như cái phanh tay để kiểm soát. Không có Git, bạn đang để một thứ vừa nhanh vừa hay đoán mò chạy trong repo của mình (với full permission 🆘)

Git là công cụ cực kỳ hữu ích giúp chúng ta nắm được:

  • trước khi sửa worktree có sạch không?
  • agent đã sửa file nào?
  • diff có đúng phạm vi không?
  • có thể rollback không?
  • có thể tách commit không?
  • có thể so sánh các hướng solution không?

Workflow tối thiểu nên là:

Prompt nên đặt luật rõ ràng với Git:

Trước khi sửa, chạy git status và báo worktree.
Không ghi đè thay đổi hiện có nếu không chắc đó là thay đổi của task này.
Không chạy git reset --hard, git clean, git push --force.
Nếu cần thao tác rewrite history, dừng và hỏi.

Mấy quy tắc này nhỏ thôi, nhưng cứu được rất nhiều pha đau đầu.

8. Context map

Một thói quen mình thấy rất nên áp dụng là yêu cầu agent tạo context map trước khi đụng vào code.

Prompt mẫu:

Trước khi sửa, hãy tạo context map:
- entrypoint
- file liên quan
- data flow
- test hiện có
- giả thuyết nguyên nhân
- phần chưa chắc chắn

Không sửa code trong bước này.

Context map bắt agent nói rõ nó đang hiểu hệ thống thế nào. Nếu nó hiểu sai, ta kịp thời phát hiện và điều chỉnh sớm. Đỡ hơn nhiều so với để nó sửa 15 file rồi mới phát hiện nó đi nhầm hướng =)).

Đây cũng là cách hiệu quả để giảm vấn đề context window (1 trong những nguyên nhân chính đốt token). LLM không có trí nhớ vô hạn. Nếu task kéo dài, log quá dài, hoặc agent đọc quá nhiều file, nó có thể bỏ sót chi tiết quan trọng. Context map là một cách “nén” hiểu biết hiện tại thành tài liệu ngắn, dễ review.

9. Subagents: tips & tricks

Subagent là agent phụ được giao một vai trò hẹp. Hầu như các coding agents hiện nay đều có hỗ trợ tạo subagent rồi. Có vài kiểu khá hữu dụng:

  • exploration subagent: đọc code và báo cáo, không sửa;
  • parallel solution subagents: thử nhiều hướng khác nhau;
  • specialist subagent: tập trung test, docs, security, accessibility;
  • review subagent: review diff do agent khác tạo.

Subagents đặc biệt hữu ích khi task đủ lớn, vì mỗi agent có context riêng. Nhưng đừng lạm dụng. Ba agent cùng nói một lúc cũng có thể làm bạn rối hơn chứ không thông minh hơn.

Khi dùng subagent, cần đặt ranh giới rõ:

  • có được sửa file không?
  • output tối đa bao nhiêu?
  • cần bằng chứng gì?
  • dừng ở đâu?
  • làm trên branch/worktree nào?

Với parallel agents, Git worktree là lựa chọn tốt. Mỗi agent làm trong thư mục riêng, sau đó con người so sánh diff. Không nhất thiết merge trực tiếp branch “win” dựa trên voting. Nhiều khi cách tốt nhất là học từ vài hướng, rồi yêu cầu agent làm lại một implementation sạch hơn.

10. Example

Giả sử có bug: phí ship không cập nhật khi user đổi địa chỉ sau khi nhập coupon.

Một workflow agentic ổn định sẽ không bắt đầu bằng “fix bug này đi”. Nó nên đi kiểu:

  1. Tạo branch riêng.
  2. Chạy git status.
  3. Agent explore checkout flow, không sửa.
  4. Agent tạo context map: component, hook, API, cache key, test liên quan.
  5. Con người chọn giả thuyết chính có thể gây ra lỗi.
  6. Agent viết regression test cho coupon + address change.
  7. Chạy test để thấy fail đúng lý do.
  8. Agent sửa implementation tối thiểu.
  9. Chạy test hẹp.
  10. Chạy test rộng hơn nếu cần.
  11. Agent hoặc subagent review diff.
  12. Con người đọc diff và PR description.

Prompt mở đầu:

Task: sửa bug phí ship không cập nhật khi user đổi địa chỉ sau khi nhập coupon.

Bước 1 chỉ exploration:
- tìm checkout entrypoint
- tìm nơi coupon, address và shipping quote tương tác
- tìm test hiện có
- nêu giả thuyết nguyên nhân
- không sửa file

Sau exploration, hãy báo:
- file quan trọng
- data flow
- test nên thêm
- rủi ro

Prompt implementation:

Dựa trên hướng đã chọn, hãy làm TDD:
1. Viết regression test fail cho coupon + address change.
2. Chạy test để chứng minh fail đúng lý do.
3. Sửa code tối thiểu.
4. Chạy test lại.

Ràng buộc:
- Không thêm dependency.
- Không sửa ngoài checkout/shipping nếu không giải thích.
- Nếu cần đổi API, dừng và hỏi.

Đây là agentic engineering ở dạng thực tế: agent làm nhiều việc, nhưng con người thiết kế lộ trình và quyết định khi có đủ thông tin.

Kết luận

Agentic engineering, nói đơn giản, là cách làm việc với coding agents nhưng vẫn giữ tiêu chuẩn engineering: hiểu vấn đề, giới hạn phạm vi, dùng Git, viết test, review diff, ghi bằng chứng và chịu trách nhiệm.

Tóm cái váy lại:

  • Agent là LLM + tools trong một vòng lặp quan sát và hành động.
  • Con người vẫn làm phần quan trọng nhất: chọn mục tiêu, trade-off và chịu trách nhiệm.
  • Viết code có thể trở nên rẻ hơn, nhưng good code vẫn đắt nếu thiếu review và test.
  • Kho tri thức nội bộ làm agent mạnh hơn rất nhiều.
  • Context map, instruction file và Git là những lớp bảo vệ căn bản.
  • Subagents hữu ích, nhưng chỉ khi task đủ phức tạp và có ranh giới rõ ràng.

Oke, phần đầu đi nhanh qua mấy ý chính vậy thôi, hi vọng các bạn có 1 cái nhìn tổng quan và rõ ràng hơn về cách làm việc với coding agent, thực sự có thể đạt đến chất lượng của agentic engineering thay vì đốt token cho vibe coding. Phần 2 mình có thể sẽ đi sâu thêm 1 số ý và tập trung vào việc dùng coding agent trong test/review. Hi vọng vẫn sẽ được mọi người đọc và ủng hộ.

Nếu thấy bài viết hữu ích, đừng quên click 1 upvote, thêm 1 lượt share, 1 lượt comment ủng hộ tinh thần tác giả. See ya 👋


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí