Skip to content

feat(skills): add agent skills#379

Open
mkmeral wants to merge 19 commits intostrands-agents:mainfrom
mkmeral:feature/agent-skills
Open

feat(skills): add agent skills#379
mkmeral wants to merge 19 commits intostrands-agents:mainfrom
mkmeral:feature/agent-skills

Conversation

@mkmeral
Copy link
Copy Markdown
Contributor

@mkmeral mkmeral commented Jan 23, 2026

Description

This PR adds a new skills tool that implements support for Agent Skills - modular packages of specialized instructions that help AI agents perform specific tasks effectively.

What are Agent Skills?

Agent Skills are folders containing SKILL.md files with structured instructions. They follow the AgentSkills.io specification and enable:

  • Progressive Disclosure: Load only skill metadata initially (~100 tokens), full instructions on demand
  • Modular Knowledge: Package domain-specific expertise as reusable skills
  • No Code Changes: Add/remove capabilities via markdown files

Tool Design

The tool follows the action-based pattern used by other tools (like mcp_client, memory, slack):

from strands import Agent
from strands_tools import skills

agent = Agent(tools=[skills])

# List available skills (auto-discovered from STRANDS_SKILLS_DIR)
agent.tool.skills(action="list")

# Use a skill - loads its instructions into conversation
agent.tool.skills(action="use", skill_name="code-reviewer")

# Load a resource file from a skill
agent.tool.skills(action="get_resource", skill_name="code-reviewer", resource_path="scripts/analyze.py")

Actions

Action Description
list Show all available skills with descriptions
use Load a skill's full instructions (returned as tool result)
get_resource Load a script/reference/asset file from a skill
list_resources List all files available in a skill

Helper Function

The tool also provides a get_skills_prompt() helper for users who want proactive skill awareness in their agent's system prompt:

from strands import Agent
from strands_tools.skills import skills, get_skills_prompt

# Optional: Add skills to system prompt for proactive awareness
base_prompt = "You are a helpful assistant."
agent = Agent(
    tools=[skills],
    system_prompt=base_prompt + get_skills_prompt()
)

Design Decisions

  1. Simple stateless design: Skills are loaded on demand and returned as tool results. No state tracking or system prompt modification - this matches how Anthropic's skills and AWS sample implementation work.

  2. No activate/deactivate: These concepts don't exist in the AgentSkills.io spec. Skills are simply loaded when needed via conversation history.

  3. Auto-discovery: Skills are automatically discovered from STRANDS_SKILLS_DIR (default: ./skills) on first use.

  4. SKILL.md format: Follows AgentSkills.io spec with YAML frontmatter for metadata and markdown body for instructions.

SKILL.md Frontmatter Fields

The tool parses YAML frontmatter from SKILL.md files. Supported fields:

Field Required Description Usage
name Yes Skill identifier (kebab-case, max 64 chars) Used as the key for skill_name parameter
description Yes Brief description of the skill Shown in list action output
license No License identifier (e.g., Apache-2.0) Stored in metadata, not currently displayed
allowed-tools No Comma-separated list of tools the skill expects Shown in list action output (informational only)

Example SKILL.md:

---
name: code-reviewer
description: Performs thorough code reviews with focus on security and best practices.
license: Apache-2.0
allowed-tools: file_read, shell
---

# Code Reviewer Instructions

Your detailed instructions here...

Note: The allowed-tools field is informational only - the tool doesn't enforce or validate tool availability. It's displayed to help users understand what tools a skill expects to use.

Skill Directory Structure

skills/
├── code-reviewer/
│   ├── SKILL.md              # Required: YAML frontmatter + instructions
│   ├── scripts/              # Optional: Executable code
│   │   └── analyze.py
│   └── references/           # Optional: Additional documentation
│       └── security.md
└── data-analyst/
    └── SKILL.md

Environment Variables

Variable Default Description
STRANDS_SKILLS_DIR ./skills Directory containing skill folders

Related Issues

Documentation PR

N/A - Documentation is included in README.md updates in this PR.

Type of Change

New Tool

Testing

  • 16 unit tests covering all actions, error handling, auto-discovery, and get_skills_prompt helper
  • All tests pass (python -m pytest tests/test_skills.py -v)
  • Linting passes (ruff check src/strands_tools/skills.py tests/test_skills.py)

Test coverage includes:

  • Skill listing (empty, non-existent, valid directories)
  • Skill usage (valid, non-existent, missing parameters)
  • Resource handling (list, get, path traversal protection)
  • Error handling (invalid actions, missing required params)
  • Auto-discovery from environment variable
  • get_skills_prompt() helper function (XML output, empty directory, env var usage, cache sharing)

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
  • 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.

Containerized Agent added 4 commits January 23, 2026 15:39
Implements Agent Skills support following the AgentSkills.io specification.

Features:
- Single tool with action-based interface (discover, list, activate, deactivate, get_resource, list_resources, status)
- Progressive disclosure: metadata-only discovery, full instructions on activation
- Resource loading for scripts, references, and assets
- Path traversal protection and file size limits
- Thread-safe registry for multi-connection scenarios

Actions:
- discover: Scan directory for available skills
- list: Show all discovered skills with activation status
- activate: Load skill instructions into context
- deactivate: Remove skill from active context
- get_resource: Load specific resource file from skill
- list_resources: List available resources in a skill
- status: Show current skills directory and activation status

Follows the pattern established by mcp_client tool with action parameter.

Refs: strands-agents/sdk-python#1181
- Add auto-discovery on first use (controlled by STRANDS_SKILLS_AUTO_DISCOVER env var)
- Rename parameter to STRANDS_SKILLS_DIR to follow strands env var naming convention
- Centralize auto-discovery logic in _get_or_create_registry
- Add tests for auto-discovery feature

Environment Variables:
- STRANDS_SKILLS_DIR: Directory containing skills (default: ./skills)
- STRANDS_SKILLS_AUTO_DISCOVER: Enable auto-discovery on first use (default: true)

Usage:
  # Just use the tool - skills are auto-discovered from STRANDS_SKILLS_DIR
  agent.tool.skills(action='list')
  agent.tool.skills(action='activate', skill_name='code-reviewer')

  # Or override the directory
  agent.tool.skills(action='list', STRANDS_SKILLS_DIR='/custom/path')
Simplify the skills tool to match how other implementations work:
- Remove 'activate' action, rename to 'use' (just loads instructions)
- Remove 'deactivate' action (not a real concept in skills)
- Remove 'discover' action (auto-discovery handles this)
- Remove 'status' action (no state to track)
- Remove registry tracking (unnecessary complexity)

The tool now simply:
1. Auto-discovers skills from STRANDS_SKILLS_DIR
2. Lists available skills with 'list' action
3. Returns skill instructions with 'use' action
4. Loads resources with 'get_resource' action

This matches the pattern used by:
- Anthropic's skills implementation
- AWS sample-strands-agents-agentskills

Actions:
- list: Show available skills
- use: Load skill instructions (returned as tool result)
- get_resource: Load a script/reference file
- list_resources: List files in a skill
- Add skills tool to tools overview table
- Add Agent Skills usage example section
- Add STRANDS_SKILLS_DIR environment variable documentation
- Fix ruff linting issues (unused f-string prefix)
Windows uses backslashes for paths, but the test and categorization logic
expects forward slashes. Using Path.as_posix() ensures consistent forward
slashes on all platforms.
- Added get_skills_prompt() function that generates XML-formatted skills list
- Uses same cache as skills tool (no duplicate discovery)
- Returns empty string if no skills found
- Follows AgentSkills.io recommended format for system prompts
- Improved list_resources with Path.parts for cross-platform support
- Updated tests for simplified API (list/use vs activate/deactivate)
Copy link
Copy Markdown

@vivekghatala vivekghatala left a comment

Choose a reason for hiding this comment

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

Thank you for working on this. I was thinking to pick this up as one of the consumer.

cagataycali
cagataycali previously approved these changes Feb 1, 2026
@ShotaOki
Copy link
Copy Markdown

ShotaOki commented Feb 2, 2026

I think this is an excellent pull request !
However, when I ran the steps below, I got an error. Will this be fixed?

  1. pip install strands-agents strands-agents-tools
  2. Replace strands-agent-tools to mkmeral:feature/agent-skills
  3. Write the code “from strands_tools.skills import skills”
  4. Run the code from step 2
yaml-no-named

The skills tool uses yaml.safe_load() to parse YAML frontmatter from
SKILL.md files (AgentSkills.io specification), but PyYAML was not
listed as a dependency, causing ModuleNotFoundError on import.
afarntrog
afarntrog previously approved these changes Feb 3, 2026
Copy link
Copy Markdown

@afarntrog afarntrog left a comment

Choose a reason for hiding this comment

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

This is great! Wondering if it should be vended as part of the core SDK instead of the tools repo.

@mkmeral mkmeral enabled auto-merge (squash) February 3, 2026 21:52
@mkmeral
Copy link
Copy Markdown
Contributor Author

mkmeral commented Feb 5, 2026

@afarntrog strands-agents/docs#528 what do you think?

@mkmeral mkmeral disabled auto-merge February 5, 2026 19:50
@tahitimoon
Copy link
Copy Markdown

This tool feels really great. I’ve been waiting for it for a long time and I’m wondering when it will be released.

@kevmyung
Copy link
Copy Markdown

Hi @kazuu-bp , you're right, I was talking about how this tool could work with Strands, also noticed the design doc mentions handling this via Plugin later

Rename 'import_dir' param to 'source' and extend the import action to
auto-detect the source type:

- Directory path: discovers all skills in subdirectories (existing behavior)
- File path: imports a single skill from a SKILL.md file
- HTTPS URL: fetches and imports a single skill from a remote SKILL.md

Key changes:
- Add 'source' param replacing 'import_dir' (unreleased API, no compat concern)
- Add 'virtual' and 'instructions' fields to SkillMetadata for file/URL imports
- Virtual skills work with list/use but return clear errors for get_resource/list_resources
- HTTPS-only URLs with 1MB size limit, 30s timeout, redirect protection
- Uses urllib.request (stdlib only, no new dependencies)

New helpers: _import_from_content, _import_from_file, _import_from_url,
_import_from_directory

Tests: 44 passing (23 new tests covering file import, URL import with mocks,
virtual skill behavior, and edge cases)
File-imported skills (source='/path/to/SKILL.md') now use the parent
directory as the skill path, so get_resource and list_resources work
exactly like directory-discovered skills. Only URL-imported skills are
marked virtual since they have no local directory.

Changes:
- _import_from_file: sets path=file_path.parent, virtual=False
- _import_from_file: does its own frontmatter parsing (no longer uses
  _import_from_content which is now URL-only)
- Virtual guard messages say 'URL' not 'file or URL'
- New test: test_import_from_file_resources_accessible
- TestVirtualSkillBehavior now uses URL mocks (the only virtual case)
@alhaiz313
Copy link
Copy Markdown

Is this effort still going forward?

@mkmeral
Copy link
Copy Markdown
Contributor Author

mkmeral commented Mar 6, 2026

hey folks, yes this will go forward. We are right now clarifying the difference in approaches between this PR and strands-agents/sdk-python#1755

The idea is to have two approaches where one is self-contained tool (this PR, depends on strands-agents/sdk-python#1822), so we can keep the tool spec up to date with loaded skills.

Then we have the more "complete" example with tools and hooks on strands-agents/sdk-python#1755

@cagataycali
Copy link
Copy Markdown
Contributor

What I would ask for next is, is there a future plan to add "plugins" tool to wrap plugin implementation?

Use case is to enable agents to load the skills in test-time, SDK feature is an amazing goal but secondary use which often missed first like building tools for directly agent would be beneficial to release first.

Internal SDK compositon can follow patterns are battle-tested by community in this way too ^^

note that, this is my humble opinion

@mkmeral
Copy link
Copy Markdown
Contributor Author

mkmeral commented Mar 10, 2026

hey folks, jfyi strands-agents/sdk-python#1755 where we develop skills as a plugin is merged. I will followup on this PR later this week for next week's release

mkmeral added 2 commits March 12, 2026 20:12
…at import

- Replace custom skill loading with Skill.from_directory/from_file/from_content
- Switch from per-agent cache to module-level _cache (matches other tools pattern)
- Auto-discover skills at import time when STRANDS_SKILLS_DIR is set
- Keep sync_skills() as public helper for programmatic pre-loading
- Remove tool_context from action handlers (only needed on main skills() fn)
- Remove experimental warnings
- Expand test coverage from 45 to 93 tests
Copy link
Copy Markdown
Contributor

@agent-of-mkmeral agent-of-mkmeral left a comment

Choose a reason for hiding this comment

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

Adversarial Testing Review

TL;DR: The skills tool survived comprehensive adversarial testing. 142 tests total (93 original + 49 adversarial), all passing. The code is solid — security boundaries hold, error handling is thorough, and it works correctly with real production skills.

🔬 Full Adversarial Testing Report

Adversarial Testing Result: PASS — no reproducible failures found

Scope: Path traversal, URL import SSRF, cache poisoning, YAML injection, XML injection, concurrent access, binary file handling, contract verification, real skills compatibility

Tests written: 49 adversarial tests
Tests passing: 49
Tests failing (findings): 0

Test Categories & Results

Category Tests Result Details
Path Traversal & Symlinks 6 ✅ PASS Symlink escape, null bytes, double-dots, absolute paths — all blocked
URL Import Security 6 ✅ PASS SSRF redirect to AWS metadata, data: URI, javascript:, non-HTTPS — all rejected
Cache Poisoning 3 ✅ PASS Import collision protection works, external mutation is by-design
YAML Attacks 6 ✅ PASS YAML bomb, !!python/object RCE attempt, empty frontmatter — all handled safely
XML Injection 3 ✅ PASS Script injection, CDATA injection, name injection — all properly escaped via xml.sax.saxutils.escape()
Concurrent Access 2 ✅ PASS Multi-threaded sync and import/use — no crashes
Binary & Encoding 4 ✅ PASS Binary files, BOM, case-insensitive SKILL.md, spaces in names
Cache Behavior 2 ✅ PASS Stale cache is by-design, import adds to existing cache correctly
Contract Verification 5 ✅ PASS Progressive disclosure, experimental warning, default dir, API surface
Real Skills 6 ✅ PASS All 6 production skills (adversarial-tester, doc-writer, implementer, refiner, release-notes, reviewer) load and work correctly
Additional Edge Cases 6 ✅ PASS None/empty params, file-as-dir, deep nesting, idempotency

Security Assessment

Path traversal: _is_safe_path() correctly uses resolve() + relative_to() to prevent symlink escapes. Tested with symlinks to /etc/passwd, multi-level ../ traversal, null bytes, and absolute paths.

URL import: HTTPS-only enforcement works. Redirect detection catches SSRF attempts (e.g., redirect to http://169.254.169.254/latest/meta-data/). Non-HTTPS schemes (http://, ftp://, file://, data:, javascript:) all rejected.

YAML safety: Uses yaml.safe_load() via the SDK's Skill.from_content()!!python/object tags are not executed.

XML injection: xml.sax.saxutils.escape() properly handles <, >, &, and " in skill names and descriptions.

Notable Observations (Not Bugs)

  1. Cache staleness by design: _sync_skills() only discovers skills on the first call when cache is empty. Subsequent calls with different skills_dir values will NOT discover new skills. This is documented behavior — users must call sync_skills() explicitly to refresh. The import action correctly bypasses this by adding directly to the existing cache.

  2. PR description inconsistency: The PR body references get_skills_prompt() helper function, but the actual implementation uses sync_skills(). The code is correct; the PR description is outdated.

  3. URL credentials in logs: URLs with embedded credentials (e.g., https://user:pass@host/SKILL.md) are passed through to logger.info(). While functional, this could leak credentials in logs. Low severity since it requires intentional credential embedding.

  4. Thread safety: The global _cache dict is a plain dict (not threading.Lock-protected). In practice this is safe for CPython due to the GIL, and concurrent access tests pass. However, for PyPy or future GIL-free Python, a threading.Lock would be needed.

🧪 Real Skills Compatibility Test

Tested against 6 production skills from a real repository:

Skill List Use Resources Spec Update
task-adversarial-tester
task-doc-writer
task-implementer
task-refiner
task-release-notes
task-reviewer

All skills are correctly discovered, their full instructions load properly, resource listing works, and the tool spec is updated with the complete skills catalog XML.

📝 Adversarial Test File

The full adversarial test suite (49 tests, ~967 lines) is available as tests/test_adversarial_skills.py. Run with:

pip install -e ".[dev]"
pip install opentelemetry-propagator-aws-xray  # needed for SDK import
python -m pytest tests/test_adversarial_skills.py -v

🤖 AI agent response. Strands Agents. Feedback welcome!

@agent-of-mkmeral
Copy link
Copy Markdown
Contributor

TL;DR: Adversarial testing + real skills validation. 43/45 adversarial tests pass. 2 failed due to test design (not code bugs). Code is solid — no security vulnerabilities found. README has 2 incorrect parameter names. pyproject.toml must be fixed before merge.

🔴 Adversarial Testing Report

Adversarial Testing Result: PASS — 0 code bugs found

Scope: Security (path traversal, symlinks, injection, SSRF), edge cases (unicode, empty inputs, large payloads, YAML bombs), cache behavior (stale cache, concurrency, poisoning), contract verification (API shape, return formats, documented actions), and real production skills validation.

Tests written: 45
Tests passing: 43
Tests failing (test design, not code bugs): 2

Test Categories

Category Tests Result
Real Skills (6 production skills) 6 ✅ All pass
Security (path traversal, symlinks, XSS, injection) 6 ✅ All pass
_is_safe_path direct tests 4 ✅ All pass
Cache edge cases (stale, concurrent, shared) 3 ✅ All pass
Import adversarial (YAML bomb, empty, XSS, long name, URIs) 9 ✅ 7 pass, 2 test-design failures
Unicode & special chars 3 ✅ All pass
Contract verification 4 ✅ All pass
sync_skills adversarial 4 ✅ All pass
_load_resource direct 4 ✅ All pass
Case sensitivity 1 ✅ Pass
Import interactions (dupes, URL+file) 2 ✅ All pass
Tool context handling 1 ✅ Pass

Real Skills Validation

Tested against 6 production skills from strands-coder-private:

  • task-adversarial-tester — discovered, loaded, instructions > 100 chars
  • task-doc-writer — discovered, loaded, instructions > 100 chars
  • task-implementer — discovered, loaded, instructions > 100 chars
  • task-refiner — discovered, loaded, instructions > 100 chars
  • task-release-notes — discovered, loaded, instructions > 100 chars
  • task-reviewer — discovered, loaded, instructions > 100 chars

All real skills: proper frontmatter ✅, list_resources works ✅, tool_spec updated with all 6 ✅, import by file path works ✅

Security Assessment

Vector Result
../../../etc/passwd path traversal ✅ Blocked
URL-encoded traversal (..%2F..%2F) ✅ Blocked (file not found)
Absolute path (/etc/passwd) ✅ Blocked
Symlink escape to /etc/hostname ✅ Blocked by _is_safe_path
Null byte injection (helper.py\x00.txt) ✅ Safe (Python 3 handles correctly)
XSS in skill name (<script>alert()) ✅ Rejected by SDK validation
Long name (200 chars) ✅ Rejected by SDK validation
YAML bomb (billion laughs) ✅ Safe (pyyaml safe_load)
Non-HTTPS URLs (http://, ftp://, file://) ✅ Rejected
data: and javascript: URIs ✅ Rejected
HTTPS→HTTP redirect ✅ Detected and blocked

Notes

The 2 failing tests (test_import_frontmatter_only_no_body, test_import_massive_instructions) failed because the test put SKILL.md files inside the skills_dir, causing auto-discovery to find them before the import action ran. This is expected cache behavior, not a code bug.


🤖 AI agent response. Strands Agents. Feedback welcome!

@agent-of-mkmeral
Copy link
Copy Markdown
Contributor

🐛 Bug found: import action silently fails for single skill directories

Tested against all 17 skills from https://github.com/anthropics/skills163 tests total (93 original + 70 new), all passing, but one test documents a real bug:

The issue

_import_from_directory() doesn't handle the case where the source directory is a skill (contains SKILL.md) rather than a parent of skill directories.

# This works (parent directory):
skills(action="import", source="/path/to/anthropics/skills")
# → Imported 17 skill(s) ✅

# This silently "succeeds" with 0 imports (single skill dir):
skills(action="import", source="/path/to/anthropics/skills/pdf")
# → Imported 0 skill(s) 🐛 (status: "success")

# Workaround — point at the file:
skills(action="import", source="/path/to/anthropics/skills/pdf/SKILL.md")
# → Imported skill 'pdf' ✅

Root cause

_import_from_directory always delegates to Skill.from_directory() which scans child subdirectories for SKILL.md. It doesn't check if the directory itself contains SKILL.md.

Contrast with _resolve_skills() which correctly handles both cases:

# _resolve_skills checks has_skill_md first:
has_skill_md = (path / "SKILL.md").is_file()
if has_skill_md:
    skill = Skill.from_file(path)  # ← handles single skill dir
else:
    for skill in Skill.from_directory(path):  # ← handles parent dir

Suggested fix

Add the same check in _import_from_directory:

def _import_from_directory(source, cache):
    import_path = Path(source).expanduser().resolve()
    # ...
    has_skill_md = (import_path / "SKILL.md").is_file() or (import_path / "skill.md").is_file()
    if has_skill_md:
        return _import_from_file(str(import_path / "SKILL.md"), cache)
    # ... existing Skill.from_directory logic

Everything else looks great

All 17 anthropics skills (algorithmic-art, brand-guidelines, canvas-design, claude-api, doc-coauthoring, docx, frontend-design, internal-comms, mcp-builder, pdf, pptx, skill-creator, slack-gif-creator, theme-factory, web-artifacts-builder, webapp-testing, xlsx) work correctly with discovery, listing, use, resource loading, and XML generation. Security (path traversal, null bytes, URL scheme rejection) all solid.


🤖 AI agent response. Strands Agents. Feedback welcome!

Copy link
Copy Markdown
Contributor

@agent-of-mkmeral agent-of-mkmeral left a comment

Choose a reason for hiding this comment

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

Assessment: Comment — 2 items must be fixed before merge, rest looks solid

Code quality is high. Security is well-handled. Tested against 6 real production skills — all work correctly. The main blockers are the git dependency in pyproject.toml (not releasable) and incorrect README examples.

Review Summary
  • Blocking: pyproject.toml — Uses git+https:// dependency for strands-agents. Must be pinned to a released version before merge.
  • Blocking: README.md — Two code examples use wrong parameter names (import_dirsource, STRANDS_SKILLS_DIRskills_dir).
  • Minor: PyYAML dependency — Already a transitive dep of strands-agents SDK. Adding it directly is fine for explicitness but worth noting.
  • Design observation: _import_from_file accepts any filename — Not just SKILL.md. A file named FOO.txt with valid frontmatter will import successfully. This is fine for flexibility but worth documenting.
  • Design observation: Stale cache_sync_skills only populates cache when empty. Skills added to disk after first sync aren't discovered until cache is cleared. This is documented behavior but users may find it surprising.

The code survived thorough adversarial testing (45 tests across security, edge cases, concurrency, contract verification, and real production skills). Nice work on the implementation.


🤖 AI agent response. Strands Agents. Feedback welcome!

Comment thread pyproject.toml
Comment thread README.md
Comment thread README.md
- pyproject.toml: Replace git+https:// dependency with strands-agents>=1.32.0,<2.0.0
  (required for PyPI release, Skill class available since 1.32.0)
- README.md: Fix wrong parameter name import_dir → source (line 822)
- README.md: Fix wrong parameter name STRANDS_SKILLS_DIR → skills_dir (line 828)
- skills.py: Fix _import_from_directory to handle single skill directories
  (directories containing SKILL.md directly, not just parent directories)
  Matches the pattern already used in _resolve_skills()

Resolves all 3 unresolved review threads + 1 reported bug.
@mkmeral
Copy link
Copy Markdown
Contributor Author

mkmeral commented Mar 25, 2026

/strands review

Comment thread src/strands_tools/skills.py Outdated
@mkmeral mkmeral changed the title feat(skills): Add agent skills feat(skills): add agent skills Apr 6, 2026
- Remove experimental warning from tool spec description
- Remove experimental warning from skills() function docstring
- Add note about SDK's native AgentSkills plugin to module docstring
- Add usage example for SDK plugin alongside tool usage
- Add link to SDK plugin documentation

The Skills feature is now stable in the SDK (strands.vended_plugins.skills.AgentSkills),
so the experimental warning is no longer needed.
@agent-of-mkmeral
Copy link
Copy Markdown
Contributor

Pushed commit f428621 to address the unresolved review thread:

Changes

  1. Removed experimental warning from _update_tool_spec() base_description — no more ⚠️ EXPERIMENTAL prefix in the tool spec
  2. Removed experimental warning from skills() function docstring — clean docstring starting with the actual description
  3. Added SDK plugin info to the top module docstring:
    • Note about strands.vended_plugins.skills.AgentSkills plugin as the native alternative
    • Usage example for the SDK plugin alongside the tool usage
    • Link to SDK plugin documentation

The Skills feature is stable in the SDK, so the experimental flag is no longer needed.


🤖 AI agent response. Strands Agents. Feedback welcome!

Copy link
Copy Markdown
Contributor Author

@mkmeral mkmeral left a comment

Choose a reason for hiding this comment

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

@agent-of-mkmeral we still have warning in readme. also check the unit tests, are there any we can combine?

Comment thread README.md Outdated
- Remove experimental warnings from README.md (table entry + section blockquote)
- Replace with note about SDK plugin availability
- Combine 9 pairs of related tests into consolidated tests:
  - test_use_skill + includes_metadata + includes_resources → single test
  - test_list_empty_directory + nonexistent → parametrized
  - test_basic_response + no_instructions → combined
  - test_cache_persists + cache_cleared → test_cache_lifecycle
  - test_populates_cache + updates_tool_spec → single test
  - test_import_ftp_rejected + file_scheme → parametrized
  - test_url_urlerror + oserror → test_network_errors
  - test_list_resources_missing + nonexistent → test_error_cases
  - test_get_resource_missing + nonexistent → test_error_cases

All 85 tests pass. No behavior changes.
@agent-of-mkmeral
Copy link
Copy Markdown
Contributor

Pushed commit 5706ab2 addressing both items from @mkmeral's review:

1. ✅ Removed experimental warnings from README.md

  • Table entry (line 136): ⚠️ Experimental: ... → Clean description with link to AgentSkills.io and SDK plugin
  • Section blockquote (line 793): ⚠️ Experimental: ... → Note about SDK plugin availability

grep -i experimental README.md now returns nothing.

2. ✅ Consolidated unit tests

Combined 9 sets of closely related tests that were testing the same action multiple times:

Before After What changed
test_use_skill + test_use_skill_includes_metadata + test_use_skill_includes_resources Single test_use_skill Same result, all assertions in one test
test_list_empty_directory + test_list_nonexistent_directory @pytest.mark.parametrize Both return "No skills found"
test_basic_response + test_no_instructions Single test_basic_response_and_empty_instructions Both test _format_skill_response
test_cache_persists_across_calls + test_cache_cleared_allows_rediscovery Single test_cache_lifecycle Sequential cache operations
test_populates_cache + test_updates_tool_spec Single test_populates_cache_and_updates_tool_spec Both test sync_skills()
test_import_ftp_rejected + test_import_file_scheme_rejected @pytest.mark.parametrize Both assert scheme rejection
test_import_from_url_urlerror + test_import_from_url_oserror Single test_import_from_url_network_errors Both test network errors
test_list_resources_missing_skill_name + nonexistent_skill Single test_list_resources_error_cases Both test error paths
test_get_resource_missing_skill_name + nonexistent_skill Single test_get_resource_error_cases Both test error paths

Result: 85 tests all passing ✅ (net reduction of ~38 lines, no behavior changes)


🤖 AI agent response. Strands Agents. Feedback welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants