Skills¶
Modules: promptframe.skill, promptframe.skill_registry
Skills are rich markdown instruction documents — best practices, decision frameworks, step-by-step guides — that get injected verbatim into prompts as context. Unlike short parameterised YAML prompts, skills are human-authored prose meant to guide LLM behavior across many tasks.
File Conventions¶
Skills are .md files with optional YAML frontmatter. Two layouts are supported and can coexist:
Folder-based (preferred)¶
Flat-file¶
Frontmatter schema¶
---
name: frontend-design # required; derived from filename if omitted
description: When to use this skill.
tags:
- frontend
- react
version: "1.0"
---
## Overview
Skill content here...
Only name is required. Everything else is optional.
Skill¶
A loaded skill — frontmatter metadata plus the markdown body.
Attributes¶
| Attribute | Type | Description |
|---|---|---|
name |
str |
Skill name (from frontmatter or derived from filename) |
description |
str \| None |
What this skill does / when to use it |
tags |
List[str] |
Optional tags (empty list if not set) |
version |
str \| None |
Version string |
content |
str |
Raw markdown body |
source_path |
str \| None |
Absolute path to the source file |
extra |
Dict[str, Any] |
Any additional frontmatter keys not listed above |
Properties¶
sections -> Dict[str, str]¶
Cached dictionary of top-level #, ##, and ### headings mapped to their content. Lets you extract individual sections of a large skill file.
skill.sections
# {"Overview": "...", "Guidelines": "...", "Examples": "..."}
skill.sections["Guidelines"]
# "- Use semantic HTML\n- Prefer CSS variables..."
Methods¶
get_section(heading: str) -> str | None¶
Return the content of a specific section, or None if not found.
render(sections=None, *, include_name=True) -> str¶
Render the skill to a string for injection into a prompt.
Arguments:
| Argument | Type | Default | Description |
|---|---|---|---|
sections |
List[str] \| None |
None |
If provided, only include these section headings (in the given order) |
include_name |
bool |
True |
Prepend ## {name} heading |
Returns: Rendered skill content as a plain string.
# Full content
skill.render()
# Only specific sections
skill.render(sections=["Guidelines", "Examples"])
# Without the name heading
skill.render(include_name=False)
__str__() -> str¶
Returns the raw content markdown body.
load_skill_from_path(path: str) -> Skill¶
Module: promptframe.skill
Parse a single .md skill file and return a Skill instance.
from promptframe.skill import load_skill_from_path
skill = load_skill_from_path("skills/frontend-design/SKILL.md")
Raises:
- FileNotFoundError — path does not exist
- ValueError — file cannot be parsed
SkillRegistry¶
Discover and load skills from a directory tree. Supports both folder-based and flat-file layouts simultaneously. Skills are cached in memory after the first load.
Constructor¶
| Argument | Type | Description |
|---|---|---|
base |
str |
Root directory to scan for skill files (stored as absolute path) |
Methods¶
get(key: str, *, force_reload: bool = False) -> Skill¶
Load a skill by its directory name or file stem (e.g. "frontend-design"). Returns from cache on subsequent calls unless force_reload=True.
Raises: KeyError if no skill with that key exists, with a list of available keys in the message.
load_all(*, force_reload: bool = False) -> Dict[str, Skill]¶
Load every discovered skill into the cache and return them all.
list() -> List[Dict[str, Any]]¶
Return a lightweight summary of all skills without loading full content. Reads only frontmatter for uncached skills — fast even with many files.
Returns: List of dicts with keys key, name, description, tags.
registry.list()
# [
# {"key": "frontend-design", "name": "Frontend Design", "description": "...", "tags": ["frontend"]},
# {"key": "data-analysis", "name": "Data Analysis", "description": "...", "tags": ["data"]},
# ]
Using Skills in Prompts¶
Skills are injected via SkillComponent:
from promptframe import SkillRegistry, StructuredPromptBuilder
from promptframe.components import SimplePromptComponent, SkillComponent
registry = SkillRegistry("skills/")
skill = registry.get("frontend-design")
prompt = (
StructuredPromptBuilder()
>> SimplePromptComponent("You are a frontend expert.")
>> SkillComponent(skill, sections=["Guidelines"])
>> SimplePromptComponent("Task: {task}")
).build({"task": "Build a login page"})
Skills can also be loaded via PromptRegistry: