diff --git a/src/google/adk/tools/skill_toolset.py b/src/google/adk/tools/skill_toolset.py index a6796d8c49a..4f080c1e01c 100644 --- a/src/google/adk/tools/skill_toolset.py +++ b/src/google/adk/tools/skill_toolset.py @@ -162,9 +162,10 @@ class SearchSkillsTool(BaseTool): """Tool to search for relevant skills in the registry.""" def __init__(self, toolset: "SkillToolset"): - if not toolset._registry: + registry = toolset._registry + if not registry: raise ValueError("SearchSkillsTool requires a configured skill registry.") - description = toolset._registry.search_tool_description() or ( + description = registry.search_tool_description() or ( "Searches for relevant skills in the registry based on a semantic or" " keyword query." ) @@ -173,6 +174,7 @@ def __init__(self, toolset: "SkillToolset"): description=description, ) self._toolset = toolset + self._registry = registry def _get_declaration(self) -> types.FunctionDeclaration | None: properties = { @@ -201,7 +203,7 @@ async def run_async( "error_code": "INVALID_ARGUMENTS", } try: - results = await self._toolset._registry.search_skills(query=query) + results = await self._registry.search_skills(query=query) formatted_results = [] for r in results: if r.name in self._toolset._skills: @@ -1037,7 +1039,7 @@ async def run_async( code_executor = self._toolset._code_executor if code_executor is None: agent = tool_context._invocation_context.agent - if hasattr(agent, "code_executor"): + if agent is not None and hasattr(agent, "code_executor"): code_executor = agent.code_executor if code_executor is None: return { diff --git a/tests/unittests/tools/test_skill_toolset.py b/tests/unittests/tools/test_skill_toolset.py index e8069620084..8a0a4205337 100644 --- a/tests/unittests/tools/test_skill_toolset.py +++ b/tests/unittests/tools/test_skill_toolset.py @@ -992,6 +992,24 @@ async def test_execute_script_agent_code_executor_none(mock_skill1): assert result["error_code"] == "NO_CODE_EXECUTOR" +@pytest.mark.asyncio +async def test_execute_script_agent_is_none(mock_skill1): + """An absent agent reports NO_CODE_EXECUTOR instead of raising.""" + toolset = skill_toolset.SkillToolset([mock_skill1]) + tool = skill_toolset.RunSkillScriptTool(toolset) + # The helper substitutes a MagicMock for a falsy agent, so the agent has to + # be cleared after it returns. + ctx = _make_tool_context_with_agent() + ctx._invocation_context.agent = None + + result = await tool.run_async( + args={"skill_name": "skill1", "file_path": "setup.sh"}, + tool_context=ctx, + ) + + assert result["error_code"] == "NO_CODE_EXECUTOR" + + @pytest.mark.asyncio async def test_execute_script_unsupported_type(mock_skill1): executor = _make_mock_executor()