
Điểm khác biệt lớn nhất của Hermes so với mấy con agent khác là khái niệm "skill" - bạn viết 1 Python function, đăng ký vào agent, từ đó nó nhớ vĩnh viễn và tự gọi khi tình huống đúng. Không phải tool tạm dùng rồi quên. Bài này dạy bạn viết, đăng ký, test và share skill từ A đến Z.
Skill là gì - phân biệt với tool tạm
Hermes Agent có 2 lớp năng lực:
- Built-in tools: 40+ tool đi kèm khi cài (web_search, browser, file ops, x_search, computer_use, vision_analyze, video_generate, ...). Cố định, không sửa được trực tiếp.
- Skills: Python function bạn viết. Hermes load lúc khởi động, lưu vào memory, học cách dùng theo thời gian. Đây là điểm "the agent that grows with you" - càng dùng, skill set càng giàu.
Skill khác đoạn code one-off ở chỗ: nó tồn tại giữa các session. Hôm nay bạn dạy Hermes skill "tính lương freelance theo VND", ngày mai bật terminal lên hỏi, nó vẫn nhớ và gọi đúng.
Cấu trúc một skill file
Skill là Python file đặt trong ~/.hermes/skills/. Mỗi file 1 hoặc nhiều function, mỗi function là 1 skill. Hermes scan thư mục này lúc start và lúc bạn gõ /reload.
Skeleton tối thiểu:
# ~/.hermes/skills/calc_freelance_tax.py
from hermes_cli.tools import register
@register("calc_freelance_tax")
def calc_freelance_tax(revenue_vnd: float, has_invoice: bool = True) -> dict:
"""Tính thuế TNCN cho freelancer VN theo doanh thu năm.
Áp dụng cho cá nhân kinh doanh, thuế khoán:
- Doanh thu < 100tr/năm: miễn thuế
- 100tr-300tr: 5% TNCN + 5% GTGT = 10%
- 300tr+: theo bậc lũy tiến (tối giản hoá ở đây)
Args:
revenue_vnd: Doanh thu năm tính bằng VND
has_invoice: True nếu xuất hoá đơn GTGT
Returns:
dict chứa tax_amount, net_income, breakdown
"""
if revenue_vnd < 100_000_000:
return {
"tax_amount": 0,
"net_income": revenue_vnd,
"breakdown": "Dưới ngưỡng chịu thuế"
}
rate = 0.10 if has_invoice else 0.075
tax = revenue_vnd * rate
return {
"tax_amount": round(tax),
"net_income": round(revenue_vnd - tax),
"breakdown": f"Áp dụng {rate*100}% cho doanh thu {revenue_vnd:,} VND"
}
Phân tích từng phần
1. Decorator @register
Đây là cầu nối với Hermes. Tên trong register("calc_freelance_tax") sẽ là tên tool agent dùng để gọi. Convention: snake_case, không trùng tên built-in.
2. Type hints - bắt buộc
Hermes parse type hint thành JSON schema để LLM biết argument có dạng gì. Không có type hint = agent đoán mò = lỗi runtime. Dùng đúng str, int, float, bool, list, dict. Phức tạp hơn dùng typing.Optional, typing.Literal.
3. Docstring là spec
Hermes feed docstring vào LLM như mô tả tool. Đây là phần quan trọng nhất - viết docstring rõ thì agent gọi đúng, mơ hồ thì agent skip. Format tối thiểu: 1 dòng tóm tắt, đoạn mô tả khi nào dùng, block Args, block Returns.
4. Return type structured
Trả về dict hoặc list, đừng trả string raw. Agent xử lý cấu trúc dễ hơn nhiều và có thể chain output sang skill khác.
Đăng ký và load skill
Lưu file vào ~/.hermes/skills/ xong, có 2 cách load:
- Restart Hermes (
exitrồihermes) - Gõ
/reloadtrong Hermes - hot reload, không mất context
Verify skill đã load:
You: /skills
Hermes: Available skills:
- calc_freelance_tax (custom): Tính thuế TNCN cho freelancer VN
- rotate_proxy (custom): Pick a random proxy from pool
- web_search (built-in)
- browser_navigate (built-in)
...
Test skill thực tế
Cách 1: hỏi tự nhiên, để agent tự pick skill:
You: nếu mình freelance kiếm 250 triệu năm 2026 có xuất hoá đơn, thuế bao nhiêu?
Hermes: [calc_freelance_tax revenue_vnd=250000000 has_invoice=True]
-> {"tax_amount": 25000000, "net_income": 225000000, "breakdown": "..."}
Với doanh thu 250tr/năm và có xuất hoá đơn GTGT, bạn nộp khoảng 25 triệu
tiền thuế (10%), thu nhập ròng còn 225 triệu.
Cách 2: force gọi để debug:
You: gọi trực tiếp calc_freelance_tax với revenue=500000000 has_invoice=False
Hermes: [calc_freelance_tax revenue_vnd=500000000 has_invoice=False]
-> {"tax_amount": 37500000, "net_income": 462500000, ...}
Skill nâng cao: gọi API ngoài
Skill không bị giới hạn ở logic pure. Bạn có thể gọi HTTP, đọc DB, chạy subprocess. Ví dụ skill check tỷ giá USD/VND realtime:
# ~/.hermes/skills/check_usd_vnd_rate.py
import requests
from hermes_cli.tools import register
@register("check_usd_vnd_rate")
def check_usd_vnd_rate() -> dict:
"""Lấy tỷ giá USD/VND hiện tại từ Vietcombank.
When to use: user hỏi tỷ giá, quy đổi USD ra VND,
so sánh giá nước ngoài với giá VN.
Returns:
dict với buy, sell, updated_at
"""
r = requests.get(
"https://www.vietcombank.com.vn/api/exchangerates?date=now",
timeout=10
)
data = r.json()
usd = next(x for x in data["Data"] if x["currencyCode"] == "USD")
return {
"buy": float(usd["cash"]),
"sell": float(usd["transfer"]),
"updated_at": data["UpdatedDate"]
}
Lưu ý: nếu skill cần package ngoài (như requests), cài vào venv của Hermes:
source ~/.hermes/venv/bin/activate
pip install requests pandas beautifulsoup4
deactivate
Skill có state - dùng file để persist
Skill chạy stateless mỗi lần gọi. Muốn nhớ giữa các lần, đọc/ghi file:
# ~/.hermes/skills/track_daily_tasks.py
import json
from pathlib import Path
from datetime import date
from hermes_cli.tools import register
STATE_FILE = Path.home() / ".hermes" / "data" / "daily_tasks.json"
STATE_FILE.parent.mkdir(parents=True, exist_ok=True)
def _load() -> dict:
if STATE_FILE.exists():
return json.loads(STATE_FILE.read_text())
return {}
def _save(data: dict) -> None:
STATE_FILE.write_text(json.dumps(data, ensure_ascii=False, indent=2))
@register("add_daily_task")
def add_daily_task(task: str) -> dict:
"""Thêm task vào danh sách ngày hôm nay.
Args:
task: nội dung task ngắn gọn
"""
today = date.today().isoformat()
data = _load()
data.setdefault(today, []).append({"task": task, "done": False})
_save(data)
return {"added": task, "total_today": len(data[today])}
@register("list_daily_tasks")
def list_daily_tasks() -> list:
"""List tasks của ngày hôm nay."""
today = date.today().isoformat()
return _load().get(today, [])
Bây giờ Hermes có một todo list persistent giữa các session. Skill này tích hợp tự nhiên với memory system của Hermes (skill + conversational + user modeling).
Tiêu chuẩn agentskills.io - chuẩn share community
Nous Research đang thúc đẩy chuẩn agentskills.io để skill có thể trao đổi giữa các agent. Skill theo chuẩn này có thêm metadata file:
# ~/.hermes/skills/calc_freelance_tax/skill.toml
[skill]
name = "calc_freelance_tax"
version = "1.0.0"
author = "your-name"
license = "MIT"
description = "Tính thuế TNCN freelancer VN"
tags = ["finance", "vietnam", "tax"]
[skill.dependencies]
python = ">=3.11"
Khi skill đủ chín, bạn đẩy lên GitHub repo riêng, người khác clone về ~/.hermes/skills/ là dùng được ngay. Một số dev VN đã bắt đầu share skill kiểu "tra cứu mã số thuế DN", "check số dư VietQR", "convert đơn vị đo VN".
Anti-pattern khi viết skill
| Sai | Đúng |
|---|---|
| Docstring 1 dòng mơ hồ | Mô tả + when to use + when NOT to use |
| Trả về string raw "Kết quả: 25tr" | Trả dict structured |
| Skill quá rộng (do_everything) | 1 skill = 1 việc cụ thể |
| Không type hint hoặc dùng Any | Type hint cụ thể, có default value |
| Lưu state vào biến global | Persist ra file/DB |
| Raise exception thô | Catch + return {"error": "..."} |
Debug skill khi agent không gọi
Triệu chứng phổ biến: bạn viết skill, gõ /skills thấy có tên, nhưng agent không bao giờ chủ động dùng. Nguyên nhân thường ở docstring quá mơ hồ. Sửa bằng cách thêm trigger phrase rõ ràng:
"""Tính thuế TNCN cho freelancer VN theo doanh thu năm.
Use this skill when user mentions:
- "thuế freelance", "thuế tự do"
- "nộp thuế bao nhiêu"
- doanh thu/revenue cụ thể bằng VND
"""
Skill chạy ổn cần VPS nào
Skill bình thường chỉ cần Python runtime, RAM ~50-100MB/skill khi active. Vấn đề là khi bạn có 20-30 skill dùng đồng thời, cộng với LLM context, cộng với browser tool, dễ chạm 4GB RAM. VPS 50 (4vCPU/4GB) đủ cho mức skill set nhỏ-trung. Nếu dùng nhiều skill có gọi browser hoặc DB, lên VPS 80 (6vCPU/6GB) yên tâm hơn.
Đọc thêm về cách chọn VPS cho dev AI agent để hiểu rõ trade-off.
Bài viết liên quan
Cần VPS chạy Hermes Agent và skill set của bạn
VPS TND Cloud Ceph SSD NVMe, RAM ECC, đủ tài nguyên để cài Hermes + Python venv + nhiều skill chạy song song. Từ 639k/tháng VPS 50, lên 999k VPS 80 đủ cho mọi nhu cầu.


