google-adk 1.6.1__py3-none-any.whl → 1.8.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. google/adk/a2a/converters/event_converter.py +5 -85
  2. google/adk/a2a/converters/request_converter.py +1 -2
  3. google/adk/a2a/executor/a2a_agent_executor.py +45 -16
  4. google/adk/a2a/logs/log_utils.py +1 -2
  5. google/adk/a2a/utils/__init__.py +0 -0
  6. google/adk/a2a/utils/agent_card_builder.py +544 -0
  7. google/adk/a2a/utils/agent_to_a2a.py +118 -0
  8. google/adk/agents/__init__.py +5 -0
  9. google/adk/agents/agent_config.py +46 -0
  10. google/adk/agents/base_agent.py +239 -41
  11. google/adk/agents/callback_context.py +41 -0
  12. google/adk/agents/common_configs.py +79 -0
  13. google/adk/agents/config_agent_utils.py +184 -0
  14. google/adk/agents/config_schemas/AgentConfig.json +566 -0
  15. google/adk/agents/invocation_context.py +5 -1
  16. google/adk/agents/live_request_queue.py +15 -0
  17. google/adk/agents/llm_agent.py +201 -9
  18. google/adk/agents/loop_agent.py +35 -1
  19. google/adk/agents/parallel_agent.py +24 -3
  20. google/adk/agents/remote_a2a_agent.py +17 -5
  21. google/adk/agents/sequential_agent.py +22 -1
  22. google/adk/artifacts/gcs_artifact_service.py +110 -20
  23. google/adk/auth/auth_handler.py +3 -3
  24. google/adk/auth/credential_manager.py +23 -23
  25. google/adk/auth/credential_service/base_credential_service.py +6 -6
  26. google/adk/auth/credential_service/in_memory_credential_service.py +10 -8
  27. google/adk/auth/credential_service/session_state_credential_service.py +8 -8
  28. google/adk/auth/exchanger/oauth2_credential_exchanger.py +3 -3
  29. google/adk/auth/oauth2_credential_util.py +2 -2
  30. google/adk/auth/refresher/oauth2_credential_refresher.py +4 -4
  31. google/adk/cli/agent_graph.py +3 -1
  32. google/adk/cli/browser/index.html +2 -2
  33. google/adk/cli/browser/main-W7QZBYAR.js +3914 -0
  34. google/adk/cli/browser/polyfills-B6TNHZQ6.js +17 -0
  35. google/adk/cli/cli_eval.py +87 -12
  36. google/adk/cli/cli_tools_click.py +143 -82
  37. google/adk/cli/fast_api.py +150 -69
  38. google/adk/cli/utils/agent_loader.py +35 -1
  39. google/adk/code_executors/base_code_executor.py +14 -19
  40. google/adk/code_executors/built_in_code_executor.py +4 -1
  41. google/adk/evaluation/base_eval_service.py +46 -2
  42. google/adk/evaluation/eval_metrics.py +4 -0
  43. google/adk/evaluation/eval_sets_manager.py +5 -1
  44. google/adk/evaluation/evaluation_generator.py +1 -1
  45. google/adk/evaluation/final_response_match_v2.py +2 -2
  46. google/adk/evaluation/gcs_eval_sets_manager.py +2 -1
  47. google/adk/evaluation/in_memory_eval_sets_manager.py +151 -0
  48. google/adk/evaluation/local_eval_service.py +389 -0
  49. google/adk/evaluation/local_eval_set_results_manager.py +2 -2
  50. google/adk/evaluation/local_eval_sets_manager.py +24 -9
  51. google/adk/evaluation/metric_evaluator_registry.py +16 -6
  52. google/adk/evaluation/vertex_ai_eval_facade.py +7 -1
  53. google/adk/events/event.py +7 -2
  54. google/adk/flows/llm_flows/auto_flow.py +6 -11
  55. google/adk/flows/llm_flows/base_llm_flow.py +66 -29
  56. google/adk/flows/llm_flows/contents.py +16 -10
  57. google/adk/flows/llm_flows/functions.py +89 -52
  58. google/adk/memory/in_memory_memory_service.py +21 -15
  59. google/adk/memory/vertex_ai_memory_bank_service.py +12 -10
  60. google/adk/models/anthropic_llm.py +46 -6
  61. google/adk/models/base_llm_connection.py +2 -0
  62. google/adk/models/gemini_llm_connection.py +17 -6
  63. google/adk/models/google_llm.py +46 -11
  64. google/adk/models/lite_llm.py +52 -22
  65. google/adk/plugins/__init__.py +17 -0
  66. google/adk/plugins/base_plugin.py +317 -0
  67. google/adk/plugins/plugin_manager.py +265 -0
  68. google/adk/runners.py +122 -18
  69. google/adk/sessions/database_session_service.py +51 -52
  70. google/adk/sessions/vertex_ai_session_service.py +27 -12
  71. google/adk/tools/__init__.py +2 -0
  72. google/adk/tools/_automatic_function_calling_util.py +20 -2
  73. google/adk/tools/agent_tool.py +15 -3
  74. google/adk/tools/apihub_tool/apihub_toolset.py +38 -39
  75. google/adk/tools/application_integration_tool/application_integration_toolset.py +35 -37
  76. google/adk/tools/application_integration_tool/integration_connector_tool.py +2 -3
  77. google/adk/tools/base_tool.py +9 -9
  78. google/adk/tools/base_toolset.py +29 -5
  79. google/adk/tools/bigquery/__init__.py +3 -3
  80. google/adk/tools/bigquery/metadata_tool.py +2 -0
  81. google/adk/tools/bigquery/query_tool.py +15 -1
  82. google/adk/tools/computer_use/__init__.py +13 -0
  83. google/adk/tools/computer_use/base_computer.py +265 -0
  84. google/adk/tools/computer_use/computer_use_tool.py +166 -0
  85. google/adk/tools/computer_use/computer_use_toolset.py +220 -0
  86. google/adk/tools/enterprise_search_tool.py +4 -2
  87. google/adk/tools/exit_loop_tool.py +1 -0
  88. google/adk/tools/google_api_tool/google_api_tool.py +16 -1
  89. google/adk/tools/google_api_tool/google_api_toolset.py +9 -7
  90. google/adk/tools/google_api_tool/google_api_toolsets.py +41 -20
  91. google/adk/tools/google_search_tool.py +4 -2
  92. google/adk/tools/langchain_tool.py +16 -6
  93. google/adk/tools/long_running_tool.py +21 -0
  94. google/adk/tools/mcp_tool/mcp_toolset.py +27 -28
  95. google/adk/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.py +5 -0
  96. google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +8 -8
  97. google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +4 -6
  98. google/adk/tools/retrieval/vertex_ai_rag_retrieval.py +3 -2
  99. google/adk/tools/tool_context.py +0 -10
  100. google/adk/tools/url_context_tool.py +4 -2
  101. google/adk/tools/vertex_ai_search_tool.py +4 -2
  102. google/adk/utils/model_name_utils.py +90 -0
  103. google/adk/version.py +1 -1
  104. {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/METADATA +3 -2
  105. {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/RECORD +108 -91
  106. google/adk/cli/browser/main-RXDVX3K6.js +0 -3914
  107. google/adk/cli/browser/polyfills-FFHMD2TL.js +0 -17
  108. {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/WHEEL +0 -0
  109. {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/entry_points.txt +0 -0
  110. {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from typing import Any
16
18
  from typing import Dict
17
19
  from typing import Optional
@@ -23,7 +25,9 @@ from .. import BaseTool
23
25
  from ...auth import AuthCredential
24
26
  from ...auth import AuthCredentialTypes
25
27
  from ...auth import OAuth2Auth
28
+ from ...auth.auth_credential import ServiceAccount
26
29
  from ..openapi_tool import RestApiTool
30
+ from ..openapi_tool.auth.auth_helpers import service_account_scheme_credential
27
31
  from ..tool_context import ToolContext
28
32
 
29
33
 
@@ -34,6 +38,7 @@ class GoogleApiTool(BaseTool):
34
38
  rest_api_tool: RestApiTool,
35
39
  client_id: Optional[str] = None,
36
40
  client_secret: Optional[str] = None,
41
+ service_account: Optional[ServiceAccount] = None,
37
42
  ):
38
43
  super().__init__(
39
44
  name=rest_api_tool.name,
@@ -41,7 +46,10 @@ class GoogleApiTool(BaseTool):
41
46
  is_long_running=rest_api_tool.is_long_running,
42
47
  )
43
48
  self._rest_api_tool = rest_api_tool
44
- self.configure_auth(client_id, client_secret)
49
+ if service_account is not None:
50
+ self.configure_sa_auth(service_account)
51
+ else:
52
+ self.configure_auth(client_id, client_secret)
45
53
 
46
54
  @override
47
55
  def _get_declaration(self) -> FunctionDeclaration:
@@ -63,3 +71,10 @@ class GoogleApiTool(BaseTool):
63
71
  client_secret=client_secret,
64
72
  ),
65
73
  )
74
+
75
+ def configure_sa_auth(self, service_account: ServiceAccount):
76
+ auth_scheme, auth_credential = service_account_scheme_credential(
77
+ service_account
78
+ )
79
+ self._rest_api_tool.auth_scheme = auth_scheme
80
+ self._rest_api_tool.auth_credential = auth_credential
@@ -14,18 +14,15 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- import inspect
18
- import os
19
- from typing import Any
20
17
  from typing import List
21
18
  from typing import Optional
22
- from typing import Type
23
19
  from typing import Union
24
20
 
25
21
  from typing_extensions import override
26
22
 
27
23
  from ...agents.readonly_context import ReadonlyContext
28
24
  from ...auth import OpenIdConnectWithConfig
25
+ from ...auth.auth_credential import ServiceAccount
29
26
  from ...tools.base_toolset import BaseToolset
30
27
  from ...tools.base_toolset import ToolPredicate
31
28
  from ..openapi_tool import OpenAPIToolset
@@ -48,11 +45,13 @@ class GoogleApiToolset(BaseToolset):
48
45
  client_id: Optional[str] = None,
49
46
  client_secret: Optional[str] = None,
50
47
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
48
+ service_account: Optional[ServiceAccount] = None,
51
49
  ):
52
50
  self.api_name = api_name
53
51
  self.api_version = api_version
54
52
  self._client_id = client_id
55
53
  self._client_secret = client_secret
54
+ self._service_account = service_account
56
55
  self._openapi_toolset = self._load_toolset_with_oidc_auth()
57
56
  self.tool_filter = tool_filter
58
57
 
@@ -61,10 +60,10 @@ class GoogleApiToolset(BaseToolset):
61
60
  self, readonly_context: Optional[ReadonlyContext] = None
62
61
  ) -> List[GoogleApiTool]:
63
62
  """Get all tools in the toolset."""
64
- tools = []
65
-
66
63
  return [
67
- GoogleApiTool(tool, self._client_id, self._client_secret)
64
+ GoogleApiTool(
65
+ tool, self._client_id, self._client_secret, self._service_account
66
+ )
68
67
  for tool in await self._openapi_toolset.get_tools(readonly_context)
69
68
  if self._is_tool_selected(tool, readonly_context)
70
69
  ]
@@ -106,6 +105,9 @@ class GoogleApiToolset(BaseToolset):
106
105
  self._client_id = client_id
107
106
  self._client_secret = client_secret
108
107
 
108
+ def configure_sa_auth(self, service_account: ServiceAccount):
109
+ self._service_account = service_account
110
+
109
111
  @override
110
112
  async def close(self):
111
113
  if self._openapi_toolset:
@@ -12,12 +12,14 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
15
16
 
16
17
  import logging
17
18
  from typing import List
18
19
  from typing import Optional
19
20
  from typing import Union
20
21
 
22
+ from ...auth.auth_credential import ServiceAccount
21
23
  from ..base_toolset import ToolPredicate
22
24
  from .google_api_toolset import GoogleApiToolset
23
25
 
@@ -29,11 +31,14 @@ class BigQueryToolset(GoogleApiToolset):
29
31
 
30
32
  def __init__(
31
33
  self,
32
- client_id: str = None,
33
- client_secret: str = None,
34
+ client_id: Optional[str] = None,
35
+ client_secret: Optional[str] = None,
34
36
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
37
+ service_account: Optional[ServiceAccount] = None,
35
38
  ):
36
- super().__init__("bigquery", "v2", client_id, client_secret, tool_filter)
39
+ super().__init__(
40
+ "bigquery", "v2", client_id, client_secret, tool_filter, service_account
41
+ )
37
42
 
38
43
 
39
44
  class CalendarToolset(GoogleApiToolset):
@@ -41,11 +46,14 @@ class CalendarToolset(GoogleApiToolset):
41
46
 
42
47
  def __init__(
43
48
  self,
44
- client_id: str = None,
45
- client_secret: str = None,
49
+ client_id: Optional[str] = None,
50
+ client_secret: Optional[str] = None,
46
51
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
52
+ service_account: Optional[ServiceAccount] = None,
47
53
  ):
48
- super().__init__("calendar", "v3", client_id, client_secret, tool_filter)
54
+ super().__init__(
55
+ "calendar", "v3", client_id, client_secret, tool_filter, service_account
56
+ )
49
57
 
50
58
 
51
59
  class GmailToolset(GoogleApiToolset):
@@ -53,11 +61,14 @@ class GmailToolset(GoogleApiToolset):
53
61
 
54
62
  def __init__(
55
63
  self,
56
- client_id: str = None,
57
- client_secret: str = None,
64
+ client_id: Optional[str] = None,
65
+ client_secret: Optional[str] = None,
58
66
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
67
+ service_account: Optional[ServiceAccount] = None,
59
68
  ):
60
- super().__init__("gmail", "v1", client_id, client_secret, tool_filter)
69
+ super().__init__(
70
+ "gmail", "v1", client_id, client_secret, tool_filter, service_account
71
+ )
61
72
 
62
73
 
63
74
  class YoutubeToolset(GoogleApiToolset):
@@ -65,11 +76,14 @@ class YoutubeToolset(GoogleApiToolset):
65
76
 
66
77
  def __init__(
67
78
  self,
68
- client_id: str = None,
69
- client_secret: str = None,
79
+ client_id: Optional[str] = None,
80
+ client_secret: Optional[str] = None,
70
81
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
82
+ service_account: Optional[ServiceAccount] = None,
71
83
  ):
72
- super().__init__("youtube", "v3", client_id, client_secret, tool_filter)
84
+ super().__init__(
85
+ "youtube", "v3", client_id, client_secret, tool_filter, service_account
86
+ )
73
87
 
74
88
 
75
89
  class SlidesToolset(GoogleApiToolset):
@@ -77,11 +91,14 @@ class SlidesToolset(GoogleApiToolset):
77
91
 
78
92
  def __init__(
79
93
  self,
80
- client_id: str = None,
81
- client_secret: str = None,
94
+ client_id: Optional[str] = None,
95
+ client_secret: Optional[str] = None,
82
96
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
97
+ service_account: Optional[ServiceAccount] = None,
83
98
  ):
84
- super().__init__("slides", "v1", client_id, client_secret, tool_filter)
99
+ super().__init__(
100
+ "slides", "v1", client_id, client_secret, tool_filter, service_account
101
+ )
85
102
 
86
103
 
87
104
  class SheetsToolset(GoogleApiToolset):
@@ -89,9 +106,10 @@ class SheetsToolset(GoogleApiToolset):
89
106
 
90
107
  def __init__(
91
108
  self,
92
- client_id: str = None,
93
- client_secret: str = None,
109
+ client_id: Optional[str] = None,
110
+ client_secret: Optional[str] = None,
94
111
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
112
+ service_account: Optional[ServiceAccount] = None,
95
113
  ):
96
114
  super().__init__("sheets", "v4", client_id, client_secret, tool_filter)
97
115
 
@@ -101,8 +119,11 @@ class DocsToolset(GoogleApiToolset):
101
119
 
102
120
  def __init__(
103
121
  self,
104
- client_id: str = None,
105
- client_secret: str = None,
122
+ client_id: Optional[str] = None,
123
+ client_secret: Optional[str] = None,
106
124
  tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
125
+ service_account: Optional[ServiceAccount] = None,
107
126
  ):
108
- super().__init__("docs", "v1", client_id, client_secret, tool_filter)
127
+ super().__init__(
128
+ "docs", "v1", client_id, client_secret, tool_filter, service_account
129
+ )
@@ -19,6 +19,8 @@ from typing import TYPE_CHECKING
19
19
  from google.genai import types
20
20
  from typing_extensions import override
21
21
 
22
+ from ..utils.model_name_utils import is_gemini_1_model
23
+ from ..utils.model_name_utils import is_gemini_model
22
24
  from .base_tool import BaseTool
23
25
  from .tool_context import ToolContext
24
26
 
@@ -46,7 +48,7 @@ class GoogleSearchTool(BaseTool):
46
48
  ) -> None:
47
49
  llm_request.config = llm_request.config or types.GenerateContentConfig()
48
50
  llm_request.config.tools = llm_request.config.tools or []
49
- if llm_request.model and 'gemini-1' in llm_request.model:
51
+ if is_gemini_1_model(llm_request.model):
50
52
  if llm_request.config.tools:
51
53
  raise ValueError(
52
54
  'Google search tool can not be used with other tools in Gemini 1.x.'
@@ -54,7 +56,7 @@ class GoogleSearchTool(BaseTool):
54
56
  llm_request.config.tools.append(
55
57
  types.Tool(google_search_retrieval=types.GoogleSearchRetrieval())
56
58
  )
57
- elif llm_request.model and 'gemini-' in llm_request.model:
59
+ elif is_gemini_model(llm_request.model):
58
60
  llm_request.config.tools.append(
59
61
  types.Tool(google_search=types.GoogleSearch())
60
62
  )
@@ -41,14 +41,13 @@ class LangchainTool(FunctionTool):
41
41
  name: Optional override for the tool's name
42
42
  description: Optional override for the tool's description
43
43
 
44
- Examples:
45
- ```python
44
+ Examples::
45
+
46
46
  from langchain.tools import DuckDuckGoSearchTool
47
47
  from google.genai.tools import LangchainTool
48
48
 
49
49
  search_tool = DuckDuckGoSearchTool()
50
50
  wrapped_tool = LangchainTool(search_tool)
51
- ```
52
51
  """
53
52
 
54
53
  _langchain_tool: Union[BaseTool, object]
@@ -60,15 +59,26 @@ class LangchainTool(FunctionTool):
60
59
  name: Optional[str] = None,
61
60
  description: Optional[str] = None,
62
61
  ):
63
- # Check if the tool has a 'run' method
64
62
  if not hasattr(tool, 'run') and not hasattr(tool, '_run'):
65
- raise ValueError("Langchain tool must have a 'run' or '_run' method")
63
+ raise ValueError(
64
+ "Tool must be a Langchain tool, have a 'run' or '_run' method."
65
+ )
66
66
 
67
67
  # Determine which function to use
68
68
  if isinstance(tool, StructuredTool):
69
69
  func = tool.func
70
- else:
70
+ # For async tools, func might be None but coroutine exists
71
+ if func is None and hasattr(tool, 'coroutine') and tool.coroutine:
72
+ func = tool.coroutine
73
+ elif hasattr(tool, '_run') or hasattr(tool, 'run'):
71
74
  func = tool._run if hasattr(tool, '_run') else tool.run
75
+ else:
76
+ raise ValueError(
77
+ "This is not supported. Tool must be a Langchain tool, have a 'run'"
78
+ " or '_run' method. The tool is: ",
79
+ type(tool),
80
+ )
81
+
72
82
  super().__init__(func)
73
83
  # run_manager is a special parameter for langchain tool
74
84
  self._ignore_params.append('run_manager')
@@ -12,7 +12,13 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from typing import Callable
18
+ from typing import Optional
19
+
20
+ from google.genai import types
21
+ from typing_extensions import override
16
22
 
17
23
  from .function_tool import FunctionTool
18
24
 
@@ -37,3 +43,18 @@ class LongRunningFunctionTool(FunctionTool):
37
43
  def __init__(self, func: Callable):
38
44
  super().__init__(func)
39
45
  self.is_long_running = True
46
+
47
+ @override
48
+ def _get_declaration(self) -> Optional[types.FunctionDeclaration]:
49
+ declaration = super()._get_declaration()
50
+ if declaration:
51
+ instruction = (
52
+ "\n\nNOTE: This is a long-running operation. Do not call this tool"
53
+ " again if it has already returned some intermediate or pending"
54
+ " status."
55
+ )
56
+ if declaration.description:
57
+ declaration.description += instruction
58
+ else:
59
+ declaration.description = instruction.lstrip()
60
+ return declaration
@@ -61,28 +61,27 @@ class MCPToolset(BaseToolset):
61
61
  that can be used by an agent. It properly implements the BaseToolset
62
62
  interface for easy integration with the agent framework.
63
63
 
64
- Usage:
65
- ```python
66
- toolset = MCPToolset(
67
- connection_params=StdioServerParameters(
68
- command='npx',
69
- args=["-y", "@modelcontextprotocol/server-filesystem"],
70
- ),
71
- tool_filter=['read_file', 'list_directory'] # Optional: filter specific tools
72
- )
73
-
74
- # Use in an agent
75
- agent = LlmAgent(
76
- model='gemini-2.0-flash',
77
- name='enterprise_assistant',
78
- instruction='Help user accessing their file systems',
79
- tools=[toolset],
80
- )
81
-
82
- # Cleanup is handled automatically by the agent framework
83
- # But you can also manually close if needed:
84
- # await toolset.close()
85
- ```
64
+ Usage::
65
+
66
+ toolset = MCPToolset(
67
+ connection_params=StdioServerParameters(
68
+ command='npx',
69
+ args=["-y", "@modelcontextprotocol/server-filesystem"],
70
+ ),
71
+ tool_filter=['read_file', 'list_directory'] # Optional: filter specific tools
72
+ )
73
+
74
+ # Use in an agent
75
+ agent = LlmAgent(
76
+ model='gemini-2.0-flash',
77
+ name='enterprise_assistant',
78
+ instruction='Help user accessing their file systems',
79
+ tools=[toolset],
80
+ )
81
+
82
+ # Cleanup is handled automatically by the agent framework
83
+ # But you can also manually close if needed:
84
+ # await toolset.close()
86
85
  """
87
86
 
88
87
  def __init__(
@@ -103,12 +102,12 @@ class MCPToolset(BaseToolset):
103
102
 
104
103
  Args:
105
104
  connection_params: The connection parameters to the MCP server. Can be:
106
- `StdioConnectionParams` for using local mcp server (e.g. using `npx` or
107
- `python3`); or `SseConnectionParams` for a local/remote SSE server; or
108
- `StreamableHTTPConnectionParams` for local/remote Streamable http
109
- server. Note, `StdioServerParameters` is also supported for using local
110
- mcp server (e.g. using `npx` or `python3` ), but it does not support
111
- timeout, and we recommend to use `StdioConnectionParams` instead when
105
+ ``StdioConnectionParams`` for using local mcp server (e.g. using ``npx`` or
106
+ ``python3``); or ``SseConnectionParams`` for a local/remote SSE server; or
107
+ ``StreamableHTTPConnectionParams`` for local/remote Streamable http
108
+ server. Note, ``StdioServerParameters`` is also supported for using local
109
+ mcp server (e.g. using ``npx`` or ``python3`` ), but it does not support
110
+ timeout, and we recommend to use ``StdioConnectionParams`` instead when
112
111
  timeout is needed.
113
112
  tool_filter: Optional filter to select specific tools. Can be either: - A
114
113
  list of tool names to include - A ToolPredicate function for custom
@@ -111,6 +111,11 @@ class OpenApiSpecParser:
111
111
  if operation_dict is None:
112
112
  continue
113
113
 
114
+ # Append path-level parameters
115
+ operation_dict["parameters"] = operation_dict.get(
116
+ "parameters", []
117
+ ) + path_item.get("parameters", [])
118
+
114
119
  # If operation ID is missing, assign an operation id based on path
115
120
  # and method
116
121
  if "operationId" not in operation_dict:
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import json
16
18
  import logging
17
19
  from typing import Any
@@ -39,8 +41,8 @@ logger = logging.getLogger("google_adk." + __name__)
39
41
  class OpenAPIToolset(BaseToolset):
40
42
  """Class for parsing OpenAPI spec into a list of RestApiTool.
41
43
 
42
- Usage:
43
- ```
44
+ Usage::
45
+
44
46
  # Initialize OpenAPI toolset from a spec string.
45
47
  openapi_toolset = OpenAPIToolset(spec_str=openapi_spec_str,
46
48
  spec_str_type="json")
@@ -55,7 +57,6 @@ class OpenAPIToolset(BaseToolset):
55
57
  agent = Agent(
56
58
  tools=[openapi_toolset.get_tool('tool_name')]
57
59
  )
58
- ```
59
60
  """
60
61
 
61
62
  def __init__(
@@ -70,8 +71,8 @@ class OpenAPIToolset(BaseToolset):
70
71
  ):
71
72
  """Initializes the OpenAPIToolset.
72
73
 
73
- Usage:
74
- ```
74
+ Usage::
75
+
75
76
  # Initialize OpenAPI toolset from a spec string.
76
77
  openapi_toolset = OpenAPIToolset(spec_str=openapi_spec_str,
77
78
  spec_str_type="json")
@@ -86,7 +87,6 @@ class OpenAPIToolset(BaseToolset):
86
87
  agent = Agent(
87
88
  tools=[openapi_toolset.get_tool('tool_name')]
88
89
  )
89
- ```
90
90
 
91
91
  Args:
92
92
  spec_dict: The OpenAPI spec dictionary. If provided, it will be used
@@ -96,10 +96,10 @@ class OpenAPIToolset(BaseToolset):
96
96
  spec_str_type: The type of the OpenAPI spec string. Can be "json" or
97
97
  "yaml".
98
98
  auth_scheme: The auth scheme to use for all tools. Use AuthScheme or use
99
- helpers in `google.adk.tools.openapi_tool.auth.auth_helpers`
99
+ helpers in ``google.adk.tools.openapi_tool.auth.auth_helpers``
100
100
  auth_credential: The auth credential to use for all tools. Use
101
101
  AuthCredential or use helpers in
102
- `google.adk.tools.openapi_tool.auth.auth_helpers`
102
+ ``google.adk.tools.openapi_tool.auth.auth_helpers``
103
103
  tool_filter: The filter used to filter the tools in the toolset. It can be
104
104
  either a tool predicate or a list of tool names of the tools to expose.
105
105
  """
@@ -70,13 +70,12 @@ class RestApiTool(BaseTool):
70
70
  * Generates request params and body
71
71
  * Attaches auth credentials to API call.
72
72
 
73
- Example:
74
- ```
73
+ Example::
74
+
75
75
  # Each API operation in the spec will be turned into its own tool
76
76
  # Name of the tool is the operationId of that operation, in snake case
77
77
  operations = OperationGenerator().parse(openapi_spec_dict)
78
78
  tool = [RestApiTool.from_parsed_operation(o) for o in operations]
79
- ```
80
79
  """
81
80
 
82
81
  def __init__(
@@ -92,13 +91,12 @@ class RestApiTool(BaseTool):
92
91
  """Initializes the RestApiTool with the given parameters.
93
92
 
94
93
  To generate RestApiTool from OpenAPI Specs, use OperationGenerator.
95
- Example:
96
- ```
94
+ Example::
95
+
97
96
  # Each API operation in the spec will be turned into its own tool
98
97
  # Name of the tool is the operationId of that operation, in snake case
99
98
  operations = OperationGenerator().parse(openapi_spec_dict)
100
99
  tool = [RestApiTool.from_parsed_operation(o) for o in operations]
101
- ```
102
100
 
103
101
  Hint: Use google.adk.tools.openapi_tool.auth.auth_helpers to construct
104
102
  auth_scheme and auth_credential.
@@ -24,11 +24,12 @@ from google.genai import types
24
24
  from typing_extensions import override
25
25
  from vertexai.preview import rag
26
26
 
27
+ from ...utils.model_name_utils import is_gemini_2_model
27
28
  from ..tool_context import ToolContext
28
29
  from .base_retrieval_tool import BaseRetrievalTool
29
30
 
30
31
  if TYPE_CHECKING:
31
- from ...models.llm_request import LlmRequest
32
+ from ...models import LlmRequest
32
33
 
33
34
  logger = logging.getLogger('google_adk.' + __name__)
34
35
 
@@ -62,7 +63,7 @@ class VertexAiRagRetrieval(BaseRetrievalTool):
62
63
  llm_request: LlmRequest,
63
64
  ) -> None:
64
65
  # Use Gemini built-in Vertex AI RAG tool for Gemini 2 models.
65
- if llm_request.model and llm_request.model.startswith('gemini-2'):
66
+ if is_gemini_2_model(llm_request.model):
66
67
  llm_request.config = (
67
68
  types.GenerateContentConfig()
68
69
  if not llm_request.config
@@ -69,16 +69,6 @@ class ToolContext(CallbackContext):
69
69
  def get_auth_response(self, auth_config: AuthConfig) -> AuthCredential:
70
70
  return AuthHandler(auth_config).get_auth_response(self.state)
71
71
 
72
- async def list_artifacts(self) -> list[str]:
73
- """Lists the filenames of the artifacts attached to the current session."""
74
- if self._invocation_context.artifact_service is None:
75
- raise ValueError('Artifact service is not initialized.')
76
- return await self._invocation_context.artifact_service.list_artifact_keys(
77
- app_name=self._invocation_context.app_name,
78
- user_id=self._invocation_context.user_id,
79
- session_id=self._invocation_context.session.id,
80
- )
81
-
82
72
  async def search_memory(self, query: str) -> SearchMemoryResponse:
83
73
  """Searches the memory of the current user."""
84
74
  if self._invocation_context.memory_service is None:
@@ -19,6 +19,8 @@ from typing import TYPE_CHECKING
19
19
  from google.genai import types
20
20
  from typing_extensions import override
21
21
 
22
+ from ..utils.model_name_utils import is_gemini_1_model
23
+ from ..utils.model_name_utils import is_gemini_2_model
22
24
  from .base_tool import BaseTool
23
25
  from .tool_context import ToolContext
24
26
 
@@ -46,9 +48,9 @@ class UrlContextTool(BaseTool):
46
48
  ) -> None:
47
49
  llm_request.config = llm_request.config or types.GenerateContentConfig()
48
50
  llm_request.config.tools = llm_request.config.tools or []
49
- if llm_request.model and 'gemini-1' in llm_request.model:
51
+ if is_gemini_1_model(llm_request.model):
50
52
  raise ValueError('Url context tool can not be used in Gemini 1.x.')
51
- elif llm_request.model and 'gemini-2' in llm_request.model:
53
+ elif is_gemini_2_model(llm_request.model):
52
54
  llm_request.config.tools.append(
53
55
  types.Tool(url_context=types.UrlContext())
54
56
  )
@@ -20,6 +20,8 @@ from typing import TYPE_CHECKING
20
20
  from google.genai import types
21
21
  from typing_extensions import override
22
22
 
23
+ from ..utils.model_name_utils import is_gemini_1_model
24
+ from ..utils.model_name_utils import is_gemini_model
23
25
  from .base_tool import BaseTool
24
26
  from .tool_context import ToolContext
25
27
 
@@ -86,8 +88,8 @@ class VertexAiSearchTool(BaseTool):
86
88
  tool_context: ToolContext,
87
89
  llm_request: LlmRequest,
88
90
  ) -> None:
89
- if llm_request.model and 'gemini-' in llm_request.model:
90
- if 'gemini-1' in llm_request.model and llm_request.config.tools:
91
+ if is_gemini_model(llm_request.model):
92
+ if is_gemini_1_model(llm_request.model) and llm_request.config.tools:
91
93
  raise ValueError(
92
94
  'Vertex AI search tool can not be used with other tools in Gemini'
93
95
  ' 1.x.'