Skip to content

Skills Plane

The Skills plane (s) provides agents with curated instruction sets, prompt templates, and workflow definitions. Unlike the knowledge plane (which stores documents for search), skills are structured recipes that agents load directly into their context when they need domain-specific guidance.

Agent writes: ?s "deployment" #devops ^3
Gateway: Routes to SkillRegistry.search()
Registry: Scores skills by name, tag, description, ID relevance
Response: { ok: true, results: [{ id, name, description, tags, score }] }

Skills are stored as SKILL.md files with YAML frontmatter in a configurable directory. The SkillStore scans this directory, parses each file, and caches results with mtime-based invalidation — if a file hasn’t changed, it’s served from cache.

Each skill is a directory containing a SKILL.md file:

skills/
├── deployment/
│ └── SKILL.md # YAML frontmatter + markdown body
├── code-review/
│ └── SKILL.md
└── testing-strategy/
└── SKILL.md
---
description: "Step-by-step deployment workflow for production"
domain: development
version: 1.0.0
tags: [devops, deploy, production]
---
# Deployment Workflow
1. Run pre-deployment checks...
2. Build production bundle...
3. Deploy to staging...
FieldSourceRequired
descriptionYAML frontmatterRecommended
domainYAML frontmatter (default: development)Optional
versionYAML frontmatter (default: 1.0.0)Optional
tagsYAML frontmatter (comma-separated or array)Optional
nameFirst # heading in body (fallback: directory name)Auto-derived
tokensEstimated from content length (~4 chars/token)Auto-computed

The skills plane has 4 source files organized as a flat module at src/skills/:

FileClassPurpose
types.tsSkillDefinition, SkillSearchResult, SkillError, SkillLoadOutcome types
store.tsSkillStoreFilesystem scanner, YAML parser, mtime cache
registry.tsSkillRegistrySearch engine with relevance scoring and filtering
loader.tsSkillLoaderContext injection loader with typed error codes
SkillStore SkillRegistry SkillLoader
│ │ │
├─ loadAll() │ │
│ scan directory │ │
│ parse SKILL.md │ │
│ cache by mtime │ │
│ ├─ search(query) │
│ │ filter by tags │
│ │ score matches │
│ │ sort + limit │
│ │ ├─ load(id)
│ │ │ returns full content
│ │ │ or SKILL_NOT_FOUND

The SkillRegistry scores matches on multiple dimensions:

Match TypeScoreExample
Exact name match1.0Query "deployment" matches skill named "deployment"
Partial name match0.9Query "deploy" matches "deployment workflow"
Exact tag match0.8Query "devops" matches tag devops
Exact ID match0.7Query "code-review" matches skill ID
Partial tag match0.7Query "dev" partially matches tag devops
Partial ID match0.6Query "code" partially matches ID code-review
Description match0.5Query appears in the skill’s description

Scores use max() — a skill matching both name and tag gets the highest single score. Results are sorted by score descending, then alphabetically for stability.

Searches support optional filters:

// Search with tag and domain filters
registry.search("deploy", { tags: ["devops"], domain: "development" }, 5);
  • Tag filter — all specified tags must be present (logical AND)
  • Domain filter — exact match on domain field
  • Limit — maximum results (default: 10)
OperationExampleDescription
Search?s "deployment" #devops ^3Find skills matching query
Store+s "new-workflow" content="..."Register a new skill
Load!s deploymentLoad full skill content into context

The skills plane uses typed error codes (R2):

CodeMeaning
SKILL_NOT_FOUNDNo skill with the requested ID exists
STORE_FAILEDFilesystem or parsing error in the store
PARSE_FAILEDSKILL.md file has invalid frontmatter or structure
// Load returns a typed outcome
const result = await loader.load("nonexistent");
// { ok: false, code: "SKILL_NOT_FOUND" }