Skip to content

fix(project): resolve skills paths against project root#6587

Open
Yigtwxx wants to merge 2 commits into
crewAIInc:mainfrom
Yigtwxx:fix/skills-path-project-root
Open

fix(project): resolve skills paths against project root#6587
Yigtwxx wants to merge 2 commits into
crewAIInc:mainfrom
Yigtwxx:fix/skills-path-project-root

Conversation

@Yigtwxx

@Yigtwxx Yigtwxx commented Jul 18, 2026

Copy link
Copy Markdown

Problem

Every relative path field in a JSON crew definition is resolved against project_root: custom: tools, output_pydantic / response_model python refs, and input_files. The skills field is the one exception.

It is passed through unresolved in _agent_kwargs_from_definition and _crew_kwargs_from_definition, and reaches crewai.skills.loader.load_skill, whose final branch calls discover_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:

FileNotFoundError: Skill search path does not exist or is not a directory: skills

Root cause

skills is listed in _AGENT_OBJECT_REF_FIELDS and _CREW_OBJECT_REF_FIELDS, so python: reference dicts are converted to Skill objects. Plain path strings, however, are left untouched and never normalized against project_root.

Change

Resolve skills entries that denote filesystem paths against project_root, reusing the existing _resolve_project_path helper that already backs input_files.

_is_skill_path_ref mirrors the string dispatch order of load_skill so the two stay in sync:

Entry Handling
@org/name registry reference, left untouched
---\n... inline SKILL.md document, left untouched
Skill object already resolved, left untouched
anything else filesystem path, resolved against project_root

Normalization runs after _resolve_agent_python_refs / _resolve_crew_python_refs, so python: refs are already Skill instances by that point and only genuine strings remain. It is confined to the resolve_tools=True branch, leaving validation and deploy mode free of any project code execution.

Behavior change

An absolute skill path pointing outside the project root now raises JSONProjectValidationError instead of loading. This matches the existing input_files semantics 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 existing input_files path tests:

  • agent-level skills resolves against project_root with monkeypatch.chdir pointing elsewhere, which fails without this change
  • crew-level skills stores the project-rooted path
  • @acme/research reaches the registry resolver verbatim, guarding the Skills Repository path
  • ../evil_skills is rejected with outside the project root

Fixes #6585

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
@Yigtwxx

Yigtwxx commented Jul 18, 2026

Copy link
Copy Markdown
Author

Per CONTRIBUTING.md, this contribution was authored with an AI coding assistant and therefore requires the llm-generated label. I do not have permission to apply labels on this repository, so could a maintainer please add it.

Flagging the one behavior change explicitly for review: an absolute skill path resolving outside the project root now raises JSONProjectValidationError rather than loading. This follows the existing input_files containment semantics, but it is the only case where a previously working configuration would now be rejected. Happy to gate that behind a warning instead if you would prefer a non-breaking path.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f6e4572e-7638-4e3a-9d1d-bf08620069db

📥 Commits

Reviewing files that changed from the base of the PR and between 7033f33 and 6294ddf.

📒 Files selected for processing (1)
  • lib/crewai/tests/project/test_crew_loader.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/crewai/tests/project/test_crew_loader.py

📝 Walkthrough

Walkthrough

The JSON loader now resolves agent and crew filesystem skill paths against project_root, while preserving registry and inline references. Tests cover resolution, storage, passthrough, and project-root boundary validation.

Changes

Skills path resolution

Layer / File(s) Summary
Skill normalization and loader wiring
lib/crewai/src/crewai/project/json_loader.py
Agent and crew skill lists normalize qualifying filesystem paths against project_root while leaving registry references and inline SKILL.md content unchanged.
Skill resolution validation
lib/crewai/tests/project/test_crew_loader.py
Tests verify agent and crew path resolution, registry reference passthrough, fixture skill loading, and rejection of paths outside the project root.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: resolving skills paths against the project root.
Description check ✅ Passed The description is directly related to the code changes and explains the path-resolution fix and tests.
Linked Issues check ✅ Passed The PR satisfies #6585 by resolving JSON skills paths against project_root instead of process cwd.
Out of Scope Changes check ✅ Passed The added helper logic and tests are all in scope for the skills path resolution fix.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

Agent "skills" paths resolve against process cwd instead of project_root (unlike tools/output_pydantic)

1 participant