Lớp engine biến bundle khai báo (persona yaml + skill markdown + content) thành hệ nhiều người dùng / nhiều persona chạy được. KHÔNG chứa nội dung mentor — chỉ máy móc chạy ngầm. Bù vào đúng các chỗ Hermes để trống.
| # | Vấn đề | Cách giải |
|---|---|---|
| Riêng tư | LLM có thể đọc/ghi nhầm folder người khác (chỉ "dặn" là không đủ) | hook pre_tool_call chặn cứng truy cập file/terminal thoát khỏi users/<uid>/ (guard.py) |
| Định danh | Skill không nhận user_id tự nhiên | resolve qua HERMES_SESSION_* (ContextVar-aware) → tg_<id> (identity.py); ensure dir + registry khi on_session_start |
| State per-user | Skill phải shell python + tự tính path | tool mentor_state_read/write/list engine tự scope (state.py) |
| Chọn chuyên gia | Registry personas/*.yaml chỉ để người đọc |
/experts, /mentor <id> lọc theo org_role (personas.py) |
| Admin xem team | Cần đọc chéo nhưng không lộ hội thoại | tool team_progress_read gate org_role bằng code, chỉ đọc progress.md (team.py) |
pre_tool_call (guard) · on_session_start (ensure user + registry)mentor_state_read · mentor_state_write · mentor_state_list · team_progress_read/aiwhoami (debug) · /experts · /mentor <id>Plugin Hermes mặc định tắt và được phát hiện ở ~/.hermes/plugins/. Bundle nằm ở terminal.cwd (vd /opt/ai-os).
# 1) Đưa plugin vào nơi Hermes quét (symlink để git pull/update tự theo)
ln -s /opt/ai-os/core/plugin/ai-os ~/.hermes/plugins/ai-os
# 2) Bật trong ~/.hermes/config.yaml
# plugins:
# enabled: [ai-os]
# 3) Trỏ engine vào bundle root (nơi có users/ + personas/)
# Đặt trong môi trường gateway/systemd:
# AI_OS_BUNDLE_ROOT=/opt/ai-os
# (nếu bỏ trống, plugin tự dò terminal.cwd / cwd có thư mục users/)
# 4) restart gateway
python3 core/plugin/ai-os/selftest.py # kỳ vọng: SELFTEST_OK (21/21)
Đã xác minh từ source Hermes: chữ ký register_*, payload hook, pre_tool_call veto {"action":"block","message":...}, HERMES_SESSION_* bơm vào subprocess.
✅ Đã smoke trên VPS thật (Hermes v0.16.0, 2026-06-18): enable + restart OK (NRestarts=0, no error); /aiwhoami → user_id=tg_<id> · org_role=ceo; /experts lọc đúng theo org_role; selftest 24/24 trên Python 3.14; bundle_root = terminal.cwd (vd /opt/ai-os/products/ceo).
Lưu ý cơ chế quan trọng (đã phát hiện khi smoke): plugin slash-command handler được Hermes dispatch (run.py:~7820) TRƯỚC khi set session ContextVars (set_session_vars ~L8435 bọc agent turn), nên trong slash handler get_session_env() rỗng. → Hook pre_gateway_dispatch (fire sớm nhất, có event.source) bridge identity vào os.environ (stash_identity) cho slash handler đọc. Guard pre_tool_call chạy trong agent turn nên vẫn dùng ContextVar chuẩn — không ảnh hưởng.
Còn lại cần kiểm khi có dịp:
1. pre_tool_call fire cho đúng tên tool file thật (write_file/read_file/terminal/edit_file…) — chưa test bằng 1 tool-call thật trong turn. Nếu tên khác → bổ sung _PATH_ARG_KEYS/danh sách trong guard.py.
2. Nhóm/forum topic: session dùng chung → onboarding/nudge phải ở DM để có chat_id riêng (đúng plan).
3. Conflict tool name với builtin (override= nếu cần).
core/lib/identity.pycore/lib/identity.py = CLI script skill shell ra (subprocess, os.environ). Plugin này = in-process, ContextVar-aware. Chung convention tg_<id> + guardrail users/<uid>/ nên 1 người được định danh y hệt ở cả 2 đường. Trùng một ít logic là cố ý (an toàn hơn cross-import path mong manh).