Skip to content

Commit 2ceb2cc

Browse files
authored
Merge branch 'main' into feat/bigquery-default-attributes
2 parents d0d01f4 + 21f63f6 commit 2ceb2cc

File tree

9 files changed

+234
-0
lines changed

9 files changed

+234
-0
lines changed

src/google/adk/cli/cli_deploy.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ def to_agent_engine(
689689
adk_app: str,
690690
staging_bucket: Optional[str] = None,
691691
trace_to_cloud: Optional[bool] = None,
692+
otel_to_cloud: Optional[bool] = None,
692693
api_key: Optional[str] = None,
693694
adk_app_object: Optional[str] = None,
694695
agent_engine_id: Optional[str] = None,
@@ -733,6 +734,8 @@ def to_agent_engine(
733734
staging_bucket (str): Deprecated. This argument is no longer required or
734735
used.
735736
trace_to_cloud (bool): Whether to enable Cloud Trace.
737+
otel_to_cloud (bool): Whether to enable exporting OpenTelemetry signals
738+
to Google Cloud.
736739
api_key (str): Optional. The API key to use for Express Mode.
737740
If not provided, the API key from the GOOGLE_API_KEY environment variable
738741
will be used. It will only be used if GOOGLE_GENAI_USE_VERTEXAI is true.
@@ -910,6 +913,14 @@ def to_agent_engine(
910913
if 'GOOGLE_API_KEY' in env_vars:
911914
api_key = env_vars['GOOGLE_API_KEY']
912915
click.echo(f'api_key set by GOOGLE_API_KEY in {env_file}')
916+
if otel_to_cloud:
917+
if 'GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY' in env_vars:
918+
click.secho(
919+
'Ignoring GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY in .env'
920+
' as `--otel_to_cloud` was explicitly passed and takes precedence',
921+
fg='yellow',
922+
)
923+
env_vars['GOOGLE_CLOUD_AGENT_ENGINE_ENABLE_TELEMETRY'] = 'true'
913924
if env_vars:
914925
if 'env_vars' in agent_config:
915926
click.echo(

src/google/adk/cli/cli_tools_click.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,14 @@ def cli_migrate_session(
17511751
default=None,
17521752
help="Optional. Whether to enable Cloud Trace for Agent Engine.",
17531753
)
1754+
@click.option(
1755+
"--otel_to_cloud",
1756+
type=bool,
1757+
is_flag=True,
1758+
show_default=True,
1759+
default=None,
1760+
help="Optional. Whether to enable OpenTelemetry for Agent Engine.",
1761+
)
17541762
@click.option(
17551763
"--display_name",
17561764
type=str,
@@ -1842,6 +1850,7 @@ def cli_deploy_agent_engine(
18421850
staging_bucket: Optional[str],
18431851
agent_engine_id: Optional[str],
18441852
trace_to_cloud: Optional[bool],
1853+
otel_to_cloud: Optional[bool],
18451854
api_key: Optional[str],
18461855
display_name: str,
18471856
description: str,
@@ -1872,6 +1881,7 @@ def cli_deploy_agent_engine(
18721881
region=region,
18731882
agent_engine_id=agent_engine_id,
18741883
trace_to_cloud=trace_to_cloud,
1884+
otel_to_cloud=otel_to_cloud,
18751885
api_key=api_key,
18761886
adk_app_object=adk_app_object,
18771887
display_name=display_name,

src/google/adk/tools/load_artifacts_tool.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
from google.genai import types
2525
from typing_extensions import override
2626

27+
from ..features import FeatureName
28+
from ..features import is_feature_enabled
2729
from .base_tool import BaseTool
2830

2931
# MIME types Gemini accepts for inline data in requests.
@@ -132,6 +134,20 @@ def __init__(self):
132134
)
133135

134136
def _get_declaration(self) -> types.FunctionDeclaration | None:
137+
if is_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL):
138+
return types.FunctionDeclaration(
139+
name=self.name,
140+
description=self.description,
141+
parameters_json_schema={
142+
'type': 'object',
143+
'properties': {
144+
'artifact_names': {
145+
'type': 'array',
146+
'items': {'type': 'string'},
147+
},
148+
},
149+
},
150+
)
135151
return types.FunctionDeclaration(
136152
name=self.name,
137153
description=self.description,

src/google/adk/tools/load_memory_tool.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
from pydantic import Field
2222
from typing_extensions import override
2323

24+
from ..features import FeatureName
25+
from ..features import is_feature_enabled
2426
from ..memory.memory_entry import MemoryEntry
2527
from .function_tool import FunctionTool
2628
from .tool_context import ToolContext
@@ -59,6 +61,18 @@ def __init__(self):
5961

6062
@override
6163
def _get_declaration(self) -> types.FunctionDeclaration | None:
64+
if is_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL):
65+
return types.FunctionDeclaration(
66+
name=self.name,
67+
description=self.description,
68+
parameters_json_schema={
69+
'type': 'object',
70+
'properties': {
71+
'query': {'type': 'string'},
72+
},
73+
'required': ['query'],
74+
},
75+
)
6276
return types.FunctionDeclaration(
6377
name=self.name,
6478
description=self.description,

src/google/adk/tools/retrieval/base_retrieval_tool.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,34 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
from __future__ import annotations
16+
1517
from google.genai import types
1618
from typing_extensions import override
1719

20+
from ...features import FeatureName
21+
from ...features import is_feature_enabled
1822
from ..base_tool import BaseTool
1923

2024

2125
class BaseRetrievalTool(BaseTool):
2226

2327
@override
2428
def _get_declaration(self) -> types.FunctionDeclaration:
29+
if is_feature_enabled(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL):
30+
return types.FunctionDeclaration(
31+
name=self.name,
32+
description=self.description,
33+
parameters_json_schema={
34+
'type': 'object',
35+
'properties': {
36+
'query': {
37+
'type': 'string',
38+
'description': 'The query to retrieve.',
39+
},
40+
},
41+
},
42+
)
2543
return types.FunctionDeclaration(
2644
name=self.name,
2745
description=self.description,

tests/unittests/cli/utils/test_cli_tools_click.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,38 @@ def test_cli_deploy_agent_engine_success(
410410
assert called_kwargs.get("region") == "us-central1"
411411

412412

413+
# cli deploy agent_engine with --otel_to_cloud
414+
def test_cli_deploy_agent_engine_otel_to_cloud_success(
415+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
416+
) -> None:
417+
"""Successful path should call cli_deploy.to_agent_engine with --otel_to_cloud."""
418+
rec = _Recorder()
419+
monkeypatch.setattr(cli_tools_click.cli_deploy, "to_agent_engine", rec)
420+
421+
agent_dir = tmp_path / "agent_ae"
422+
agent_dir.mkdir()
423+
runner = CliRunner()
424+
result = runner.invoke(
425+
cli_tools_click.main,
426+
[
427+
"deploy",
428+
"agent_engine",
429+
"--project",
430+
"test-proj",
431+
"--region",
432+
"us-central1",
433+
"--otel_to_cloud",
434+
str(agent_dir),
435+
],
436+
)
437+
assert result.exit_code == 0
438+
assert rec.calls, "cli_deploy.to_agent_engine must be invoked"
439+
called_kwargs = rec.calls[0][1]
440+
assert called_kwargs.get("project") == "test-proj"
441+
assert called_kwargs.get("region") == "us-central1"
442+
assert called_kwargs.get("otel_to_cloud")
443+
444+
413445
# cli deploy gke
414446
def test_cli_deploy_gke_success(
415447
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.adk.features import FeatureName
16+
from google.adk.features._feature_registry import temporary_feature_override
17+
from google.adk.tools.retrieval.base_retrieval_tool import BaseRetrievalTool
18+
from google.genai import types
19+
20+
21+
class _TestRetrievalTool(BaseRetrievalTool):
22+
"""Concrete implementation of BaseRetrievalTool for testing."""
23+
24+
def __init__(self):
25+
super().__init__(
26+
name='test_retrieval',
27+
description='A test retrieval tool.',
28+
)
29+
30+
async def run_async(self, *, args, tool_context):
31+
return {'result': 'test'}
32+
33+
34+
def test_get_declaration_with_json_schema_feature_disabled():
35+
"""Test that _get_declaration uses parameters when feature is disabled."""
36+
tool = _TestRetrievalTool()
37+
38+
with temporary_feature_override(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, False):
39+
declaration = tool._get_declaration()
40+
41+
assert declaration.name == 'test_retrieval'
42+
assert declaration.description == 'A test retrieval tool.'
43+
assert declaration.parameters_json_schema is None
44+
assert isinstance(declaration.parameters, types.Schema)
45+
assert declaration.parameters.type == types.Type.OBJECT
46+
assert 'query' in declaration.parameters.properties
47+
48+
49+
def test_get_declaration_with_json_schema_feature_enabled():
50+
"""Test that _get_declaration uses parameters_json_schema when feature is enabled."""
51+
tool = _TestRetrievalTool()
52+
53+
with temporary_feature_override(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, True):
54+
declaration = tool._get_declaration()
55+
56+
assert declaration.name == 'test_retrieval'
57+
assert declaration.description == 'A test retrieval tool.'
58+
assert declaration.parameters is None
59+
assert declaration.parameters_json_schema == {
60+
'type': 'object',
61+
'properties': {
62+
'query': {
63+
'type': 'string',
64+
'description': 'The query to retrieve.',
65+
},
66+
},
67+
}

tests/unittests/tools/test_load_artifacts_tool.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
import base64
1616

17+
from google.adk.features import FeatureName
18+
from google.adk.features._feature_registry import temporary_feature_override
1719
from google.adk.models.llm_request import LlmRequest
1820
from google.adk.tools.load_artifacts_tool import _maybe_base64_to_bytes
1921
from google.adk.tools.load_artifacts_tool import load_artifacts_tool
@@ -160,3 +162,21 @@ def test_maybe_base64_to_bytes_returns_none_for_invalid():
160162
"""Invalid base64 strings return None."""
161163
# Single character is invalid (base64 requires length % 4 == 0 after padding)
162164
assert _maybe_base64_to_bytes('x') is None
165+
166+
167+
def test_get_declaration_with_json_schema_feature_enabled():
168+
"""Test that _get_declaration uses parameters_json_schema when feature is enabled."""
169+
with temporary_feature_override(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, True):
170+
declaration = load_artifacts_tool._get_declaration()
171+
172+
assert declaration.name == 'load_artifacts'
173+
assert declaration.parameters is None
174+
assert declaration.parameters_json_schema == {
175+
'type': 'object',
176+
'properties': {
177+
'artifact_names': {
178+
'type': 'array',
179+
'items': {'type': 'string'},
180+
},
181+
},
182+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.adk.features import FeatureName
16+
from google.adk.features._feature_registry import temporary_feature_override
17+
from google.adk.tools.load_memory_tool import load_memory_tool
18+
from google.genai import types
19+
20+
21+
def test_get_declaration_with_json_schema_feature_disabled():
22+
"""Test that _get_declaration uses parameters when feature is disabled."""
23+
with temporary_feature_override(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, False):
24+
declaration = load_memory_tool._get_declaration()
25+
26+
assert declaration.name == 'load_memory'
27+
assert declaration.parameters_json_schema is None
28+
assert isinstance(declaration.parameters, types.Schema)
29+
assert declaration.parameters.type == types.Type.OBJECT
30+
assert 'query' in declaration.parameters.properties
31+
32+
33+
def test_get_declaration_with_json_schema_feature_enabled():
34+
"""Test that _get_declaration uses parameters_json_schema when feature is enabled."""
35+
with temporary_feature_override(FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, True):
36+
declaration = load_memory_tool._get_declaration()
37+
38+
assert declaration.name == 'load_memory'
39+
assert declaration.parameters is None
40+
assert declaration.parameters_json_schema == {
41+
'type': 'object',
42+
'properties': {
43+
'query': {'type': 'string'},
44+
},
45+
'required': ['query'],
46+
}

0 commit comments

Comments
 (0)