Skip to content

feat(skills): support .agents/skills directory#1914

Open
enyst wants to merge 2 commits intomainfrom
support-agents-skills-dir
Open

feat(skills): support .agents/skills directory#1914
enyst wants to merge 2 commits intomainfrom
support-agents-skills-dir

Conversation

@enyst
Copy link
Collaborator

@enyst enyst commented Feb 5, 2026

Summary

  • add .agents/skills to project skill discovery with highest priority
  • update loader documentation/comment to mention .agents/skills

Testing

  • uv run pre-commit run --files openhands-sdk/openhands/sdk/context/skills/skill.py

Context


Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22 Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:305f559-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-305f559-python \
  ghcr.io/openhands/agent-server:305f559-python

All tags pushed for this build

ghcr.io/openhands/agent-server:305f559-golang-amd64
ghcr.io/openhands/agent-server:305f559-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:305f559-golang-arm64
ghcr.io/openhands/agent-server:305f559-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:305f559-java-amd64
ghcr.io/openhands/agent-server:305f559-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:305f559-java-arm64
ghcr.io/openhands/agent-server:305f559-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:305f559-python-amd64
ghcr.io/openhands/agent-server:305f559-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-amd64
ghcr.io/openhands/agent-server:305f559-python-arm64
ghcr.io/openhands/agent-server:305f559-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-arm64
ghcr.io/openhands/agent-server:305f559-golang
ghcr.io/openhands/agent-server:305f559-java
ghcr.io/openhands/agent-server:305f559-python

About Multi-Architecture Support

  • Each variant tag (e.g., 305f559-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 305f559-python-amd64) are also available if needed

Add .agents/skills to project skill discovery with priority.

Co-authored-by: openhands <[email protected]>
Copy link
Collaborator

@all-hands-bot all-hands-bot left a comment

Choose a reason for hiding this comment

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

Review Summary

The change is well-structured and maintains backward compatibility. However, there are a few areas that could be improved:

  1. Testing coverage: No tests added to verify the new directory priority logic
  2. Documentation scope: May need updates beyond the docstring
  3. Implementation clarity: The precedence mechanism could be more explicit

Overall: ✅ Good change, but needs test coverage before merging.

Document .agents/skills priority and add precedence tests.

Co-authored-by: openhands <[email protected]>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 5, 2026

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-sdk/openhands/sdk/context/skills
   skill.py3472193%90–91, 246–247, 433–439, 442, 531–534, 751–752, 864, 871–872
TOTAL16915496570% 

@enyst enyst added the review-this This label triggers a PR review by OpenHands label Feb 5, 2026
Copy link
Collaborator

@all-hands-bot all-hands-bot left a comment

Choose a reason for hiding this comment

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

Review Summary

This PR cleanly implements support for .agents/skills directory with proper priority ordering. The implementation is solid and well-tested. I have a few suggestions for enhancement:

🟡 Suggestions

  1. Add debug logging - Consider logging which directory skills are loaded from to help with troubleshooting
  2. Migration nudge - Add an info log when both .agents/skills and .openhands/skills exist to encourage migration to the new standard
  3. Test coverage - Add a test for loading different (non-duplicate) skills from multiple directories

✅ Positive Feedback

  • Excellent documentation with clear precedence examples
  • Clean, minimal implementation
  • Comprehensive duplicate-handling tests
  • Proper priority ordering in the code

Overall, this is a well-executed feature addition. The suggestions above are optional enhancements that could improve user experience.

# Load project-specific skills from .agents/skills, .openhands/skills,
# and legacy microagents (priority order; first wins for duplicates)
project_skills_dirs = [
work_dir / ".agents" / "skills",
Copy link
Collaborator

Choose a reason for hiding this comment

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

🟡 Suggestion: Consider adding debug logging to help users understand which directory skills are being loaded from. This would make troubleshooting easier.

Example: Add a comment or logging in the loop that loads from these directories.

project_skills_dirs = [
work_dir / ".agents" / "skills",
work_dir / ".openhands" / "skills",
work_dir / ".openhands" / "microagents", # Legacy support
Copy link
Collaborator

Choose a reason for hiding this comment

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

🟡 Suggestion: Consider adding an info/warning log when both .agents/skills and .openhands/skills directories exist, to encourage users to migrate to the new standard location. This would help with the transition mentioned in the X post.

Example:

agents_skills_dir = work_dir / ".agents" / "skills"
openhands_skills_dir = work_dir / ".openhands" / "skills"
if agents_skills_dir.exists() and openhands_skills_dir.exists():
    logger.info("Both .agents/skills and .openhands/skills found. Consider migrating to .agents/skills as the standard location.")

assert len(skills) == 1
assert skills[0].name == "duplicate"
assert skills[0].content == "From .agents/skills."

Copy link
Collaborator

Choose a reason for hiding this comment

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

🟡 Suggestion: Consider adding a test that verifies loading different (non-duplicate) skills from multiple directories works correctly. The current tests cover duplicates well, but not the merge behavior when skills have different names.

Example test case:

def test_load_project_skills_merges_from_multiple_dirs(tmp_path):
    """Test skills from different directories are merged correctly."""
    agents_dir = tmp_path / ".agents" / "skills"
    skills_dir = tmp_path / ".openhands" / "skills"
    agents_dir.mkdir(parents=True)
    skills_dir.mkdir(parents=True)
    
    (agents_dir / "skill1.md").write_text("---\nname: skill1\n---\nContent 1.")
    (skills_dir / "skill2.md").write_text("---\nname: skill2\n---\nContent 2.")
    
    skills = load_project_skills(tmp_path)
    assert len(skills) == 2
    skill_names = {s.name for s in skills}
    assert skill_names == {"skill1", "skill2"}

Use .agents/skills for new skills. .openhands/skills is the legacy
OpenHands location, and .openhands/microagents is deprecated.

Example: If "my-skill" exists in both .agents/skills/ and
Copy link
Collaborator

Choose a reason for hiding this comment

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

🟢 Nit: Excellent documentation! The example clearly illustrates the precedence behavior. This will help users understand the priority system.

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

Labels

review-this This label triggers a PR review by OpenHands

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants