Manifesto de skill
Skills externas são executáveis subprocesso descritos por um arquivo skill.json colocado sob um dos diretórios allow-list do manager. O loader percorre esses diretórios no boot, parseia cada skill.json, e registra um SubprocessSkill no skill registry global. O LLM então vê a skill ao lado das tools built-in.
Fonte de verdade: internal/skill/loader.go.
Layout em disco
/etc/ongrid/skills/ ← uma entrada em $ONGRID_SKILLS_EXTERNAL_DIRS
└── disk-cleaner/
├── skill.json
└── run.sh ← o executávelCada skill.json está no topo de seu próprio subdiretório. A árvore de diretórios é percorrida recursivamente; qualquer arquivo nomeado skill.json é tratado como um manifesto. Múltiplas skills podem viver sob o mesmo allow-list root.
Schema do manifesto
{
"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"
}| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name | string | sim | Chave de skill. Precisa ser lower_snake casando [a-z0-9_]+. Vira o nome de função voltado ao LLM. |
description | string | sim | Mostrada a humanos (UI) e ao LLM (descrição de função). |
schema | JSON Schema | não | JSON Schema cru para o objeto args. Faltante = schema de objeto vazio. |
entry | string | sim | Path para o executável. Paths relativos resolvem contra o diretório contendo skill.json. Paths absolutos precisam estar sob um allow-list root. |
env_allow | string[] | não | Lista explícita de nomes de env-var encaminhadas ao child. Lista vazia = sem env nenhuma (nem PATH). Adicione "PATH" para opt-in ao PATH. |
timeout_seconds | int | não | Timeout do subprocesso. Zero cai para DefaultSubprocessTimeout (30s). |
class | enum | não | safe (padrão), mutating, dangerous. Veja taxonomia de class. |
category | string | não | Label de grupo free-form. Default para external. UI agrupa skills subprocess por isso. |
Protocolo wire
O subprocesso é invocado com stdin = objeto JSON de args, stdout = objeto JSON de result, stderr = linhas de log para o manager.
$ cat /tmp/args.json
{"path": "/var/cache", "dry_run": true}
$ run.sh < /tmp/args.json
{"freed_bytes": 1048576, "files_deleted": 17}Exit code não-zero é tratado como falha. Stderr é capturado na timeline de event de tool-call para que o LLM possa ler progresso parcial.
O objeto de result é retornado verbatim ao LLM. O agent kernel o formata como a response da chamada de tool; o LLM é esperado raciocinar sobre o formato JSON.
Taxonomia de class
A mesma taxonomia {safe, mutating, dangerous} aplica a skills nativas e skills subprocess.
| Class | O que pode fazer | Permissão de persona requerida |
|---|---|---|
safe | Read-only — sem efeitos colaterais no host ou em qualquer sistema. | read-only (qualquer persona) |
mutating | Cria / atualiza estado. Reversível. | mutating-with-confirm ou dual-sign-required |
dangerous | Irreversível (deleta, reinicia, exec-arbitrário). | dual-sign-required (SOP) |
O campo permission_mode da persona gateia quais classes podem rodar sem confirmação. Veja Formato de persona de agent.
Regras de allow-list
Operadores configuram diretórios allow-list via ONGRID_SKILLS_EXTERNAL_DIRS (paths absolutos separados por dois-pontos ou vírgula). O loader os impõe estritamente:
- Cada diretório precisa ser um path absoluto. Paths relativos são pulados com linha de log.
- Paths não-existentes são pulados (para que uma instalação fresca sem
/etc/ongrid/skillsboote bem). - O
entryde cada manifesto é canonicalizado comfilepath.EvalSymlinkse checado para viver sob o allow-list root. Um symlink que aponta fora do root é rejeitado (entry %s escapes allowlist root %s).
Sandboxing além disso é responsabilidade do subprocesso. Se a skill precisa ser apertadamente contida, rode sob um wrapper (bwrap, firejail, nsenter) referenciado como o entry.
Comportamento do 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)- Falhas de validação por-manifesto são logadas e puladas. Um pack quebrado não deve bloquear boot.
- Nomes duplicados são pulados em vez de errar (para que um redeploy que coloque um manifesto novo antes de remover o antigo não crashe o manager).
- Loader retorna a contagem de skills registradas com sucesso. Startup do manager é não-blocante no loader de skill: um dir externo vazio é um no-op.
Log no startup
O manager loga uma linha por manifesto:
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/skillsFaça tail em journalctl -u docker-compose@ongrid ou docker compose logs ongrid para confirmar o que foi pego.
Veja também
- Capacidades → Skills — catálogo de skill built-in.
- Formato de persona de agent — como uma persona escolhe quais skills pode chamar.
- Marketplace — instala um pack de skills como uma unidade.
- REST API →
/v1/skills— listing e execução direta.
Metadados de skill nativa (frontmatter SKILL.md)
Skills built-in distribuídas sob ./skills/ usam um formato SKILL.md mais rico com YAML-frontmatter que interopera com os ecossistemas de skill openclaw / claude-code. O schema está definido em 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 ...Para skills subprocess escritas por terceiros, prefira o formato skill.json mais simples acima. SKILL.md é para skills que compilam no binário do manager.