Agent Skills
The WorkflowFramework.Extensions.Agents.Skills package implements the Agent Skills standard — a convention for packaging reusable agent instructions as SKILL.md files with YAML frontmatter.
Installation
dotnet add package WorkflowFramework.Extensions.Agents.Skills
Key Types
| Type | Purpose |
|---|---|
SkillDefinition |
Parsed skill with metadata and body |
SkillLoader |
Parses SKILL.md files (YAML frontmatter + markdown body) |
SkillDiscovery |
Scans standard and custom paths for skills |
SkillToolProvider |
Exposes skills as invocable tools |
SkillContextSource |
Injects skill instructions into agent prompts |
SKILL.md Format
A skill file consists of YAML frontmatter followed by markdown instructions:
---
name: code-review
description: Reviews code for bugs, style issues, and best practices
license: MIT
compatibility: Claude, GPT-4, Qwen
allowed-tools:
- read_file
- list_directory
metadata:
author: team
version: 1.0
---
# Code Review Skill
When asked to review code:
1. Read the file with `read_file`
2. Check for common bugs and anti-patterns
3. Verify naming conventions and code style
4. Suggest improvements with specific line references
5. Rate severity: critical / warning / info
SkillLoader
Parses SKILL.md content or files:
// Parse from file
SkillDefinition skill = SkillLoader.ParseFile("./skills/code-review/SKILL.md");
// Parse from string
SkillDefinition skill = SkillLoader.Parse(markdownContent);
Console.WriteLine(skill.Name); // "code-review"
Console.WriteLine(skill.Description); // "Reviews code for bugs..."
Console.WriteLine(skill.License); // "MIT"
Console.WriteLine(skill.AllowedTools); // ["read_file", "list_directory"]
Console.WriteLine(skill.Body); // The markdown body after frontmatter
Console.WriteLine(skill.SourcePath); // File path (when parsed from file)
SkillDiscovery
Scans directories for SKILL.md files. Standard paths follow the Agent Skills convention:
var discovery = new SkillDiscovery(
scanStandardPaths: true,
additionalPaths: new[] { "./project-skills", "/shared/skills" }
);
// Discover all skills
IReadOnlyList<SkillDefinition> skills = discovery.DiscoverAll();
// Or scan a specific directory
IReadOnlyList<SkillDefinition> projectSkills = discovery.ScanDirectory("./project-skills");
Standard paths scanned (when scanStandardPaths: true):
~/.agents/skills/~/.claude/skills/./.agents/skills/./.claude/skills/
Each path is searched recursively for SKILL.md files.
SkillToolProvider
Exposes discovered skills as tools in the ToolRegistry. When invoked, a skill tool returns its body (the markdown instructions):
var skills = discovery.DiscoverAll();
var toolProvider = new SkillToolProvider(skills);
registry.Register(toolProvider);
// Skills appear as tools
var tools = await toolProvider.ListToolsAsync();
// [{ Name: "code-review", Description: "Reviews code for bugs..." }]
// Invoking returns the skill body
var result = await toolProvider.InvokeToolAsync("code-review", "{}");
// result.Content = "# Code Review Skill\n\nWhen asked to review code:..."
SkillContextSource
Injects skill instructions directly into agent prompts as context:
var contextSource = new SkillContextSource(skills);
var workflow = new WorkflowBuilder()
.AgentLoop(provider, registry, options =>
{
options.ContextSources.Add(contextSource);
})
.Build();
Each skill becomes a ContextDocument with:
Name= skill nameContent= skill body (markdown)Source= file pathMetadata["description"]= skill description
DI Registration
services.AddAgentSkills(options =>
{
options.ScanStandardPaths = true;
options.AutoDiscover = true;
options.AdditionalPaths.Add("./custom-skills");
});
services.AddAgentTooling(); // Auto-discovers SkillToolProvider
AddAgentSkills() registers:
SkillOptionsandSkillDiscoveryas singletons- Auto-discovered
IReadOnlyList<SkillDefinition> SkillToolProviderasIToolProviderSkillContextSourceasIContextSource
Complete Example
// Directory structure:
// ./skills/
// code-review/SKILL.md
// summarize/SKILL.md
// translate/SKILL.md
var discovery = new SkillDiscovery(
scanStandardPaths: false,
additionalPaths: new[] { "./skills" }
);
var skills = discovery.DiscoverAll();
Console.WriteLine($"Found {skills.Count} skills");
var registry = new ToolRegistry();
registry.Register(new SkillToolProvider(skills));
registry.Register(new FileSystemToolProvider());
var workflow = new WorkflowBuilder()
.AgentLoop(provider, registry, options =>
{
options.SystemPrompt = "You have access to specialized skills. " +
"Use them to guide your work on complex tasks.";
options.ContextSources.Add(new SkillContextSource(skills));
options.MaxIterations = 20;
})
.Build();
await workflow.RunAsync(context);