Project mẫu · shop-support-agent

Project mẫu và cách Claude đọc project

Agent chăm sóc khách hàng cho shop sách “Sách Hay”, gom mọi thứ của 5 domain vào một project thật. Trang này giải thích bằng sơ đồ: cấu trúc thư mục, Claude Code nạp file nào trước, một lượt xử lý đi qua những bước nào, và agent API chạy ra sao.

Xem mã nguồn trên GitHub Mẹo nhớ

1. Cấu trúc thư mục

Màu cam là thư mục. Mỗi file có ghi chú ai đọc nó và khi nào.

2. Ai đọc file nào, khi nào

FileAi đọcKhi nàoDomain
CLAUDE.md (+ @docs/architecture.md)Claude CodeLúc mở phiên, luôn nằm trong contextClaude Code
.claude/settings.jsonHarness của Claude Code (không phải model)Lúc mở phiên, áp dụng cho mọi lần gọi toolClaude Code
.mcp.jsonClaude CodeLúc mở phiên, hỏi bạn duyệt server lần đầuTool Design & MCP
.claude/skills/*/SKILL.mdModelLúc đầu chỉ đọc name + description; nội dung đầy đủ khi skill được dùngClaude Code
.claude/agents/*.mdClaude CodeLúc mở phiên nạp định nghĩa; subagent chạy trong context riêng khi được giao việcClaude Code
.claude/rules/python-style.mdModelChỉ khi Claude đọc file khớp paths (src/**/*.py)Context Management
.claude/hooks/*.shHarness chạy như lệnh shellTrước và sau khi tool Edit/Write chạyClaude Code
prompts/system.md + knowledge/*.mdAgent API (src/agent.py)Mỗi request, được cache nhờ cache_controlPrompt · Context
src/tools.pyCode của bạn chạy tool; model chỉ thấy schemaKhi model trả tool_useTool Design & MCP
evals/, tests/Bạn và CITrước khi merge thay đổi prompt hoặc toolAgentic Architecture

3. Claude Code nạp gì khi mở phiên

Thứ tự nạp theo tài liệu Claude Code. Settings được gộp trước, sau đó đến bộ nhớ (CLAUDE.md), công cụ (MCP), các mô tả (skills, subagents), cuối cùng là hook SessionStart.

Thứ tự ưu tiên settings (cao → thấp)Thứ tự nạp CLAUDE.md
  1. Managed settings (tổ chức)
  2. Tham số dòng lệnh --settings
  3. .claude/settings.local.json
  4. .claude/settings.json
  5. ~/.claude/settings.json

Rule permission được gộp từ mọi cấp, quy tắc chặt nhất thắng: deny > ask > allow.

  1. Managed policy (tổ chức)
  2. ~/.claude/CLAUDE.md (user)
  3. ./CLAUDE.md hoặc ./.claude/CLAUDE.md (project), kể cả ở các thư mục cha
  4. CLAUDE.local.md (cá nhân, nối sau CLAUDE.md cùng thư mục)
  5. CLAUDE.md ở thư mục con và rule có paths: chỉ nạp khi Claude đọc file ở đó

@duong/dan để import file khác, tối đa 4 tầng.

4. Vòng đời một phiên Claude Code

Từ lúc gõ claude đến lúc thoát, Claude Code đi qua 4 giai đoạn:

  1. Khởi động: nạp luật và kiến thức nền.
  2. Mỗi lượt: nạp thêm file khi cần, gọi tool.
  3. Khi context gần đầy: tóm tắt (compact) hội thoại.
  4. Kết thúc phiên.
Bắt đầuBước xử lýĐiểm rẽ nhánhKết thúcVòng lặp

Từng file: nạp khi nào, để làm gì, không có thì sao

#FileNạp khi nàoDùng để làm gìNếu không có
1Managed settings / policy của tổ chứcKhởi động, trước mọi thứLuật công ty mà không ai ghi đè được, ví dụ cấm MCP lạ hoặc cấm đọc secretChỉ còn luật của team và cá nhân. Không sao với dự án cá nhân, nhưng rủi ro với công ty lớn
2~/.claude/settings.jsonKhởi độngSở thích và quyền cá nhân áp dụng cho mọi projectDùng mặc định, nên Claude hỏi quyền nhiều hơn
3.claude/settings.jsonKhởi độngLuật chung của team: allow lệnh test, deny đọc .env, đăng ký hooksMỗi người cấu hình một kiểu, không ai chặn đọc .env, hook không chạy
4.claude/settings.local.jsonKhởi động (ưu tiên cao hơn file 3)Ghi đè cho riêng bạn, không commitKhông sao, file này là tuỳ chọn
5~/.claude/CLAUDE.mdKhởi độngThói quen cá nhân, ví dụ “trả lời tiếng Việt”, “dùng pnpm”Claude không biết sở thích của bạn, bạn phải nhắc lại mỗi phiên
6./CLAUDE.md (và của các thư mục cha)Khởi động, luôn nằm trong contextBộ nhớ dự án: lệnh build/test, cấu trúc, điều không hiển nhiênMỗi phiên Claude phải tự khám phá lại, tốn token, dễ chạy sai lệnh (ví dụ npm test thay vì pnpm turbo test)
7CLAUDE.local.mdKhởi động, nối sau CLAUDE.mdGhi chú riêng của bạn trong projectKhông sao
8.claude/rules/*.md không có pathsKhởi độngQuy tắc chung tách khỏi CLAUDE.md cho gọnQuy tắc phải dồn vào CLAUDE.md
9.mcp.jsonKhởi động, hỏi duyệt lần đầuKết nối công cụ ngoài: DB, GitHub, Jira…Claude không truy cập được hệ thống ngoài, bạn phải copy dữ liệu vào tay
10.claude/skills/*/SKILL.mdKhởi động: chỉ nạp name + description. Toàn bộ nội dung: khi được dùngQuy trình dùng lại được, ví dụ “thêm migration”, “thêm FAQ”Mỗi lần bạn phải giải thích lại quy trình, kết quả mỗi lần một kiểu
11.claude/agents/*.mdKhởi động nạp định nghĩa, chạy khi được giao việcChuyên gia có context riêng và tool giới hạn, ví dụ reviewer chỉ được đọcChỉ có các subagent có sẵn, không có reviewer bị giới hạn quyền
12Hook SessionStartCuối giai đoạn khởi độngChèn trạng thái dự án, ví dụ nhánh git hoặc ticket đang làmClaude bắt đầu mà không biết bối cảnh hiện tại
13CLAUDE.md ở thư mục con (apps/api/CLAUDE.md)Khi cần: lúc Claude đọc file trong thư mục đóKiến thức riêng từng app: NestJS khác Next.jsClaude dùng quy ước chung, dễ lẫn cách viết giữa backend và frontend
14.claude/rules/*.md có pathsKhi cần: lúc đọc file khớp mẫuQuy tắc theo loại file, chỉ tốn context khi liên quanQuy tắc phải luôn nằm trong CLAUDE.md, tốn context mọi lúc
15.claude/hooks/* (PreToolUse, PostToolUse, Stop…)Mỗi lần gọi tool / kết thúc lượtTự động hoá chắc chắn: chặn secret, format, chạy testChỉ còn dựa vào việc model nhớ chỉ dẫn, có lúc sẽ quên
Quy tắc chọn chỗ đặt thông tin:

5. Claude “nhìn thấy” gì trong một request

Context được ghép theo thứ tự cố định. Phần trên ổn định nên được cache, phần dưới thay đổi mỗi lượt.

6. Một lượt xử lý trong Claude Code

Ví dụ: bạn gõ “Sửa lỗi định dạng mã đơn trong tools.py”. Hook PreToolUse chạy trước bước kiểm tra permission.

7. Agent API trong src/agent.py chạy thế nào

Ví dụ: khách hỏi “Đơn SH1024 của tôi đang ở đâu?”.

Diễn biến thật

Hai request cho một câu hỏi

  1. Request 1: system (chỉ dẫn + chính sách, đã cache) + tools + câu hỏi. Claude trả stop_reason: "tool_use" với lookup_order({"order_id": "SH1024"}).
  2. Code của bạn chạy lookup_order, đọc data/orders.json, trả về {"status": "Đang giao", "eta": "2026-10-03", ...}.
  3. Request 2: gửi lại toàn bộ lịch sử + tool_result. Lần này cache_read_input_tokens > 0 vì system không đổi.
  4. Claude trả end_turn: “Đơn SH1024 đang được giao, dự kiến tới ngày 03/10…”.

Nếu khách gõ sai mã “1024”, tool ném ToolError kèm hướng dẫn định dạng → trả is_error: true → Claude tự hỏi lại khách mã đúng.

8. Cùng một tool, hai cách dùng

tools.py là lõi. agent.py gửi schema của nó qua Messages API cho khách hàng. orders_mcp.py mở cùng các hàm đó qua MCP để nhân viên dùng trong Claude Code. Viết một lần, dùng hai nơi.

9. Thử ngay với Claude Code

Bạn gõĐiều xảy raHọc được
“Tra đơn SH1025”Gọi tool mcp__orders__lookup_order, được allow sẵn nên không hỏiMCP + permission allow
“Thêm chính sách thanh toán COD”Skill add-faq được nạp: tạo file knowledge + thêm eval caseSkill theo mô tả
“Sửa file .env thêm key”Hook protect-secrets.sh exit 2 và rule deny chặnPhòng thủ nhiều lớp
“Sửa src/tools.py cho gọn”Rule python-style.md được nạp; sau khi sửa, hook chạy ruff formatRule theo đường dẫn + PostToolUse
“Dùng code-reviewer kiểm tra thay đổi”Subagent chỉ có tool đọc, trả báo cáo tóm tắtCô lập context, quyền tối thiểu
“Chạy eval”Hỏi xác nhận vì rule ask (tốn phí API)Permission ask

Tóm tắt & mẹo nhớ

Ghi nhớ cốt lõi

  • Settings do harness áp dụng; CLAUDE.md là kiến thức cho model. Luật cứng đặt trong settings/hook, còn kiến thức và quy ước đặt trong CLAUDE.md.
  • Lúc mở phiên, skill và subagent chỉ nạp mô tả, nội dung đầy đủ chỉ nạp khi dùng. CLAUDE.md ở thư mục con và rule có paths nạp khi cần.
  • PreToolUse chạy trước permission. Exit 2 thì chặn tool và gửi stderr cho Claude.
  • Thứ tự cache: tools → system → messages. Nội dung thay đổi đặt cuối cùng.
  • Code của bạn mới là thứ chạy tool; model chỉ thấy schema và kết quả trả về.

Mẹo nhớ nhanh

  • “S-M-M-S-H” khi mở phiên: Settings → Memory (CLAUDE.md) → MCP → Skills/Subagents (mô tả) → Hook SessionStart.
  • “Chặn trước, hỏi sau”: PreToolUse chặn trước, permission hỏi sau.
  • Settings cao → thấp: “Công ty – Lệnh – Local – Team – Tôi” (managed, --settings, local, project, user).
  • “Deny là sếp”: deny luôn thắng ask và allow, dù rule nằm ở file nào.
  • “Menu trước, món sau”: skill giống menu. Claude đọc tên món (description) trước, gọi món thì bếp mới nấu (nạp SKILL.md).
  • “Tủ lạnh – bàn – đĩa” cho cache: tools là tủ lạnh (ít đổi), system là bàn bếp, messages là đĩa thức ăn (đổi liên tục). Đổi tủ lạnh thì phải dọn lại cả bàn lẫn đĩa.