Skip to content

SkillToolset additional-tools resolution aborts entirely when one provided toolset fails to list its toolsΒ #6507

Description

@hawktang

πŸ”΄ Required Information

Describe the Bug:

SkillToolset._resolve_additional_tools_from_state gathers tools from every provided toolset with a bare asyncio.gather(...) β€” no return_exceptions=True:

https://github.com/google/adk-python/blob/main/src/google/adk/tools/skill_toolset.py#L1096-L1099

ts_results = await asyncio.gather(*(
    ts.get_tools_with_prefix(readonly_context)
    for ts in self._provided_toolsets
))

Because asyncio.gather propagates the first exception, a single toolset that raises while listing its tools aborts resolution of ALL skill additional tools β€” including healthy individual tools and healthy toolsets that have nothing to do with the failing one.

This is easy to hit in practice with MCP-backed toolsets: McpToolset.get_tools opens a live session to a remote MCP server, so any restart / 503 / network blip makes listing raise. The blast radius is not limited to that MCP's tools β€” every adk_additional_tools entry of every activated skill disappears for that invocation, including tools that have no MCP dependency at all. The user-visible symptom is simply that the tool does not exist, which makes this hard to trace back to the MCP server.

Steps to Reproduce:

  1. Install google-adk==2.5.0.
  2. Construct a SkillToolset with two entries in additional_tools: one plain BaseTool (say good_tool), and one BaseToolset whose get_tools raises β€” an McpToolset pointed at an unreachable server, or any stub that raises ConnectionError.
  3. Register one skill whose adk_additional_tools metadata names a tool from each (good_tool plus one from the failing toolset), and mark that skill activated for the agent (state key _adk_activated_skill_<agent_name>).
  4. Trigger additional-tools resolution for an invocation in which that skill is activated.

Expected Behavior:

The toolset that fails to list its tools degrades to "no tools from this toolset", and every other additional tool still resolves β€” good_tool is returned.

Observed Behavior:

Resolution aborts entirely and the failing toolset's exception propagates out of _resolve_additional_tools_from_state. good_tool is never resolved, even though it is a plain individual tool that cannot fail:

  File ".../google/adk/tools/skill_toolset.py", line 1096, in _resolve_additional_tools_from_state
    ts_results = await asyncio.gather(*(
                 ^^^^^^^^^^^^^^^^^^^^^^^
ConnectionError: MCP server unreachable (503)

Environment Details:

  • ADK Library Version: 2.5.0 (also verified present in 2.4.0 and on main @ skill_toolset.py:1096)
  • Desktop OS: macOS
  • Python Version: 3.13 (also observed on 3.12)

Model Information:

  • Are you using LiteLLM: N/A β€” the bug is in toolset resolution, before any model call
  • Which model is being used: N/A (model-independent)

🟑 Optional Information

Regression:

Not a regression β€” the bare gather has been there since SkillToolset gained _resolve_additional_tools_from_state.

Possible Direction (description only β€” I am not submitting a patch):

Passing return_exceptions=True to that gather, then skipping (with a warning log) any toolset whose listing raised while re-raising asyncio.CancelledError so cancellation still propagates, would confine the failure to the toolset that actually failed. Individual tools and healthy toolsets would then resolve normally.

Verification:

I made that change locally against an unmodified google-adk==2.5.0 install and re-ran my local reproduction. The healthy tool resolved (['good_tool']), and the failing toolset was logged and skipped β€” contributing no tools for that invocation and recovering on the next one, since tool listing is cached per invocation_id.


Note: this is filed as a defect report and is conspicuously designated "Not a Contribution" as that term is used in the Google CLA. I am not submitting any code for inclusion in the Work; please implement any fix independently.

Metadata

Metadata

Labels

needs review[Status] The PR/issue is awaiting review from the maintainertools[Component] This issue is related to tools

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions