Skip to content

feat(skills): support loading skills from URLs#2091

Merged
mkmeral merged 9 commits intostrands-agents:mainfrom
dgallitelli:feat/skills-github-url-loading
Apr 15, 2026
Merged

feat(skills): support loading skills from URLs#2091
mkmeral merged 9 commits intostrands-agents:mainfrom
dgallitelli:feat/skills-github-url-loading

Conversation

@dgallitelli
Copy link
Copy Markdown
Contributor

@dgallitelli dgallitelli commented Apr 8, 2026

Summary

Closes #2090

  • Add support for remote Git repository URLs as skill sources in AgentSkills and Skill.from_url()
  • Support https://, git@, and ssh:// URLs with optional @ref suffix for branch/tag pinning (e.g., https://github.com/org/skill@v1.0.0)
  • Repositories are shallow-cloned (--depth 1) and cached locally at ~/.cache/strands/skills/ (configurable via cache_dir parameter)

Usage

from strands import Agent, AgentSkills

# Load skill directly from a GitHub repo
plugin = AgentSkills(skills=["https://github.com/dgallitelli/aws-data-agent-skill"])

# With version pinning
plugin = AgentSkills(skills=["https://github.com/org/skill-repo@v1.0.0"])

# Mixed with local skills
plugin = AgentSkills(skills=[
    "https://github.com/org/skill-repo",
    "./local-skills/my-skill",
])

# Or use the Skill classmethod directly
from strands import Skill
skills = Skill.from_url("https://github.com/org/skill-repo@main")

Changes

File Change
_url_loader.py (new) URL parsing, git clone with shallow depth, hash-based caching
skill.py Added Skill.from_url() classmethod
agent_skills.py Updated _resolve_skills() to detect URL strings; added cache_dir parameter
test_url_loader.py (new) 22 tests for URL detection, parsing, cache keys, and clone behavior
test_skill.py 6 tests for Skill.from_url()
test_agent_skills.py 4 tests for URL resolution in AgentSkills

Design decisions

  • Git clone via subprocess: No new dependencies — uses git which is universally available. Handles auth naturally (SSH keys, credential helpers, tokens).
  • Shallow clone: --depth 1 minimizes bandwidth and disk for skill repos.
  • Hash-based caching: sha256(url + ref)[:16] as cache directory name. Repeated loads are instant.
  • Graceful degradation: Failed URL clones log a warning and skip (consistent with how nonexistent filesystem paths are handled).
  • No new dependencies: Only stdlib modules (subprocess, hashlib, shutil).

Test plan

  • All 171 skill tests pass (32 new tests added)
  • Ruff lint and format pass
  • Pre-existing mypy error is unchanged (unrelated @hook decorator typing)
  • Manual test with a real public skill repo (e.g., aws-data-agent-skill)
  • Manual test with a nested real public skill repo (e.g., obra/superpowers/brainstorming)

Davide Gallitelli and others added 2 commits April 9, 2026 00:06
Add support for remote Git repository URLs as skill sources in
AgentSkills, enabling teams to share and reference skills directly
from GitHub without manual cloning.

Closes strands-agents#2090

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Parse GitHub web URLs like /tree/<ref>/path to extract the clone URL,
branch, and subdirectory path. This enables loading skills from
subdirectories within mono-repos.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dgallitelli dgallitelli force-pushed the feat/skills-github-url-loading branch from 01a4fc3 to 83966f6 Compare April 9, 2026 00:06
@github-actions github-actions bot added size/l and removed size/l labels Apr 9, 2026
@mkmeral
Copy link
Copy Markdown
Contributor

mkmeral commented Apr 9, 2026

/strands review

@mkmeral mkmeral self-assigned this Apr 9, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Comment thread src/strands/vended_plugins/skills/_url_loader.py Outdated
Comment thread src/strands/vended_plugins/skills/_url_loader.py Outdated
Comment thread src/strands/vended_plugins/skills/_url_loader.py Outdated
Comment thread src/strands/vended_plugins/skills/_url_loader.py Outdated
Comment thread src/strands/vended_plugins/skills/skill.py Outdated
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

Issue: This PR introduces new public API surface (Skill.from_url() classmethod, cache_dir parameter on AgentSkills.__init__). Per the API Bar Raising guidelines, this should have the needs-api-review label since it adds a new public classmethod that customers will use directly.

Key questions an API reviewer should evaluate:

  1. Should from_url return list[Skill] (inconsistent with from_file which returns a single Skill)? The list return type is due to the possibility of multi-skill repos, but this creates an asymmetric API. Consider whether a separate from_url_directory would be cleaner, or if from_url should raise when multiple skills are found unless the user explicitly opts in.
  2. Is cache_dir the right parameter name and placement? It's only relevant when URL sources are used but appears as a top-level AgentSkills.__init__ parameter alongside unrelated parameters like state_key and max_resource_files.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

Issue: The _url_loader module is not mentioned in the directory structure in AGENTS.md. Per the AGENTS.md instructions: "After making changes that affect the directory structure (adding new directories, moving files, or adding significant new files), you MUST update this directory structure section."

Suggestion: Add _url_loader.py under the vended_plugins/skills/ section in the AGENTS.md directory tree.

Comment thread src/strands/vended_plugins/skills/skill.py Outdated
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

Review Summary

Assessment: Request Changes

This is a well-structured feature that fills a real user need. The design decisions (subprocess git, shallow clone, hash-based caching) are sound and well-documented in the PR description. The test coverage is thorough with 32 new tests.

Review Categories
  • Security: http:// URL support exposes users to MITM risks; Path.home() at import time can fail in containers. The subprocess usage is properly handled with shell=False.
  • Reliability: Race condition in cache directory creation when concurrent processes clone the same URL. No cache invalidation mechanism for unpinned refs means stale content with no obvious path to refresh.
  • API Design: This PR adds public API surface (Skill.from_url(), cache_dir on AgentSkills) and should have the needs-api-review label. The from_url returning list[Skill] is asymmetric with from_file returning Skill — worth discussing with an API reviewer.
  • Documentation: No documentation PR linked — this adds new public API that users need to know about. AGENTS.md directory tree and set_available_skills docstring need updating.

The core implementation is solid — addressing the security and reliability items above would make this ready to merge.

- Security: remove http:// support (MITM risk), only allow https/ssh/git@
- Reliability: atomic clone via tempdir + rename to prevent race conditions
- Reliability: evaluate cache dir lazily (not at import time) for containers
- Usability: respect XDG_CACHE_HOME for cache directory
- Usability: add force_refresh parameter to re-clone stale unpinned refs
- Docs: add ValueError to Skill.from_url() Raises section
- Docs: add _url_loader.py to AGENTS.md directory tree
- Tests: add coverage for XDG_CACHE_HOME, force_refresh, race condition,
  http:// rejection (184 tests total)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions bot removed the size/l label Apr 10, 2026
Comment thread src/strands/vended_plugins/skills/agent_skills.py Outdated
Comment thread src/strands/vended_plugins/skills/skill.py Outdated
Comment thread src/strands/vended_plugins/skills/_url_loader.py Outdated
Per maintainer feedback:
- Remove _url_loader.py — inline fetch logic directly into Skill.from_url()
- Move imports to top of module (not inside methods)
- Use source.startswith("https://") directly in _resolve_skills()
- Remove AGENTS.md entry for deleted file

The entire URL loading feature is now ~15 lines in skill.py with no
separate module.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix stale "auto-resolved to raw content" in AgentSkills docstring
- Add test for non-SKILL.md content (HTML page → ValueError)
- Add from_url() example to Skill class docstring

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Review Summary

Assessment: Comment

The implementation is now clean and minimal — Skill.from_url() is ~15 lines of straightforward urllib fetch → from_content, with no external dependencies, no caching, no GitHub-specific resolution. All prior review feedback has been addressed except one minor docstring gap.

Remaining Items
  • Docstring: set_available_skills still doesn't mention URL support (carried over from prior round)
  • Test coverage: Codecov flags the duplicate-URL-skill warning branch as uncovered — a small test would close the gap

The doc PR (strands-agents/docs#756) is linked. Nice work iterating on the design to reach this simple, focused solution. 👍

Comment thread src/strands/vended_plugins/skills/agent_skills.py
… test

- Mention HTTPS URL support in set_available_skills docstring
- Add test for duplicate skill names from URL sources (Codecov gap)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

Review Summary

Assessment: Approve

All 14 prior review threads have been addressed. The implementation has been iteratively refined from ~900 lines (git clone + cache) → ~450 lines (HTTPS + GitHub resolution) → 242 lines (pure HTTPS fetch, no new files). I've replied to each stale thread to mark it resolved.

The final implementation is clean and focused: Skill.from_url() validates https://, fetches via urllib, and delegates to from_content(). All docstrings are consistent, test coverage includes happy path, error cases, strict mode, invalid content, and the duplicate-name branch. Documentation PR is linked (strands-agents/docs#756).

@mkmeral mkmeral changed the title feat(skills): support loading skills from GitHub/Git URLs feat(skills): support loading skills from URLs Apr 15, 2026
@mkmeral mkmeral enabled auto-merge (squash) April 15, 2026 14:51
@mkmeral mkmeral merged commit 09902bd into strands-agents:main Apr 15, 2026
20 of 21 checks passed
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.

AgentSkills: support loading skills from GitHub URLs

2 participants