Skip to content

Commit c6a94b8

Browse files
xuanyang15copybara-github
authored andcommitted
fix: Add credential_key to ApplicationIntegrationToolset and IntegrationConnectorTool
This change allows a credential key to be passed through the toolset and connector, enabling the ToolAuthHandler to use a specific key when looking up credentials in the tool context. Fixes #4553 Co-authored-by: Xuan Yang <xygoogle@google.com> PiperOrigin-RevId: 941375909
1 parent e98633a commit c6a94b8

4 files changed

Lines changed: 31 additions & 5 deletions

File tree

src/google/adk/tools/application_integration_tool/application_integration_toolset.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ def __init__(
103103
auth_scheme: Optional[AuthScheme] = None,
104104
auth_credential: Optional[AuthCredential] = None,
105105
tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
106+
credential_key: Optional[str] = None,
106107
):
107108
"""Args:
108109
@@ -146,12 +147,14 @@ def __init__(
146147
self._service_account_json = service_account_json
147148
self._auth_scheme = auth_scheme
148149
self._auth_credential = auth_credential
150+
self._credential_key = credential_key
149151
# Store auth config as instance variable so ADK can populate
150152
# exchanged_auth_credential in-place before calling get_tools()
151153
self._auth_config: Optional[AuthConfig] = (
152154
AuthConfig(
153155
auth_scheme=auth_scheme,
154156
raw_auth_credential=auth_credential,
157+
credential_key=credential_key,
155158
)
156159
if auth_scheme
157160
else None
@@ -221,6 +224,7 @@ def _parse_spec_to_toolset(
221224
spec_dict=spec_dict,
222225
auth_credential=auth_credential,
223226
auth_scheme=auth_scheme,
227+
credential_key=self._credential_key,
224228
tool_filter=self.tool_filter,
225229
)
226230
return
@@ -274,6 +278,7 @@ def _parse_spec_to_toolset(
274278
rest_api_tool=rest_api_tool,
275279
auth_scheme=connector_auth_scheme,
276280
auth_credential=connector_auth_credential,
281+
credential_key=self._credential_key,
277282
)
278283
)
279284

src/google/adk/tools/application_integration_tool/integration_connector_tool.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ def __init__(
8080
rest_api_tool: RestApiTool,
8181
auth_scheme: Optional[Union[AuthScheme, str]] = None,
8282
auth_credential: Optional[Union[AuthCredential, str]] = None,
83+
credential_key: Optional[str] = None,
8384
):
8485
"""Initializes the ApplicationIntegrationTool.
8586
@@ -115,6 +116,7 @@ def __init__(
115116
self._rest_api_tool = rest_api_tool
116117
self._auth_scheme = auth_scheme
117118
self._auth_credential = auth_credential
119+
self._credential_key = credential_key
118120

119121
@override
120122
def _get_declaration(self) -> FunctionDeclaration:
@@ -156,7 +158,10 @@ async def run_async(
156158
) -> Dict[str, Any]:
157159

158160
tool_auth_handler = ToolAuthHandler.from_tool_context(
159-
tool_context, self._auth_scheme, self._auth_credential
161+
tool_context,
162+
self._auth_scheme,
163+
self._auth_credential,
164+
credential_key=self._credential_key,
160165
)
161166
auth_result = await tool_auth_handler.prepare_auth_credentials()
162167

tests/unittests/tools/application_integration_tool/test_application_integration_toolset.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ async def test_init_with_connection_and_custom_auth(
567567
tool_instructions=tool_instructions,
568568
auth_scheme=oauth2_scheme,
569569
auth_credential=auth_credential,
570+
credential_key="test-key",
570571
)
571572
mock_integration_client.assert_called_once_with(
572573
project,
@@ -594,6 +595,7 @@ async def test_init_with_connection_and_custom_auth(
594595
assert (await toolset.get_tools())[0]._operation == "EXECUTE_ACTION"
595596
assert (await toolset.get_tools())[0]._auth_scheme == oauth2_scheme
596597
assert (await toolset.get_tools())[0]._auth_credential == auth_credential
598+
assert (await toolset.get_tools())[0]._credential_key == "test-key"
597599

598600

599601
@pytest.mark.asyncio

tests/unittests/tools/application_integration_tool/test_integration_connector_tool.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from google.adk.tools.application_integration_tool.integration_connector_tool import IntegrationConnectorTool
2424
from google.adk.tools.openapi_tool.openapi_spec_parser.rest_api_tool import RestApiTool
2525
from google.adk.tools.openapi_tool.openapi_spec_parser.tool_auth_handler import AuthPreparationResult
26+
from google.adk.tools.openapi_tool.openapi_spec_parser.tool_auth_handler import ToolAuthHandler
2627
from google.genai.types import FunctionDeclaration
2728
from google.genai.types import Schema
2829
from google.genai.types import Type
@@ -96,6 +97,7 @@ def integration_tool_with_auth(mock_rest_api_tool):
9697
credentials=HttpCredentials(token="mocked_token"),
9798
),
9899
),
100+
credential_key="test-key",
99101
)
100102

101103

@@ -190,8 +192,8 @@ async def test_run_with_auth_async_none_token(
190192
"sortByColumns": ["a", "b"],
191193
}
192194

193-
with mock.patch(
194-
"google.adk.tools.openapi_tool.openapi_spec_parser.rest_api_tool.ToolAuthHandler.from_tool_context"
195+
with mock.patch.object(
196+
ToolAuthHandler, "from_tool_context", autospec=True
195197
) as mock_from_tool_context:
196198
mock_tool_auth_handler_instance = mock.MagicMock()
197199
# Simulate an AuthCredential that would cause _prepare_dynamic_euc to return None
@@ -214,6 +216,12 @@ async def test_run_with_auth_async_none_token(
214216
result = await integration_tool_with_auth.run_async(
215217
args=input_args, tool_context={}
216218
)
219+
mock_from_tool_context.assert_called_once_with(
220+
{},
221+
None,
222+
integration_tool_with_auth._auth_credential,
223+
credential_key="test-key",
224+
)
217225

218226
mock_rest_api_tool.call.assert_called_once_with(
219227
args=expected_call_args, tool_context={}
@@ -241,8 +249,8 @@ async def test_run_with_auth_async(
241249
"action": "TestAction",
242250
}
243251

244-
with mock.patch(
245-
"google.adk.tools.openapi_tool.openapi_spec_parser.rest_api_tool.ToolAuthHandler.from_tool_context"
252+
with mock.patch.object(
253+
ToolAuthHandler, "from_tool_context", autospec=True
246254
) as mock_from_tool_context:
247255
mock_tool_auth_handler_instance = mock.MagicMock()
248256

@@ -262,6 +270,12 @@ async def test_run_with_auth_async(
262270
result = await integration_tool_with_auth.run_async(
263271
args=input_args, tool_context={}
264272
)
273+
mock_from_tool_context.assert_called_once_with(
274+
{},
275+
None,
276+
integration_tool_with_auth._auth_credential,
277+
credential_key="test-key",
278+
)
265279
mock_rest_api_tool.call.assert_called_once_with(
266280
args=expected_call_args, tool_context={}
267281
)

0 commit comments

Comments
 (0)