Skip to content

Commit ad66660

Browse files
authored
Merge branch 'main' into feature/ollama-llm
2 parents b765e1e + f95ac48 commit ad66660

37 files changed

Lines changed: 2411 additions & 998 deletions

.github/workflows/pre-commit.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Copyright 2026 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+
name: pre-commit
16+
17+
on:
18+
push:
19+
branches: [main, v2]
20+
paths:
21+
- '**.py'
22+
- '.pre-commit-config.yaml'
23+
- 'pyproject.toml'
24+
pull_request:
25+
branches: [main, v2]
26+
paths:
27+
- '**.py'
28+
- '.pre-commit-config.yaml'
29+
- 'pyproject.toml'
30+
31+
jobs:
32+
pre-commit:
33+
runs-on: ubuntu-latest
34+
steps:
35+
- name: Checkout Code
36+
uses: actions/checkout@v6
37+
38+
- name: Run pre-commit checks
39+
uses: pre-commit/action@v3.0.1

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ You can install the latest stable version of ADK using `pip`:
6969
pip install google-adk
7070
```
7171

72+
To install optional integrations, you can use the following command:
73+
```bash
74+
pip install "google-adk[extensions]"
75+
```
76+
7277
The release cadence is roughly bi-weekly.
7378

7479
This version is recommended for most users as it represents the most recent official release.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ dependencies = [
3333
"fastapi>=0.124.1, <1.0.0", # FastAPI framework
3434
"google-api-python-client>=2.157.0, <3.0.0", # Google API client discovery
3535
"google-auth[pyopenssl]>=2.47.0", # Google Auth library
36-
"google-cloud-aiplatform[agent_engines]>=1.148.0, <2.0.0", # For VertexAI integrations, e.g. example store.
36+
"google-cloud-aiplatform[agent_engines]>=1.148.1, <2.0.0", # For VertexAI integrations, e.g. example store.
3737
"google-cloud-bigquery-storage>=2.0.0",
3838
"google-cloud-bigquery>=2.2.0",
3939
"google-cloud-bigtable>=2.32.0", # For Bigtable database
@@ -90,6 +90,7 @@ dev = [
9090
"flit>=3.10.0",
9191
"isort>=6.0.0",
9292
"mypy>=1.15.0",
93+
"pre-commit>=4.0.0",
9394
"pyink>=25.12.0",
9495
"pylint>=2.6.0",
9596
# go/keep-sorted end

src/google/adk/a2a/converters/from_adk_event.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ def _serialize_value(value: Any) -> Optional[Any]:
257257
try:
258258
dumped = value.model_dump(
259259
exclude_none=True,
260-
exclude_unset=True,
261260
exclude_defaults=True,
262261
by_alias=True,
263262
)

src/google/adk/agents/base_agent.py

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
import inspect
1818
import logging
19-
import sys
2019
from typing import Any
2120
from typing import AsyncGenerator
2221
from typing import Awaitable
@@ -43,8 +42,7 @@
4342
from ..events.event_actions import EventActions
4443
from ..features import experimental
4544
from ..features import FeatureName
46-
from ..telemetry import tracing
47-
from ..telemetry.tracing import tracer
45+
from ..telemetry import _instrumentation
4846
from ..utils.context_utils import Aclosing
4947
from .base_agent_config import BaseAgentConfig
5048
from .callback_context import CallbackContext
@@ -286,11 +284,8 @@ async def run_async(
286284
Event: the events generated by the agent.
287285
"""
288286

289-
cm = tracer.start_as_current_span(f'invoke_agent {self.name}')
290-
span = cm.__enter__()
291-
try:
292-
ctx = self._create_invocation_context(parent_context)
293-
tracing.trace_agent_invocation(span, self, ctx)
287+
ctx = self._create_invocation_context(parent_context)
288+
async with _instrumentation.record_agent_invocation(ctx, self):
294289
if event := await self._handle_before_agent_callback(ctx):
295290
yield event
296291
if ctx.end_invocation:
@@ -305,23 +300,6 @@ async def run_async(
305300

306301
if event := await self._handle_after_agent_callback(ctx):
307302
yield event
308-
except BaseException:
309-
try:
310-
cm.__exit__(*sys.exc_info())
311-
except ValueError:
312-
logger.warning(
313-
'Failed to detach context during generator cleanup, likely due to'
314-
' cancellation.'
315-
)
316-
raise
317-
else:
318-
try:
319-
cm.__exit__(None, None, None)
320-
except ValueError:
321-
logger.warning(
322-
'Failed to detach context during generator cleanup, likely due to'
323-
' cancellation.'
324-
)
325303

326304
@final
327305
async def run_live(
@@ -338,9 +316,8 @@ async def run_live(
338316
Event: the events generated by the agent.
339317
"""
340318

341-
with tracer.start_as_current_span(f'invoke_agent {self.name}') as span:
342-
ctx = self._create_invocation_context(parent_context)
343-
tracing.trace_agent_invocation(span, self, ctx)
319+
ctx = self._create_invocation_context(parent_context)
320+
async with _instrumentation.record_agent_invocation(ctx, self):
344321
if event := await self._handle_before_agent_callback(ctx):
345322
yield event
346323
if ctx.end_invocation:

src/google/adk/agents/config_agent_utils.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,31 @@ def _resolve_agent_class(agent_class: str) -> type[BaseAgent]:
8080
)
8181

8282

83+
_BLOCKED_YAML_KEYS = frozenset({"args"})
84+
_ENFORCE_DENYLIST = False
85+
86+
87+
def _set_enforce_denylist(value: bool) -> None:
88+
global _ENFORCE_DENYLIST
89+
_ENFORCE_DENYLIST = value
90+
91+
92+
def _check_config_for_blocked_keys(node: Any, filename: str) -> None:
93+
"""Recursively check if the configuration contains any blocked keys."""
94+
if isinstance(node, dict):
95+
for key, value in node.items():
96+
if key in _BLOCKED_YAML_KEYS:
97+
raise ValueError(
98+
f"Blocked key {key!r} found in {filename!r}. "
99+
f"The '{key}' field is not allowed in agent configurations "
100+
"because it can execute arbitrary code."
101+
)
102+
_check_config_for_blocked_keys(value, filename)
103+
elif isinstance(node, list):
104+
for item in node:
105+
_check_config_for_blocked_keys(item, filename)
106+
107+
83108
def _load_config_from_path(config_path: str) -> AgentConfig:
84109
"""Load an agent's configuration from a YAML file.
85110
@@ -100,6 +125,9 @@ def _load_config_from_path(config_path: str) -> AgentConfig:
100125
with open(config_path, "r", encoding="utf-8") as f:
101126
config_data = yaml.safe_load(f)
102127

128+
if _ENFORCE_DENYLIST:
129+
_check_config_for_blocked_keys(config_data, config_path)
130+
103131
return AgentConfig.model_validate(config_data)
104132

105133

src/google/adk/cli/browser/index.html

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

src/google/adk/cli/browser/main-3OBAHHYV.js renamed to src/google/adk/cli/browser/main-TCIQIOZ3.js

Lines changed: 186 additions & 186 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/adk/cli/fast_api.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ def get_fast_api_app(
148148
The configured FastAPI application instance.
149149
"""
150150

151+
# Enable denylist enforcement for config loads if web UI is enabled.
152+
if web:
153+
from ..agents import config_agent_utils
154+
155+
config_agent_utils._set_enforce_denylist(True)
156+
151157
# Set up eval managers.
152158
if eval_storage_uri:
153159
gcs_eval_managers = evals.create_gcs_eval_managers_from_uri(

src/google/adk/features/_feature_registry.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ class FeatureName(str, Enum):
4141
GOOGLE_CREDENTIALS_CONFIG = "GOOGLE_CREDENTIALS_CONFIG"
4242
GOOGLE_TOOL = "GOOGLE_TOOL"
4343
JSON_SCHEMA_FOR_FUNC_DECL = "JSON_SCHEMA_FOR_FUNC_DECL"
44+
# Private (leading underscore): not part of the public API surface.
45+
# GE flips this on by setting the env var
46+
# `ADK_ENABLE_MCP_GRACEFUL_ERROR_HANDLING=1`; nothing should import this
47+
# enum member by name. Keeping it private avoids a backward-compat
48+
# obligation for what is intended as a temporary, internal kill-switch.
49+
_MCP_GRACEFUL_ERROR_HANDLING = "MCP_GRACEFUL_ERROR_HANDLING"
4450
PROGRESSIVE_SSE_STREAMING = "PROGRESSIVE_SSE_STREAMING"
4551
PUBSUB_TOOL_CONFIG = "PUBSUB_TOOL_CONFIG"
4652
PUBSUB_TOOLSET = "PUBSUB_TOOLSET"
@@ -131,6 +137,9 @@ class FeatureConfig:
131137
FeatureName.JSON_SCHEMA_FOR_FUNC_DECL: FeatureConfig(
132138
FeatureStage.WIP, default_on=False
133139
),
140+
FeatureName._MCP_GRACEFUL_ERROR_HANDLING: FeatureConfig(
141+
FeatureStage.EXPERIMENTAL, default_on=False
142+
),
134143
FeatureName.PROGRESSIVE_SSE_STREAMING: FeatureConfig(
135144
FeatureStage.EXPERIMENTAL, default_on=True
136145
),

0 commit comments

Comments
 (0)