Implementation:Openclaw Openclaw LoadSkillEntries
loadSkillEntries and shouldIncludeSkill
loadSkillEntries discovers and loads all skill entries from multiple directories in precedence order, parsing frontmatter and resolving metadata. shouldIncludeSkill evaluates eligibility criteria for each skill entry based on the runtime environment, configuration, and skill metadata.
Principle:Openclaw_Openclaw_Skill_Loading
Source Location
| Function | File | Lines |
|---|---|---|
loadSkillEntries |
src/agents/skills/workspace.ts |
99-189 |
shouldIncludeSkill |
src/agents/skills/config.ts |
114-191 |
Repository: github.com/openclaw/openclaw
loadSkillEntries
Signature
function loadSkillEntries(
workspaceDir: string,
opts?: {
config?: OpenClawConfig;
managedSkillsDir?: string;
bundledSkillsDir?: string;
},
): SkillEntry[]
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
workspaceDir |
string |
(required) | The workspace root directory. Skills are loaded from <workspaceDir>/skills/.
|
opts.config |
OpenClawConfig? |
undefined |
The full OpenClaw config, used to resolve skills.load.extraDirs and plugin skill dirs.
|
opts.managedSkillsDir |
string? |
~/.openclaw/skills |
Override for the managed skills directory. |
opts.bundledSkillsDir |
string? |
auto-resolved | Override for the bundled skills directory. |
Return Value
Returns SkillEntry[], where each entry contains:
export type SkillEntry = {
skill: Skill;
frontmatter: ParsedSkillFrontmatter;
metadata?: OpenClawSkillMetadata;
invocation?: SkillInvocationPolicy;
};
Behavior
The function loads skills from four source categories and merges them by name:
- Resolve directories. Computes the paths for managed, workspace, bundled, extra, and plugin skill directories.
- Load from each source. Calls
loadSkillsFromDir()(from@mariozechner/pi-coding-agent) for each directory, normalizing the result into aSkill[]array. - Merge by precedence. Uses a
Map<string, Skill>to merge skills. The insertion order determines precedence (later entries override earlier ones):- Extra skills + plugin skills (lowest)
- Bundled skills
- Managed skills
- Workspace skills (highest)
- Parse frontmatter. For each merged skill, reads the
SKILL.mdfile, parses YAML frontmatter viaparseFrontmatter(), and resolves OpenClaw-specific metadata viaresolveOpenClawMetadata(). - Resolve invocation policy. Determines
userInvocableanddisableModelInvocationfrom frontmatter keys.
Precedence Diagram
extra/plugin dirs --> bundled --> managed --> workspace (lowest) (highest) When the same skill name appears in multiple sources, the highest-precedence source wins.
shouldIncludeSkill
Signature
export function shouldIncludeSkill(params: {
entry: SkillEntry;
config?: OpenClawConfig;
eligibility?: SkillEligibilityContext;
}): boolean
Parameters
| Parameter | Type | Description |
|---|---|---|
entry |
SkillEntry |
The skill entry to evaluate. |
config |
OpenClawConfig? |
The full OpenClaw configuration for resolving per-skill entries and config paths. |
eligibility |
SkillEligibilityContext? |
Optional remote environment context for cross-platform eligibility. |
Return Value
Returns boolean: true if the skill should be included, false if it should be filtered out.
Evaluation Cascade
The function applies checks in this specific order:
| Step | Check | Result if Failed |
|---|---|---|
| 1 | skillConfig.enabled === false |
Exclude (explicit disable) |
| 2 | Bundled skill not in allowBundled list |
Exclude |
| 3 | OS list non-empty and runtime platform not in list (also checks remote platforms) | Exclude |
| 4 | metadata.always === true |
Include (skip remaining checks) |
| 5 | requires.bins: all listed binaries must be in PATH or available remotely |
Exclude if any missing |
| 6 | requires.anyBins: at least one listed binary must be available |
Exclude if none found |
| 7 | requires.env: all listed env vars must be set in process env, skill config env, or via apiKey+primaryEnv |
Exclude if any missing |
| 8 | requires.config: all listed config paths must be truthy |
Exclude if any falsy |
| 9 | All checks passed | Include |
Environment Variable Resolution
For requires.env, the function checks three sources for each variable:
process.env[envName]-- the actual environment variable.skillConfig.env[envName]-- the per-skill config override.skillConfig.apiKeywhenmetadata.primaryEnv === envName-- the skill's API key satisfies its primary env requirement.
Supporting Functions
resolveSkillConfig
export function resolveSkillConfig(
config: OpenClawConfig | undefined,
skillKey: string,
): SkillConfig | undefined
Looks up the per-skill configuration from config.skills.entries[skillKey]. Returns undefined if the config, entries map, or specific entry is missing.
resolveConfigPath / isConfigPathTruthy
export function resolveConfigPath(config: OpenClawConfig | undefined, pathStr: string): unknown
export function isConfigPathTruthy(config: OpenClawConfig | undefined, pathStr: string): boolean
Walks the config object using dot-separated path segments (e.g., "browser.enabled"). isConfigPathTruthy() also consults a default values map for known config paths.
hasBinary
export function hasBinary(bin: string): boolean
Scans PATH directories to check if a binary exists and is executable.
Public Export
loadSkillEntries is not directly exported but is exposed through the public wrapper:
export function loadWorkspaceSkillEntries(
workspaceDir: string,
opts?: {
config?: OpenClawConfig;
managedSkillsDir?: string;
bundledSkillsDir?: string;
},
): SkillEntry[] {
return loadSkillEntries(workspaceDir, opts);
}