diff --git a/lib/crewai/src/crewai/agent/core.py b/lib/crewai/src/crewai/agent/core.py index a2df8c2b9..113adbea8 100644 --- a/lib/crewai/src/crewai/agent/core.py +++ b/lib/crewai/src/crewai/agent/core.py @@ -394,15 +394,17 @@ class Agent(BaseAgent): self, resolved_crew_skills: list[SkillModel] | None = None, ) -> None: - """Resolve skill paths and activate skills to INSTRUCTIONS level. + """Resolve skill paths while preserving explicit disclosure levels. - Path entries trigger discovery and activation. Pre-loaded Skill objects - below INSTRUCTIONS level are activated. Crew-level skills are merged in - with event emission so observability is consistent regardless of origin. + Path entries trigger discovery and activation because directory-based + skills opt into eager loading. Pre-loaded Skill objects keep their + current disclosure level so callers can attach METADATA-only skills and + progressively activate them later. Crew-level skills are merged in with + event emission so observability is consistent regardless of origin. Args: - resolved_crew_skills: Pre-resolved crew skills (already discovered - and activated). When provided, avoids redundant discovery per agent. + resolved_crew_skills: Pre-resolved crew skills. When provided, + avoids redundant discovery per agent. """ from crewai.crew import Crew @@ -443,8 +445,7 @@ class Agent(BaseAgent): elif isinstance(item, SkillModel): if item.name not in seen: seen.add(item.name) - activated = activate_skill(item, source=self) - if activated is item and item.disclosure_level >= INSTRUCTIONS: + if item.disclosure_level >= INSTRUCTIONS: crewai_event_bus.emit( self, event=SkillActivatedEvent( @@ -454,7 +455,7 @@ class Agent(BaseAgent): disclosure_level=item.disclosure_level, ), ) - resolved.append(activated) + resolved.append(item) self.skills = resolved if resolved else None diff --git a/lib/crewai/tests/skills/test_integration.py b/lib/crewai/tests/skills/test_integration.py index 23004d79e..c13054e31 100644 --- a/lib/crewai/tests/skills/test_integration.py +++ b/lib/crewai/tests/skills/test_integration.py @@ -4,6 +4,8 @@ from pathlib import Path import pytest +from crewai import Agent +from crewai.agent.utils import append_skill_context from crewai.skills.loader import activate_skill, discover_skills, format_skill_context from crewai.skills.models import INSTRUCTIONS, METADATA @@ -76,3 +78,23 @@ class TestSkillDiscoveryAndActivation: all_skills.extend(discover_skills(search_path)) names = {s.name for s in all_skills} assert names == {"skill-a", "skill-b"} + + def test_agent_preserves_metadata_for_discovered_skills(self, tmp_path: Path) -> None: + _create_skill_dir(tmp_path, "travel", body="Use this skill for travel planning.") + discovered = discover_skills(tmp_path) + + agent = Agent( + role="Travel Advisor", + goal="Provide personalized travel suggestions.", + backstory="An experienced travel consultant.", + skills=discovered, + ) + + assert agent.skills is not None + assert agent.skills[0].disclosure_level == METADATA + assert agent.skills[0].instructions is None + + prompt = append_skill_context(agent, "Plan a 10-day Japan itinerary.") + assert "## Skill: travel" in prompt + assert "Skill travel" in prompt + assert "Use this skill for travel planning." not in prompt