May 17, 2026, 11:40 PM

This commit is contained in:
Paweł Domański
2026-05-18 06:40:19 +00:00
commit 64944cf004
896 changed files with 310709 additions and 0 deletions
+882
View File
@@ -0,0 +1,882 @@
Pewnie — poniżej masz **dwie gotowe, “produkcyjne” wersje SKILL.md dopasowane pod OpenClaw runtime**:
1. **LLMonly** (bez narzędzi)
2. **Toolfirst** (narzędzia jako domyślny silnik, LLM tylko do planu/formatowania)
Dodatkowo dorzucam **gating (load-time)**, **slash-command**, oraz przykładowe **wpisy do `~/.openclaw/openclaw.json`** + rekomendowane **polityki narzędzi (`tools.profile/allow/deny`)**. Wszystko zgodne z tym, jak OpenClaw ładuje i filtruje skille. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/creating-skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
***
# 0) Kontekst OpenClaw (ważne, bo wpływa na projekt)
* Skill w OpenClaw to **katalog z plikiem `SKILL.md`** (YAML frontmatter + instrukcje w Markdown). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/creating-skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* Skille są ładowane m.in. z **`<workspace>/skills`** oraz **`~/.openclaw/skills`**; a gdy nazwy się pokrywają, **workspace wygrywa** nad lokalnym i bundlowanym. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* OpenClaw potrafi **filtrować skille przy ładowaniu** na podstawie `metadata.openclaw.requires` (np. wymagane binarki/env/config). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* Frontmatter ma ograniczenia: parser wspiera **jednolinijkowe klucze**, a `metadata` powinno być **jednolinijkowym JSON**. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* Dostępność i bezpieczeństwo narzędzi kontrolujesz w `openclaw.json` przez `tools.profile`, `tools.allow`, `tools.deny` i grupy `group:*`. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
***
# 1) Struktura katalogu (dla obu wariantów)
> Minimalnie:
<workspace>/skills/my-custom-skill-llm-only/SKILL.md
<workspace>/skills/my-custom-skill-tool-first/SKILL.md
OpenClaw odkryje te katalogi i zindeksuje `SKILL.md` (po restarcie gateway albo “refresh skills”). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/creating-skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
***
# 2) Wersja A — **LLMonly** (zero narzędzi, maksymalna przewidywalność)
### Kiedy to ma sens?
* gdy chcesz **czystą logikę/pisanie/transformację tekstu**
* gdy chcesz **zero sideeffectów** i brak ryzyka toolabuse
* gdy wolisz “prompt jako skill” + ustandaryzowany output
### `SKILL.md` (LLMonly)
```markdown
---
name: my-custom-skill-llm-only
description: Deterministic LLM-only skill. No tools. Produces structured output for [topic].
user-invocable: true
disable-model-invocation: false
metadata: {"openclaw":{"emoji":"🧠","os":["darwin","linux","win32"],"always":true}}
---
# My Custom Skill (LLM-only)
## Purpose (single responsibility)
Zamień nieuporządkowaną prośbę użytkownika na **ustrukturyzowaną odpowiedź** dla: **[topic]**.
## Hard rules (MUST)
- **NIE używaj żadnych narzędzi** (read/write/exec/web_* / browser / nodes / cron).
- Jeśli brakuje danych: **zadaj maksymalnie 3 pytania doprecyzowujące**.
- Brak zgadywania faktów. Brak “dopowiadania” danych wejściowych.
- Zachowaj deterministyczny format wyjścia (poniżej).
## When to use
Użyj tylko gdy:
- użytkownik chce: analizę/plan/porównanie/rewriting/checklistę/specyfikację dla **[topic]**
Nie używaj gdy:
- potrzebne jest pobranie danych z pliku/WWW/systemu albo jakiekolwiek działanie w środowisku.
## Output format (strict)
Zwróć odpowiedź zawsze w tym układzie:
### TL;DR
- ...
### Inputs (what I used)
- ...
### Result
- ...
### Assumptions
- ...
### Next actions (max 5)
1. ...
2. ...
## Quality checklist (internal)
- Czy output ma TL;DR + Inputs + Result + Assumptions + Next actions?
- Czy nie ma w nim “narzędzi” ani sugestii wykonania poleceń?
- Czy nie ma halucynacji faktów?
```
**Dlaczego te pola?**
* `user-invocable` / `disable-model-invocation` to opcjonalne klucze frontmatter (OpenClaw) — przydatne do ekspozycji jako slash command albo ukrycia przed automatycznym doborem. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* `metadata` jako jednolinijkowy JSON i `always`/`os` są zgodne z mechanizmem gatingu. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
***
## Zalecana polityka narzędzi (żeby LLMonly był naprawdę “no-tools”)
W `~/.openclaw/openclaw.json` ustaw np. profil minimalny (albo jawne deny):
```json5
{
"tools": {
"profile": "minimal",
"deny": ["group:fs", "group:runtime", "group:web", "group:ui", "group:nodes", "group:automation"]
}
}
```
* `tools.profile` i grupy `group:*` są wspierane i opisane w dokumentacji narzędzi. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
> Jeśli chcesz, możesz to ograniczyć per-agent (np. tylko dla “writer” agenta), ale powyższe jest najprostsze.
***
# 3) Wersja B — **Toolfirst** (narzędzia domyślnie, LLM tylko do planu + interpretacji)
### Kiedy to ma sens?
* gdy skill ma **pobierać dane** (pliki/WWW), **uruchamiać komendy**, **zapisywać artefakty**
* gdy chcesz przewidywalny pipeline: preflight → gather → execute → output
* gdy chcesz *mniej halucynacji*, bo fakty biorą się z tool outputów
***
## `SKILL.md` (Toolfirst)
> Uwaga: nazwy narzędzi i grupy są zgodne z listą OpenClaw tools (np. `read`, `write`, `exec`, `web_fetch`, `web_search`). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/web)
```markdown
---
name: my-custom-skill-tool-first
description: Tool-first skill for [topic]. Fetches/reads inputs, executes deterministic steps, writes auditable artifacts.
user-invocable: true
metadata: {"openclaw":{"emoji":"🛠️","requires":{"config":["tools.web.fetch.enabled"],"env":["MY_SKILL_API_KEY"],"bins":["jq"]},"primaryEnv":"MY_SKILL_API_KEY"}}
---
# My Custom Skill (Tool-first)
## Purpose (single responsibility)
Wykonaj workflow dla **[topic]** w sposób audytowalny:
1) zbierz dane → 2) przetwórz → 3) zapisz wynik.
## Load-time gates (runtime safety)
Ten skill ma być aktywny tylko gdy:
- `MY_SKILL_API_KEY` jest dostępny (env lub skills.entries.*.apiKey),
- `tools.web.fetch.enabled` jest włączone,
- binarka `jq` istnieje na PATH.
(Jeśli w sandboxie — binarka musi istnieć także w kontenerze.)
## Tools allowed (prefer)
- `read` / `write` (artefakty)
- `web_fetch` (zawartość stron)
- `web_search` (tylko jeśli user nie podał URL)
- `exec` (tylko deterministyczne polecenia, bez wstrzykiwania parametrów od usera)
## Guardrails (MUST)
- Nie uruchamiaj `exec` z argumentami sklejanymi z surowego inputu użytkownika (ryzyko injection).
- Zanim użyjesz narzędzi: wykonaj Pre-flight.
- Zawsze zapisuj artefakty w `{baseDir}/runs/<timestamp>/...` (bezpieczny scope).
- Jeśli jakikolwiek krok nie ma danych → przerwij i poproś o doprecyzowanie.
---
## Execution (deterministic)
### Step 0 — Pre-flight (fail-fast)
1. Waliduj input (topic, opcje).
2. Sprawdź dostępność narzędzi wymaganych w `requires`.
3. Ustaw `runId = YYYYMMDD-HHMMSS` i katalog:
`{baseDir}/runs/{runId}/`
### Step 1 — Gather (minimum necessary)
- Jeśli user podał URL → `web_fetch(url=...)`
- Jeśli nie podał URL → `web_search(query=...)` → wybierz 13 wyniki → `web_fetch(...)`
- Jeśli user podał plik ścieżką → `read(path=...)`
Zapisz:
- `{baseDir}/runs/{runId}/inputs.json`
- `{baseDir}/runs/{runId}/sources.md`
### Step 2 — Transform (tool-first)
- Preferuj deterministyczne przetwarzanie:
- proste ekstrakcje i walidacje przez `exec` (np. `jq`) tylko na danych z własnych plików w katalogu run.
- LLM używaj tylko do:
- ułożenia planu
- formatowania końcowego raportu
Zapisz:
- `{baseDir}/runs/{runId}/result.raw`
### Step 3 — Output (auditable)
Wygeneruj raport w Markdown:
- `{baseDir}/runs/{runId}/report.md`
Raport MA zawierać:
- TL;DR
- Źródła (linki/fragmenty)
- Kroki wykonania (logicznie, bez sekretów)
- Artefakty (ścieżki)
Na końcu zwróć użytkownikowi:
- krótką odpowiedź + link/ścieżkę do report.md
```
### Dlaczego takie `metadata.openclaw.requires`?
* `requires.bins/env/config` to dokładnie ten mechanizm, którym OpenClaw filtruje skille przy ładowaniu. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* `primaryEnv` wiąże się z wygodnym `skills.entries.<name>.apiKey` w configu. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* `{baseDir}` to wspierany placeholder do referencji folderu skilla. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
***
## Zalecana konfiguracja `skills.entries` (openclaw\.json)
```json5
{
"skills": {
"entries": {
"my-custom-skill-tool-first": {
"enabled": true,
"apiKey": { "source": "env", "provider": "default", "id": "MY_SKILL_API_KEY" },
"env": {
"MY_SKILL_API_KEY": "REDACTED"
},
"config": {
"maxRetries": 2,
"maxSources": 3
}
}
}
}
}
```
* `skills.entries.*.env`, `skills.entries.*.apiKey` i `skills.entries.*.config` są wspierane jako override per-skill. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
***
## Zalecana polityka narzędzi dla Toolfirst (żeby działał i był bezpieczny)
```json5
{
"tools": {
"profile": "coding",
"allow": ["group:fs", "group:web", "group:runtime"],
"deny": ["browser", "canvas", "nodes", "cron"]
}
}
```
* Profile (`coding`) i grupy (`group:fs`, `group:web`, `group:runtime`) są częścią mechanizmu policy w OpenClaw. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
* `web_fetch` i `web_search` to wbudowane web narzędzia (bez JS; do JSheavy stron jest `browser`). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/web), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
***
# 4) Bonus: “hybryda” sterowana komendą (szybki slash → tool dispatch)
Jeśli chcesz, żeby komenda **omijała model** i wywoływała bezpośrednio narzędzie (np. do “/my-skill fetch …”), możesz użyć `command-dispatch: tool` + `command-tool`.
To jest super do operacji typu “zrób X jednym toolcall”. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
***
# 5) Dwa krótkie wybory architektoniczne (żebyś nie wpadł w typowe pułapki)
### LLMonly
✅ przewidywalne, zero sideeffectów, tanie w utrzymaniu
❌ nie pobierze danych z zewnątrz, nie zapisze plików (chyba że pozwolisz narzędzia)
### Toolfirst
✅ minimalizuje halucynacje, audytowalne artefakty, pipeline “jak w produkcji”
❌ wymaga dobrych guardrails i policy (szczególnie dla `exec`) [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
***
## Pytanie, które pozwoli mi dopiąć to “na gotowo” (bez długiej wymiany)
Jaki jest **konkretny cel** Twojego skilla w praktyce?
Daj 1 zdanie w stylu:
* “Zbiera dane z URL + robi raport”
* “Czyta logi / pliki i generuje podsumowanie”
* “Uruchamia komendy diagnostyczne (DB/Splunk/SQL) i zapisuje wynik”
…i wtedy dopasuję Ci:
* dokładne `requires.config` pod Twoje narzędzia,
* strukturę artefaktów,
* i bezpieczne allowlisty dla `exec` (jeśli w ogóle ma być).
Jasne — poniżej masz **wersję hybrydową SKILL.md dla OpenClaw**, która łączy:
1. **tryb “agentowy” (LLM + toolfirst)** w normalnej rozmowie
2. **tryb “komendowy” (/… → direct tool dispatch)** dla deterministycznych akcji ze slash command
To jest zgodne z tym, jak OpenClaw ładuje skille z katalogu z `SKILL.md` (YAML frontmatter + Markdown) i jak działa gating (`metadata.openclaw.requires`) oraz obsługa slash commands (`user-invocable`, `command-dispatch`, `command-tool`, `command-arg-mode`). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/creating-skills), [\[moely.ai\]](https://www.moely.ai/resources/openclaw-skills-extension-design)
> **Uwaga praktyczna:** Direct tool dispatch wymaga, żeby wskazany tool akceptował parametry przekazywane przez dispatcher (`{ command, commandName, skillName }`). OpenClaw opisuje to wprost.
> Jeśli Twoja instalacja ma **ściśle walidowane schematy narzędzi** i wywali się na “nadmiarowych polach”, daję też wariant “bez bypassu” (slash dalej wybiera skill, ale przez LLM) w sekcji **Plan B**. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[moely.ai\]](https://www.moely.ai/resources/openclaw-skills-extension-design)
***
## ✅ 1) Hybrydowy `SKILL.md` (Toolfirst + Slash direct-dispatch)
Wklej jako:
`<workspace>/skills/my-custom-skill-hybrid/SKILL.md`
(Workspace ma najwyższy priorytet ładowania względem `~/.openclaw/skills` i bundli). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/creating-skills)
```markdown
---
name: my-custom-skill-hybrid
description: Hybrid skill: tool-first in chat, optional deterministic slash dispatch (bypass model) for quick actions.
user-invocable: true
disable-model-invocation: false
command-dispatch: tool
command-tool: exec
command-arg-mode: raw
metadata: {"openclaw":{"emoji":"🧩","os":["darwin","linux","win32"],"requires":{"config":["tools.exec.enabled"],"bins":["jq"]}}}
---
# My Custom Skill (HYBRID)
Ten skill ma **dwa tryby pracy**:
## Mode A — Chat / Agent mode (default)
Gdy użytkownik opisuje problem normalnie, skill działa **tool-first**:
- zbierz dane (read/web_fetch/web_search)
- przetwórz deterministycznie (preferuj narzędzia)
- dopiero na końcu użyj LLM do formatowania raportu
## Mode B — Slash / Deterministic mode (bypass model)
Gdy użytkownik użyje komendy slash dla tego skilla, OpenClaw ma **ominiąć model**
i wywołać wskazane narzędzie bezpośrednio (command-dispatch: tool).
W tym trybie parametr `args` trafia jako `command` do toola.
> Komenda jest przekazywana jako:
> { command: "<raw args>", commandName: "<slash>", skillName: "<skill>" }.
---
## Safety & Guardrails (MANDATORY)
- Nigdy nie wykonuj poleceń destrukcyjnych (rm -rf, format, wipe, itp.).
- Nie uruchamiaj poleceń z sekretami w treści.
- Jeśli w Mode A potrzebujesz `exec`, to:
- używaj allowlisty komend,
- nie sklejaj argumentów z “surowego” inputu użytkownika.
- Artefakty zapisuj wyłącznie w `{baseDir}/runs/<runId>/`.
---
## When to Use
Użyj, gdy użytkownik chce:
- zebrać dane z pliku/URL i zrobić raport / analizę dla [topic]
- albo wykonać szybkie, deterministyczne akcje komendą (Mode B)
Nie używaj, gdy:
- zadanie wymaga browser logowania/JS-heavy — wtedy preferuj browser tool (poza tym skillem).
---
## Execution (Mode A — tool-first)
### Step 0: Pre-flight
1) Ustal `runId = YYYYMMDD-HHMMSS`.
2) Sprawdź, czy masz minimalne dane wejściowe (topic / źródło / zakres).
3) Jeśli braki → max 3 pytania doprecyzowujące.
### Step 1: Gather
- Jeśli user podał plik → `read`
- Jeśli podał URL → `web_fetch`
- Jeśli nie podał źródła → `web_search` (max 3 wyniki) → `web_fetch`
Zapisz:
- `{baseDir}/runs/{runId}/inputs.json`
- `{baseDir}/runs/{runId}/sources.md`
### Step 2: Transform
- Preferuj narzędzia i deterministykę.
- Jeśli musisz, użyj `exec` tylko dla bezpiecznych transformacji na plikach z katalogu run.
- LLM wyłącznie do: streszczenia, formatowania, wyjaśnienia.
Zapisz:
- `{baseDir}/runs/{runId}/result.raw`
### Step 3: Output
Wygeneruj `{baseDir}/runs/{runId}/report.md` zawierający:
- TL;DR
- Źródła i cytowane fragmenty
- Kroki wykonania (bez sekretów)
- Artefakty (ścieżki)
---
## Slash usage (Mode B — bypass model)
### /my-custom-skill-hybrid <raw>
Przykłady (bezpieczne, read-only):
- `/my-custom-skill-hybrid echo "hello"`
- `/my-custom-skill-hybrid jq --version`
Zasady:
- traktuj to jako tryb “operator executes a command”
- jeśli komenda wygląda na destrukcyjną → przerwij i poproś o potwierdzenie poza trybem bypass
```
### Dlaczego to jest “OpenClawnative”?
* Skill jako katalog z `SKILL.md` + frontmatter jest standardem OpenClaw. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/creating-skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* `metadata.openclaw.requires` (bins/config/os) to mechanizm **loadtime gating**. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[moely.ai\]](https://www.moely.ai/resources/openclaw-skills-extension-design)
* `user-invocable`, `command-dispatch: tool`, `command-tool`, `command-arg-mode` to oficjalnie opisane pola dla komend i bypassu. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[moely.ai\]](https://www.moely.ai/resources/openclaw-skills-extension-design)
* `exec` jest narzędziem do uruchamiania komend, kontrolowanym politykami narzędzi. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
***
## ✅ 2) Konfiguracja `openclaw.json` (narzędzia + skill entry)
### a) Bezpieczna polityka narzędzi (dla hybrydy)
Poniżej ustawiasz profil i allow/deny (OpenClaw wspiera `tools.profile`, `tools.allow`, `tools.deny` i grupy). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
```json5
{
"tools": {
"profile": "coding",
"allow": ["group:fs", "group:web", "group:runtime"],
"deny": ["browser", "canvas", "nodes", "cron"]
},
"skills": {
"entries": {
"my-custom-skill-hybrid": {
"enabled": true,
"config": {
"maxSources": 3,
"maxRetries": 2
}
}
}
}
}
```
***
# 🔧 Plan B (jeśli direct-dispatch nie działa w Twojej instalacji)
W części wdrożeń bywa, że komendy skillowe (w tym `command-dispatch: tool`) nie odpalają się jak trzeba zależnie od wersji/konfiguracji (widziano przypadek zależności od aliasów modeli). [\[github.com\]](https://github.com/openclaw/openclaw/issues/25239)
**Wtedy zrób hybrydę bez bypassu:**
* Usuń z frontmatter:
* `command-dispatch`, `command-tool`, `command-arg-mode`
* Zostaw `user-invocable: true`
* A w treści skilla dodaj regułę:
* “Jeśli użytkownik wywoła skill ze slash command i poda argumenty, traktuj je jako tryb komendowy, ale nadal przejdź przez Pre-flight i guardrails.”
To nadal daje **dwa tryby**, tylko Mode B idzie przez LLM (mniej deterministycznie, ale bardziej kompatybilnie). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
***
# Następny krok (żeby to było “idealnie pod Ciebie”)
W tej chwili hybryda ma Mode B ustawiony na `exec` (bo to najprostszy “tool dispatch”).
Powiedz mi w 1 zdaniu: **co Mode B ma robić w Twoim realnym use-case?** [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
Przykłady:
* “/skill diag” → zebrać statusy i zapisać report
* “/skill fetch <url>” → pobrać stronę i znormalizować do markdown
* “/skill sqlcheck” → odpalić kilka read-only poleceń diagnostycznych
A ja dopasuję:
* bezpieczną allowlistę komend (albo całkiem wyeliminuję `exec`),
* parametry “raw args” i format,
* oraz gating (`requires.config/env/bins`) pod Twoje runtime. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools)
Pewnie — pokażę Ci **jak wygląda rozbicie na “skill (orchestrator) + subskille” w OpenClaw** oraz dorzucę **allowlistę komend** (dla `exec`) tak, żeby dało się to utrzymać i nie otworzyć sobie drzwi na commandinjection. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model), [\[deepwiki.com\]](https://deepwiki.com/openclaw/openclaw/6.4-skills-system)
> **Ważna uwaga o architekturze w OpenClaw:** “subskille” to po prostu **osobne skille** (oddzielne katalogi z `SKILL.md`), które agent wybiera zależnie od intencji. Orchestrator nie “wywołuje” ich jak funkcji w kodzie, ale **kieruje agentem** (instrukcjami) żeby użył właściwego sub-skilla dla danego kroku. OpenClaw ładuje i filtruje skille (gating), a potem wstrzykuje ich opis do promptu, na podstawie którego model decyduje, którego użyć. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[deepwiki.com\]](https://deepwiki.com/openclaw/openclaw/6.4-skills-system)
***
## 1) Jak to będzie wyglądać — struktura katalogów (suite: skill + subskille)
Skille w OpenClaw to **katalog + `SKILL.md`**; najlepiej trzymać to w `<workspace>/skills`, bo ma najwyższy priorytet nad `~/.openclaw/skills` i bundlami. [\[deepwiki.com\]](https://deepwiki.com/openclaw/openclaw/6.4-skills-system), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
Przykładowa “paczka” (suite):
<workspace>/skills/
my-suite-orchestrator/
SKILL.md
my-suite-gather-web/
SKILL.md
my-suite-gather-files/
SKILL.md
my-suite-transform/
SKILL.md
my-suite-report/
SKILL.md
my-suite-quickfetch/ # opcjonalny "hybrydowy" slash bypass (bezpieczny)
SKILL.md
* **orchestrator**: routuje do sub-skilli + trzyma wspólne guardrails i spójny format artefaktów. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* **gather-\***: izolują pobieranie danych (WWW / pliki). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model), [\[deepwiki.com\]](https://deepwiki.com/miaoxworld/OpenClawInstaller/5.3-creating-custom-skills)
* **transform**: deterministyczne przetwarzanie + allowlista `exec`. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* **report**: format i finalny raport. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
* **quickfetch**: jeśli chcesz **prawdziwy “hybrydowy” bypass** bez ryzyka (dispatch do `web_fetch`, a nie do `exec`). `web_fetch` jest z natury “bezpieczniejszy” niż `exec`, bo nie uruchamia poleceń, tylko pobiera URL i ekstrahuje treść. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model), [\[deepwiki.com\]](https://deepwiki.com/miaoxworld/OpenClawInstaller/5.3-creating-custom-skills)
***
## 2) Skill #1 — Orchestrator (główny “suite skill”)
**Cel:** jeden skill, który:
* wybiera odpowiedni sub-skill,
* pilnuje spójnej struktury `runs/<runId>/`,
* pilnuje zasad bezpieczeństwa i “kiedy exec jest w ogóle dozwolony”. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
`<workspace>/skills/my-suite-orchestrator/SKILL.md`
```markdown
---
name: my-suite-orchestrator
description: Orchestrates the suite: routes to sub-skills, enforces guardrails, and produces auditable outputs.
user-invocable: true
metadata: {"openclaw":{"emoji":"🧭","always":true}}
---
# My Suite — Orchestrator
## Responsibility (single)
Zarządzaj wykonaniem zadania: wybierz właściwy sub-skill, utrzymaj porządek artefaktów i guardrails.
## Routing rules (deterministic)
- Jeśli źródło to URL / WWW → użyj **my-suite-gather-web**
- Jeśli źródło to plik/ścieżka → użyj **my-suite-gather-files**
- Jeśli trzeba przetworzyć/oczyścić dane → użyj **my-suite-transform**
- Jeśli trzeba złożyć wynik w raport → użyj **my-suite-report**
## Global guardrails (MUST)
- Preferuj narzędzia “read-only” i web tools (web_fetch/web_search) nad exec.
- `exec` tylko gdy:
1) to konieczne,
2) pasuje do allowlisty z my-suite-transform,
3) dotyczy wyłącznie plików w `{baseDir}/runs/<runId>/`.
- Artefakty zapisuj w `{baseDir}/runs/<runId>/...`
- Jeśli brakuje danych → max 3 pytania doprecyzowujące, potem stop.
## Output contract
Zawsze zwróć:
- TL;DR
- Co było wejściem
- Co powstało (artefakty i ścieżki)
- Następne kroki
```
**Dlaczego tak?** Orchestrator wykorzystuje fakt, że OpenClaw “podaje” modelowi listę dostępnych skilli i narzędzi, więc routing robimy instrukcjami (deterministycznie). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 3) Sub-skill: Gather Web (web\_search + web\_fetch)
`<workspace>/skills/my-suite-gather-web/SKILL.md`
```markdown
---
name: my-suite-gather-web
description: Fetches sources from the web. Uses web_search when needed, then web_fetch for extraction.
user-invocable: false
metadata: {"openclaw":{"emoji":"🌐","requires":{"config":["tools.web.fetch.enabled"]}}}
---
# Gather Web
## When to use
- Użytkownik podał URL lub trzeba znaleźć źródła w WWW.
## Steps
1) Jeśli jest URL → `web_fetch(url=..., extractMode="markdown")`
2) Jeśli brak URL → `web_search(query=..., count=3)` → wybierz 13 wyniki → `web_fetch(...)`
## Artifacts
Zapisz do:
- `{baseDir}/runs/<runId>/sources.md` (linki + krótkie ekstrakty)
- `{baseDir}/runs/<runId>/inputs.json` (metadane wejścia)
```
`web_search` i `web_fetch` są oficjalnymi web toolami w OpenClaw (wyszukiwanie + fetch bez JS). [\[deepwiki.com\]](https://deepwiki.com/miaoxworld/OpenClawInstaller/5.3-creating-custom-skills), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 4) Sub-skill: Gather Files (read)
`<workspace>/skills/my-suite-gather-files/SKILL.md`
```markdown
---
name: my-suite-gather-files
description: Loads input from local files safely and stores normalized copies in the run folder.
user-invocable: false
metadata: {"openclaw":{"emoji":"📁","requires":{"config":["group:fs"]}}}
---
# Gather Files
## When to use
- Użytkownik wskazuje plik/ścieżkę lub potrzebujesz odczytać artefakt z wcześniejszego run.
## Steps
1) Użyj `read(path=...)` na wejściu.
2) Skopiuj/znormalizuj treść do `{baseDir}/runs/<runId>/input.txt` (bez modyfikowania oryginału).
## Artifacts
- `{baseDir}/runs/<runId>/input.txt`
- `{baseDir}/runs/<runId>/inputs.json`
```
Narzędzia plikowe (`read/write/edit/...`) są grupowane i kontrolowane politykami tooli w OpenClaw (`group:fs`). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 5) Sub-skill: Transform (TU dodajemy allowlistę komend)
To jest miejsce, gdzie robisz “bezpieczny runtime” dla `exec`. `exec` w OpenClaw to narzędzie do uruchamiania komend w workspace (z parametrami m.in. `command`, `timeout`, `security`). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
`<workspace>/skills/my-suite-transform/SKILL.md`
```markdown
---
name: my-suite-transform
description: Deterministic transformations with a strict command allowlist (exec is optional and constrained).
user-invocable: false
metadata: {"openclaw":{"emoji":"🧪","requires":{"config":["group:runtime"],"bins":["jq"]}}}
---
# Transform (Allowlisted exec)
## Golden rule
Preferuj transformacje bez `exec`. Jeśli `exec` jest potrzebny → tylko allowlista poniżej.
## Command allowlist (STRICT)
Dozwolone są WYŁĄCZNIE te komendy (dokładne wzorce):
1) `jq --version`
2) `jq -c . <INPUT >OUTPUT`
3) `jq -r . <INPUT >OUTPUT`
4) `head -n <N> <INPUT`
5) `tail -n <N> <INPUT`
6) `wc -l <INPUT`
7) `grep -n "<literal>" <INPUT`
8) `sed -n '<start>,<end>p' <INPUT`
### Constraints (MUST)
- `<INPUT>` i `<OUTPUT>` MUSZĄ być ścieżkami pod `{baseDir}/runs/<runId>/`
- `<N>` to liczba 1..500
- `"<literal>"` nie może zawierać znaków: `; | & $ \` ( ) { }`
- Zakaz: `rm`, `mv`, `cp` poza run, `curl`, `wget`, `ssh`, `sudo`, `chmod`, `chown`, `dd`, `mkfs`, `> /dev/*` itd.
## Execution steps
1) Waliduj, czy polecenie pasuje do allowlisty i constraintów.
2) Jeśli nie pasuje → przerwij i zaproponuj alternatywę bez exec.
3) Jeśli pasuje → uruchom `exec` tylko na plikach w katalogu run.
4) Wynik zapisz do:
- `{baseDir}/runs/<runId>/transform.log`
- `{baseDir}/runs/<runId>/<output files>`
## Why this exists
Zapobiega command injection i ogranicza skutki błędów do sandboxowego katalogu run.
```
### Dlaczego allowlista w SKILL.md ma sens?
Bo w OpenClaw to model wybiera i parametryzuje toolcall (np. `exec(command=...)`), a Ty chcesz mu **zawęzić przestrzeń decyzji** do znanych, bezpiecznych wzorców. Narzędzie `exec` jest potężne, więc guardrails muszą być twarde. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 6) Sub-skill: Report (formatowanie i final)
`<workspace>/skills/my-suite-report/SKILL.md`
```markdown
---
name: my-suite-report
description: Produces the final report.md from gathered/transformed artifacts. No exec.
user-invocable: false
metadata: {"openclaw":{"emoji":"📝","always":true}}
---
# Report
## Inputs
- `{baseDir}/runs/<runId>/sources.md` i/lub `input.txt`
- `{baseDir}/runs/<runId>/result.raw` (jeśli istnieje)
- `transform.log` (opcjonalnie)
## Output
Zapisz:
- `{baseDir}/runs/<runId>/report.md`
Format report.md:
- TL;DR
- Evidence (źródła, linki, fragmenty)
- Steps taken (bez sekretów)
- Artifacts (ścieżki)
- Next actions (max 5)
```
***
## 7) Hybryda: “quick” slash bypass (bezpieczny) — opcjonalnie 📦
Jeśli nadal chcesz “hybrydę” w sensie **slash command → direct tool dispatch**, to **nie dispatchuj do `exec`** (bo omijasz model, więc omijasz allowlistę!). Zamiast tego zrób osobny “quickfetch” dispatchujący do `web_fetch`. Mechanizm `command-dispatch: tool` + `command-tool` jest wspierany. [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
`<workspace>/skills/my-suite-quickfetch/SKILL.md`
```markdown
---
name: my-suite-quickfetch
description: Slash-safe quick fetch: bypass model and run web_fetch directly on provided URL.
user-invocable: true
command-dispatch: tool
command-tool: web_fetch
command-arg-mode: raw
metadata: {"openclaw":{"emoji":"⚡","requires":{"config":["tools.web.fetch.enabled"]}}}
---
# QuickFetch (slash)
Usage:
- `/my-suite-quickfetch https://example.com`
Notes:
- This bypasses the model and dispatches to web_fetch.
- Provide a single URL as the raw args string.
```
`web_fetch` jest narzędziem do pobrania i ekstrakcji treści (bez JS), więc jako bypass jest dużo mniej ryzykowne niż `exec`. [\[deepwiki.com\]](https://deepwiki.com/miaoxworld/OpenClawInstaller/5.3-creating-custom-skills), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
# 8) Konfiguracja narzędzi (tools policy) — minimalny “safe” zestaw
OpenClaw pozwala ustawić bazową politykę przez `tools.profile` oraz `tools.allow/deny` i grupy (`group:fs`, `group:web`, `group:runtime`). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
Przykład “suite-friendly” (umożliwia pliki+web+exec, ale blokuje UI/nodes/cron):
```json5
{
"tools": {
"profile": "coding",
"allow": ["group:fs", "group:web", "group:runtime"],
"deny": ["browser", "canvas", "nodes", "cron"]
}
}
```
***
# 9) Co dostajesz dzięki takiemu rozbiciu?
**Mniej halucynacji** (gather i transform to narzędzia, a nie “zgadywanie”).
**Mniejszy prompt** per skill (subskille są węższe i prostsze).
**Łatwiejszy audyt** (artefakty w jednym run folderze).
**Bezpieczniejsze `exec`** dzięki allowliście + constraintom na ścieżki.
**“Hybryda”**: szybki slash do bezpiecznego toola (`web_fetch`) + pełny agentowy pipeline w rozmowie. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model), [\[deepwiki.com\]](https://deepwiki.com/miaoxworld/OpenClawInstaller/5.3-creating-custom-skills) [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills) [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model) [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model) [\[deepwiki.com\]](https://deepwiki.com/miaoxworld/OpenClawInstaller/5.3-creating-custom-skills), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## Szybkie doprecyzowanie (jedno zdanie wystarczy)
Chcesz allowlistę komend pod **jakie realne zadania**? (np. parsowanie JSON logów, wyciąganie fragmentów tekstu, walidacja plików, itd.)
Jeśli powiesz “do czego”, dopasuję allowlistę tak, żeby:
* była **minimalna** (im mniej, tym lepiej),
* nie była “zbyt ogólna” (np. nie dam `python -c` bo to prawie jak pełny shell),
* i żeby nie blokowała Twojego flow.
Poniżej masz **praktyczne ograniczenia i “pułapki” używania `exec` w OpenClaw** czyli co realnie ogranicza to narzędzie, jak działa w sandboxie/na hoście, jakie ma limity i jakie mechanizmy bezpieczeństwa wpływają na to, czy komenda w ogóle się wykona. Wszystko w oparciu o oficjalny opis narzędzi OpenClaw. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 1) `exec` działa w określonym “kontekście uruchomienia” (workspace / sandbox / node)
* Domyślnie `exec` uruchamia komendy **w workspace** (w praktyce: w katalogu roboczym sesji/agenta). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* `exec` ma parametr `host`, który determinuje **gdzie** wykonać polecenie: `sandbox | gateway | node`. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* W trybie sandbox (kontener) to, co działa na hoście, **nie musi działać w sandboxie** (brak binarek, brak sieci, inny filesystem). OpenClaw wprost zaznacza, że przy sandboxie binarki wymagane przez skill muszą istnieć również w kontenerze, a instalacje w kontenerze wymagają m.in. egressu sieci, zapisywalnego FS i uprawnień (root). [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
**Wniosek:** jeśli Twoja komenda “działa u Ciebie w terminalu”, to nadal może nie działać w sandboxie agenta (inne środowisko). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model), [\[docs.openclaw.ai\]](https://docs.openclaw.ai/tools/skills)
***
## 2) Narzędzie może być całkowicie niedostępne przez polityki narzędzi (`tools.profile/allow/deny`)
* OpenClaw ma globalne polityki narzędzi: `tools.profile`, `tools.allow`, `tools.deny` (deny wygrywa) i wspiera grupy typu `group:runtime` (gdzie jest m.in. `exec`). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* Jeśli `exec` (albo `group:runtime`) jest zablokowany w polityce, to model **nie dostanie** schematu narzędzia, a więc nie będzie mógł go wywołać. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
**Wniosek:** “skill mówi żeby użyć exec” ≠ “agent może użyć exec”. O tym decyduje policy. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 3) `exec` ma wbudowane limity czasu i tryby pracy (sync vs background)
* Kluczowe parametry `exec` to m.in.: `yieldMs` (domyślnie 10000), `background`, `timeout` (sekundy; domyślnie 1800), `pty`, `host`, `security`, `ask`. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* Jeśli proces przekroczy `yieldMs`, OpenClaw może go **zabackgroundować** i zwrócić status `running` z `sessionId`. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* Do obsługi procesów w tle służy narzędzie `process` (list/poll/log/write/kill/clear/remove). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* Jeżeli `process` jest zablokowane, OpenClaw zaznacza, że `exec` działa wtedy **synchronicznie** i ignoruje `yieldMs/background` (czyli tracisz wygodny mechanizm longrunning jobów). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
**Wniosek:** długie komendy bez `process` mogą “nie mieć gdzie żyć” albo będą ucinane/timeoutowane, albo zablokują przebieg. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 4) Ograniczenia bezpieczeństwa: `security` + “exec approvals” + `ask`
OpenClaw przewiduje kilka warstw kontroli:
* `exec` ma parametr `security` (np. `deny | allowlist | full`) i parametr `ask` (`off | on-miss | always`) do sterowania zgodami/warunkami uruchomienia. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* Dodatkowo, OpenClaw ma osobny mechanizm “Exec approvals” (zatwierdzanie/ograniczanie uruchamiania komend) dokumentacja `exec` odwołuje się do tego wprost. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* W praktyce oznacza to, że nawet jeśli agent potrafi złożyć komendę, może zostać zatrzymany przez politykę “approval/allowlist” (zależnie od konfiguracji). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
**Wniosek:** w produkcyjnych setupach `exec` często jest “supervised”: albo wymaga potwierdzeń, albo działa tylko na allowliście, albo jest wyłączony. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 5) `elevated` (uruchomienie na hoście) ma dodatkowe bramki
* `elevated` to alias zachowania “uruchom na gateway host z pełnymi uprawnieniami”, ale **działa sensownie głównie wtedy, gdy sesja jest sandboxowana** (w przeciwnym razie bywa noop). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* Jest to dodatkowo “gated” przez `tools.elevated` i ewentualne override per-agent oba muszą pozwalać. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
**Wniosek:** jeśli liczysz na “wyjście z sandboxa” przez `elevated`, to musisz to mieć jawnie włączone; w wielu środowiskach będzie to celowo zablokowane. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 6) `exec` nie daje prawdziwego TTY bez `pty: true` (a i tak bywa ograniczone)
* Dokumentacja wskazuje: “Need a real TTY? Set `pty: true`.” [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* To rozwiązuje część problemów z programami interaktywnymi, ale w praktyce nadal możesz wpadać na ograniczenia sandboxa / braku urządzeń / braku UI. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
**Wniosek:** `exec` nie jest idealne do narzędzi wymagających pełnej interakcji terminalowej, jeśli środowisko nie jest do tego przygotowane. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 7) `exec` może być “ucinane” przez loopdetection (gdy agent zapętla toolcalls)
* OpenClaw ma mechanizm loopdetection, który może ostrzegać/blokować powtarzalne wywołania narzędzi bez postępu (można włączyć i konfigurować progi). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
**Wniosek:** jeśli agent wpada w pętlę `exec → poll → exec → poll`, system może to wykryć i zablokować. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## 8) Kluczowe “praktyczne” ograniczenie: ryzyko injection i brak automatycznej sanityzacji
To nie jest pojedyncza flaga, tylko fakt wynikający z charakteru `exec`:
* `exec` uruchamia **shell commands**, więc jeśli sklejasz komendę z surowego inputu usera, otwierasz się na injection. Dokumentacja narzędzi podkreśla, że `exec` to narzędzie w grupie “runtime” i wymaga świadomej polityki bezpieczeństwa (deny/allowlist/approvals). [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
* W docs “Creating Skills” jest ostrzeżenie: jeśli skill używa “bash/exec”, trzeba uważać na **arbitrary command injection** z niezaufanego inputu. [\[deepwiki.com\]](https://deepwiki.com/openclaw/openclaw/6.4-skills-system)
**Wniosek:** najtwardszym ograniczeniem “w praktyce” jest to, że w dobrym projekcie `exec` **musi** być ograniczone allowlistą + kontrolą parametrów. [\[deepwiki.com\]](https://deepwiki.com/openclaw/openclaw/6.4-skills-system), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
# Rekomendacja (krótko, produkcyjnie)
Jeśli chcesz używać `exec` w skillach “na serio”, to zwykle wygląda to tak:
1. `tools.profile` + `tools.allow/deny` ogranicza dostęp do `exec` tylko tam, gdzie naprawdę trzeba. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
2. Skill ma **allowlistę komend** + walidację argumentów + ograniczenie ścieżek do runfolderu. (To jest najlepsza praktyka wynikająca z ryzyk `exec` i ostrzeżeń dot. injection). [\[deepwiki.com\]](https://deepwiki.com/openclaw/openclaw/6.4-skills-system), [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
3. Długie komendy → `process` musi być dostępny, inaczej longrunning flow się posypie. [\[blog.laozhang.ai\]](https://blog.laozhang.ai/en/posts/openclaw-custom-model)
***
## Dopytam jedno (żeby odpowiedzieć “pod Twoją konfigurację”, nie ogólnie)
U Ciebie `exec` ma działać **w sandboxie** czy **na hoście**? (I czy włączone jest `process`?)
Na tej podstawie mogę zaproponować konkretny, bezpieczny zestaw: policy + allowlista + wzorce komend pod Twój usecase.