diff --git a/src/google/adk/tools/skill_toolset.py b/src/google/adk/tools/skill_toolset.py index c09b2dcdda..f85eadef5d 100644 --- a/src/google/adk/tools/skill_toolset.py +++ b/src/google/adk/tools/skill_toolset.py @@ -105,6 +105,14 @@ def _build_skill_system_instruction(prefix: str | None = None) -> str: ) +def _skill_has_scripts(skill: models.Skill) -> bool: + """Returns whether a skill exposes at least one executable script.""" + resources = getattr(skill, "resources", None) + if resources is None: + return False + return bool(resources.list_scripts()) + + class ListSkillsTool(BaseTool): """Tool to list all available skills.""" @@ -1037,8 +1045,11 @@ def __init__( ListSkillsTool(self), LoadSkillTool(self), LoadSkillResourceTool(self), - RunSkillScriptTool(self), ] + if self._registry or any( + _skill_has_scripts(skill) for skill in self._skills.values() + ): + self._tools.append(RunSkillScriptTool(self)) if self._registry: self._tools.append(SearchSkillsTool(self)) diff --git a/tests/unittests/tools/test_skill_toolset.py b/tests/unittests/tools/test_skill_toolset.py index 450dbe3f30..8aaeb120bd 100644 --- a/tests/unittests/tools/test_skill_toolset.py +++ b/tests/unittests/tools/test_skill_toolset.py @@ -225,6 +225,38 @@ async def test_get_tools(mock_skill1, mock_skill2): assert isinstance(tools[3], skill_toolset.RunSkillScriptTool) +@pytest.mark.asyncio +async def test_get_tools_excludes_run_skill_script_when_no_skill_has_scripts( + mock_skill2, +): + toolset = skill_toolset.SkillToolset([mock_skill2]) + + tools = await toolset.get_tools() + + assert [tool.name for tool in tools] == [ + "list_skills", + "load_skill", + "load_skill_resource", + ] + assert not any( + isinstance(tool, skill_toolset.RunSkillScriptTool) for tool in tools + ) + + +@pytest.mark.asyncio +async def test_get_tools_includes_run_skill_script_when_any_skill_has_scripts( + mock_skill1, + mock_skill2, +): + toolset = skill_toolset.SkillToolset([mock_skill2, mock_skill1]) + + tools = await toolset.get_tools() + + assert any( + isinstance(tool, skill_toolset.RunSkillScriptTool) for tool in tools + ) + + @pytest.mark.asyncio async def test_resolve_additional_tools_from_state_none(mock_skill1): toolset = skill_toolset.SkillToolset([mock_skill1])