Prompt Engineering Frameworks
Cập nhật: 02/2026
Tổng hợp nghiên cứu từ Anthropic, OpenAI, Google, IBM, và cộng đồng developer (2025-2026)
1. Nguyên Tắc Cơ Bản
1.1. Specificity, Clarity & Context Assembly — Cụ thể, rõ ràng và cung cấp đầy đủ ngữ cảnh
Reasons:
-
Context Quality: Hầu hết lỗi của agent không phải do model kém mà do context kém. Cung cấp đủ ngữ cảnh giúp agent hiểu chính xác bạn muốn gì trong hoàn cảnh nào.
-
Context Retrieval: Coding agent sử dụng prompt để tìm kiếm và lấy ngữ cảnh từ codebase. Prompt càng cụ thể (có tên file, function, component cụ thể), agent càng tìm đúng files/code liên quan để nạp vào working memory. Prompt mơ hồ/thiếu ngữ cảnh → search queries kém → context thiếu/sai → output kém chất lượng.
-
Tool Selection: Agent quyết định dùng tools nào (Glob, Grep, Read, Edit) dựa trên prompt. Prompt rõ ràng giúp agent chọn đúng tools và parameters.
-
Scope Definition: Prompt cụ thể định rõ scope công việc, tránh agent làm quá nhiều (over-engineering) hoặc quá ít (thiếu features).
-
Time Efficiency: Giảm số lần iterations. Prompt mơ hồ/thiếu ngữ cảnh → output sai → phải refine prompt → lặp lại nhiều lần. Prompt cụ thể từ đầu → đúng ngay lần 1.
Bad prompt:
Viết code xử lý Login Form, validate email và password
Good prompt (theo RACE Framework):
<role>Senior React developer</role>
<action>
Viết LoginForm component và API Hook để xử lý login
</action>
<context>
- Cần đọc các service, các form khác hiện có trong dự án để đồng bộ patterns
</context>
<expectation>
- Yêu cầu form: Dùng React Hook Form + Zod validation
- 2 fields: email (bắt buộc, format email, chỉ chấp nhận business email), password (bắt buộc, min 8 ký tự, có uppercase + number)
- Submit: POST /api/auth/login với payload { email, password } sử dụng API Hook đã định nghĩa
- Hiển thị error message dưới mỗi field khi validation fail
- File output: src/components/login-form.tsx, src/services/auth/use-login.ts, src/pages/auth/login.tsx
- Code TypeScript với proper types, export default component
</expectation>
Lời khuyên:
- Sử dụng cấu trúc rõ ràng (Structured Prompting): Dùng XML tags (như
<context>,<task>) hoặc markdown để phân tách rõ các phần, giúp agent không nhầm lẫn giữa instruction, constraint và context. - Định nghĩa output rõ ràng (Output Specification): Nếu không chỉ định format output, agent sẽ tự chọn và có thể không theo convention của bạn. Chỉ rõ output format giúp kết quả sử dụng được ngay, giảm thời gian chỉnh sửa.
- Nêu rõ ràng buộc (Constraints & Boundaries): Nêu rõ những việc không được làm (ví dụ: không dùng thư viện mới, không sửa file X) nhằm giới hạn phạm vi, tránh việc agent over-engineer hoặc sửa những phần ngoài dự kiến.
- Bỏ qua các ràng buộc hiển nhiên (Omit Obvious Constraints): Không cần thiết đưa vào các thông tin hiển nhiên như "project sử dụng React và TypeScript" vì Agent Reasoning (đặc biệt khi kết hợp với công cụ đọc/hiểu codebase) đã tự hiểu rõ ngữ cảnh này. Thay vào đó, tập trung vào các ràng buộc mang tính quyết định.
- Cung cấp ví dụ (Few-shot Prompting): Đưa ra pattern đã có trong dự án làm ví dụ, nó hoạt động như 'ràng buộc ngầm' hướng dẫn agent tuân theo format/style mong muốn mà không cần giải thích dài dòng.
- Sử dụng Project-level rules (Persistent Instructions): Viết coding conventions vào file (như
.cursorruleshoặcCLAUDE.md) như một "source of truth", giúp agent tuân thủ nhất quán ở mọi prompt mà không phải lặp lại.
1.2. Task Decomposition — Chia nhỏ task phức tạp
Reasons:
-
Curse of instructions: Khi nhồi quá nhiều yêu cầu vào một prompt, agent bị "quá tải chỉ dẫn" khiến nó không tuân thủ tốt bất kỳ cái nào. Chia nhỏ giúp agent tập trung, dễ kiểm tra lỗi, và output chất lượng hơn.
-
Context pollution: Coding agent dựa vào prompt để tìm kiếm và nạp ngữ cảnh từ codebase. Một yêu cầu quá lớn (ví dụ: "xây dựng toàn bộ chức năng giỏ hàng cả frontend lẫn backend") sẽ khiến agent tìm và nạp một lượng lớn code/file không liên quan cho từng sub-task cụ thể (như khi viết UI nhưng lại bị nạp file cấu hình DB). Việc bão hòa ngữ cảnh rác này làm giảm khả năng phân tích của model, dẫn đến output chất lượng kém hơn.
Bad prompt:
Viết tính năng Giỏ hàng (Cart): bao gồm giao diện hiển thị danh sách sản phẩm, quản lý state thêm/sửa/xoá items, tính tổng tiền, và kết nối API thanh toán (checkout).
Good prompt (chia nhỏ theo RACE, 1 prompt/step):
Step 1:
<role>Senior React developer</role>
<action>
Tạo Zustand store để quản lý state của Giỏ hàng (Cart)
</action>
<context>
- Không dùng Redux hay Context API
- Cần đọc các store hiện có trong dự án để đồng bộ patterns
</context>
<expectation>
- Yêu cầu store: Dùng Zustand
- Interface: Cần có interface cho CartItem (id, name, price, quantity)
- Actions: Cần có các action để thêm/xoá/sửa số lượng item
- Selectors: Cần có hàm tiện ích để tính tổng số tiền và tổng số lượng
- Ràng buộc: KHÔNG xây dựng phần UI hiển thị trong bước này
- File output: src/stores/cart-store.ts, src/utils/cart.ts
- Code TypeScript với proper types, export default store
</expectation>
Step 2 (sau khi Step 1 xong):
<role>Senior React developer</role>
<action>
Viết giao diện Cart page component và tích hợp API checkout
</action>
<context>
- Cần đọc các files như src/stores/cart-store.ts, src/utils/cart.ts để lấy dữ liệu giỏ hàng hiển thị
- Cần đọc các components hiện có trong dự án để đồng bộ patterns
</context>
<expectation>
- Yêu cầu UI: Giao diện hiển thị danh sách item, tổng tiền, nút thanh toán (style bằng Tailwind).
- Chia nhỏ UI thành các components nhỏ hơn: CartItem, CartList, CartSummary.
- API Integration: Submit POST /api/checkout với payload là mảng các items.
- UX: Xử lý trạng thái loading/error khi gọi API đồng bộ với các tính năng khác.
- Tính năng: Nếu checkout báo thành công, phải gọi action clearCart để làm trống giỏ hàng.
- File output: src/components/CartItem.tsx, src/components/CartList.tsx, src/components/CartSummary.tsx, src/components/Cart.tsx.
- Code TypeScript với proper types, export default component.
</expectation>
1.3. Verification & Testing — Yêu cầu kiểm chứng
Reason: Nếu không yêu cầu verification, bạn sẽ nhận được code "trông hợp lý" nhưng chưa được chứng minh hoạt động. Yêu cầu test hoặc verification buộc agent phải suy nghĩ kỹ hơn về edge cases và đảm bảo code đúng.
Bad prompt:
Viết function validate email.
Good prompt (theo RACE + Verification):
<role>Senior TypeScript developer</role>
<action>
Viết thêm function validateEmail với test coverage đầy đủ
</action>
<context>
- Đọc các utils hiện có trong dự án để đồng bộ patterns
</context>
<expectation>
- KHÔNG dùng thư viện external (validator.js, etc.)
- Dùng regex native
- TypeScript strict mode
- Export cả function và test file: src/utils/validateEmail.ts và src/utils/validateEmail.test.ts
</expectation>
<verification>
Viết unit test cover các case:
Valid emails:
- "[email protected]" → true
- "[email protected]" → true
Invalid emails:
- "" → false
- "user@" → false
- "@domain.com" → false
- "user @domain.com" → false
- "[email protected]" → false
Edge cases:
- Email > 254 chars → false
- Email có unicode "用户@domain.com" → handle gracefully
Sau khi viết, chạy: npm test validateEmail
Tất cả tests phải PASS trước khi return code.
</verification>
1.4. Iterative Refinement — Lặp lại và tinh chỉnh
Reason: Prompt engineering là quá trình lặp, không phải one-shot. Nếu output lần một chưa đúng, đừng viết lại từ đầu – hãy tinh chỉnh bằng cách bổ sung thông tin thiếu hoặc điều chỉnh constraint. Mỗi lần iterate bạn học được cách giao tiếp tốt hơn với agent. Tuy nhiên, nếu sau khoảng 3 lần lặp mà kết quả vẫn chưa ổn, hãy cân nhắc tạo cuộc hội thoại mới (hoặc viết prompt mới hoàn toàn). Việc lặp lại quá nhiều lần trong một cuộc hội thoại sẽ khiến agent nạp thêm nhiều context rác vào lịch sử, làm agent "lose focus" vào nhiệm vụ và mục tiêu ban đầu. (Lưu ý: Đối với Claude, bạn có thể sử dụng tính năng Checkpointer để revert (quay lại) chính xác thời điểm mà bạn cho là Context đang chuẩn nhất, tránh việc phải bắt đầu lại từ đầu).
Bad approach:
(Output không đúng ý → xóa hết → viết prompt hoàn toàn mới)
Good approach:
Prompt 1: "Viết component ProductCard hiển thị name, price, image."
(Output thiếu responsive design)
Prompt 2: "ProductCard ở trên chưa responsive. Hãy cập nhật:
- Mobile (<768px): card full width, image trên text dưới
- Desktop (>=768px): card 300px width, layout ngang
- Dùng CSS Grid, không dùng media query nếu có thể (dùng container query)"
1.5. Chain-of-Thought — Yêu cầu giải thích reasoning
Reason: Chain of thought cải thiện khả năng lập luận của LLM bằng cách yêu cầu AI giải quyết một vấn đề từng bước một. Khi agent giải thích reasoning, bạn có thể verify logic đúng hay sai trước khi chấp nhận code. Điều này đặc biệt tốt cho việc giải quyết vấn đề hoặc các nhiệm vụ phân tích, tính toán phức tạp.
Tất cả những gì bạn phải làm là thêm cụm từ đơn giản “Let’s think step-by-step” (hoặc "Hãy suy nghĩ từng bước một") vào cuối prompt của bạn.
Prompt Template:
"[insert your prompt instructions]. Let's think through it step-by-step."
2. Công Thức Prompt
2.1. RTF Framework — Role, Task, Format
Công thức đơn giản nhất, phù hợp cho task nhanh, ít phức tạp.
| Thành phần | Ý nghĩa | Ví dụ coding |
|---|---|---|
| R — Role | AI đóng vai gì | "Act as a senior TypeScript developer" |
| T — Task | Việc cần làm cụ thể | "Viết function validate phone number VN" |
| F — Format | Định dạng output mong muốn | "Return TypeScript code với JSDoc comments" |
Công thức: [Role] + [Task] + [Format]
Ví dụ áp dụng:
Role: Bạn là senior TypeScript developer.
Task: Viết function validatePhoneVN(phone: string): boolean kiểm tra số điện thoại Việt Nam (10 số, bắt đầu bằng 03/05/07/08/09).
Format: Return TypeScript code, kèm unit test, có ít nhất 5 test cases.
Khi nào dùng: Quick fix, utility function, code snippet đơn lẻ, câu hỏi ngắn.
2.2. RACE Framework — Role, Action, Context, Expectation
Bổ sung thêm Context và Expectation so với RTF, phù hợp cho task có ngữ cảnh dự án.
| Thành phần | Ý nghĩa | Ví dụ coding |
|---|---|---|
| R — Role | AI đóng vai gì | "Senior React developer" |
| A — Action | Hành động cụ thể cần thực hiện | "Refactor component từ class sang functional" |
| C — Context | Bối cảnh dự án, tech stack, file liên quan | "Dự án dùng React 18 + TypeScript + Zustand" |
| E — Expectation | Kết quả mong đợi, tiêu chí thành công | "Component vẫn pass tất cả existing tests" |
Công thức: [Role] + [Action] + [Context] + [Expectation]
Ví dụ áp dụng:
Role: Senior React developer.
Action: Refactor UserProfile component từ class component sang functional component với hooks.
Context: Dự án React 18 + TypeScript. Component hiện tại dùng this.state và lifecycle methods. File: src/components/user-profile.tsx. State management: Zustand.
Expectation: Component hoạt động giống hệt bản cũ, tất cả existing tests trong user-profile.test.tsx vẫn pass. Dùng useState/useEffect thay thế state/lifecycle.
Khi nào dùng: Refactoring, bug fix, feature nhỏ trong dự án có sẵn.
2.3. RISEN Framework — Role, Instructions, Steps, End goal, Narrowing
Framework chi tiết nhất cho task phức tạp, nhiều bước, được khuyến nghị nhiều nhất cho coding tasks.
| Thành phần | Ý nghĩa | Ví dụ coding |
|---|---|---|
| R — Role | Persona / chuyên môn của AI | "Fullstack engineer chuyên Next.js + PostgreSQL" |
| I — Instructions | Mô tả chi tiết nhiệm vụ chính | "Xây dựng REST API authentication hoàn chỉnh" |
| S — Steps | Các bước cụ thể cần thực hiện (có thứ tự) | "1. Design schema → 2. Viết API → 3. Viết test" |
| E — End goal | Kết quả cuối cùng mong muốn | "User có thể register, login, refresh token" |
| N — Narrowing | Ràng buộc, giới hạn, điều KHÔNG được làm | "Không dùng ORM, chỉ raw SQL. Không thêm lib mới" |
Công thức: [Role] + [Instructions] + [Steps] + [End goal] + [Narrowing]
Ví dụ áp dụng:
Role: Bạn là fullstack engineer chuyên Next.js 14 App Router + PostgreSQL.
Instructions: Xây dựng hệ thống authentication với JWT cho dự án hiện tại.
Steps:
1. Tạo database migration cho bảng users (id, email, password_hash, created_at)
2. Viết API route POST /api/auth/register - validate input, hash password bằng bcrypt, insert DB
3. Viết API route POST /api/auth/login - verify credentials, return access token (15min) + refresh token (7d)
4. Viết API route POST /api/auth/refresh - verify refresh token, issue new access token
5. Viết middleware withAuth() để protect các route cần authentication
6. Viết unit test cho mỗi endpoint
End goal: User có thể register → login → nhận JWT → dùng token để access protected routes → refresh token khi hết hạn. Tất cả tests pass.
Narrowing:
- KHÔNG dùng NextAuth/Auth.js - implement manual JWT
- KHÔNG dùng ORM, dùng pg driver trực tiếp
- KHÔNG thêm dependency ngoài bcrypt và jsonwebtoken (đã có trong package.json)
- Passwords phải được hash, KHÔNG BAO GIỜ lưu plaintext
- Tuân thủ folder structure hiện tại: src/app/api/...
Khi nào dùng: Feature lớn, multi-step implementation, system design, task cần plan rõ ràng.
2.4. COSTAR Framework — Context, Objective, Style, Tone, Audience, Response
Framework toàn diện nhất, phù hợp khi cần kiểm soát cả chất lượng code lẫn cách trình bày.
| Thành phần | Ý nghĩa | Ví dụ coding |
|---|---|---|
| C — Context | Background, tech stack, tình trạng hiện tại | "Dự án e-commerce Next.js, đang có performance issue" |
| O — Objective | Mục tiêu cần đạt được | "Giảm First Contentful Paint từ 4s xuống <1.5s" |
| S — Style | Coding style, pattern, convention | "Functional programming, immutable data, pure functions" |
| T — Tone | Mức độ chi tiết của giải thích | "Giải thích chi tiết từng thay đổi như đang mentor junior dev" |
| A — Audience | Ai sẽ đọc/maintain code này | "Team 3 junior devs, cần code dễ đọc hơn là clever" |
| R — Response | Format output mong muốn | "Code kèm inline comments, trước mỗi file ghi tóm tắt thay đổi" |
Công thức: [Context] + [Objective] + [Style] + [Tone] + [Audience] + [Response]
Ví dụ áp dụng:
Context: Dự án e-commerce Next.js 14 + React Query. Trang product listing đang load chậm (FCP ~4s). Hiện tại fetch tất cả products một lần rồi filter client-side.
Objective: Optimize trang product listing để FCP < 1.5s và TTI < 2.5s.
Style: Dùng server components khi có thể. Prefer streaming + Suspense over loading states. Giữ nguyên pattern React Query cho client components.
Tone: Giải thích chi tiết reasoning đằng sau mỗi optimization, ghi rõ trước/sau performance impact.
Audience: Team có 3 junior developers, ưu tiên code dễ hiểu, tránh abstraction phức tạp.
Response: Với mỗi file cần thay đổi:
1. Ghi tóm tắt 1 dòng về thay đổi
2. Giải thích WHY thay đổi này improve performance
Khi nào dùng: Code review, optimization, documentation, task cần cân bằng giữa code quality và knowledge transfer.
2.5. So sánh các Framework
| Công thức | Độ phức tạp task | Số thành phần | Best for |
|---|---|---|---|
| RTF | Thấp | 3 | Quick fix, snippet, câu hỏi ngắn |
| RACE | Trung bình | 4 | Bug fix, refactor nhỏ |
| RISEN | Cao | 5 | Feature lớn, multi-step, system design |
| COSTAR | Cao | 6 | Code review, optimization, mentoring |
Tip: Không nhất thiết phải dùng đủ mọi thành phần. Task đơn giản chỉ cần 2-3 thành phần. Điều quan trọng là luôn có Goal rõ ràng và Context đầy đủ.
3. Tổng Kết
3.1. Bảng tóm tắt các nguyên tắc
| # | Tiêu chí | Keyword |
|---|---|---|
| 1 | Cụ thể, rõ ràng và đầy đủ ngữ cảnh | Specificity & Context |
| 2 | Chia nhỏ task phức tạp | Decomposition |
| 3 | Yêu cầu verification | Testing |
| 4 | Lặp lại và tinh chỉnh | Iteration |
| 5 | Yêu cầu giải thích reasoning | Chain-of-thought |
4. Tài Liệu Tham Khảo
4.1. Nguyên tắc & Best Practices
- Anthropic - Claude Prompting Best Practices
- Addy Osmani - The Prompt Engineering Playbook for Programmers
- Addy Osmani - How to Write a Good Spec for AI Agents
- Lakera - The Ultimate Guide to Prompt Engineering 2026
- IBM - The 2026 Guide to Prompt Engineering
- OpenAI - Prompt Engineering Best Practices
- Graphite - How to Write Better Prompts for AI Code Generation
- Ranthebuilder - Agentic AI Prompting Best Practices
- Thomas Wiegold - Prompt Engineering Best Practices 2026