0

Build app với AI agent: cách mình tổ chức một dự án để AI làm việc đúng convention ngay từ prompt đầu

TL;DR: Bài này không bàn về tech stack. Bài này bàn về cách tổ chức một dự án sao cho AI agent (Claude Code / Cursor / Copilot) hiểu codebase, tuân theo convention, và nhớ context giữa các phiên làm việc. Mình chia sẻ kinh nghiệm thực tế từ một boilerplate đang xây — gồm: cách viết tài liệu cho AI đọc, agent skill hoạt động ra sao, hệ thống auto-memory, và những anti-pattern mình đã vấp.


Mục lục

  1. Vấn đề: AI coding "ngu hơn lần trước" mỗi session
  2. Triết lý "AI-first project"
  3. Tầng 1 — Always-loaded: AGENTS.md & CLAUDE.md
  4. Tầng 2 — Tài liệu chi tiết: docs/
  5. Tầng 3 — On-demand: Skills là gì và khi nào dùng
  6. Tầng 4 — Persistent: Auto-memory giữa các session
  7. AI workflow trong thực tế — một feature từ A đến Z
  8. Lợi ích thực tế quan sát được
  9. Anti-pattern đã học từ chính dự án này
  10. Bắt đầu từ đâu cho dự án của bạn

1. Vấn đề: AI coding "ngu hơn lần trước" mỗi session

Ai đã dùng AI assist code đều quen các tình huống:

  • AI gen ra code dùng API đã deprecated (vì training data cũ).
  • AI tự ý disable ESLint rule hoặc dùng any để "fix" nhanh.
  • AI không biết file đặt ở đâu — tạo components/Button.tsx trong khi project dùng components/atoms/Button.tsx.
  • Mỗi session mới phải explain lại context: "đây là Next.js 16 không phải 14", "đây là dự án DDD", "đừng đụng vào legacy folder X".
  • AI đồng ý mọi yêu cầu ngay cả khi yêu cầu sai (vd: bypass commit hook để push gấp).
  • 6 tháng sau quay lại, AI không nhớ bài học cũ — lặp lại sai lầm tương tự.

Cốt lõi: AI có training data tốt, nhưng không biết project của bạn. Mỗi prompt là một tabula rasa.

Câu hỏi: làm sao biến AI thành thành viên dự án thực thụ — biết quy tắc, tuân thủ convention, học từ feedback?

Câu trả lời mình rút ra qua nhiều dự án: tổ chức tài liệu thành nhiều tầng — mỗi tầng cho một loại "memory" khác nhau của AI.


2. Triết lý "AI-first project"

Trước đây, mình viết tài liệu cho người đọc (README dài, wiki Notion). Người đọc thì lười — đọc 10% rồi đi hỏi đồng nghiệp. Tài liệu chết dần.

Bây giờ mình viết tài liệu cho AI đọc. AI thì rất chăm — bạn bảo đọc, nó đọc hết. Và:

  • Khi AI làm theo tài liệu → output đúng convention
  • Khi tài liệu sai/thiếu → AI sẽ đụng phải lúc làm task → bạn cập nhật tài liệu
  • Tài liệu trở thành runtime spec của project, không phải decoration

Tài liệu được chia thành 4 tầng dựa trên cách AI tiếp cận:

Tầng Loại file Khi nào AI đọc Mục đích
1 AGENTS.md, CLAUDE.md Luôn luôn — mỗi session Quy tắc cốt lõi, không bao giờ vi phạm
2 docs/*.md Khi task yêu cầu (theo "required reading order") Convention chi tiết theo domain
3 Skills (~/.claude/skills/) On-demand — khi context match trigger Expertise sâu (Figma API, security review, …)
4 Memory (~/.claude/projects/<project>/memory/) Tự động load mỗi session Bài học, feedback, project state

Mỗi tầng có vai trò riêng. Hiểu sai → AI bị quá tải context (tầng 1 quá lớn) hoặc thiếu context (skill bị bỏ quên, memory không cập nhật).


3. Tầng 1 — Always-loaded: AGENTS.md & CLAUDE.md

Đây là file đầu tiên AI đọc. Mọi session, mọi tool (Claude Code, Cursor, Copilot, Codex).

Quy ước cross-tool

CLAUDE.md      → chỉ chứa: @AGENTS.md     (Claude Code đọc trước)
AGENTS.md      → entry point thật, cross-tool

Tại sao tách 2 file? Vì:

  • Claude Code ưu tiên CLAUDE.md
  • Cursor / Copilot / Codex chuẩn hóa quanh AGENTS.md (ecosystem AGENTS.md đang trở thành de facto cross-tool standard)
  • File CLAUDE.md chỉ trỏ về AGENTS.md → cross-tool sync mà không trùng nội dung

Nội dung AGENTS.md nên có

  1. Cảnh báo ngay đầu: phiên bản tool / framework có gì khác training data

    This is NOT the Next.js you know.
    This version has breaking changes — APIs may differ from your training data.
    Read node_modules/next/dist/docs/ before writing any code.
    

    → AI biết: training data không reliable cho project này, phải đọc bundled docs.

  2. Link sang docs/ — index của tài liệu chi tiết. AGENTS.md ngắn (50–80 dòng), chi tiết ở docs/.

  3. Operation rules — luật cứng không được vi phạm:

    • no-bypass-commit-hook (không git commit --no-verify)
    • no-bypass-eslint (không disable rule)
    • no-bypass-type-check (không @ts-ignore / any)
    • no-auto-release (không tự deploy)
  4. Important notes — convention tổng quan:

    • Package manager nào (yarn / npm / pnpm)
    • Port nào
    • Env file ở đâu

Vì sao AGENTS.md phải ngắn?

Vì nó load mỗi session. Mỗi dòng trong AGENTS.md = token đốt mỗi prompt. Nếu nhồi 500 dòng convention vào → context window đầy nhanh, AI quên chính nội dung quan trọng.

Quy tắc: AGENTS.md chỉ chứa "không bao giờ vi phạm""đọc cái gì khi cần". Chi tiết đẩy xuống docs/.


4. Tầng 2 — Tài liệu chi tiết: docs/

Tầng này AI đọc khi task yêu cầu, không phải mỗi session. Phỏng theo cấu trúc tài liệu của các dự án production lớn.

Cấu trúc

docs/
├── README.md                    # Index + "required reading order"
├── ai-agent-guidelines.md       # Do / Don't quick reference
├── operation.md                 # No-bypass rules (chi tiết hơn AGENTS.md)
├── project-overview.md          # Project là gì, môi trường gì
├── technology.md                # Stack chi tiết, scope
└── core-principles-and-coding-standards/
    ├── structure.md             # Thư mục, component hierarchy
    ├── coding-conventions.md    # Pattern theo domain
    ├── coding-style.md          # Lint, format, command
    └── instructions-and-work-flows/
        ├── README.md            # Index workflow
        └── adding-a-new-page.md # Workflow chi tiết từng task

Required reading order

File quan trọng nhất là docs/README.md. Trong đó có trình tự bắt buộc AI phải đọc khi nhận task:

1. Start → docs/README.md, project-overview.md
2. Guidelines → ai-agent-guidelines.md, AGENTS.md
3. Structure & tech → technology.md, structure.md
4. Patterns → coding-conventions.md, coding-style.md, DESIGN.md
5. Framework docs → node_modules/<framework>/docs/<page>
6. Existing code → tương tự dưới app/

AI làm theo trình tự này → từ tổng quát đến cụ thể → đến code thực tế. Cuối cùng output gần như chắc chắn đúng pattern.

Workflows — task có nhiều bước

Một số task (vd: "add new page", "add new feature") có quy trình nhiều bước. Đóng gói thành workflow doc:

# Adding a new page

## Checklist
1. Decide route public hay protected
2. Tạo folder + page.tsx
3. Extract UI thành atoms/molecules/organisms
4. Nếu mutate data → tạo actions.ts
5. Nếu cần new DB table → migration
6. Verify: yarn lint, yarn build, manual smoke test

AI đọc workflow → check từng bước → không bỏ sót. Khác hẳn với việc "tự suy ra phải làm gì".

Coding conventions chi tiết

Thay vì tản mác trong code review, gói vào doc. Ví dụ section "Form patterns":

## Form patterns (Apple HIG)

- Label ABOVE field, không dùng placeholder làm label
- Placeholder = helper text (vd: "name@example.com")
- Input height 48–56px (touch target chuẩn iOS)
- Autocomplete attributes BẮT BUỘC cho email/password
- Errors render dưới field bằng red caption
- Server Actions co-located: app/<segment>/actions.ts
- Return { error?: string; message?: string }; redirect on success

→ Lần sau AI làm form: đọc section này → output đúng pattern, không cần human nhắc.


5. Tầng 3 — On-demand: Skills là gì và khi nào dùng

Đây là phần ít người biết nhất.

Skill là gì?

Skill là một bundle of expertise mà AI có thể invoke khi context match. Skill thường là một thư mục <skill-name>/ chứa:

  • SKILL.md — main reference (mục đích, khi nào dùng, các bước)
  • references/*.md — reference deep-dive (tùy chọn)
  • assets/* — file mẫu (tùy chọn)

Skill được khai báo qua YAML frontmatter:

---
name: figma-use
description: MANDATORY prerequisite — load this skill BEFORE every use_figma tool call.
  Triggers when the user wants to write/edit/delete nodes, set up variables, build
  components and variants, modify auto-layout, or inspect Figma file programmatically.
---

# Figma Plugin API workflow

[content...]

description rất quan trọng — đó là cái AI scan để quyết định "skill này có liên quan task hiện tại không".

Skill khác AGENTS.md / docs/ chỗ nào?

AGENTS.md / docs/ Skill
Load khi nào Mỗi session (AGENTS.md) hoặc khi task yêu cầu (docs/) On-demand — chỉ khi context match description
Token cost Đốt mỗi session Chỉ đốt khi invoke
Scope Project-specific Có thể project-specific HOẶC global (user-level)
Mục đích Convention, rule, file structure Expertise sâu, multi-step process, reference data lớn

Khi nào tạo skill mới?

Quy tắc rút ra: skill chỉ cho on-demand content KHÔNG thuộc về convention của project.

Tạo skill khi:

  • ✅ Process phức tạp nhiều bước (vd: "review code chống lại company anti-pattern list", "design Figma component library")
  • ✅ Reference data lớn (vd: 30 files RLS best practices của Supabase)
  • ✅ Expertise đặc thù (Figma Plugin API, Claude API caching patterns)

KHÔNG tạo skill khi:

  • ❌ Quy tắc dự án đã có trong AGENTS.md / docs/
  • ❌ Convention đặt file (đó là docs/structure.md)
  • ❌ Coding style (đó là docs/coding-style.md)

Bài học mình rút ra: AGENTS.md được load mọi session, skill chỉ load on-demand. Wrap convention thành skill = duplicate context. Skill bị overlooked nếu trigger description không match.

Ví dụ skill thật trong project này

Một số skill global của Claude Code bộ Supabase tự ship:

  • supabase — Triggers: "Supabase Auth / Database / Edge Functions / RLS / migrations". Chứa: security checklist, CLI gotchas, MCP setup, migration workflow.
  • supabase-postgres-best-practices — Triggers: "Postgres query / RLS / index / lock". Có 30+ reference files (lock-advisory, query-missing-indexes, schema-partitioning, …).

Khi mình hỏi AI "thêm migration cho table X", skill supabase được kích hoạt → AI đọc SKILL.md → biết phải enable RLS, dùng to authenticated (không phải auth.role() deprecated), thêm cả USING lẫn WITH CHECK cho UPDATE policy, v.v.

Nếu KHÔNG có skill → AI có thể gen migration thiếu RLS, hoặc dùng pattern outdated.

Skill discovery & invocation

  • User-global: ~/.claude/skills/<name>/SKILL.md — apply mọi project
  • Project-local: .claude/skills/<name>/SKILL.md — apply chỉ project này
  • Installed via plugin: nhiều skill đến từ plugin chính thức (Supabase, Figma, GitHub, …)

AI scan tất cả skill có sẵn, đọc description của từng cái, chọn skill có description match task hiện tại → load full SKILL.md → áp dụng.


6. Tầng 4 — Persistent: Auto-memory giữa các session

Claude Code có hệ thống auto-memory — folder ~/.claude/projects/<project-path>/memory/. Mỗi memory là 1 file markdown nhỏ.

4 loại memory

Loại Khi nào lưu Ví dụ
user Khi biết về role / preference / background của người dùng "User là Go expert mới học React"
feedback Khi nhận correction hoặc confirmation về cách làm việc "Không tạo skill nếu AGENTS.md đã enforce"
project Khi học fact về project (state, decision, deadline) "Port pinned 3002, design tokens managed by getdesign CLI"
reference Khi biết về external resource "Linear project ABC track pipeline bugs"

Mỗi memory có format

---
name: no-redundant-skills
description: Don't create project-level skills that duplicate AGENTS.md rules
metadata:
  type: feedback
---

Don't create a project-level skill if AGENTS.md / CLAUDE.md already enforces the same rule.

**Why:** Project instruction files are always loaded into context every session.
A skill that restates the same rule is pure duplication. The user pushed back
hard ("có cái này r thì thêm skill vào làm gì??") when I created a `.claude/skills/nextjs/`
that just repeated AGENTS.md's "read node_modules/next/dist/docs/" rule.

**How to apply:** When asked to "add a skill" for project-specific behavior,
first check AGENTS.md / CLAUDE.md. If the rule already lives there, push back
instead of building.

Field quan trọng:

  • Why: lý do — để session sau biết khi nào rule này còn áp dụng / khi nào không
  • How to apply: condition cụ thể để invoke

MEMORY.md — index

Index của các memory: MEMORY.md ở cùng folder. Là single file luôn load đầu session. Format:

- [No redundant skills](feedback_no_redundant_skills.md) — if AGENTS.md/CLAUDE.md already enforces a rule, don't wrap it in a project skill
- [ad-manager project basics](project_ad_manager.md) — Next.js 16.2.6 / React 19.2.4 / App Router / port 3002 / docs layout
- [getdesign CLI](reference_getdesign_cli.md) — npx tool that writes DESIGN.md at project root; user runs it manually

Mỗi entry 1 dòng — Claude scan MEMORY.md, thấy entry nào relevant task → mở file đó đọc chi tiết.

Workflow build memory tự nhiên

Memory không phải bạn ngồi viết một mạch. Nó tự build qua đối thoại:

  1. User: "tạo skill nextjs"
  2. AI: tạo skill
  3. User: "có AGENTS.md rồi mà, tạo skill làm gì??"
  4. AI: nhận ra sai → xóa skill → lưu memory feedback "no-redundant-skills" với nội dung trên
  5. Session sau, task tương tự → AI thấy memory → không lặp lại sai lầm

→ Memory biến mỗi sai lầm thành học cụ thể, persistent. AI thực sự "học" project này theo thời gian.

Memory KHÔNG nên lưu gì

  • ❌ Code pattern (đọc code là biết)
  • ❌ Git history (chạy git log là biết)
  • ❌ Debug fix (commit message ghi rồi)
  • ❌ Nội dung đã có trong AGENTS.md / docs/
  • ❌ Task progress hiện tại (đó là dùng TODO list trong session)

Memory chỉ cho fact / preference / decision có context window không có trong code.


7. AI workflow trong thực tế — một feature từ A đến Z

Ví dụ task: "thêm trang /settings để user đổi password"

Bước 1 — Session start

AI load tự động:

  • CLAUDE.md@AGENTS.md
  • AGENTS.md → Next.js warning + link sang docs/
  • MEMORY.md → biết project là Next.js 16, port 3002, atoms/molecules/organisms, getdesign convention
  • Memory no-redundant-skills, project-ad-manager, getdesign-cli

Bước 2 — User prompt

User: "thêm trang /settings cho phép user đổi password"

Bước 3 — AI tự đọc theo required reading order

  • docs/README.md → biết phải đọc gì
  • docs/ai-agent-guidelines.md → do/don't
  • docs/structure.md → page thuộc app/, UI thuộc atoms/molecules/organisms
  • docs/coding-conventions.md → Server Components default, Server Action cho mutation, autocomplete attribute mandatory
  • docs/instructions-and-work-flows/adding-a-new-page.md → workflow chi tiết

Bước 4 — Skill match (nếu có)

Nếu có skill supabase: AI invoke (vì task có "đổi password" — Supabase Auth). Skill SKILL.md → biết supabase.auth.updateUser({ password }).

Bước 5 — AI propose plan

1. Tạo app/settings/page.tsx (Server Component, redirect nếu chưa auth)
2. Tạo app/settings/actions.ts với updatePassword Server Action
3. Tạo components/organisms/ChangePasswordForm.tsx (Client Component)
4. Add "/settings" link vào home page header
5. Translate strings: thêm key vào lib/i18n/dictionaries.ts (en + vi)
6. Verify: yarn lint, yarn build

Bước 6 — Implement

AI làm theo plan. Mỗi file:

  • Đặt đúng folder (theo structure.md)
  • Server Component default (theo coding-conventions.md)
  • Form có autocomplete new-password (theo "Form patterns" trong coding-conventions.md)
  • Errors localize qua tServer (vì AGENTS.md / docs đề cập i18n)

Bước 7 — Verify

AI tự chạy:

  • yarn lint — phải pass (no-bypass-eslint)
  • yarn build — phải pass (no-bypass-type-check) Không bypass.

Bước 8 — Done + lessons

Nếu có gì khác thường (vd: gặp edge case Supabase nào đó) → AI lưu vào memory để session sau tận dụng.


8. Lợi ích thực tế quan sát được

Sau khi áp dụng 4-layer này vào dự án:

1. Onboarding gần như instant. Mở Claude Code lên, prompt "explore codebase và cho tôi 3 chỗ refactor". AI đọc AGENTS.md → docs/ → đề xuất chuẩn xác mà không cần human giải thích gì.

2. Convention drift giảm rõ rệt. AI tuân thủ docs/ > tuân thủ training data. Tránh được trường hợp AI "tự sáng tạo" pattern lạ.

3. Memory tích lũy thành asset. Mỗi lần feedback "đừng làm thế" → memory ghi lại. Session 10 sẽ "khôn" hơn session 1. Khác với reset zero mỗi session.

4. Skill che được expertise lớn. Supabase RLS có 30+ best practice files — không cách nào nhồi vào docs/. Skill supabase-postgres-best-practices để on-demand → AI chỉ load khi viết SQL.

5. Tài liệu sống. Vì AI ĐỌC tài liệu (không như human đọc 10%), bất kỳ outdated section nào sẽ lộ ngay khi AI làm task. Bạn fix tài liệu → cập nhật rule → cycle khép kín.

6. Cross-tool tự nhiên. AGENTS.md là cross-tool spec → Cursor, Copilot, Codex cùng đọc → đổi tool không phải viết lại docs.


9. Anti-pattern đã học từ chính dự án này

9.1 Wrap convention thành skill

Sai: Tạo .claude/skills/nextjs/SKILL.md lặp lại nội dung AGENTS.md "đọc node_modules/next/dist/docs/".

Đúng: AGENTS.md load mọi session, skill chỉ on-demand. Convention thuộc về AGENTS.md / docs/.

9.2 Fight với convention của tool

getdesign CLI ghi DESIGN.md ở project root. Move vào docs/design.md cho gọn → lần update sau tool ghi lại ở root → break references.

Đúng: Theo convention của tool. Memory hóa hành vi: "getdesign CLI ghi DESIGN.md ở root, don't move".

9.3 Nhồi nhét AGENTS.md

Cám dỗ: bỏ tất cả rule vào AGENTS.md cho "chắc". Hậu quả: AGENTS.md 500 dòng → token cost mỗi session → quan trọng bị loãng.

Đúng: AGENTS.md ngắn (50-80 dòng), chỉ "không bao giờ vi phạm" và link sang docs/. Chi tiết đẩy xuống docs/.

9.4 Memory ghi quá nhiều

Cám dỗ: lưu mọi thứ AI học vào memory. Hậu quả: MEMORY.md 200 entries → AI scan không xuể.

Đúng: Memory chỉ ghi non-obvious facts không có trong code. Code-derivable info (architecture, file path) → đọc code.

9.5 Auto-execute mọi yêu cầu

Cám dỗ: AI thấy user nhờ là làm. Hậu quả: AI tự cài package lạ, push code, gửi message.

Đúng: operation.md no-bypass rules + auto-mode classifier chặn action có blast radius cao. AI phải hỏi trước nếu action vượt scope.

9.6 Mỗi feature 1 README riêng

Cám dỗ: viết doc cho từng feature lẻ.

Đúng: Có 1 entry point (docs/README.md), required reading order, AI tự discover. Doc rời rạc = AI bỏ sót.


10. Bắt đầu từ đâu cho dự án của bạn

Áp dụng dần, không cần làm hết một lần:

Tuần 1 — chỉ AGENTS.md

Tạo AGENTS.md ở root project. Nội dung tối thiểu:

  • Cảnh báo version framework / tool (nếu khác training data phổ biến)
  • Package manager (yarn / npm / pnpm)
  • Port, env file ở đâu
  • 2-3 luật cứng: no-bypass-eslint, no-bypass-type-check, no-auto-deploy

Tạo CLAUDE.md chỉ chứa: @AGENTS.md.

Test: mở Claude Code → prompt "What package manager does this project use?" — phải trả lời đúng ngay.

Tuần 2 — docs/ folder

Tạo docs/README.md với required reading order. Bắt đầu với 2-3 file:

  • docs/project-overview.md (1 paragraph)
  • docs/technology.md (stack table)
  • docs/operation.md (no-bypass rules chi tiết)

Update AGENTS.md → link sang docs/.

Tuần 3 — workflow & memory

Khi gặp task lặp (vd: "add new page"), ngồi viết workflow vào docs/.../instructions-and-work-flows/.

Khi AI sai một lần → user feedback → lưu memory bằng cách prompt:

"save feedback: <lesson>"

Claude Code sẽ tạo file memory.

Tuần 4+ — skills khi cần

Khi gặp expertise sâu / reference data lớn không nhét được vào docs (Figma, Supabase RLS, security review checklist, …) → tạo skill hoặc cài skill chính thức của tool đó.

Không vội. Skill thừa còn tệ hơn không có skill.

Kiểm tra định kỳ

3 tháng / lần:

  • Đọc lại AGENTS.md → có gì outdated?
  • Đọc lại MEMORY.md → có entry nào stale?
  • AI gần đây làm sai gì → có nên thêm vào docs / memory không?

Tài liệu cho AI cần maintain như code. Không phải viết một lần để đó.


Kết luận

AI agent không phải "magic". Bạn cho nó context tốt → output tốt. Cho nó context tệ / không cho gì → output về mean của training data (thường là 2 năm trước).

4 tầng tài liệu mình mô tả không phải framework / library — đó là cách tổ chức. Bạn áp dụng được vào Next.js, Rails, Django, Go, Flutter — đều được. Cái cốt lõi là:

  • AGENTS.md = quy tắc cứng, always-loaded, ngắn gọn
  • docs/ = chi tiết theo domain, AI đọc khi task yêu cầu
  • Skills = on-demand expertise, không lặp lại docs
  • Memory = persistent learning giữa session, fact không có trong code

Khi 4 tầng này hoạt động đồng bộ, AI làm việc gần như một thành viên dự án có 6 tháng experience. Không phải intern session-zero mỗi lần.

Cách tiếp cận này không bias về Claude Code. Cursor, Copilot, Codex đều đọc AGENTS.md. Memory là Claude Code-specific, nhưng các tool khác cũng đang phát triển hệ thống tương đương (Cursor có "Rules", Copilot có "Custom Instructions").

Repo demo (Next.js 16 + Supabase + Tailwind v4 + tổ chức AI 4-tầng): [link sẽ thêm sau khi push lên GitHub]

Bạn đang setup project với AI thế nào? Comment chia sẻ — mình muốn học thêm từ ai đã đi xa hơn 🙏


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í