Files
cleveragents-core/docs/reference/agent_skills.md
T
aditya cb82fc51df feat(skill): add agent skills loader
Implemented AgentSkillSpec loader that parses SKILL.md frontmatter and
progressive disclosure sections (discover/activate/deactivate) into
structured SkillStep objects with stable 1-based ordering.

Mapped Agent Skills to AgentSkillToolDescriptor with namespaced naming
(namespace/short_name), source="agent_skill", read-only defaults, and
AgentSkillResourceSlot bindings for scripts/, references/, and assets/
directories. All resource slots are unconditionally read_only.

Added explicit validation for missing frontmatter fields (name,
description) and invalid namespace format with actionable error messages.

Added docs/reference/agent_skills.md covering folder layout, SKILL.md
parsing rules, progressive disclosure model, and tool mapping.

Added Behave scenarios covering valid/invalid SKILL.md parsing,
namespaced naming, step ordering, missing frontmatter errors, progressive
disclosure lifecycle, tool mapping, and resource binding slots.

Added Robot Framework integration tests using the deploy-to-staging
example skill folder (robot/agent_skills_loader.robot).

Added ASV benchmarks for parsing throughput, folder load, progressive
disclosure lifecycle, and resource listing
(benchmarks/agent_skills_loader_bench.py).

ISSUES CLOSED: #160
2026-02-26 09:10:35 +00:00

8.7 KiB
Raw Blame History

Agent Skills Standard Loader

The Agent Skills loader (cleveragents.skills.agent_skills_loader) implements the AgentSkills.io standard for packaging instruction-driven, multi-step workflows as SKILL.md files with optional resource sub-directories.

Agent Skills differ from MCP tools: instead of a single function call, they load procedural instructions that an LLM agent follows—potentially invoking multiple tools in sequence.


Folder Layout

my-skill/
├── SKILL.md            ← required — frontmatter + instructions
├── scripts/            ← optional — Python/shell scripts the agent may run
│   └── deploy.py
├── references/         ← optional — supplementary Markdown documents
│   └── runbook.md
└── assets/             ← optional — any binary or static resources
    └── config.json

Only SKILL.md is required. The three resource sub-directories are discovered automatically when present and made available on demand during Tier 3 disclosure.


SKILL.md Format

SKILL.md files follow Markdown with a YAML frontmatter block:

---
name: local/deploy-to-staging
description: Deploy the current branch to the staging environment.
steps:                     # optional — structured steps with stable ordering
  - Verify all tests pass
  - Push the branch to the remote
  - Run the CI pipeline
  - Execute scripts/deploy.py to deploy
  - Check the health endpoint
version: 1.0.0             # optional
compatibility:             # optional
  min_agent_version: "3.0.0"
metadata:                  # optional — arbitrary key/value pairs
  author: team
  environment: staging
allowed-tools:             # optional — restrict which tools the skill may call
  - builtin/shell
  - builtin/git-status
---

# Deployment Details

Additional prose context for each step, loaded on activation.

Required Frontmatter Fields

Field Type Description
name string Namespaced name: namespace/short-name (e.g. local/deploy-staging)
description string Short human-readable description of the skill

Optional Frontmatter Fields

Field Type Default Description
steps list[string] [] Ordered step instructions parsed into SkillStep objects with stable 1-based indexing
version string "0.0.0" Semantic version of the skill
compatibility mapping {} Compatibility constraints (e.g. min_agent_version)
metadata mapping {} Arbitrary key/value pairs (author, tags, etc.)
allowed-tools list[string] [] Tools the skill is permitted to invoke

Structured Steps

When the steps key is present, each list entry becomes a SkillStep with a stable 1-based index and non-empty content string:

spec = AgentSkillSpec.from_file(Path("my-skill/SKILL.md"))
for step in spec.steps:
    print(f"{step.index}. {step.content}")
# 1. Verify all tests pass
# 2. Push the branch to the remote
# ...

Steps are stored in insertion order and never reordered — step.index is always equal to the step's position in the original list.


Namespaced Naming

Skill names follow the same namespace/short-name convention as tools and actors (see Tool Model):

local/deploy-to-staging       ← user-defined, default namespace
devops/code-review-pipeline   ← custom namespace
team/onboarding-workflow      ← team namespace

Rules:

  • Both namespace and short-name must start with an alphanumeric character.
  • Allowed characters: letters, digits, hyphens (-), underscores (_).
  • No spaces or special characters.

Three-Tier Progressive Disclosure

The loader implements the three-tier model defined in the specification (docs/specification.md § AgentSkillAdapter):

Tier Method What loads Token cost
1 — Metadata discover() name + description only ~50100 tokens per skill
2 — Instructions activate() Full SKILL.md Markdown body Recommended < 5000 tokens
3 — Resources list_resources() Paths from scripts/, references/, assets/ Variable, on demand

This means an actor can have dozens of Agent Skills available but only pay the token cost for their metadata at startup. Full instructions load only when the LLM determines a task matches the skill.


Tool Mapping

Agent Skills are registered in the Tool Registry with source="agent_skill". The AgentSkillToolDescriptor carries:

Field Value Notes
source "agent_skill" Fixed
name From frontmatter name e.g. local/deploy-to-staging
description From frontmatter description Used in system prompt
read_only True Default — skill itself does not write
writes False Default
agent_skill_path Absolute folder path Runtime uses this to locate SKILL.md
allowed_tools From frontmatter allowed-tools Optional restrict list
body Empty at discover; full body after activate Progressive disclosure
resource_slots List of AgentSkillResourceSlot One slot per discovered resource directory

Resource Binding Slots

Each discovered sub-directory (scripts/, references/, assets/) becomes a read-only resource binding slot in the tool descriptor:

td = loader.to_tool_descriptor()
for slot in td.resource_slots:
    print(slot.name)          # "scripts", "references", or "assets"
    print(slot.resource_type) # "agent_skill_scripts", etc.
    print(slot.access)        # "read_only"
    print(slot.path)          # absolute path on disk

Slots are only created for directories that exist — if a skill has no references/ folder, no references slot is emitted. All slots are unconditionally access="read_only".

Read-Only Default Rationale

The skill descriptor is read-only by default because the skill's instructions do not themselves perform writes — the LLM agent decides which (potentially write-capable) tools to invoke during execution. Individual tools in allowed-tools may write; the skill descriptor's own capability metadata does not.


Python API

from pathlib import Path
from cleveragents.skills.agent_skills_loader import AgentSkillLoader, AgentSkillSpec

# Parse a SKILL.md string directly
spec = AgentSkillSpec.from_string("""
---
name: local/my-skill
description: Does something useful.
---
Step 1: Do this.
""")

# Load a full folder
loader = AgentSkillLoader.from_folder(Path("./skills/my-skill"))

# Tier 1 — discover (metadata only)
descriptor = loader.discover()
print(descriptor.name)        # "local/my-skill"
print(descriptor.body)        # ""  (empty)

# Tier 2 — activate (load instructions)
activated = loader.activate()
print(activated.body)         # "Step 1: Do this."

# Tier 3 — list resources on demand
resources = loader.list_resources()
for path in resources:
    print(path.name)

# Deactivate to free token budget
loader.deactivate()
print(loader.active_body)     # None

# Convert to Tool Registry descriptor
tool_descriptor = loader.to_tool_descriptor()
print(tool_descriptor.source)         # "agent_skill"
print(tool_descriptor.read_only)      # True
print(tool_descriptor.agent_skill_path)  # "/abs/path/to/my-skill"

Path Safety

All file paths returned by list_resources(), script_paths, reference_paths, and asset_paths are absolute paths that have been verified to reside within the skill folder. The loader uses Path.resolve() + rglob() to prevent path traversal outside the skill boundary.


Error Handling

Condition Exception Message pattern
SKILL.md not found in folder ValueError mentions "SKILL.md"
Folder path does not exist FileNotFoundError mentions "not found"
Missing --- frontmatter ValueError mentions "frontmatter"
Missing required name field ValueError mentions "name"
Missing required description field ValueError mentions "description"
Invalid namespace/name format ValueError mentions "namespace"
Malformed YAML in frontmatter ValueError mentions "YAML"

  • Skills ProtocolSkillDefinition, SkillMetadata
  • Skill CLIagents skill commands
  • Tool ModelTool, ToolSource.AGENT_SKILL
  • MCP Adapter — MCP tool source (counterpart)
  • docs/specification.md § AgentSkillAdapter — authoritative spec
  • ADR-028 — Agent Skills Standard adoption decision