Skip to content

fix: support custom user skills dirs via env var and API parameter#2713

Closed
xingyaoww wants to merge 1 commit intomainfrom
openhands/fix-user-skills-loading-2417
Closed

fix: support custom user skills dirs via env var and API parameter#2713
xingyaoww wants to merge 1 commit intomainfrom
openhands/fix-user-skills-loading-2417

Conversation

@xingyaoww
Copy link
Copy Markdown
Collaborator

@xingyaoww xingyaoww commented Apr 5, 2026

Summary

Fixes #2417

When the agent-server runs inside a container, the host's ~/.openhands/skills/ directory is not visible, making user skills inaccessible. This PR adds two complementary mechanisms for specifying additional user skill directories:

1. OPENHANDS_USER_SKILLS_DIRS environment variable

A path-separated list of additional directories to search for user skills. The container can be started with this env var pointing to mounted paths:

# Mount user skills and set the env var
docker run -v ~/.openhands/skills:/mounted/skills \
  -e OPENHANDS_USER_SKILLS_DIRS=/mounted/skills \
  agent-server

2. user_skills_dirs API parameter

The /skills endpoint now accepts an optional user_skills_dirs list, allowing the app-server to tell the agent-server where user skills have been mounted:

{
  "load_user": true,
  "user_skills_dirs": ["/mounted/user-skills"]
}

Priority order

Both mechanisms are additive — they prepend to the default search paths with proper precedence:

  1. extra_dirs (API parameter) — highest priority
  2. OPENHANDS_USER_SKILLS_DIRS env var
  3. Default paths (~/.agents/skills/, ~/.openhands/skills/, ~/.openhands/microagents/) — lowest priority

Changes

  • openhands-sdk/openhands/sdk/context/skills/skill.py: Added get_user_skills_dirs(), USER_SKILLS_DIRS_ENV constant, and extra_dirs parameter to load_user_skills() and user_skills_dirs to load_available_skills()
  • openhands-agent-server/openhands/agent_server/skills_service.py: Thread user_skills_dirs through load_all_skills()
  • openhands-agent-server/openhands/agent_server/skills_router.py: Added user_skills_dirs field to SkillsRequest
  • Tests: Added 7 new tests covering env var, extra_dirs, priority, and pass-through behavior

Checklist

  • If the PR is changing/adding functionality, are there tests to reflect this?
  • If there is an example, have you run the example to make sure that it works?
  • If there are instructions on how to run the code, have you followed the instructions and made sure that it works?
  • If the feature is significant enough to require documentation, is there a PR open on the OpenHands/docs repository with the same branch name?
  • Is the github CI passing?

@xingyaoww can click here to continue refining the PR


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-slim 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:ae301f8-python

Run

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

All tags pushed for this build

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

About Multi-Architecture Support

  • Each variant tag (e.g., ae301f8-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., ae301f8-python-amd64) are also available if needed

When the agent-server runs inside a container, the host's
~/.openhands/skills/ directory is not visible. This makes user skills
inaccessible unless the user manually mounts the directory.

This change adds two mechanisms for specifying additional user skill
directories:

1. OPENHANDS_USER_SKILLS_DIRS environment variable: a path-separated
   list of additional directories to search for user skills. The
   container can be started with this env var pointing to a mounted
   path.

2. user_skills_dirs API parameter: the /skills endpoint now accepts
   an optional list of additional directories, allowing the app-server
   to tell the agent-server where user skills have been mounted.

Both mechanisms are additive - they prepend to the default search
paths (~/.agents/skills/, ~/.openhands/skills/, ~/.openhands/microagents/)
with proper precedence (extra_dirs > env var > defaults).

Fixes #2417

Co-authored-by: openhands <openhands@all-hands.dev>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

Python API breakage checks — ✅ PASSED

Result:PASSED

Action log

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

REST API breakage checks (OpenAPI) — ✅ PASSED

Result:PASSED

Action log

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 5, 2026

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-agent-server/openhands/agent_server
   skills_service.py1343573%118, 152, 155–158, 161–163, 166–167, 170–174, 177–181, 183, 187–188, 190, 201–205, 347–348, 352–354
openhands-sdk/openhands/sdk/context/skills
   skill.py44730831%82, 86–87, 91–92, 96–97, 225–231, 237–241, 247–254, 285, 287–288, 290–291, 293, 307–308, 310–313, 316, 319–322, 327–330, 333–336, 338, 360–362, 365–366, 370, 372–375, 378, 381–383, 385, 413, 416, 424, 429–431, 437, 439–445, 448, 460–461, 473, 491, 493–494, 501, 515, 521–524, 539–540, 542, 548–549, 551, 565–568, 576–578, 586–588, 597–600, 602, 610–614, 622, 649, 672–673, 675–678, 684–686, 690–692, 695–696, 699–701, 704–705, 707–708, 714, 746, 749–751, 754–759, 762, 764, 790–791, 793–794, 796, 799, 810–813, 823–827, 829, 850–853, 855–857, 860, 866–867, 899–900, 902–903, 905, 908–910, 915–916, 919–927, 931–932, 938, 942, 945, 969, 971–974, 976–978, 981, 983, 985, 989, 991–999, 1045, 1047, 1049–1050, 1052–1054, 1057–1060, 1063–1064, 1066, 1069, 1073, 1077, 1079–1085, 1087–1090, 1092, 1098–1101, 1103, 1108–1110, 1114–1120, 1122–1123, 1125, 1128, 1165, 1167–1172, 1174–1179, 1181–1186, 1188, 1218, 1233–1234, 1247–1248, 1251–1255, 1266–1267
TOTAL222211009454% 

Copy link
Copy Markdown
Collaborator Author

Closing — the root cause of #2417 is a documentation/deployment gap, not a code bug. The SDK already has the correct user skill paths (~/.agents/skills/, ~/.openhands/skills/). The issue is that Docker containers don't see the host filesystem. The fix is to mount the skills directory using SUBVOLUME_MOUNT.

Documentation fix: OpenHands/docs#436

This comment was posted by an AI assistant (OpenHands) on behalf of @xingyaoww.

@xingyaoww xingyaoww closed this Apr 6, 2026
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.

[Bug]: User skills do not load in v1.3.0

2 participants