skills data types: sources, outputs, and errors
The skills module’s types split into four groups: the output payloads
(SkillInfo, SkillContent, SkillOutput), the source types
(SkillSource, EmbeddedSkill), the schema that carries all policy
(SkillSchema, SkillAction), and the error enum. The output and error
types implement Serialize; the input types additionally derive
Deserialize + JsonSchema and double as the tool argument schemas.
Output types
SkillInfo — lightweight metadata
pub struct SkillInfo {
pub name: String,
pub description: String,
}
Name + description only — the “card” for a skill. list and match_skills
return these; the body is deliberately not included (listing 50 skills must
not dump 50 bodies into context).
SkillContent — the full skill
pub struct SkillContent {
pub info: SkillInfo,
pub body: String, // SKILL.md body with frontmatter stripped
}
Returned by read: the metadata plus the instructions body.
SkillOutput — the discriminated result
pub enum SkillOutput {
List { skills: Vec<SkillInfo> },
Read { skill: SkillContent },
ReadAsset { content: String },
Match { matched: Vec<SkillInfo> },
}
One variant per action, so the caller can match on which action it requested.
Source types
SkillSource
pub enum SkillSource {
Directory { path: String },
Embedded { skill: EmbeddedSkill },
}
Where to look for skills. Directory points at a parent directory whose
subdirectories contain SKILL.md files; Embedded provides one skill
directly in memory. The ordering of the sources vector matters — the first
source wins on name collision.
EmbeddedSkill
pub struct EmbeddedSkill {
pub name: String,
pub description: String,
/// Full SKILL.md content, including frontmatter and body.
pub content: String,
pub globs: Vec<String>,
pub always_apply: bool,
}
The in-memory equivalent of a skill directory. content is parsed like a
real SKILL.md; fields present in the embedded content’s frontmatter
override the struct fields (see frontmatter). Embedded
skills have no directory, so read_asset rejects them.
The schema and action
SkillAction
pub enum SkillAction { List, Read, ReadAsset, Match }
The four operations, as data. Each variant maps to one action.
SkillSchema — the full policy
pub struct SkillSchema {
pub action: SkillAction,
pub sources: Vec<SkillSource>, // ordered; first wins on name collision
pub skill_name: Option<String>, // target for Read / ReadAsset
pub asset_path: Option<String>, // relative sub-path for ReadAsset
pub match_paths: Vec<String>, // active file paths for Match
pub recursive: bool,
pub ignore: Vec<String>,
pub include: Vec<String>, // non-empty = allowlist
}
The module has zero hardcoded policy: every path, name, and filter is
carried in the schema. The Skills wrapper
builds one of these per call from its configuration — callers normally never
construct one by hand, but the free form exists for direct engine use.
Input types
SkillsReadInput { name }, SkillsReadAssetInput { name, asset_path }, and
SkillsMatchInput { match_paths } are thin wrappers matching the tool call
arguments — one field per argument, deserialized straight from JSON.
SkillError
pub enum SkillError {
NotFound(String), // skill, asset, or asset file missing
PathTraversal(String), // asset path escapes the skill directory
InvalidAction(String), // missing argument, or unsupported combo
InvalidSource(String), // directory source unusable
}
The single error type. The variants tell the caller which kind of problem
occurred — a missing skill (NotFound) is a normal “nothing here” case,
while PathTraversal is a security rejection. The Display messages are
meant to be actionable ("skill not found: foo").