Skill Là Gì Và Tại Sao Phải Build Riêng?
OpenClaw Skill là các module mở rộng giúp agent có thêm khả năng mới — từ gọi API, thao tác file, đến điều khiển thiết bị thông minh. Thay vì phụ thuộc vào skill có sẵn, developer có thể build skill riêng để tích hợp API nội bộ, hệ thống proprietary, hoặc logic nghiệp vụ đặc thù.
Bài này bỏ qua phần giới thiệu cơ bản. Nếu bạn chưa cài OpenClaw, xem hướng dẫn cài đặt Clawdbot/OpenClaw toàn diện trước.
Cấu Trúc Thư Mục Skill Chuẩn
Mọi workspace skill đều đặt tại ~/.openclaw/workspace/skills/:
skills/
your-skill-name/
SKILL.md # Metadata + documentation cho agent
scripts/ # Logic thực thi
main.py # (hoặc index.js, run.sh)
tools/ # Tool definitions (JSON schema)
your-tool.json
requirements.txt # Python dependencies (nếu có)
Quy tắc đặt tên: Dùng kebab-case cho tên thư mục (price-checker, không phải PriceChecker). Agent đọc tên thư mục này để nhận diện skill.
File SKILL.md — System Prompt Cho Skill
SKILL.md không phải README thông thường. Đây là system prompt dành riêng cho skill — agent đọc file này để hiểu khi nào và cách nào nên dùng skill.
# Your Skill Name
Mô tả ngắn gọn skill làm gì (1-2 câu).
## Khi Nào Sử Dụng
- [trigger condition 1]
- [trigger condition 2]
## Tools
- tool-name: Mô tả ngắn gọn tool làm gì
## Giới Hạn
- Không xử lý [edge case]
- Yêu cầu [dependency]
## Permissions
- domains: api.example.com
Viết SKILL.md như viết instruction cho junior developer: rõ trigger, liệt kê giới hạn, khai báo domain được phép gọi. Agent dùng file này để quyết định có invoke skill hay không.
Mỗi tool trong thư mục tools/ là một JSON schema mô tả interface:
{
"name": "check-inventory",
"description": "Kiểm tra số lượng tồn kho của sản phẩm theo SKU",
"parameters": {
"type": "object",
"properties": {
"sku": {
"type": "string",
"description": "Mã SKU của sản phẩm"
},
"warehouse_id": {
"type": "string",
"description": "ID kho hàng. Mặc định: kho chính",
"default": "main"
}
},
"required": ["sku"]
}
}
Nguyên tắc viết schema:
description phải đủ cụ thể để LLM biết khi nào truyền tham số nào
- Đặt
default cho optional parameter, không để LLM tự đoán
- Tránh dùng
any type — LLM cần biết format chính xác
Script nhận input qua stdin (JSON) và trả về kết quả qua stdout:
import sys
import json
def check_inventory(sku: str, warehouse_id: str = "main") -> dict:
result = query_database(sku, warehouse_id)
return {
"sku": sku,
"quantity": result["qty"],
"location": result["bin"],
"last_updated": result["timestamp"]
}
if __name__ == "__main__":
params = json.loads(sys.stdin.read())
tool_name = params.get("tool")
args = params.get("args", {})
if tool_name == "check-inventory":
output = check_inventory(**args)
print(json.dumps(output))
Tối ưu token khi trả về output: LLM đọc toàn bộ output của tool — output dài tốn token và tăng latency. Nguyên tắc:
- Chỉ trả về fields cần thiết, bỏ metadata thừa
- Nếu kết quả là list, giới hạn 10–20 items và thêm
"total" để LLM biết còn bao nhiêu
- Trả về số nguyên thay vì float khi không cần độ chính xác cao
Bảo Mật: Least Privilege First
Skill chạy với quyền của user hiện tại. Một skill viết ẩu có thể đọc/ghi file tùy ý hoặc gọi network không kiểm soát. Áp dụng Least Privilege:
Cô lập file system:
import os
from pathlib import Path
ALLOWED_DIR = Path(os.environ.get("SKILL_DATA_DIR", "/tmp/skill-data"))
def safe_read(filename: str) -> str:
target = (ALLOWED_DIR / filename).resolve()
if not str(target).startswith(str(ALLOWED_DIR)):
raise PermissionError(f"Truy cập ngoài vùng cho phép: {filename}")
return target.read_text()
Kiểm soát network:
- Whitelist domain được phép gọi trong
SKILL.md dưới section ## Permissions
- Áp dụng timeout cho mọi HTTP request (mặc định 10 giây)
- Không bao giờ log credentials hoặc sensitive data
Secrets qua biến môi trường:
import os
api_key = os.environ["INVENTORY_API_KEY"]
Best Practices: Log, Error Handling, Token
Ghi log ra stderr — không ảnh hưởng stdout của tool:
import sys
def log(msg: str):
print(f"[skill] {msg}", file=sys.stderr)
Error handling chuẩn — trả về structured error:
try:
result = call_external_api(sku)
except TimeoutError:
print(json.dumps({"error": "API timeout", "retry": True}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
Agent đọc exit code để phân loại kết quả: exit 0 = success, exit 1 = retryable error, exit 2 = lỗi terminal không thể tiếp tục.
Đóng Gói Và Cài Đặt
Cài từ Git repo:
clawdbot skill install https://github.com/your-org/your-skill
Cài từ thư mục local:
clawdbot skill install ./skills/your-skill-name
Publish lên ClawHub:
clawdbot skills publish ./skills/your-skill-name
Lệnh này đóng gói skill và submit để review. Sau khi được duyệt, cộng đồng cài bằng:
clawdbot skills install your-skill-name
Skill Đang Hoạt Động
Sau khi cài, restart OpenClaw:
openclaw restart
Nhắn cho agent: "kiểm tra tồn kho SKU-123" — agent tự phát hiện skill phù hợp và gọi tool. Không cần config thêm. Để debug, xem log:
openclaw logs --skill your-skill-name
Xây dựng skill tốt là xây dựng tool đáng tin cậy: output sạch, lỗi rõ ràng, quyền tối thiểu. Agent chỉ tốt bằng các tool nó có. Đọc thêm về kiến trúc AI agent tại bài phân tích AI Agent 2026 và cách MCP Protocol chuẩn hóa kết nối tool tại MCP Protocol: Chuẩn Kết Nối AI Agent.