Skill-манифест
Внешние скиллы — это subprocess-исполняемые файлы, описанные файлом skill.json, помещённым в одну из allow-list директорий manager'а. Loader обходит эти директории при boot, парсит каждый skill.json и регистрирует SubprocessSkill в глобальном реестре скиллов. LLM затем видит скилл наряду со встроенными tools.
Источник истины: internal/skill/loader.go.
Layout на диске
/etc/ongrid/skills/ ← one entry in $ONGRID_SKILLS_EXTERNAL_DIRS
└── disk-cleaner/
├── skill.json
└── run.sh ← the executableКаждый skill.json находится в вершине своей подпапки. Дерево директорий обходится рекурсивно; любой файл с именем skill.json трактуется как манифест. Несколько скиллов могут жить под одним allow-list корнем.
Схема манифеста
{
"name": "disk_cleaner",
"description": "Free up disk by clearing stale build caches and journals.",
"schema": {
"type": "object",
"properties": {
"path": { "type": "string", "description": "Root path to clean." },
"dry_run": { "type": "boolean", "default": true }
},
"required": ["path"]
},
"entry": "run.sh",
"env_allow": ["PATH", "HOME"],
"timeout_seconds": 60,
"class": "mutating",
"category": "ops"
}| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
name | string | да | Skill-ключ. Должен быть lower_snake, соответствующим [a-z0-9_]+. Становится LLM-facing именем функции. |
description | string | да | Показывается людям (UI) и LLM (описание функции). |
schema | JSON Schema | нет | Сырая JSON Schema для объекта аргументов. Отсутствие = схема пустого объекта. |
entry | string | да | Путь к исполняемому файлу. Относительные пути резолвятся относительно директории, содержащей skill.json. Абсолютные пути должны находиться под allow-list корнем. |
env_allow | string[] | нет | Явный список имён env-переменных, форвардящихся ребёнку. Пустой список = никакого env (даже PATH). Добавьте "PATH" для opt-in PATH. |
timeout_seconds | int | нет | Таймаут subprocess'а. Ноль откатывается на DefaultSubprocessTimeout (30s). |
class | enum | нет | safe (по умолчанию), mutating, dangerous. См. таксономию классов. |
category | string | нет | Свободная group-label. По умолчанию external. UI группирует subprocess-скиллы по этому. |
Wire-протокол
Subprocess вызывается с stdin = JSON-объект аргументов, stdout = JSON-объект результата, stderr = строки логов для manager'а.
$ cat /tmp/args.json
{"path": "/var/cache", "dry_run": true}
$ run.sh < /tmp/args.json
{"freed_bytes": 1048576, "files_deleted": 17}Non-zero exit-код трактуется как failure. Stderr захватывается в таймлайн событий tool-call'а, так что LLM может прочитать частичный прогресс.
Объект результата возвращается дословно LLM. Agent-ядро форматирует его как ответ tool-call'а; ожидается, что LLM рассуждает над JSON-формой.
Таксономия классов
Та же таксономия {safe, mutating, dangerous} применяется и к нативным, и к subprocess-скиллам.
| Класс | Что он может | Требуемое permission persona |
|---|---|---|
safe | Read-only — никаких side-эффектов на хост или любую систему. | read-only (любая persona) |
mutating | Создаёт / обновляет состояние. Обратимо. | mutating-with-confirm или dual-sign-required |
dangerous | Необратимо (удаления, рестарты, exec-arbitrary). | dual-sign-required (SOP) |
Поле permission_mode у persona гейтит, какие классы могут работать без подтверждения. См. формат persona агента.
Правила allow-list
Операторы конфигурируют allow-list директории через ONGRID_SKILLS_EXTERNAL_DIRS (colon- или comma-separated абсолютные пути). Loader enforce'ит их строго:
- Каждая директория должна быть абсолютным путём. Относительные пути пропускаются с лог-строкой.
- Несуществующие пути пропускаются (так что свежая установка без
/etc/ongrid/skillsboot'ит нормально). entryкаждого манифеста канонизируется черезfilepath.EvalSymlinksи проверяется, что лежит под allow-list корнем. Symlink, указывающий за пределы корня, отвергается (entry %s escapes allowlist root %s).
Sandboxing сверх этого — ответственность subprocess'а. Если скилл должен быть жёстко изолирован, запускайте его под wrapper'ом (bwrap, firejail, nsenter), указанным как entry.
Поведение loader'а
LoadDirs(cfg)
for each dir in cfg.Dirs:
filepath.Walk(dir)
for each skill.json found:
parseManifest(path)
buildSubprocessSkill(manifest, path, root)
if skill already registered: skip (log line)
else Register(skill)- Per-manifest валидационные сбои логируются и пропускаются. Один сломанный пак не должен блокировать boot.
- Дублирующиеся имена пропускаются, а не ошибаются (так что redeploy, который кладёт новый манифест перед удалением старого, не крашит manager).
- Loader возвращает количество успешно зарегистрированных скиллов. Старт manager'а non-blocking на skill-loader'е: пустая внешняя директория — это no-op.
Логирование при старте
Manager логирует одну строку на манифест:
skill loader: registered subprocess skill "disk_cleaner" from /etc/ongrid/skills/disk-cleaner/skill.json
skill loader: skill "broken_one" already registered, skipping /etc/ongrid/skills/broken-one/skill.json
skill loader: parse /etc/ongrid/skills/typo/skill.json: invalid character ',' looking for beginning of object key
skill loader: build "bad_path": entry /tmp/escape.sh escapes allowlist root /etc/ongrid/skillsTail journalctl -u docker-compose@ongrid или docker compose logs ongrid для подтверждения, что было подхвачено.
См. также
- Возможности → Скиллы — каталог встроенных скиллов.
- Формат persona агента — как persona выбирает, какие скиллы она может вызывать.
- Marketplace — установка пака скиллов как единицы.
- REST API →
/v1/skills— листинг и прямое исполнение.
Метаданные нативного скилла (frontmatter SKILL.md)
Встроенные скиллы, поставляемые под ./skills/, используют более богатый формат SKILL.md с YAML-frontmatter, который совместим со skill-экосистемами openclaw / claude-code. Схема определена в internal/manager/biz/aiops/chatruntime/types.go:
---
name: query_promql
description: Run a PromQL query and return the result matrix.
when_to_use: When the user asks for current or recent metric values.
activation:
mode: always
metadata:
os: [linux, darwin]
requires:
bins: []
config: []
ongrid:
scope: manager
activation:
mode: always
tools:
- name: query_promql
impl: builtin:prom.QueryPromQL
class: read
description: Execute a PromQL query and return the matrix.
---
# query_promql
PromQL query tool ...Для subprocess-скиллов, написанных третьими сторонами, предпочитайте более простой формат skill.json выше. SKILL.md — для скиллов, которые компилируются в бинарь manager'а.