Skip to content

Skill manifest

외부 skill 은 매니저의 허용 목록 디렉터리 중 하나에 떨어뜨린 skill.json 파일로 기술되는 subprocess 실행 파일입니다. 로더는 부팅 시 해당 디렉터리들을 순회하면서 각 skill.json 을 파싱하고, 글로벌 skill 레지스트리에 SubprocessSkill 을 등록합니다. 그러면 LLM 은 그 skill 을 빌트인 도구와 나란히 보게 됩니다.

소스 오브 트루스: internal/skill/loader.go.

디스크 레이아웃

text
/etc/ongrid/skills/                  ← one entry in $ONGRID_SKILLS_EXTERNAL_DIRS
└── disk-cleaner/
    ├── skill.json
    └── run.sh                       ← the executable

skill.json 은 자신의 서브디렉터리 최상위에 있습니다. 디렉터리 트리는 재귀적으로 순회되며, skill.json 이라는 이름의 파일은 모두 매니페스트로 취급됩니다. 같은 허용 목록 루트 아래에 여러 skill 이 살 수 있습니다.

매니페스트 스키마

json
{
  "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"
}
필드타입필수설명
namestringskill 키. [a-z0-9_]+ 에 매치되는 lower_snake. LLM 노출 함수 이름이 됨.
descriptionstring사람 (UI) 과 LLM (함수 description) 에 표시.
schemaJSON Schema아니오args 객체의 raw JSON Schema. 없으면 빈 객체 스키마.
entrystring실행 파일 경로. 상대 경로는 skill.json 이 있는 디렉터리 기준. 절대 경로는 허용 목록 루트 아래에 있어야 함.
env_allowstring[]아니오자식에게 전달되는 env 변수 이름의 명시적 리스트. 빈 리스트 = env 가 전혀 없음 (PATH 조차도 아님). PATH 를 opt-in 하려면 "PATH" 를 추가.
timeout_secondsint아니오subprocess 타임아웃. 0 이면 DefaultSubprocessTimeout (30s) 으로 폴백.
classenum아니오safe (기본), mutating, dangerous. class 분류 참고.
categorystring아니오자유 형식 그룹 라벨. 기본 external. UI 가 subprocess skill 을 이걸로 그룹핑.

와이어 프로토콜

subprocess 는 stdin = JSON args 객체, stdout = JSON 결과 객체, stderr = 매니저용 로그 라인 으로 호출됩니다.

text
$ cat /tmp/args.json
{"path": "/var/cache", "dry_run": true}

$ run.sh < /tmp/args.json
{"freed_bytes": 1048576, "files_deleted": 17}

0 이 아닌 exit 코드는 실패로 취급됩니다. stderr 은 LLM 이 부분 진행 상황을 읽을 수 있도록 도구 호출 이벤트 타임라인에 캡처됩니다.

결과 객체는 LLM 에 그대로 반환됩니다. 에이전트 커널은 그것을 도구 호출의 응답으로 포맷하며, LLM 은 JSON 모양 위에서 추론할 것을 기대받습니다.

Class 분류

같은 {safe, mutating, dangerous} 분류가 네이티브 skill 과 subprocess skill 모두에 적용됩니다.

Class할 수 있는 것필요한 persona 권한
safe읽기 전용 — 호스트나 어떤 시스템에도 부작용 없음.read-only (어떤 persona 든)
mutating상태 생성 / 수정. 가역.mutating-with-confirm 또는 dual-sign-required
dangerous불가역 (삭제, 재시작, exec-arbitrary).dual-sign-required (SOP)

persona 의 permission_mode 필드가 확인 없이 실행 가능한 클래스를 게이팅합니다. 에이전트 persona 포맷 참고.

허용 목록 규칙

운영자는 ONGRID_SKILLS_EXTERNAL_DIRS (콜론 또는 콤마 구분 절대 경로) 로 허용 목록 디렉터리를 구성합니다. 로더는 이를 엄격히 강제합니다:

  • 각 디렉터리는 절대 경로여야 합니다. 상대 경로는 로그 라인과 함께 건너뜁니다.
  • 존재하지 않는 경로는 건너뜁니다 (그래서 /etc/ongrid/skills 가 없는 신규 설치도 잘 부팅됩니다).
  • 각 매니페스트의 entryfilepath.EvalSymlinks 로 정규화되며 허용 목록 루트 아래에 사는지 검사됩니다. 루트 바깥을 가리키는 symlink 는 거절됩니다 (entry %s escapes allowlist root %s).

그 이상의 샌드박싱은 subprocess 의 책임입니다. skill 이 엄격히 격리되어야 한다면 wrapper (bwrap, firejail, nsenter) 를 entry 로 참조해 그 아래에서 실행하세요.

로더 동작

text
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)
  • 매니페스트별 검증 실패는 로깅 후 건너뜀. 깨진 pack 하나가 부팅을 막지 않습니다.
  • 중복 이름은 에러를 내지 않고 건너뜁니다 (그래서 이전 매니페스트를 제거하기 전에 새 매니페스트를 떨어뜨리는 재배포가 매니저를 깨뜨리지 않습니다).
  • 로더는 성공적으로 등록된 skill 의 개수를 반환합니다. skill 로더에 대해 매니저 기동은 non-blocking 입니다 — 비어 있는 외부 디렉터리는 no-op.

기동 시 로깅

매니저는 매니페스트당 한 줄을 로깅합니다:

text
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/skills

무엇이 픽업되었는지 확인하려면 journalctl -u docker-compose@ongrid 또는 docker compose logs ongrid 를 tail 하세요.

함께 보기

네이티브 skill 메타데이터 (SKILL.md frontmatter)

./skills/ 아래에 배포되는 빌트인 skill 들은 openclaw / claude-code skill 생태계와 상호운용되는 풍부한 YAML frontmatter 형식의 SKILL.md 를 사용합니다. 스키마는 internal/manager/biz/aiops/chatruntime/types.go 에 정의되어 있습니다:

yaml
---
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 ...

제3자가 작성하는 subprocess skill 에는 위의 더 단순한 skill.json 포맷을 선호하세요. SKILL.md 는 매니저 바이너리에 컴파일되는 skill 용입니다.