* feat(skills): capture reusable experience safely * feat(skills): review completed work for reusable learning * docs(skills): explain self-learning * docs: clarify self-learning runtime scope * fix(skills): harden autonomous workshop reviews * test(skills): align review prompt fixture
17 KiB
title, sidebarTitle, summary, read_when
| title | sidebarTitle | summary | read_when | |||
|---|---|---|---|---|---|---|
| Skills config | Skills config | Full reference for the skills.* config schema, agent allowlists, workshop settings, and sandbox env var handling. |
|
Most skills configuration lives under skills in
~/.openclaw/openclaw.json. Agent-specific visibility lives under
agents.defaults.skills and agents.list[].skills.
{
skills: {
allowBundled: ["gemini", "peekaboo"],
load: {
extraDirs: ["~/Projects/agent-scripts/skills"],
allowSymlinkTargets: ["~/Projects/manager/skills"],
watch: true,
watchDebounceMs: 250,
},
install: {
preferBrew: true,
nodeManager: "npm",
allowUploadedArchives: false,
},
workshop: {
autonomous: { enabled: false },
allowSymlinkTargetWrites: false,
approvalPolicy: "pending",
maxPending: 50,
maxSkillBytes: 40000,
},
entries: {
"image-lab": {
enabled: true,
apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" },
env: { GEMINI_API_KEY: "GEMINI_KEY_HERE" },
},
peekaboo: { enabled: true },
sag: { enabled: false },
},
},
}
Loading (skills.load)
Additional skill directories to scan, at the lowest precedence (below
bundled and plugin skills). Paths are expanded with `~` support.
Trusted real target directories that symlinked skill folders may resolve
into, even when the symlink lives outside the configured root. Use this for
intentional sibling-repo layouts such as
`/skills/manager -> ~/Projects/manager/skills`. Keep this list
narrow — do not point at broad roots like `~` or `~/Projects`.
Watch skill folders and refresh the skills snapshot when `SKILL.md` files
change. Covers nested files under grouped skill roots.
Debounce window for skill watcher events in milliseconds.
Install (skills.install)
Prefer Homebrew installers when `brew` is available.
Node package manager preference for skill installs. This only affects skill
installs - the OpenClaw CLI and Gateway runtime require Node because the
canonical state store uses `node:sqlite`. `openclaw setup --node-manager` and
`openclaw onboard --node-manager` accept `npm`, `pnpm`, or `bun`; set
`"yarn"` directly in config for Yarn-backed skill installs.
Allow trusted `operator.admin` Gateway clients to install private zip
archives staged through `skills.upload.*`. Normal ClawHub installs do not
need this setting.
Operator Install Policy (security.installPolicy)
Use security.installPolicy when operators need a trusted local command to
approve or block skill and plugin installs with host-specific policy. The
policy runs after OpenClaw has staged source material and before the install
or update continues. It applies to ClawHub skills, uploaded skills, Git/local
skills, skill dependency installers, and plugin install/update sources.
{
security: {
installPolicy: {
enabled: true,
// Omit targets to cover every supported target.
targets: ["skill", "plugin"],
exec: {
source: "exec",
command: "/usr/local/bin/openclaw-install-policy",
args: ["--json"],
timeoutMs: 10000,
noOutputTimeoutMs: 10000,
maxOutputBytes: 1048576,
passEnv: ["OPENCLAW_STATE_DIR", "PATH"],
env: { POLICY_MODE: "strict" },
trustedDirs: ["/usr/local/bin"],
},
},
},
}
The policy receives one JSON object on stdin with protocolVersion: 1,
openclawVersion, targetType, targetName, sourcePath, sourcePathKind,
optional structured source, structured origin, and request. It must
write one JSON object on stdout: { "protocolVersion": 1, "decision": "allow" }
or { "protocolVersion": 1, "decision": "block", "reason": "..." }. Non-zero
exit, timeout, malformed JSON, missing fields, or unsupported protocol
versions fail closed.
OpenClaw does not execute install policy during normal Gateway startup.
Installs and updates fail closed when policy is enabled but unavailable.
openclaw doctor performs static validation; openclaw doctor --deep
executes a synthetic install probe against the configured command.
Bulk updates apply policy per target: a blocked skill or plugin update fails that target without disabling the policy or skipping later targets in the batch.
Example stdin:
{
"protocolVersion": 1,
"openclawVersion": "2026.6.1",
"targetType": "skill",
"targetName": "weather",
"sourcePath": "/var/folders/.../openclaw-skill-clawhub/root",
"sourcePathKind": "directory",
"source": {
"kind": "clawhub",
"authority": "openclaw",
"mutable": false,
"network": true
},
"origin": {
"type": "clawhub",
"registry": "https://clawhub.openclaw.ai",
"slug": "weather",
"version": "1.0.0"
},
"request": {
"kind": "skill-install",
"mode": "install",
"requestedSpecifier": "clawhub:weather@1.0.0"
},
"skill": {
"installId": "clawhub"
}
}
Minimal policy command:
#!/usr/bin/env node
let input = "";
process.stdin.setEncoding("utf8");
process.stdin.on("data", (chunk) => {
input += chunk;
});
process.stdin.on("end", () => {
const request = JSON.parse(input);
if (request.targetType === "plugin" && request.source?.kind === "local-path") {
process.stdout.write(
JSON.stringify({
protocolVersion: 1,
decision: "block",
reason: "local plugin paths are not approved on this host",
}),
);
return;
}
process.stdout.write(JSON.stringify({ protocolVersion: 1, decision: "allow" }));
});
Bundled skill allowlist
Optional allowlist for **bundled** skills only. When set, only bundled skills in the list are eligible. Managed, agent-level, and workspace skills are unaffected.Per-skill entries (skills.entries)
Keys under entries match the skill name by default. If a skill defines
metadata.openclaw.skillKey, use that key instead. Quote hyphenated names
(JSON5 allows quoted keys).
Agent allowlists (agents)
Use agent config when you want the same machine/workspace skill roots but a different visible skill set per agent.
{
agents: {
defaults: {
skills: ["github", "weather"], // shared baseline
},
list: [
{ id: "writer" }, // inherits github, weather
{ id: "docs", skills: ["docs-search"] }, // replaces defaults entirely
{ id: "locked-down", skills: [] }, // no skills
],
},
}
Workshop (skills.workshop)
When `true`, OpenClaw can create pending proposals from durable corrections
and can review successful, substantial completed work after the system becomes
idle. This can add a background model run after eligible turns. User-prompted
skill creation and `/learn` continue to work when the setting is `false`.
See Self-learning for eligibility, privacy, cost, proposal-only permissions, and troubleshooting.
`pending` requires operator approval before agent-initiated apply, reject, or quarantine. `auto` allows those actions without approval. Allow Skill Workshop apply to write through workspace skill symlinks whose real target is already trusted by `skills.load.allowSymlinkTargets`. Keep this disabled unless generated proposal applies should mutate that shared skill root. Maximum pending and quarantined proposals retained per workspace (allowed range: 1-200). Maximum proposal body size in bytes (allowed range: 1024-200000). Proposal descriptions are hard-capped at 160 bytes separately, because they appear in discovery and listing output.See Skill Workshop for the proposal lifecycle, CLI commands, agent tool parameters, and Gateway methods this config controls.
Symlinked skill roots
By default, workspace, project-agent, extra-dir, and bundled skill roots are
containment boundaries. A symlinked skill folder under <workspace>/skills
that resolves outside the root is skipped with a log message.
To allow an intentional symlink layout, declare the trusted target:
{
skills: {
load: {
extraDirs: ["~/Projects/manager/skills"],
allowSymlinkTargets: ["~/Projects/manager/skills"],
},
},
}
With this config, <workspace>/skills/manager -> ~/Projects/manager/skills
is accepted after realpath resolution. extraDirs scans the sibling repo
directly; allowSymlinkTargets preserves the symlinked path for existing
layouts.
Skill Workshop apply does not write through those symlinks by default. To let Workshop apply mutate skills under already-trusted symlink targets, opt in separately:
{
skills: {
load: {
allowSymlinkTargets: ["~/Projects/manager/skills"],
},
workshop: {
allowSymlinkTargetWrites: true,
},
},
}
Managed ~/.openclaw/skills and personal ~/.agents/skills directories
already accept skill-directory symlinks unconditionally (per-skill
SKILL.md containment still applies) — allowSymlinkTargets is only needed
for workspace, extra-dir, and project-agent (<workspace>/.agents/skills)
roots.
Sandboxed skills and env vars
`skills.entries..env` and `apiKey` apply to **host** runs only. Inside a sandbox they have no effect — a skill that depends on `GEMINI_API_KEY` will fail with `apiKey not configured` unless the sandbox is given the variable separately.Pass secrets into a Docker sandbox with:
{
agents: {
defaults: {
sandbox: {
docker: {
env: { GEMINI_API_KEY: "your-key-here" },
},
},
},
},
}
Loading order reminder
workspace/skills (highest)
workspace/.agents/skills
~/.agents/skills
~/.openclaw/skills
bundled skills
skills.load.extraDirs (lowest)
Changes to skills and config take effect on the next new session when the watcher is enabled, or on the next agent turn when the watcher detects a change.