fix(project): resolve skills paths against project root#6587
Conversation
Every other relative path field in a JSON crew definition (custom: tools, output_pydantic python refs, input_files) is resolved against project_root. The agent and crew skills fields were the exception: they were passed through unresolved and reached discover_skills(Path(skill)), which resolves against the process cwd at call time. This made the same crew definition succeed or fail purely based on where the process was launched from, breaking server and container deployments where cwd is not the project directory. Resolve skills entries that denote filesystem paths against project_root, mirroring the string dispatch order of skills.loader.load_skill so registry references and inline SKILL.md documents reach the loader untouched. Fixes crewAIInc#6585
|
Per CONTRIBUTING.md, this contribution was authored with an AI coding assistant and therefore requires the Flagging the one behavior change explicitly for review: an absolute skill path resolving outside the project root now raises |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe JSON loader now resolves agent and crew filesystem skill paths against ChangesSkills path resolution
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
Every relative path field in a JSON crew definition is resolved against
project_root:custom:tools,output_pydantic/response_modelpython refs, andinput_files. Theskillsfield is the one exception.It is passed through unresolved in
_agent_kwargs_from_definitionand_crew_kwargs_from_definition, and reachescrewai.skills.loader.load_skill, whose final branch callsdiscover_skills(Path(skill)). That resolves against the process working directory at call time.The result is that the same crew definition succeeds or fails purely based on where the process was launched from. Running a script from its own directory works; running the identical code under uvicorn, in a container, or from an IDE run configuration raises:
Root cause
skillsis listed in_AGENT_OBJECT_REF_FIELDSand_CREW_OBJECT_REF_FIELDS, sopython:reference dicts are converted toSkillobjects. Plain path strings, however, are left untouched and never normalized againstproject_root.Change
Resolve
skillsentries that denote filesystem paths againstproject_root, reusing the existing_resolve_project_pathhelper that already backsinput_files._is_skill_path_refmirrors the string dispatch order ofload_skillso the two stay in sync:@org/name---\n...Skillobjectproject_rootNormalization runs after
_resolve_agent_python_refs/_resolve_crew_python_refs, sopython:refs are alreadySkillinstances by that point and only genuine strings remain. It is confined to theresolve_tools=Truebranch, leaving validation and deploy mode free of any project code execution.Behavior change
An absolute skill path pointing outside the project root now raises
JSONProjectValidationErrorinstead of loading. This matches the existinginput_filessemantics and the containment guarantee of_resolve_project_path, but it is the one case where a previously working configuration would now be rejected.Tests
Four cases added to
lib/crewai/tests/project/test_crew_loader.py, alongside the existinginput_filespath tests:skillsresolves againstproject_rootwithmonkeypatch.chdirpointing elsewhere, which fails without this changeskillsstores the project-rooted path@acme/researchreaches the registry resolver verbatim, guarding the Skills Repository path../evil_skillsis rejected withoutside the project rootFixes #6585