Skip to content

Commit 101a92d

Browse files
authored
Merge branch 'main' into fix/pydantic-v2-swagger-ui
2 parents 0de0526 + 7cf1e44 commit 101a92d

File tree

21 files changed

+1967
-34
lines changed

21 files changed

+1967
-34
lines changed

CHANGELOG.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,88 @@
11
# Changelog
22

3+
## [1.23.0](https://github.com/google/adk-python/compare/v1.22.1...v1.23.0) (2026-01-22)
4+
5+
### ⚠ BREAKING CHANGES
6+
7+
* Breaking: Use OpenTelemetry for BigQuery plugin tracing, replacing custom `ContextVar` implementation ([ab89d12](https://github.com/google/adk-python/commit/ab89d1283430041afb303834749869e9ee331721))
8+
* Add support to automatically create a session if one does not exist ([8e69a58](https://github.com/google/adk-python/commit/8e69a58df4eadeccbb100b7264bb518a46b61fd7))
9+
10+
### Features
11+
12+
* **[Core]**
13+
* Remove `@experimental` decorator from `AgentEngineSandboxCodeExecutor` ([135f763](https://github.com/google/adk-python/commit/135f7633253f6a415302142abc3579b664601d5b))
14+
* Add `--disable_features` CLI option to override default feature enable state ([53b67ce](https://github.com/google/adk-python/commit/53b67ce6340f3f3f8c3d732f9f7811e445c76359))
15+
* Add `otel_to_cloud` flag to `adk deploy agent_engine` command ([21f63f6](https://github.com/google/adk-python/commit/21f63f66ee424501d9a70806277463ef718ae843))
16+
* Add `is_computer_use` field to agent information in `adk-web` server ([5923da7](https://github.com/google/adk-python/commit/5923da786eb1aaef6f0bcbc6adc906cbc8bf9b36))
17+
* Allow `thinking_config` in `generate_content_config` ([e162bb8](https://github.com/google/adk-python/commit/e162bb8832a806e2380048e39165bf837455f88c))
18+
* Convert A2UI messages between A2A `DataPart` metadata and ADK events ([1133ce2](https://github.com/google/adk-python/commit/1133ce219c5a7a9a85222b03e348ba6b13830c8f))
19+
* Add `--enable_features` CLI option to override default feature enable state ([79fcddb](https://github.com/google/adk-python/commit/79fcddb39f71a4c1342e63b4d67832b3eccb2652))
20+
21+
* **[Tools]**
22+
* Add flush mechanism to `BigQueryAgentAnalyticsPlugin` to ensure pending log events are written to BigQuery ([9579bea](https://github.com/google/adk-python/commit/9579bea05d946b3d8b4bfec35e510725dd371224))
23+
* Allow Google Search tool to set a different model ([b57a3d4](https://github.com/google/adk-python/commit/b57a3d43e4656f5a3c5db53addff02b67d1fde26))
24+
* Support authentication for MCP tool listing ([e3d542a](https://github.com/google/adk-python/commit/e3d542a5ba3d357407f8cd29cfdd722f583c8564) [19315fe](https://github.com/google/adk-python/commit/19315fe557039fa8bf446525a4830b1c9f40cba9))
25+
* Use JSON schema for `base_retrieval_tool`, `load_artifacts_tool`, and `load_memory_tool` declarations when the feature is enabled ([69ad605](https://github.com/google/adk-python/commit/69ad605bc4bbe9a4f018127fd3625169ee70488e))
26+
* Use JSON schema for `IntegrationConnectorTool` declaration when the feature is enabled ([2ed6865](https://github.com/google/adk-python/commit/2ed686527ac75ff64128ce7d9b1a3befc2b37c64))
27+
* Start and close `ClientSession` in a single task in `McpSessionManager` ([cce430d](https://github.com/google/adk-python/commit/cce430da799766686e65f6cae02ba64e916d5c8a))
28+
* Use JSON schema for `RestApiTool` declaration when the feature is enabled ([a5f0d33](https://github.com/google/adk-python/commit/a5f0d333d7f26f2966ed511d5d9def7a1933f0c2))
29+
30+
* **[Evals]**
31+
* Update `adk eval` CLI to consume custom metrics by adding `CustomMetricEvaluator` ([ea0934b](https://github.com/google/adk-python/commit/ea0934b9934c1fefd129a1026d6af369f126870e))
32+
* Update `EvalConfig` and `EvalMetric` data models to support custom metrics ([6d2f33a](https://github.com/google/adk-python/commit/6d2f33a59cfba358dd758378290125fc2701c411))
33+
34+
* **[Observability]**
35+
* Add minimal `generate_content {model.name}` spans and logs for non-Gemini inference and when `opentelemetry-inference-google-genai` dependency is missing ([935c279](https://github.com/google/adk-python/commit/935c279f8281bde99224f03d936b8abe51cbabfc))
36+
37+
* **[Integrations]**
38+
* Enhance `TraceManager` asynchronous safety, enrich BigQuery plugin logging, and fix serialization ([a4116a6](https://github.com/google/adk-python/commit/a4116a6cbfadc161982af5dabd55a711d79348b7))
39+
40+
* **[Live]**
41+
* Persist user input content to session in live mode ([a04828d](https://github.com/google/adk-python/commit/a04828dd8a848482acbd48acc7da432d0d2cb0aa))
42+
43+
### Bug Fixes
44+
45+
* Recursively extract input/output schema for AgentTool ([bf2b56d](https://github.com/google/adk-python/commit/bf2b56de6d0052e40b6d871b2d22c56e9225e145))
46+
* Yield buffered `function_call` and `function_response` events during live streaming ([7b25b8f](https://github.com/google/adk-python/commit/7b25b8fb1daf54d7694bf405d545d46d2c012d2b))
47+
* Update `authlib` and `mcp` dependency versions ([7955177](https://github.com/google/adk-python/commit/7955177fb28b8e5dc19aae8be94015a7b5d9882a))
48+
* Set `LITELLM_MODE` to `PRODUCTION` before importing LiteLLM to prevent implicit `.env` file loading ([215c2f5](https://github.com/google/adk-python/commit/215c2f506e21a3d8c39551b80f6356943ecae320))
49+
* Redact sensitive information from URIs in logs ([5257869](https://github.com/google/adk-python/commit/5257869d91a77ebd1381538a85e7fdc3a600da90))
50+
* Handle asynchronous driver URLs in the migration tool ([4b29d15](https://github.com/google/adk-python/commit/4b29d15b3e5df65f3503daffa6bc7af85159507b))
51+
* Remove custom metadata from A2A response events ([81eaeb5](https://github.com/google/adk-python/commit/81eaeb5eba6d40cde0cf6147d96921ed1bf7bb31))
52+
* Handle `None` inferences in eval results ([7d4326c](https://github.com/google/adk-python/commit/7d4326c3606a7ff2ba3c0fdef08d4f6af52ee71e))
53+
* Mark all parts of a thought event as thought ([f92d4e3](https://github.com/google/adk-python/commit/f92d4e397f37445fe9032a95ce26646a3a69300b))
54+
* Use `json.dumps` for error messages in SSE events ([6ad18cc](https://github.com/google/adk-python/commit/6ad18cc2fc3a3315a0fc240cb51b3283b53116b4))
55+
* Use the correct path for config-based agents when deploying to AgentEngine ([83d7bb6](https://github.com/google/adk-python/commit/83d7bb6ef0d952ad04c5d9a61aaf202672c7e17d))
56+
* Support Generator and Async Generator tool declarations in JSON schema ([19555e7](https://github.com/google/adk-python/commit/19555e7dce6d60c3b960ca0bc2f928c138ac3cc0) [7c28297](https://github.com/google/adk-python/commit/7c282973ea193841fee79f90b8a91c5e02627ccc))
57+
* Prevent stopping event processing on events with `None` content ([ed2c3eb](https://github.com/google/adk-python/commit/ed2c3ebde9cafbb5e2bf375f44db1e77cee9fb24))
58+
* Fix `'NoneType'` object is not iterable error ([7db3ce9](https://github.com/google/adk-python/commit/7db3ce9613b1c2c97e6ca3cd8115736516dc1556))
59+
* Use canonical tools to find streaming tools and register them by `tool.name` ([ec6abf4](https://github.com/google/adk-python/commit/ec6abf401019c39e8e1a8d1b2c7d5cf5e8c7ac56))
60+
* Initialize `self._auth_config` inside `BaseAuthenticatedTool` to access authentication headers in `McpTool` ([d4da1bb](https://github.com/google/adk-python/commit/d4da1bb7330cdb87c1dcbe0b9023148357a6bd07))
61+
* Only filter out audio content when sending history ([712b5a3](https://github.com/google/adk-python/commit/712b5a393d44e7b5ce35fc459da98361bae4bb16))
62+
* Add finish reason mapping and remove custom file URI handling in LiteLLM ([89bed43](https://github.com/google/adk-python/commit/89bed43f5e0c5ad12dd31c716d372145b7e33e78))
63+
* Convert unsupported inline artifact MIME types to text in `LoadArtifactsTool` ([fdc98d5](https://github.com/google/adk-python/commit/fdc98d5c927bfef021e87cf72103892e4c2ac12a))
64+
* Pass `log_level` to `uvicorn` in `web` and `api_server` commands ([38d52b2](https://github.com/google/adk-python/commit/38d52b247600fb45a2beeb041c4698e90c00d705))
65+
* Use the agent name as the author of the audio event ([ab62b1b](https://github.com/google/adk-python/commit/ab62b1bffd7ad2df5809d430ad1823872b8bd67a))
66+
* Handle `NOT_FOUND` error when fetching Vertex AI sessions ([75231a3](https://github.com/google/adk-python/commit/75231a30f1857d930804769caf88bcc20839dd08))
67+
* Fix `httpx` client closure during event pagination ([b725045](https://github.com/google/adk-python/commit/b725045e5a1192bc9fd5190cbd2758ab6ff02590))
68+
69+
### Improvements
70+
71+
* Add new conversational analytics API toolset ([82fa10b](https://github.com/google/adk-python/commit/82fa10b71e037b565cb407c82e9e908432dab0ff))
72+
* Filter out `adk_request_input` event from content list ([295b345](https://github.com/google/adk-python/commit/295b34558774d1f64022009980e3edd8eb79527b))
73+
* Always skip executing partial function calls ([d62f9c8](https://github.com/google/adk-python/commit/d62f9c896c301aba3a781e868735e16f946a8862))
74+
* Update comments of request confirmation preprocessor ([1699b09](https://github.com/google/adk-python/commit/1699b090edc9e5b13c34f461c8e664187157c5c0))
75+
* Fix various typos ([a8f2ddd](https://github.com/google/adk-python/commit/a8f2ddd943301bbf53f49b3a23300ece45803cc0))
76+
* Update sample live streaming tools agent to use latest live models ([3dd7e3f](https://github.com/google/adk-python/commit/3dd7e3f1b9be05c28adb061864d84c4202a2d922))
77+
* Make the regex to catch CLI reference strict by adding word boundary anchor ([c222a45](https://github.com/google/adk-python/commit/c222a45ef74f7b55c48dc151ba98cd8c30a15c57))
78+
* Migrate `ToolboxToolset` to use `toolbox-adk` and align validation ([7dc6adf](https://github.com/google/adk-python/commit/7dc6adf4e563330a09e4cf28d2b1994c24b007d1) [277084e](https://github.com/google/adk-python/commit/277084e31368302e6338b69d456affd35d5fedfe))
79+
* Always log API backend when connecting to live model ([7b035aa](https://github.com/google/adk-python/commit/7b035aa9fc43a43489aeffea8f877cd7eaa09f35))
80+
* Add a sample BigQuery agent using BigQuery MCP tools ([672b57f](https://github.com/google/adk-python/commit/672b57f1b76580023d1f348de76227291a9c1012))
81+
* Add a `DebugLoggingPlugin` to record human-readable debugging logs ([8973618](https://github.com/google/adk-python/commit/8973618b0b0e90c513873e22af272c147efb4904))
82+
* Upgrade the sample BigQuery agent model version to `gemini-2.5-flash` ([fd2c0f5](https://github.com/google/adk-python/commit/fd2c0f556b786417a9f6add744827b07e7a06b7d))
83+
* Import `migration_runner` lazily within the migrate command ([905604f](https://github.com/google/adk-python/commit/905604faac82aca8ae0935eebea288f82985e9c5))
84+
85+
386

487
## [1.22.1](https://github.com/google/adk-python/compare/v1.22.0...v1.22.1) (2026-01-09)
588

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Data Agent Sample
2+
3+
This sample agent demonstrates ADK's first-party tools for interacting with
4+
Data Agents powered by [Conversational Analytics API](https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/overview).
5+
These tools are distributed via
6+
the `google.adk.tools.data_agent` module and allow you to list,
7+
inspect, and
8+
chat with Data Agents using natural language.
9+
10+
These tools leverage stateful conversations, meaning you can ask follow-up
11+
questions in the same session, and the agent will maintain context.
12+
13+
## Prerequisites
14+
15+
1. An active Google Cloud project with BigQuery and Gemini APIs enabled.
16+
2. Google Cloud authentication configured for Application Default Credentials:
17+
```bash
18+
gcloud auth application-default login
19+
```
20+
3. At least one Data Agent created. You could create data agents via
21+
[Conversational API](https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/overview),
22+
its
23+
[Python SDK](https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/build-agent-sdk),
24+
or for BigQuery data
25+
[BigQuery Studio](https://docs.cloud.google.com/bigquery/docs/create-data-agents#create_a_data_agent).
26+
These agents are created and configured in the Google Cloud console and
27+
point to your BigQuery tables or other data sources.
28+
4. Follow the official
29+
[Setup and prerequisites](https://docs.cloud.google.com/gemini/docs/conversational-analytics-api/overview#setup)
30+
guide to enable the API and configure IAM permissions and authentication for
31+
your data sources.
32+
33+
## Tools Used
34+
35+
* `list_accessible_data_agents`: Lists Data Agents you have permission to
36+
access in the configured GCP project.
37+
* `get_data_agent_info`: Retrieves details about a specific Data Agent given
38+
its full resource name.
39+
* `ask_data_agent`: Chats with a specific Data Agent using natural language.
40+
This tool maintains conversation state: if you ask multiple
41+
questions to the same agent in one session, it will use the same
42+
conversation, allowing for follow-ups. If you switch agents, a new
43+
conversation will be started for the new agent.
44+
45+
## How to Run
46+
47+
1. Navigate to the root of the ADK repository.
48+
2. Run the agent using the ADK CLI:
49+
```bash
50+
adk run --agent-path contributing/samples/data_agent
51+
```
52+
3. The CLI will prompt you for input. You can ask questions like the examples
53+
below.
54+
55+
## Sample prompts
56+
57+
* "List accessible data agents."
58+
* "Using agent
59+
`projects/my-project/locations/global/dataAgents/sales-agent-123`, who were
60+
my top 3 customers last quarter?"
61+
* "How does that compare to the quarter before?"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
from . import agent
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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+
import os
16+
17+
from google.adk.agents import Agent
18+
from google.adk.auth.auth_credential import AuthCredentialTypes
19+
from google.adk.tools.data_agent.config import DataAgentToolConfig
20+
from google.adk.tools.data_agent.credentials import DataAgentCredentialsConfig
21+
from google.adk.tools.data_agent.data_agent_toolset import DataAgentToolset
22+
import google.auth
23+
import google.auth.transport.requests
24+
25+
# Define the desired credential type.
26+
# By default use Application Default Credentials (ADC) from the local
27+
# environment, which can be set up by following
28+
# https://cloud.google.com/docs/authentication/provide-credentials-adc.
29+
CREDENTIALS_TYPE = None
30+
31+
if CREDENTIALS_TYPE == AuthCredentialTypes.OAUTH2:
32+
# Initiaze the tools to do interactive OAuth
33+
# The environment variables OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET
34+
# must be set
35+
credentials_config = DataAgentCredentialsConfig(
36+
client_id=os.getenv("OAUTH_CLIENT_ID"),
37+
client_secret=os.getenv("OAUTH_CLIENT_SECRET"),
38+
)
39+
elif CREDENTIALS_TYPE == AuthCredentialTypes.SERVICE_ACCOUNT:
40+
# Initialize the tools to use the credentials in the service account key.
41+
# If this flow is enabled, make sure to replace the file path with your own
42+
# service account key file
43+
# https://cloud.google.com/iam/docs/service-account-creds#user-managed-keys
44+
creds, _ = google.auth.load_credentials_from_file(
45+
"service_account_key.json",
46+
scopes=["https://www.googleapis.com/auth/cloud-platform"],
47+
)
48+
creds.refresh(google.auth.transport.requests.Request())
49+
credentials_config = DataAgentCredentialsConfig(credentials=creds)
50+
else:
51+
# Initialize the tools to use the application default credentials.
52+
# https://cloud.google.com/docs/authentication/provide-credentials-adc
53+
application_default_credentials, _ = google.auth.default()
54+
credentials_config = DataAgentCredentialsConfig(
55+
credentials=application_default_credentials
56+
)
57+
58+
tool_config = DataAgentToolConfig(
59+
max_query_result_rows=100,
60+
)
61+
da_toolset = DataAgentToolset(
62+
credentials_config=credentials_config,
63+
data_agent_tool_config=tool_config,
64+
tool_filter=[
65+
"list_accessible_data_agents",
66+
"get_data_agent_info",
67+
"ask_data_agent",
68+
],
69+
)
70+
71+
root_agent = Agent(
72+
name="data_agent",
73+
model="gemini-2.0-flash",
74+
description="Agent to answer user questions using Data Agents.",
75+
instruction=(
76+
"## Persona\nYou are a helpful assistant that uses Data Agents"
77+
" to answer user questions about their data.\n\n## Tools\n- You can"
78+
" list available data agents using `list_accessible_data_agents`.\n-"
79+
" You can get information about a specific data agent using"
80+
" `get_data_agent_info`.\n- You can chat with a specific data"
81+
" agent using `ask_data_agent`.\n"
82+
),
83+
tools=[da_toolset],
84+
)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ test = [
126126
"litellm>=1.75.5, <1.80.17", # For LiteLLM tests
127127
"llama-index-readers-file>=0.4.0", # For retrieval tests
128128
"openai>=1.100.2", # For LiteLLM
129+
"opentelemetry-instrumentation-google-genai>=0.3b0, <1.0.0",
129130
"pytest-asyncio>=0.25.0",
130131
"pytest-mock>=3.14.0",
131132
"pytest-xdist>=3.6.1",

src/google/adk/features/_feature_registry.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class FeatureName(str, Enum):
3333
BIGTABLE_TOOL_SETTINGS = "BIGTABLE_TOOL_SETTINGS"
3434
BIGTABLE_TOOLSET = "BIGTABLE_TOOLSET"
3535
COMPUTER_USE = "COMPUTER_USE"
36+
DATA_AGENT_TOOL_CONFIG = "DATA_AGENT_TOOL_CONFIG"
37+
DATA_AGENT_TOOLSET = "DATA_AGENT_TOOLSET"
3638
GOOGLE_CREDENTIALS_CONFIG = "GOOGLE_CREDENTIALS_CONFIG"
3739
GOOGLE_TOOL = "GOOGLE_TOOL"
3840
JSON_SCHEMA_FOR_FUNC_DECL = "JSON_SCHEMA_FOR_FUNC_DECL"
@@ -97,6 +99,12 @@ class FeatureConfig:
9799
FeatureName.COMPUTER_USE: FeatureConfig(
98100
FeatureStage.EXPERIMENTAL, default_on=True
99101
),
102+
FeatureName.DATA_AGENT_TOOL_CONFIG: FeatureConfig(
103+
FeatureStage.EXPERIMENTAL, default_on=True
104+
),
105+
FeatureName.DATA_AGENT_TOOLSET: FeatureConfig(
106+
FeatureStage.EXPERIMENTAL, default_on=True
107+
),
100108
FeatureName.GOOGLE_CREDENTIALS_CONFIG: FeatureConfig(
101109
FeatureStage.EXPERIMENTAL, default_on=True
102110
),

src/google/adk/flows/llm_flows/base_llm_flow.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
from ...models.base_llm_connection import BaseLlmConnection
4242
from ...models.llm_request import LlmRequest
4343
from ...models.llm_response import LlmResponse
44+
from ...telemetry import tracing
4445
from ...telemetry.tracing import trace_call_llm
4546
from ...telemetry.tracing import trace_send_data
4647
from ...telemetry.tracing import tracer
@@ -771,7 +772,7 @@ async def _call_llm_async(
771772
llm = self.__get_llm(invocation_context)
772773

773774
async def _call_llm_with_tracing() -> AsyncGenerator[LlmResponse, None]:
774-
with tracer.start_as_current_span('call_llm'):
775+
with tracer.start_as_current_span('call_llm') as span:
775776
if invocation_context.run_config.support_cfc:
776777
invocation_context.live_request_queue = LiveRequestQueue()
777778
responses_generator = self.run_live(invocation_context)
@@ -822,6 +823,7 @@ async def _call_llm_with_tracing() -> AsyncGenerator[LlmResponse, None]:
822823
model_response_event.id,
823824
llm_request,
824825
llm_response,
826+
span,
825827
)
826828
# Runs after_model_callback if it exists.
827829
if altered_llm_response := await self._handle_after_model_callback(
@@ -1050,8 +1052,12 @@ async def _run_on_model_error_callbacks(
10501052

10511053
try:
10521054
async with Aclosing(response_generator) as agen:
1053-
async for response in agen:
1054-
yield response
1055+
with tracing.use_generate_content_span(
1056+
llm_request, invocation_context, model_response_event
1057+
) as span:
1058+
async for llm_response in agen:
1059+
tracing.trace_generate_content_result(span, llm_response)
1060+
yield llm_response
10551061
except Exception as model_error:
10561062
callback_context = CallbackContext(
10571063
invocation_context, event_actions=model_response_event.actions

0 commit comments

Comments
 (0)