Skip to content

feat(skills): add agent skills as a plugin#1755

Merged
mkmeral merged 33 commits intostrands-agents:mainfrom
mkmeral:feat/skills-plugin
Mar 10, 2026
Merged

feat(skills): add agent skills as a plugin#1755
mkmeral merged 33 commits intostrands-agents:mainfrom
mkmeral:feat/skills-plugin

Conversation

@mkmeral
Copy link
Contributor

@mkmeral mkmeral commented Feb 23, 2026

Motivation

See design strands-agents/docs#528

This PR adds SkillsPlugin, a first-class plugin that brings Agent Skills support to Strands. It follows the spec's progressive disclosure model: lightweight metadata (name + description) is injected into the system prompt at startup, and full instructions are loaded on-demand when the agent activates a skill via a tool call. This keeps context usage low while giving agents access to rich, task-specific instructions when needed.

Public API Changes

New SkillsPlugin class and Skill dataclass, both exported from the top-level strands package:

from strands import Agent
from strands.plugins.skills import SkillsPlugin, Skill

# Load skills from filesystem (individual dirs or parent dirs)
plugin = SkillsPlugin(skills=["./skills/pdf-processing", "./skills/"])

# Or provide Skill instances directly
skill = Skill(name="my-skill", description="A custom skill", instructions="Do the thing")
plugin = SkillsPlugin(skills=[skill])

agent = Agent(plugins=[plugin])

The plugin registers a skills tool that the agent calls to activate a skill by name. When activated, the tool returns the full instructions along with metadata (allowed tools, compatibility, location) and a listing of available resource files (scripts/, references/, assets/) for filesystem-based skills.

Skills can be managed at runtime via a symmetric property and a resolution method:

# Direct replacement with Skill instances
plugin.available_skills = [skill_a, skill_b]

# Load and append from filesystem paths (resolves paths, Skill instances, or parent dirs)
plugin.load_skills(["./new-skills/", another_skill])

Skill metadata is injected into the system prompt as XML before each invocation, with special characters escaped:

<available_skills>
<skill>
<name>pdf-processing</name>
<description>Extract text and tables from PDF files.</description>
<location>/path/to/pdf-processing/SKILL.md</location>
</skill>
</available_skills>

The active skill selection is persisted to agent.state for session recovery.

Use Cases

  • Skill libraries: Point the plugin at a directory of skills and let the agent pick the right one based on the user's request
  • Dynamic specialization: Swap agent behavior at runtime without rebuilding prompts or agents
  • Portable skills: Share skill directories across teams and agents using the Agent Skills standard format

Resolves: #1181

Documentation PR

TBD

Type of Change

New feature

Testing

  • Manually tested using jupyter notebook and set of skills from anthropic/skills repository

  • 100 unit tests covering the plugin, tool, XML generation/escaping, response formatting, resource listing, session persistence, and skill resolution

  • 2 integration tests against a real Bedrock model: model-driven skill activation with codeword verification, and direct tool invocation with state persistence checks

  • All existing tests (2145 total) continue to pass

  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Unshure and others added 16 commits February 20, 2026 11:12
BREAKING CHANGE: Plugin is now an abstract base class instead of a Protocol. Plugins must explicitly inherit from Plugin and implement the abstract name property and init_plugin method.

- Convert Plugin from @runtime_checkable Protocol to ABC
- Make name an abstract property
- Make init_plugin an abstract method
- Update all tests to use inheritance
- Maintain support for both sync and async init_plugin
- All tests pass (1985 passed)

🤖 Assisted by the code-assist SOP
Implement the SkillsPlugin that adds AgentSkills.io skill support to the
Strands Agents SDK. The plugin enables progressive disclosure of skill
instructions: metadata is injected into the system prompt upfront, and
full instructions are loaded on demand via a tool.

Key components:
- Skill dataclass with from_path classmethod for loading from SKILL.md
- Loader module for discovering, parsing, and validating skills
- SkillsPlugin extending the Plugin ABC with:
  - skills tool (activate/deactivate actions)
  - BeforeInvocationEvent hook for system prompt injection
  - AfterInvocationEvent hook for prompt restoration
  - Single active skill management
  - Dynamic skill management via property setter
  - Session persistence via agent.state

Files added:
- src/strands/plugins/skills/__init__.py
- src/strands/plugins/skills/skill.py
- src/strands/plugins/skills/loader.py
- src/strands/plugins/skills/skills_plugin.py
- tests/strands/plugins/skills/ (90 tests)

Files modified:
- src/strands/plugins/__init__.py (added SkillsPlugin export)
- src/strands/__init__.py (added Skill to top-level exports)
- Create @hook decorator for declarative hook registration in plugins
- Convert Plugin from Protocol to base class (breaking change)
- Add auto-discovery of @hook and @tool decorated methods in Plugin.__init__()
- Add auto-registration of hooks and tools in Plugin.init_plugin()
- Support union types for multiple event types (e.g., BeforeModelCallEvent | AfterModelCallEvent)
- Export hook from strands.plugins and strands namespaces
- Update existing tests to use inheritance-based approach
- Add comprehensive test coverage for new functionality

BREAKING CHANGE: Plugin is now a base class instead of a Protocol. Existing
plugins must inherit from Plugin instead of just implementing the protocol.
- Simplify skills tool to single activate action (remove deactivate/action param)
- Capture original system prompt once instead of save/restore pattern
- Remove AfterInvocationEvent hook (no longer needed)
- Replace optional pyyaml with required dependency
- Remove _parse_yaml_simple fallback parser
- Export Skill and SkillsPlugin from strands top-level
Replace manual hook registration and standalone tool factory with
declarative @hook and @tool decorators on SkillsPlugin methods.

- Remove _make_skills_tool() standalone function
- Convert skills() to @tool decorated instance method
- Convert _on_before_invocation() to @hook decorated method
- Remove register_hooks() (old HookProvider pattern)
- Rename skills property to available_skills (avoids collision)
- Delegate hook/tool registration to super().init_plugin()
- Update tests to match new API surface
@mkmeral mkmeral changed the title feat(skills): Add agent skills as a plugin feat(skills): add agent skills as a plugin Feb 23, 2026
This reverts commit 29f9bf4.
@codecov
Copy link

codecov bot commented Feb 23, 2026

Codecov Report

❌ Patch coverage is 92.35669% with 24 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/strands/plugins/skills/agent_skills.py 87.34% 12 Missing and 9 partials ⚠️
src/strands/plugins/skills/skill.py 97.90% 2 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@github-actions
Copy link

github-actions bot commented Mar 6, 2026

Follow-up Review: Latest Commit ✅

Good progress! The new changes address key feedback:

Changes in latest commit
  • ✅ Changed name to class attribute (name = "agent_skills") - per Unshure's feedback
  • ✅ Added skill activation tracking via _track_activated_skill()
  • ✅ Added public get_activated_skills(agent) method for activation history
  • ✅ Skills tracked in activation order (most recent last, no duplicates)

The activation tracking is a nice addition that partially addresses sanjolia's multi-skill concern - while only one skill is "active" at a time for instruction loading, the agent state now tracks the full history of activated skills.

Remaining items:

  • Documentation PR still shows "TBD" - needs to be updated before merge per repository guidelines
  • Consider if needs-api-review label should be added for this new public API

The implementation looks solid and ready for final approval once documentation is addressed.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assessment: Request Changes

The implementation is excellent and all technical feedback has been addressed. However, the PR description still shows "Documentation PR: TBD" which needs to be resolved before merge.

Review Summary

Technical Implementation: ✅ Ready

  • Clean plugin architecture following repository patterns
  • Comprehensive test coverage (unit + integration)
  • Lenient validation per AgentSkills.io spec
  • Proper XML escaping and error handling
  • Skill activation tracking for session persistence

Blocking Item:

  • Documentation PR: The PR description states "TBD" under Documentation PR. Per repository guidelines, either:
    1. Link to a documentation PR at https://github.com/strands-agents/docs/pull/...
    2. Provide justification why documentation updates are not required

Once the documentation requirement is addressed, this PR is ready to merge. Great work on iterating through the feedback! 🎉

@mehtarac
Copy link
Member

mehtarac commented Mar 6, 2026

don't block on docs /strands review

Copy link
Member

@Unshure Unshure left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mkmeral
Copy link
Contributor Author

mkmeral commented Mar 10, 2026

/strands review

@github-actions github-actions bot added size/xl and removed size/xl labels Mar 10, 2026
Unshure
Unshure previously approved these changes Mar 10, 2026
Co-authored-by: Nick Clegg <nac542@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add support for skills

6 participants