Skip to content

Commit 66930e6

Browse files
GWealecopybara-github
authored andcommitted
fix(agents): report which toolset an agent lost when one fails to load
Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 964417035
1 parent c93fcc0 commit 66930e6

2 files changed

Lines changed: 46 additions & 2 deletions

File tree

src/google/adk/agents/llm_agent.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,23 @@ async def _convert_tool_union_to_tools(
210210
try:
211211
return await tool_union.get_tools_with_prefix(ctx)
212212
except Exception as e:
213-
logger.warning(
214-
'Failed to get tools from toolset %s: %s',
213+
# The agent still runs, just without this toolset's tools, and the model
214+
# will answer as though it never had them. That is a lost capability
215+
# rather than a degraded one, so report it at error level, name which
216+
# toolset was lost, and keep the traceback: str(e) is empty for several
217+
# of the exceptions raised by transport clients.
218+
logger.error(
219+
'Agent %s will run without the tools from toolset %s%s, which failed'
220+
' to load: %s',
221+
ctx.agent_name if ctx else '<unknown>',
215222
type(tool_union).__name__,
223+
(
224+
f' (prefix {tool_union.tool_name_prefix!r})'
225+
if tool_union.tool_name_prefix
226+
else ''
227+
),
216228
e,
229+
exc_info=True,
217230
)
218231
return []
219232

tests/unittests/agents/test_llm_agent_fields.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,37 @@ def _regular_tool():
612612
assert tools[0].name == '_regular_tool'
613613
assert tools[1].name == 'working_tool'
614614

615+
async def test_canonical_tools_reports_the_toolset_it_dropped(self, caplog):
616+
"""A toolset that fails to load is reported at error level, with context."""
617+
from google.adk.tools.base_toolset import BaseToolset
618+
619+
class FailingToolset(BaseToolset):
620+
621+
async def get_tools(self, readonly_context=None):
622+
raise ConnectionError('MCP server unavailable')
623+
624+
agent = LlmAgent(
625+
name='test_agent',
626+
model='gemini-pro',
627+
tools=[FailingToolset(tool_name_prefix='books')],
628+
)
629+
ctx = await _create_readonly_context(agent)
630+
631+
with caplog.at_level(logging.ERROR, logger='google_adk'):
632+
tools = await agent.canonical_tools(ctx)
633+
634+
assert tools == []
635+
record = next(
636+
r for r in caplog.records if 'failed to load' in r.getMessage()
637+
)
638+
message = record.getMessage()
639+
assert 'test_agent' in message
640+
assert 'FailingToolset' in message
641+
assert 'books' in message
642+
assert 'MCP server unavailable' in message
643+
# The traceback is what identifies where inside the toolset it broke.
644+
assert record.exc_info is not None
645+
615646

616647
# Tests for multi-provider model support via string model names
617648
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)