Bỏ qua để đến nội dung

Input/Output Contract

Level: L4 — AI Skills (Bài 5/12)

Sau bài này, bạn có thể:

  • Liệt kê đủ 3 lớp “hợp đồng” của 1 Skill: ai được gọi (invocation), input nhận vào (arguments), và output có kiểm chứng được không (evaluation).
  • Dùng đúng các trường frontmatter kiểm soát quyền: disable-model-invocation, user-invocable, allowed-tools, disallowed-tools.
  • Truyền và dùng tham số ($ARGUMENTS, $N, tham số đặt tên) trong 1 Skill.
  • Viết 1 bộ evaluation đơn giản để kiểm chứng Skill hoạt động đúng như mong đợi.

“Input/Output Contract” của 1 Skill gồm 3 lớp, không chỉ là định dạng output:

Lớp 1 — Ai được gọi (invocation contract): mặc định cả người dùng và Claude đều gọi được Skill; 2 trường frontmatter thu hẹp quyền này:

Trường Hiệu ứng Dùng khi
disable-model-invocation: true Chỉ người dùng gọi được (/skill-name), Claude không tự kích hoạt Tác vụ có side-effect: /deploy, /commit, gửi tin nhắn
user-invocable: false Chỉ Claude gọi được, ẩn khỏi menu / Kiến thức nền không phải 1 hành động ý nghĩa để người dùng tự gõ
[S74]

Lớp 2 — Input nhận vào (argument contract): Skill có thể nhận tham số khi được gọi, qua biến $ARGUMENTS (toàn bộ chuỗi tham số), $N/$ARGUMENTS[N] (tham số theo vị trí), hoặc tham số đặt tên qua trường arguments trong frontmatter [S74]. Ví dụ: gọi /fix-issue 123 → Claude nhận “Fix GitHub issue 123…” — số 123 chính là input được truyền vào theo đúng hợp đồng đã định nghĩa trong Skill.

Lớp 3 — Output có kiểm chứng được không (evaluation contract): đây là phần dễ bị bỏ qua nhất nhưng quan trọng nhất — làm sao biết Skill “hoạt động đúng”? Tài liệu chính thức đề xuất viết evaluation — 1 cấu trúc mô tả rõ tình huống thử + hành vi mong đợi:

{
"skills": ["pdf-processing"],
"query": "Extract all text from this PDF file and save it to output.txt",
"files": ["test-files/document.pdf"],
"expected_behavior": [
"Successfully reads the PDF file using an appropriate PDF processing library or command-line tool",
"Extracts text content from all pages in the document without missing any pages",
"Saves the extracted text to a file named output.txt in a clear, readable format"
]
}

[S77]

Đây chính là 1 “output contract” cụ thể: không chỉ nói Skill “làm việc PDF”, mà định nghĩa rõ input mẫu (query, files) và tiêu chí output (expected_behavior) — có thể đối chiếu được, không mơ hồ.

Nếu bài 32 dạy cách viết instructions rõ ràng và bài 33 dạy cách tổ chức tài nguyên gọn gàng, bài này trả lời câu hỏi còn lại: làm sao biết Skill thực sự hoạt động đúng, và làm sao kiểm soát ai được quyền gọi nó? Thiếu lớp 1 (invocation contract) dẫn tới rủi ro Claude tự ý thực hiện hành động có side-effect (deploy, gửi email) mà không được yêu cầu. Thiếu lớp 3 (evaluation contract) khiến bạn không có cách nào biết Skill “tốt” hay “tệ” ngoài cảm tính.

Bảng tổng hợp hiệu ứng của 2 trường kiểm soát quyền:

Frontmatter Người dùng gọi được Claude gọi được Khi nào load vào ngữ cảnh
(mặc định) Description luôn trong ngữ cảnh, nội dung đầy đủ load khi được gọi
disable-model-invocation: true Không Description KHÔNG trong ngữ cảnh, nội dung đầy đủ chỉ load khi người dùng tự gọi
user-invocable: false Không Description luôn trong ngữ cảnh, nội dung đầy đủ load khi được gọi
[S74]

Về tham số: nếu Skill được gọi kèm tham số nhưng nội dung không dùng biến $ARGUMENTS, hệ thống tự động nối thêm dòng ARGUMENTS: <giá trị> vào cuối nội dung Skill — đảm bảo Claude luôn thấy được input dù người viết Skill quên khai báo biến [S74]. Đây là 1 dạng “graceful fallback” đáng lưu ý khi thiết kế input contract.

Tiếp nối ẩn dụ “hồ sơ đào tạo”: hợp đồng input/output giống như quy định sử dụng hồ sơ dán ở bìa ngoài — “Chỉ quản lý mới được mở hồ sơ này” (invocation contract), “Điền đủ các trường A, B, C trước khi dùng” (argument contract), và “Sau khi dùng xong, đối chiếu với danh sách kiểm tra ở trang cuối để xác nhận đã làm đúng” (evaluation contract). Không có 3 lớp quy định này, hồ sơ vẫn “chạy được” nhưng không ai đảm bảo nó được dùng đúng cách, đúng người, và cho kết quả đáng tin.

  1. Xác định: Skill này có side-effect (thay đổi dữ liệu thật, gửi tin nhắn, deploy) không? Nếu có → cân nhắc disable-model-invocation: true.
  2. Xác định: Skill này có phải 1 hành động người dùng cần tự gọi, hay chỉ là kiến thức nền Claude tự áp dụng khi cần? Nếu là kiến thức nền → cân nhắc user-invocable: false.
  3. Nếu Skill cần nhận input cụ thể mỗi lần gọi, thiết kế rõ Skill dùng $ARGUMENTS hay tham số đặt tên (arguments: [ten1, ten2]).
  4. Trước khi viết instructions chi tiết (bài 32), viết ít nhất 3 tình huống evaluation theo cấu trúc mục 2 — nguyên tắc “evaluation-driven development” [S77]: xác định lỗ hổng thật trước, viết nội dung vừa đủ để lấp đúng lỗ hổng đó.
  5. Sau khi Skill hoạt động, đối chiếu output thật với expected_behavior đã viết — không khớp thì quay lại sửa instructions, không phải sửa evaluation cho khớp kết quả sai.

Ví dụ invocation contract có side-effect — Skill deploy (S74):

---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---
Deploy $ARGUMENTS to production:
1. Run the test suite
2. Build the application
3. Push to the deployment target
4. Verify the deployment succeeded

disable-model-invocation: true đảm bảo Claude không bao giờ tự ý deploy chỉ vì “code trông có vẻ sẵn sàng” — chỉ chạy khi người dùng gõ /deploy [S74].

Ví dụ output contract của chính dự án này: file assets/chapter-template.md trong .claude/skills/ai-mastery-bible/ đóng vai trò 1 output contract cứng: mọi chapter tạo ra phải có đủ 18 mục theo đúng cấu trúc mẫu — 1 dạng “contract” không cần viết bằng JSON như S77 minh họa, mà bằng 1 file template bắt buộc tuân theo, kiểm chứng được bằng cách đối chiếu (07-quality-control/*-review.md chính là “evaluation” cho từng chapter).

Skill: [tên skill]
Input mẫu: [1 yêu cầu người dùng thật có thể gõ]
Hành vi mong đợi:
- [tiêu chí 1, cụ thể, kiểm chứng được]
- [tiêu chí 2]
- [tiêu chí 3]
Skill này có side-effect thật (tốn tiền, gửi đi, xóa/ghi đè)?
→ Có: disable-model-invocation: true
→ Không: bỏ qua trường này (mặc định Claude tự gọi được)
Skill này là 1 hành động người dùng cần chủ động gọi, hay kiến thức nền?
→ Hành động cụ thể: giữ mặc định (user-invocable: true, ngầm định)
→ Kiến thức nền: user-invocable: false
Claude gọi đượcClaude không gọi đượcNgười dùng gọi đượcNgười dùng không gọi đượccode-review (disable-model-invocation)Skill mặc định(hiếm gặp)legacy-context (user-invocable: false)
Hình 4.5 — Ma trận invocation contract: người dùng gọi được / không × Claude gọi được / không. [S74]
  1. Với Skill giả định từ bài 29/32/33, xác định: có side-effect không? Cần khóa disable-model-invocation không?
  2. Viết 3 evaluation theo template ở mục 8 cho Skill đó.
  3. Thiết kế cách Skill nhận input — dùng $ARGUMENTS hay tham số đặt tên? Viết 1 ví dụ lệnh gọi cụ thể.
  4. Đối chiếu bài tập số 2 với 07-quality-control/ của dự án này — nhận xét điểm giống/khác giữa “evaluation cho Skill” và “QC review cho chapter” đã học từ đầu dự án.
  • Không khóa disable-model-invocation cho Skill có side-effect — rủi ro Claude tự ý thực hiện hành động không được yêu cầu.
  • Viết instructions trước, viết evaluation sau (hoặc không viết) — đi ngược nguyên tắc “evaluation-driven development”, dễ dẫn tới Skill giải quyết vấn đề tưởng tượng thay vì lỗ hổng thật [S77].
  • Nhầm lẫn contract cấp Skill với structured output cấp 1 câu trả lời (L2 bài 13) — 2 khái niệm khác tầng, không thay thế nhau.

13. Giới hạn & khi nào KHÔNG nên áp dụng

Phần tiêu đề “13. Giới hạn & khi nào KHÔNG nên áp dụng”
  • Không áp dụng cho 1 prompt đơn lẻ trong 1 hội thoại — đó là phạm vi L2 bài 13 (Structured Output).
  • Tài liệu Tier 1 tự ghi rõ: “There is not currently a built-in way to run these evaluations” [S77] — evaluation là kỷ luật tự áp dụng, không phải 1 tính năng có sẵn tự động chạy.
  • Skill rất đơn giản, không side-effect, không cần tham số → có thể bỏ qua phần lớn nội dung bài này, chỉ cần giữ mặc định.

disable-model-invocation: truecơ chế an toàn quan trọng nhất học được trong Level 4 tính tới bài này — nó là ranh giới cứng ngăn Claude tự ý thực hiện hành động có hậu quả thật (deploy, gửi tin nhắn, xóa dữ liệu) chỉ vì “có vẻ hợp lý trong ngữ cảnh”. Nguyên tắc thiết kế: mặc định khóa cho mọi Skill có side-effect, không đợi tới khi xảy ra sự cố mới thêm vào.

  1. Viết evaluation trước khi viết instructions chi tiết (nhắc lại từ bài 32, áp dụng cụ thể ở đây).
  2. Với Skill có side-effect, luôn tự hỏi “nếu Claude tự gọi cái này mà không ai yêu cầu, hậu quả tệ nhất là gì?” — nếu câu trả lời đáng lo, dùng disable-model-invocation.
  3. Đặt tên tham số rõ ràng (arguments: [issue, branch]) thay vì chỉ dùng $0, $1 không tên.
16. Nội dung nâng cao (không bắt buộc)

Có thể xếp chồng nhiều Skill trong 1 lệnh gọi (/code-review /fix-issue 123) — cả 2 Skill được load, phần tham số cuối cùng (123) được truyền cho cả 2 Skill cùng lúc [S74]. Đây là 1 dạng “hợp đồng input dùng chung” nâng cao, hữu ích khi 2 Skill thường được dùng nối tiếp nhau, nhưng cũng là nguồn lỗi tiềm ẩn nếu 2 Skill diễn giải cùng 1 tham số theo 2 cách khác nhau.

[S74] Extend Claude with skills, Anthropic — 2 trường kiểm soát quyền, cơ chế tham số $ARGUMENTS/$N, xếp chồng Skill · [S77] Skill authoring best practices, Anthropic — cấu trúc evaluation, nguyên tắc evaluation-driven development · Ví dụ thực tế: .claude/skills/ai-mastery-bible/assets/chapter-template.md.

Claim kỹ thuật kiểm chứng qua nguồn Tier 1 (S74, S77) ngày 2026-07-12.