
Claude Prompt Engineering tutorial: XML tags, system prompt và best practices từ Anthropic để điều khiển AI agent
Người học áp dụng được các kỹ thuật prompt engineering chính thức của Anthropic cho Claude — XML tags, system prompt rõ ràng, role prompting và few-sh
Prompt cho Claude không giống prompt cho GPT. Bạn copy nguyên template từ ChatGPT sang Claude rồi thấy output lệch format, persona drift, hoặc model không follow instruction? Đó là vì Anthropic thiết kế Claude theo triết lý khác và recommend bộ kỹ thuật riêng. Bài này tổng hợp 5 kỹ thuật chính thức từ docs Anthropic: XML tags để cấu trúc prompt, system prompt tách khỏi user message, few-shot và prefilling để ép format, chain-of-thought với thinking tag, cùng best practices khi đưa prompt lên production.
Vì sao prompt engineering với Claude khác với GPT
Prompt engineering cho Claude có những điểm khác biệt đáng kể so với các mô hình như GPT, chủ yếu do cách Claude được huấn luyện và kiến trúc của nó. Anthropic thiết kế Claude với triết lý Constitutional AI, khiến nó phản ứng mạnh mẽ hơn với các input có cấu trúc rõ ràng thay vì chỉ ngôn ngữ tự nhiên.
Một trong những khác biệt lớn nhất là việc sử dụng XML tags. Đây là định dạng mà Anthropic chính thức khuyến nghị trong tài liệu của họ, không chỉ là một convention trong cộng đồng. Việc dùng XML tags giúp Claude hiểu rõ ràng ranh giới giữa các phần khác nhau của prompt, từ đó cải thiện độ chính xác khi xử lý các task phức tạp.
Ví dụ, khi mình gửi cùng một task cho GPT-4 và Claude Sonnet 4.6, kết quả trả về thường khác nhau. Claude Sonnet 4.6, với những cải tiến đáng kể trong suy luận ngữ cảnh dài và lập kế hoạch tác nhân [F4], thường cho ra output có cấu trúc tốt hơn nếu prompt được định dạng bằng XML tags.
Context window cũng là một yếu tố quan trọng. Claude Sonnet 4.6 có khả năng xử lý context lên đến 1M token trong phiên bản beta [F5]. Điều này thay đổi hoàn toàn cách mình thiết kế prompt, không còn phải lo lắng về việc cắt ngắn input hay mất thông tin quan trọng. Với Opus 4.8, Anthropic còn giới thiệu "dynamic workflows" cho phép mô hình quản lý các vấn đề quy mô lớn bằng cách điều phối nhiều subagent [F1]. Trong những trường hợp này, cấu trúc prompt rõ ràng sẽ quyết định liệu các subagent có hiểu và thực hiện đúng nhiệm vụ hay không.

XML tags: cú pháp Anthropic recommend cho mọi prompt phức tạp
XML tags là cú pháp Anthropic khuyến nghị để cấu trúc prompt, giúp Claude phân biệt rõ ràng các thành phần như instruction, context, ví dụ hay định dạng output. Việc này đặc biệt hữu ích khi bạn làm việc với các prompt dài và phức tạp, đảm bảo Claude hiểu đúng ý định của mình.
Một số tag phổ biến bạn nên dùng bao gồm: <instructions> cho các chỉ dẫn chính, <context> để cung cấp thông tin nền, <example> cho các ví dụ minh họa, <document> khi bạn muốn Claude phân tích một tài liệu, <thinking> để yêu cầu Claude thể hiện quá trình suy nghĩ, và <answer> cho phần phản hồi cuối cùng.
Các tag này cũng hỗ trợ lồng nhau, cho phép bạn tạo cấu trúc prompt linh hoạt hơn. Ví dụ, bạn có thể có nhiều <example> bên trong một tag <examples> lớn hơn. Claude Sonnet 4.6, mẫu Sonnet mạnh mẽ nhất của Anthropic hiện tại, có những cải tiến đáng kể trong việc suy luận ngữ cảnh dài và lập kế hoạch tác nhân, nên rất phù hợp để xử lý các prompt có cấu trúc XML phức tạp này [F4].
Mình đã thử nghiệm một prompt phân tích tài liệu với ba tag lồng nhau trên Claude Sonnet 4.6. Đây là một ví dụ về cách bạn có thể cấu trúc prompt của mình:
<instructions>
Phân tích tài liệu dưới đây và tóm tắt các điểm chính.
Sau đó, trích xuất tất cả các ngày quan trọng và sự kiện liên quan.
Cuối cùng, đề xuất 3 câu hỏi dựa trên nội dung tài liệu.
</instructions>
<document>
<title>Báo cáo tài chính Q3 2024</title>
<content>
Công ty XYZ đạt doanh thu 120 triệu USD trong Q3 2024, tăng 15% so với cùng kỳ năm trước. Lợi nhuận ròng là 25 triệu USD. Ngày công bố báo cáo: 25/10/2024. Cuộc họp cổ đông thường niên sẽ diễn ra vào ngày 15/11/2024.
</content>
</document>
<output_format>
Sử dụng định dạng JSON với các trường 'summary', 'key_dates', và 'questions'.
</output_format>Mặc dù Anthropic khuyến khích dùng các tag theo convention của họ, bạn vẫn có thể tự đặt tên tag riêng miễn là chúng có ý nghĩa và nhất quán. Tuy nhiên, việc tuân thủ convention sẽ giúp model dễ hiểu hơn và giảm thiểu lỗi.
Một số lỗi thường gặp khi dùng XML tags là quên đóng tag, hoặc nhầm lẫn giữa cú pháp XML và Markdown. Việc trộn lẫn hai loại cú pháp này trong cùng một prompt có thể khiến Claude bị nhầm lẫn và đưa ra kết quả không mong muốn. Luôn đảm bảo rằng mọi tag mở đều có tag đóng tương ứng.
System prompt: tách role khỏi task để Claude giữ persona ổn định
Trong Anthropic SDK, system prompt là field riêng khi gọi `messages.create()`, không phải prepend vào user message như nhiều framework cũ vẫn làm. Tách biệt này không chỉ là chi tiết kỹ thuật. Claude treat system prompt như persona cố định cho toàn conversation, còn user message là task từng turn. Khi bạn nhồi role và task chung một chỗ, model dễ drift persona sau vài turn vì bị overwrite bởi input mới.
Mình thường viết system prompt theo 4 phần rõ ràng. Role definition: bạn là ai, level kinh nghiệm, domain cụ thể. Capability scope: được làm gì, không được làm gì. Constraint: không suy đoán, không bịa data, không trả lời ngoài scope. Output format: JSON schema, markdown structure, hay plain text. Cấu trúc này không phải standard chính thức, mà là framework mình dùng để tránh trộn lẫn rule cố định với task cụ thể trong cùng một prompt.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
const response = await client.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
system: `Bạn là senior backend engineer 8 năm kinh nghiệm Python.
Nhiệm vụ: review code user gửi.
Constraint: chỉ comment về security, performance, readability.
Output: markdown với 3 section H3 tương ứng 3 khía cạnh trên.`,
messages: [
{ role: "user", content: "def login(u, p): return db.query(f'... {u}')" }
]
});Role prompting cụ thể tạo khác biệt rõ so với generic. Câu "Bạn là AI assistant" gần như không add gì vì Claude vốn đã biết role đó. So sánh với "Bạn là senior backend engineer review code Python, focus vào SQL injection và race condition". Model lập tức narrow scope, dùng terminology đúng domain, và filter những comment không liên quan. Mình chưa benchmark con số chính thức, nhưng cảm nhận sau nhiều lần test là output từ role cụ thể bám task chặt hơn ở mức đáng kể.
Quy tắc phân chia giữa system và user prompt mình hay dùng:
Rule cố định cho mọi turn (luôn trả JSON, không dùng emoji): vào `system`
Persona và role không đổi giữa các lần gọi: vào `system`
Task cụ thể của turn hiện tại (parse đoạn HTML này): vào `user`
Data input thay đổi mỗi request: vào `user`
Về độ dài, system prompt quá ngắn (1-2 câu) thường thiếu context để Claude hiểu boundary, còn quá dài (vài nghìn từ) dễ bị model focus chỗ này quên chỗ khác. Mình thấy sweet spot rơi vào vài đoạn ngắn, đủ cover role cộng constraint cộng output format mà không loãng. Khi prompt phình to quá mức, cách xử lý hợp lý là tách bớt các rule ít dùng sang prompt riêng cho từng nhánh task, thay vì gộp tất cả vào một system prompt monster.
Few-shot prompting và prefilling: 2 kỹ thuật ép Claude theo format
Để Claude trả về output đúng format mong muốn, đặc biệt với các tác vụ phức tạp, mình thường dùng hai kỹ thuật: few-shot prompting và prefilling. Cả hai giúp Claude hiểu rõ hơn về cấu trúc và kiểu dữ liệu bạn cần, từ đó tạo ra kết quả nhất quán hơn.
Few-shot prompting: Dạy Claude bằng ví dụ
Few-shot prompting là cách bạn cung cấp 2-5 cặp ví dụ input/output ngay trong prompt. Claude sẽ học pattern từ các ví dụ này để tạo ra output tương tự cho input mới. Để trình bày ví dụ một cách rõ ràng, bạn nên bọc chúng trong thẻ <examples> và mỗi ví dụ trong thẻ <example>, với <input> và <output> riêng biệt.
<examples>
<example>
<input>Tóm tắt bài viết về AI: "AI là công nghệ mô phỏng trí tuệ con người..."</input>
<output>{
"title": "Giới thiệu về AI",
"summary": "AI là công nghệ mô phỏng trí tuệ con người."
}</output>
</example>
<example>
<input>Tóm tắt báo cáo tài chính: "Doanh thu quý 1 tăng trưởng 10%..."</input>
<output>{
"title": "Báo cáo tài chính Q1",
"summary": "Doanh thu quý 1 tăng trưởng 10%."
}</output>
</example>
</examples>Kỹ thuật này đặc biệt hữu ích khi bạn cần Claude tạo ra output theo một format đặc thù, ví dụ như JSON schema phức tạp, hoặc cần sự nhất quán cao trong cấu trúc phản hồi.
Prefilling: Khóa chặt format đầu ra
Prefilling là một kỹ thuật đơn giản nhưng rất hiệu quả. Bạn chỉ cần bắt đầu tin nhắn của assistant bằng một ký tự hoặc chuỗi ký tự cố định. Điều này "ép" Claude phải tiếp tục theo format đó. Ví dụ, nếu bạn muốn Claude trả về JSON thuần túy mà không có bất kỳ lời mở đầu nào, bạn có thể bắt đầu tin nhắn assistant bằng ký tự '{'.
{
"role": "user",
"content": "Trích xuất tên và tuổi từ câu sau: 'Tên tôi là An, tôi 30 tuổi.'"
},
{
"role": "assistant",
"content": "{"
}Với cách này, Claude sẽ tự động hoàn thành phần JSON còn lại, giúp bạn dễ dàng parse output bằng chương trình mà không cần xử lý các đoạn văn bản không mong muốn. Tương tự, nếu bạn cần output là XML, bạn có thể bắt đầu bằng "<answer>". Kỹ thuật này rất quan trọng khi bạn cần parse output của Claude một cách tự động.
Kết hợp Few-shot và Prefilling
Để đạt được kết quả ổn định và chính xác nhất, bạn có thể kết hợp cả few-shot prompting và prefilling. Few-shot sẽ dạy Claude pattern và cấu trúc mong muốn, trong khi prefilling sẽ khóa chặt format đầu ra, đảm bảo Claude không lạc đề. Sự kết hợp này giúp Claude không chỉ hiểu bạn muốn gì mà còn trả lời đúng theo cách bạn cần.

Chain-of-thought với <thinking> tag: cho Claude không gian suy luận
Claude thường cho kết quả tốt hơn khi được yêu cầu suy luận trước khi đưa ra câu trả lời cuối cùng. Kỹ thuật này gọi là Chain-of-Thought (CoT), giúp model có không gian để xử lý vấn đề từng bước một.
Pattern chuẩn để triển khai CoT với Claude là sử dụng cặp tag `<thinking>...</thinking>` và `<answer>...</answer>`. Bên trong tag `<thinking>`, bạn hướng dẫn Claude thực hiện các bước suy luận. Sau đó, kết quả cuối cùng sẽ được đặt trong tag `<answer>`.
Một ưu điểm của việc sử dụng cặp tag này là bạn có thể dễ dàng parse và ẩn phần `<thinking>` trên giao diện người dùng, chỉ hiển thị phần `<answer>` cho người dùng cuối. Điều này giúp trải nghiệm của người dùng gọn gàng hơn mà vẫn tận dụng được khả năng suy luận của Claude.
Với các phiên bản mới như Claude Opus 4.8, Anthropic còn giới thiệu chế độ suy luận mở rộng (extended thinking mode) hay "dynamic workflows" [F1]. Trong chế độ này, model có thể tự động phân bổ token cho quá trình suy luận, giúp xử lý các vấn đề phức tạp hơn.
Tuy nhiên, việc sử dụng `<thinking>` tag cũng có những đánh đổi nhất định. Nó có thể làm tăng lượng token đầu ra thêm khoảng 30-50% và độ trễ (latency) tăng từ 1.5 đến 2 lần. Do đó, bạn cần cân nhắc sử dụng CoT cho các trường hợp phù hợp.
Best practices và pitfall thường gặp khi build production prompt
Để prompt của bạn hoạt động ổn định và hiệu quả trong môi trường production, mình khuyến nghị áp dụng các best practice giống như phát triển phần mềm. Đầu tiên, hãy coi prompt như code: lưu trữ chúng trong các file `.md` riêng biệt thay vì hardcode trực tiếp vào source code. Việc này giúp dễ dàng quản lý phiên bản (versioning) và theo dõi thay đổi.
Trước khi deploy, bạn nên test prompt với ít nhất 20 biến thể đầu vào khác nhau để đảm bảo độ tin cậy. Đồng thời, việc đo lường các metric quan trọng như tỷ lệ đúng schema JSON, độ trễ (latency) và chi phí token trên mỗi yêu cầu là cần thiết để tối ưu hóa hiệu suất và chi phí.
Một pitfall phổ biến là prompt quá dài. Điều này có thể khiến Claude bỏ lỡ các hướng dẫn quan trọng ở giữa (hiện tượng "lost in the middle"). Thứ hai, việc sử dụng các hướng dẫn tiêu cực (ví dụ: "đừng làm X") thường kém hiệu quả hơn so với hướng dẫn tích cực ("hãy làm Y"). Cuối cùng, cố gắng trộn lẫn nhiều tác vụ vào một prompt duy nhất cũng là một lỗi. Thay vào đó, hãy tách chúng thành các chuỗi tác vụ nhỏ hơn để Claude xử lý tuần tự.
Anthropic Workbench là một công cụ hữu ích để bạn A/B test các phiên bản prompt khác nhau. Đối với các system prompt cố định, bạn có thể cân nhắc áp dụng kỹ thuật prompt caching để giảm chi phí đáng kể, có thể lên đến 90%.
Tổng kết: 5 kỹ thuật trên cover phần lớn use case khi build agent với Claude — XML tags và system prompt là 2 thứ nên áp dụng ngay từ prompt đầu tiên. Phần deep dive về cách test và versioning prompt trong CI/CD mình sẽ viết riêng. Bạn có thể xem thêm docs gốc của Anthropic để tham khảo các pattern nâng cao.