Cách tự viết kỹ năng cho agent từ lỗi thực tế
Hướng dẫn viết kỹ năng cho agent bằng cách đúc kết từ lỗi lặp lại. Tìm hiểu cấu trúc file SKILL.md, cách tối ưu dòng mô tả để kích hoạt kỹ năng và phương pháp kiểm thử hiệu quả.
Viết kỹ năng agent của riêng bạn từ một lỗi thực tế
Cách tốt nhất để viết kỹ năng cho agent là đúc kết nó từ một lỗi thực tế. Hãy tìm một tác vụ mà coding agent của bạn đã làm sai hai lần, ghi lại nội dung sửa lỗi mà bạn đã nhập cả hai lần đó, rồi lưu nội dung sửa lỗi đó thành một file SKILL.md mà agent có thể tự tải. Mọi thứ sau đó chỉ là kỹ thuật: cấu trúc file và một dòng lệnh quyết định liệu kỹ năng đó có bao giờ được kích hoạt hay không.
Thứ tự đó rất quan trọng. Một kỹ năng được viết từ trí tưởng tượng sẽ ghi lại một vấn đề mà bạn chưa từng gặp phải, và nó vẫn tiêu tốn context trong mỗi phiên làm việc. Một kỹ năng được đúc kết từ lỗi mà bạn đã chứng kiến sẽ đi kèm với bài kiểm tra của riêng nó: hãy hỏi lại cùng một câu hỏi đó và xem liệu lần này agent có thực hiện đúng hay không. Nếu bản thân định dạng này còn mới với bạn, hãy đọc kỹ năng agent là gì và cách agent tải chúng trước, sau đó quay lại và viết một kỹ năng.
Bắt đầu từ một tác vụ mà agent đã thực hiện sai hai lần
Một lần là ngẫu nhiên. Hai lần là một khuôn mẫu, và một khuôn mẫu thì đáng để tạo thành một file.
Đây là một lỗi thường lặp lại trên các máy chủ thực tế. Bạn yêu cầu agent thêm một block reverse proxy vào nginx. Nó chỉnh sửa /etc/nginx/conf.d/app.conf, sau đó chạy sudo systemctl restart nginx. Bản chỉnh sửa bị lỗi cú pháp, nên nginx từ chối khởi động và trang web bị sập cho đến khi bạn sửa lại:
nginx: [emerg] unknown directive "proxy_pas" in /etc/nginx/conf.d/app.conf:12
Job for nginx.service failed because the control process exited with error code.Bạn sửa lỗi đó trong khung chat. Hãy kiểm tra cấu hình bằng sudo nginx -t trước khi tác động vào service, sau đó áp dụng nó bằng reload thay vì restart. Một tuần sau, ở một tác vụ khác, lỗi tương tự lại xảy ra. Lần thứ hai đó chính là tín hiệu.
Hãy ghi lại hai thứ khi lỗi vẫn còn ngay trước mắt bạn: yêu cầu bạn đã nhập và bản sửa lỗi bạn đã đưa ra, bằng chính ngôn ngữ bạn đã dùng. Hai dòng đó trở thành một kỹ năng (skill). Yêu cầu cho bạn biết trigger cần khớp với điều gì. Bản sửa lỗi chính là toàn bộ nội dung cần thiết.
Hướng dẫn soạn thảo của chính Anthropic đặt điều này lên hàng đầu. Hãy chạy agent trên các tác vụ tiêu biểu mà không có kỹ năng, ghi lại những nơi nó thất bại, sau đó viết các chỉ dẫn tối thiểu để khắc phục những lỗi đó. Các lỗi chính là đặc tả kỹ thuật, vì vậy một kỹ năng mà bạn không thể truy xuất nguồn gốc từ một lỗi thường là kỹ năng không ai cần đến.
Để xem một ví dụ thực tế về quá trình chắt lọc này, Ponytail biến một lỗi lặp lại, khi agent viết lại nhiều hơn những gì bạn yêu cầu, thành một kỹ năng bạn có thể đọc từ đầu đến cuối trước khi tự viết kỹ năng cho riêng mình.
Cấu trúc của một skill
Một skill là một thư mục chứa một file bắt buộc bên trong.
.claude/skills/nginx-config-changes/
├── SKILL.md
├── reference/
│ └── proxy-headers.md
└── scripts/
└── check-and-reload.shSKILL.md bắt đầu bằng một khối frontmatter, gồm một vài thiết lập viết bằng YAML (cùng định dạng cấu hình mà các file Docker Compose sử dụng) nằm giữa các dấu ---, theo sau là các hướng dẫn bằng markdown. Dưới đây là toàn bộ skill cho lỗi nêu trên.
---
name: nginx-config-changes
description: Tests and reloads nginx safely after a config edit. Use when editing files under /etc/nginx, adding a server block or a reverse proxy, or changing a TLS certificate path.
---
## Rules
Run `sudo nginx -t` after every edit under `/etc/nginx`. Do not touch the service until it prints `test is successful`.
Apply the change with `sudo systemctl reload nginx`. Never use `restart`. A reload keeps the running workers serving traffic until the new config parses, so a broken config leaves the site up. A restart stops nginx first, so a broken config takes the site down.
If `nginx -t` fails, fix the file and test again. Never reload a config that failed the test.
For the proxy header defaults this project expects, see [reference/proxy-headers.md](reference/proxy-headers.md).File đó chưa đầy hai mươi dòng và là một skill hoàn chỉnh. Các thành phần bao gồm:
name: tối đa 64 ký tự, chỉ dùng chữ thường, chữ số và dấu gạch ngang, không được chứa các từclaudehoặcanthropic. Trong một skill cá nhân hoặc dự án, đây chỉ là nhãn hiển thị. Lệnh bạn gõ lấy từ tên thư mục, vì vậy skill này phản hồi với/nginx-config-changes.description: mô tả chức năng của skill và khi nào nên dùng nó, tối đa 1.024 ký tự. Dòng này thực hiện công việc chính, và phần tiếp theo chỉ tập trung vào nội dung này.- Phần thân: các hướng dẫn, chỉ được tải khi skill thực sự kích hoạt.
reference/: các file bổ sung mà agent đọc theo yêu cầu. Hãy liên kết chúng từSKILL.mdvà giữ các liên kết ở mức một cấp, vì một file được tham chiếu từ một file đã tham chiếu khác thường chỉ được đọc một phần.scripts/: các file mà agent thực thi thay vì đọc. Chỉ output của chúng mới tốn token context, vì vậy một script 300 dòng vẫn rất nhẹ.
Vị trí bạn đặt thư mục sẽ quyết định ai có quyền truy cập skill đó.
.claude/skills/<name>/SKILL.mdtrong repository: chỉ dành cho dự án này, và nó sẽ đi kèm với bất kỳ ai clone repo.~/.claude/skills/<name>/SKILL.md: mọi dự án trên máy của bạn, và không ai khác có được.<plugin>/skills/<name>/SKILL.md: được đóng gói bên trong một plugin, khả dụng ở bất cứ đâu mà plugin đó được bật.
Tạo một skill bằng mkdir -p .claude/skills/nginx-config-changes và viết nội dung vào file. Claude Code theo dõi các thư mục này, vì vậy việc chỉnh sửa một skill hiện có sẽ có hiệu lực ngay trong phiên làm việc đang chạy. Việc tạo một thư mục skills ở cấp cao nhất mà chưa tồn tại khi phiên làm việc bắt đầu sẽ cần phải khởi động lại, vì không có gì để theo dõi khi phiên bắt đầu.
Trường description là dòng có giá trị cao nhất trong file
Khi khởi động, agent sẽ load name và description của mọi skill khả dụng vào context. Nó không load phần nội dung (body). Khi request của bạn gửi đến, dòng duy nhất đó là cơ sở để quyết định xem skill này có phù hợp hay không, vì vậy một nội dung hoàn hảo nằm sau một mô tả mơ hồ sẽ không bao giờ được đọc tới.
Hãy viết mô tả ở ngôi thứ ba. "Kiểm tra và reload nginx một cách an toàn" là cách viết tốt. "Tôi có thể giúp bạn với nginx" thì không, vì văn bản này được chèn vào system prompt, nơi ngôi thứ nhất sẽ khiến model hiểu nhầm là nó đang nói về chính mình.
Hãy đảm bảo mô tả chứa hai yếu tố: skill đó làm gì và điều kiện áp dụng. Hãy đưa use case quan trọng lên đầu, vì Claude Code sẽ cắt bớt danh sách entry ở mức 1.536 ký tự. Có một trường when_to_use tùy chọn cho các cụm từ kích hoạt bổ sung và ví dụ request, nó sẽ được nối vào phần mô tả dưới cùng giới hạn đó.
Sau đó, hãy sử dụng chính những từ ngữ mà bạn sẽ gõ. description: Helps with nginx sẽ không khớp với bất kỳ thứ gì, vì không ai gõ "helps with" cả. Ví dụ ở trên nêu tên /etc/nginx, server block, reverse proxy và TLS (transport layer security) certificate path, đây là vốn từ vựng cơ bản của bất kỳ request nào cần kích hoạt skill này.
Đây là bài kiểm tra cho một mô tả. Hãy đưa dòng đó cho một người chưa từng xem nội dung bên trong, cùng với request mà bạn định gõ, và hỏi họ xem skill đó có áp dụng được không. Nếu họ không thể trả lời, model cũng sẽ không thể làm được.
Giữ nội dung ngắn gọn vì nó sẽ nằm trong ngữ cảnh
Khi một skill được gọi, nội dung đã render của nó sẽ đi vào cuộc hội thoại dưới dạng một tin nhắn và ở đó trong suốt phần còn lại của phiên làm việc. Claude Code không đọc lại file ở các lượt sau. Mỗi dòng bạn viết là một chi phí bạn phải trả cho toàn bộ phiên, không phải chỉ cho một câu trả lời.
Anthropic khuyến nghị giữ SKILL.md dưới 500 dòng và chuyển các chi tiết vào những file riêng biệt. Cơ chế nén giải thích tại sao con số đó không phải là ngẫu nhiên. Khi cuộc hội thoại được tóm tắt để giải phóng context, Claude Code sẽ đính kèm lại lần gọi gần nhất của mỗi skill, chỉ giữ lại 5.000 token đầu tiên của mỗi skill, và lấp đầy ngân sách 25.000 token kết hợp bắt đầu từ skill được gọi gần đây nhất. Một skill dài sẽ bị cắt ngang giữa chừng. Nhiều skill dài sẽ đẩy nhau ra hoàn toàn.
Vì vậy, chỉ viết những gì model chưa biết. Nó đã biết nginx là gì và reverse proxy làm nhiệm vụ gì. Nó không biết quy tắc nội bộ của bạn về việc ưu tiên reload hơn restart, và quy tắc đó là lý do duy nhất khiến file này tồn tại.
Nếu skill yêu cầu agent chạy một script đi kèm, hãy đặt tên đường dẫn với ${CLAUDE_SKILL_DIR} để nó phân giải đúng bất kể skill được cài đặt ở đâu, và cấp quyền trước cho lệnh đó để quá trình chạy không bị dừng lại bởi thông báo xác nhận quyền.
---
name: nginx-config-changes
description: Tests and reloads nginx safely after a config edit. Use when editing files under /etc/nginx, adding a server block or a reverse proxy, or changing a TLS certificate path.
allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/check-and-reload.sh *)
---Quyền này chỉ bao gồm lượt đã gọi skill và sẽ mất đi khi bạn gửi tin nhắn tiếp theo, vì vậy nó không âm thầm trở thành quyền vĩnh viễn.
Cách kiểm chứng skill được kích hoạt
Việc theo dõi quá trình load skill cho bạn biết agent đã tìm thấy nó. Nó không cho biết câu trả lời có thay đổi hay không. Hãy kiểm tra cả hai, và kiểm tra trong một session mới, vì session nơi bạn viết skill đã lưu giữ mọi thứ bạn nói trong lúc viết. Context còn sót lại đó che giấu các lỗ hổng trong file.
- Bắt đầu một session mới với
claudetrong project. - Nhập yêu cầu theo cách bạn vẫn làm vào một ngày làm việc bình thường, bằng ngôn ngữ của riêng bạn, không cần nêu tên skill.
- Quan sát xem skill có được gọi không. Nếu skill không kích hoạt, hãy sửa lại phần mô tả. Phần thân (body) chưa phải là vấn đề lúc này.
- Gọi thủ công bằng
/nginx-config-changesđể kiểm soát. Hành vi đúng khi gọi thủ công và hành vi sai khi gọi bằng yêu cầu xác nhận vấn đề nằm ở trigger chứ không phải ở instruction. - Chạy cùng yêu cầu đó khi đã tắt skill và so sánh hai câu trả lời. Trong menu
/skills, chọn skill, nhấnSpaceđể chuyển trạng thái sangoff, sau đó nhấnEnterđể lưu. Thao tác này ghi một entryskillOverridesvào.claude/settings.local.json, và nhấnSpacelần nữa sẽ chuyển nó vềonkhi bạn hoàn tất. - Viết một vài yêu cầu không nên kích hoạt skill và kiểm tra xem nó có giữ im lặng với các yêu cầu đó không.
Để tự động hóa vòng lặp này, hãy cài đặt plugin skill-creator từ marketplace chính thức.
/plugin marketplace add anthropics/claude-plugins-official
/plugin install skill-creator@claude-plugins-officialNếu output cài đặt báo Run /reload-plugins to activate., hãy chạy lệnh đó. Sau đó yêu cầu Claude đánh giá skill của bạn theo tên. Plugin lưu trữ các test case trong evals/evals.json bên trong thư mục skill và chạy mỗi case trong một subagent riêng, vì vậy mỗi lần chạy đều bắt đầu với một context sạch. Sau đó, nó ghi lại kết quả so sánh giữa có-skill và không-có-skill, đây là con số trung thực: mức độ cải thiện tỷ lệ thành công được đo lường dựa trên số token và thời gian mà skill tiêu tốn.
Chế độ lỗi: skill không bao giờ kích hoạt
Bạn nhập yêu cầu, agent thực hiện hành động cũ sai lệch và không có dòng skill nào xuất hiện. Hãy kiểm tra lần lượt các mục sau.
- Phần mô tả nêu rõ skill làm gì nhưng không nói rõ khi nào nên sử dụng, vì vậy không có nội dung nào trong yêu cầu của bạn khớp với nó.
- Phần mô tả không chứa các từ khóa bạn nhập. Nếu bạn nói "nginx", phần mô tả bắt buộc phải có từ nginx.
disable-model-invocation: trueđược thiết lập trong frontmatter. Điều này loại bỏ hoàn toàn phần mô tả khỏi ngữ cảnh của model và chỉ cho phép bạn gọi skill bằng/name.- Một glob
pathstrong frontmatter giới hạn việc kích hoạt chỉ với các file khớp, và file bạn đang làm việc không khớp với điều kiện đó. - Skill nằm trong một thư mục
.claude/skills/lồng nhau bên dưới thư mục gốc của bạn. Các skill này chỉ được tải sau khi agent đọc hoặc chỉnh sửa một file bên trong thư mục con đó, vì vậy cho đến lúc đó, skill hoàn toàn không khả dụng.
Chế độ lỗi: kỹ năng kích hoạt liên tục
Vấn đề ngược lại là mô tả quá rộng khiến kỹ năng kích hoạt cả với những tác vụ không liên quan. "Sử dụng khi làm việc trên server" khớp với hầu hết mọi yêu cầu trong một repository server. Khi đó, phần thân (body) sẽ tải các tác vụ mà nó không thể hỗ trợ, và nó vẫn nằm trong ngữ cảnh cho phần còn lại của phiên làm việc.
Hãy thu hẹp mô tả về điều kiện thực sự quan trọng, và nêu tên các file hoặc lệnh mà nó bao phủ. Thêm một paths glob khi kỹ năng chỉ áp dụng cho một số file nhất định. Đối với bất kỳ hành động nào có tác dụng phụ, chẳng hạn như deploy hoặc commit, hãy thiết lập disable-model-invocation: true và tự mình gọi nó bằng /name, để agent không bao giờ tự quyết định thời điểm nào là thích hợp để deploy.
Chế độ lỗi: kỹ năng thuộc về file quy tắc của bạn
Một file quy tắc như CLAUDE.md hoặc AGENTS.md được tải khi bắt đầu mỗi phiên làm việc và áp dụng cho mọi tác vụ. Nội dung kỹ năng chỉ được tải khi kỹ năng đó được kích hoạt. Tần suất là yếu tố quyết định. Một thực tế đúng với mọi tác vụ trong kho lưu trữ, ví dụ như trình quản lý gói bạn đang dùng, thuộc về file quy tắc. Một quy trình chỉ áp dụng cho một phần nhỏ các tác vụ, như quy tắc nginx ở trên, thuộc về một kỹ năng, nơi nó không tiêu tốn tài nguyên vào những ngày không ai chỉnh sửa nginx.
Lỗi thực sự là đặt nó ở cả hai nơi. Hai bản sao sẽ dần khác biệt, và khi agent thực hiện sai, bạn không thể biết nó đã làm theo bản sao nào. Hãy chọn một nơi duy nhất cho mỗi chỉ dẫn. ranh giới giữa các kỹ năng, MCP server và file quy tắc giải quyết các trường hợp phức tạp hơn, bao gồm cả khi câu trả lời đúng là một MCP (model context protocol) server cung cấp cho agent một công cụ mới thay vì một chỉ dẫn mới.
Chia sẻ khi kỹ năng đã chứng minh được hiệu quả
Một kỹ năng tồn tại được sau một tuần làm việc thực tế là kỹ năng đáng để lưu lại. Các kỹ năng dự án trong .claude/skills/ được review giống như code và đi kèm với repository, vì vậy đồng nghiệp khi clone repository sẽ nhận được bản sửa lỗi của bạn mà không cần thêm bước thiết lập nào. Việc di chuyển kỹ năng giữa các repository mà không cần copy và paste là một vấn đề riêng, được đề cập trong cách chia sẻ agent skills giữa các repo.
Một lưu ý về tính di động. Claude Code chấp nhận một danh sách dài các trường frontmatter, nhưng tiêu chuẩn Agent Skills chỉ cho phép sáu trường: name, description, license, compatibility, metadata và allowed-tools. Nếu bạn upload một kỹ năng lên claude.ai hoặc đóng gói nó cho Skills API với bất kỳ nội dung nào khác trong frontmatter, hệ thống sẽ báo lỗi ngay lập tức thay vì bỏ qua trường đó:
Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, nameHãy chỉ sử dụng sáu trường này để cùng một file có thể load được trong Claude Code và mọi công cụ khác đọc theo tiêu chuẩn này. Việc viết các chỉ dẫn sao cho chúng vẫn hoạt động khi chuyển sang model khác là một công việc riêng biệt, và viết các kỹ năng hoạt động với mọi model sẽ hướng dẫn bạn thực hiện điều đó.
FAQ
File SKILL.md nên dài bao nhiêu?
Hãy giữ độ dài dưới 500 dòng, và hầu hết các kỹ năng hữu ích đều ngắn hơn mức đó rất nhiều. Nội dung của file sẽ đi vào cuộc hội thoại khi kỹ năng được gọi và tồn tại ở đó trong suốt phiên làm việc, vì vậy mỗi dòng đều là một chi phí định kỳ thay vì chỉ tốn một lần. Hãy chuyển các tài liệu tham khảo dài vào các file riêng biệt trong thư mục kỹ năng và liên kết chúng từ SKILL.md, sâu một cấp, để agent chỉ đọc khi cần. Các script đi kèm được thực thi thay vì đọc, nên chúng chỉ tốn chi phí dựa trên output trả về.
Tại sao kỹ năng của tôi không bao giờ kích hoạt?
Phần mô tả thường là nguyên nhân, vì đây là phần duy nhất của kỹ năng nằm trong ngữ cảnh khi model đưa ra quyết định. Hãy đảm bảo phần này nêu rõ khi nào cần sử dụng kỹ năng, không chỉ là nó làm gì, và nó phải chứa các từ khóa mà bạn thực sự gõ trong yêu cầu của mình. Nếu phần mô tả đã đúng, hãy kiểm tra frontmatter xem có disable-model-invocation: true không, vì nó sẽ ẩn hoàn toàn kỹ năng khỏi model, và kiểm tra paths glob xem có giới hạn kỹ năng trong các file mà bạn không thao tác hay không. Một kỹ năng nằm trong thư mục .claude/skills/ lồng nhau bên dưới thư mục gốc cũng là một nguyên nhân: nó chỉ được tải sau khi agent đọc hoặc chỉnh sửa một file trong thư mục con đó.
Đây nên là một kỹ năng hay một dòng trong file quy tắc (rules file)?
Hãy tự hỏi nó áp dụng cho bao nhiêu tác vụ của bạn. File quy tắc được tải trong mọi phiên làm việc, vì vậy nó nên chứa các thông tin đúng với mọi tác vụ, ví dụ như trình quản lý gói hoặc quy ước đặt tên nhánh. Một kỹ năng chỉ được tải khi nó được kích hoạt, vì vậy đây là nơi phù hợp cho một quy trình chỉ quan trọng với một số ít tác vụ. Đừng bao giờ viết cùng một chỉ dẫn ở cả hai nơi, vì hai bản sao sẽ dần khác biệt và bạn sẽ không thể biết agent đã tuân theo bản nào.
Làm sao để biết một kỹ năng thực sự hữu ích?
Hãy so sánh nó với một baseline. Thu thập một vài yêu cầu thực tế, chạy từng yêu cầu trong một phiên làm việc mới với kỹ năng được bật, sau đó chạy lại với kỹ năng đã tắt từ menu /skills, và đọc cả hai câu trả lời cạnh nhau. Một phiên làm việc mới rất quan trọng vì cuộc hội thoại nơi bạn viết kỹ năng vẫn chứa các giải thích của bạn, điều này khiến một file chưa hoàn thiện trông có vẻ đã đầy đủ. Plugin skill-creator sẽ chạy so sánh này giúp bạn và báo cáo tỷ lệ thành công bên cạnh chi phí token.
Tôi có thể dùng cùng một file SKILL.md với một agent khác không?
Có, miễn là bạn tuân thủ các trường mà tiêu chuẩn Agent Skills định nghĩa: name, description, license, compatibility, metadata và allowed-tools. Claude Code chấp nhận nhiều trường hơn, và nó cũng hỗ trợ các tính năng nội dung như chèn lệnh shell mà các công cụ khác không chạy. Việc tải lên một kỹ năng có trường nằm ngoài tiêu chuẩn sẽ thất bại với một lỗi rõ ràng liệt kê các thuộc tính được phép, vì vậy hãy quyết định sớm xem kỹ năng đó chỉ dành cho Claude Code hay sẽ dùng cho nhiều nơi.