Skip to content

Commit 297376d

Browse files
authored
Merge branch 'main' into main
2 parents 941d24b + 0094eea commit 297376d

26 files changed

Lines changed: 1847 additions & 427 deletions
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# BigQuery API Registry Agent
2+
3+
This agent demonstrates how to use `ApiRegistry` to discover and interact with Google Cloud services like BigQuery via tools exposed by an MCP server registered in an API Registry.
4+
5+
## Prerequisites
6+
7+
- A Google Cloud project with the API Registry API enabled.
8+
- An MCP server exposing BigQuery tools registered in API Registry.
9+
10+
## Configuration & Running
11+
12+
1. **Configure:** Edit `agent.py` and replace `your-google-cloud-project-id` and `your-mcp-server-name` with your Google Cloud Project ID and the name of your registered MCP server.
13+
2. **Run in CLI:**
14+
```bash
15+
adk run contributing/samples/api_registry_agent -- --log-level DEBUG
16+
```
17+
3. **Run in Web UI:**
18+
```bash
19+
adk web contributing/samples/
20+
```
21+
Navigate to `http://127.0.0.1:8080` and select the `api_registry_agent` agent.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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 . import agent
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
import os
16+
17+
from google.adk.agents.llm_agent import LlmAgent
18+
from google.adk.tools.api_registry import ApiRegistry
19+
20+
# TODO: Fill in with your GCloud project id and MCP server name
21+
PROJECT_ID = "your-google-cloud-project-id"
22+
MCP_SERVER_NAME = "your-mcp-server-name"
23+
24+
# Header required for BigQuery MCP server
25+
header_provider = lambda context: {
26+
"x-goog-user-project": PROJECT_ID,
27+
}
28+
api_registry = ApiRegistry(PROJECT_ID, header_provider=header_provider)
29+
registry_tools = api_registry.get_toolset(
30+
mcp_server_name=MCP_SERVER_NAME,
31+
)
32+
root_agent = LlmAgent(
33+
model="gemini-2.0-flash",
34+
name="bigquery_assistant",
35+
instruction="""
36+
Help user access their BigQuery data via API Registry tools.
37+
""",
38+
tools=[registry_tools],
39+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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 . import agent
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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 import Agent
16+
from google.genai import types
17+
18+
19+
def concat_number_and_string(num: int, s: str) -> str:
20+
"""Concatenate a number and a string.
21+
22+
Args:
23+
num: The number to concatenate.
24+
s: The string to concatenate.
25+
26+
Returns:
27+
The concatenated string.
28+
"""
29+
return str(num) + ': ' + s
30+
31+
32+
root_agent = Agent(
33+
model='gemini-3-pro-preview',
34+
name='hello_world_stream_fc_args',
35+
description='Demo agent showcasing streaming function call arguments.',
36+
instruction="""
37+
You are a helpful assistant.
38+
You can use the `concat_number_and_string` tool to concatenate a number and a string.
39+
You should always call the concat_number_and_string tool to concatenate a number and a string.
40+
You should never concatenate on your own.
41+
""",
42+
tools=[
43+
concat_number_and_string,
44+
],
45+
generate_content_config=types.GenerateContentConfig(
46+
automatic_function_calling=types.AutomaticFunctionCallingConfig(
47+
disable=True,
48+
),
49+
tool_config=types.ToolConfig(
50+
function_calling_config=types.FunctionCallingConfig(
51+
stream_function_call_arguments=True,
52+
),
53+
),
54+
),
55+
)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ dependencies = [
4141
"google-cloud-spanner>=3.56.0, <4.0.0", # For Spanner database
4242
"google-cloud-speech>=2.30.0, <3.0.0", # For Audio Transcription
4343
"google-cloud-storage>=2.18.0, <4.0.0", # For GCS Artifact service
44-
"google-genai>=1.45.0, <2.0.0", # Google GenAI SDK
44+
"google-genai>=1.51.0, <2.0.0", # Google GenAI SDK
4545
"graphviz>=0.20.2, <1.0.0", # Graphviz for graph rendering
4646
"jsonschema>=4.23.0, <5.0.0", # Agent Builder config validation
4747
"mcp>=1.10.0, <2.0.0", # For MCP Toolset

src/google/adk/cli/cli_tools_click.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
from . import cli_deploy
3737
from .. import version
3838
from ..evaluation.constants import MISSING_EVAL_DEPENDENCIES_MESSAGE
39+
from ..sessions.migration import migration_runner
3940
from .cli import run_cli
4041
from .fast_api import get_fast_api_app
4142
from .utils import envs
@@ -1485,6 +1486,41 @@ def cli_deploy_cloud_run(
14851486
click.secho(f"Deploy failed: {e}", fg="red", err=True)
14861487

14871488

1489+
@main.group()
1490+
def migrate():
1491+
"""Migrate ADK database schemas."""
1492+
pass
1493+
1494+
1495+
@migrate.command("session", cls=HelpfulCommand)
1496+
@click.option(
1497+
"--source_db_url",
1498+
required=True,
1499+
help="SQLAlchemy URL of source database.",
1500+
)
1501+
@click.option(
1502+
"--dest_db_url",
1503+
required=True,
1504+
help="SQLAlchemy URL of destination database.",
1505+
)
1506+
@click.option(
1507+
"--log_level",
1508+
type=LOG_LEVELS,
1509+
default="INFO",
1510+
help="Optional. Set the logging level",
1511+
)
1512+
def cli_migrate_session(
1513+
*, source_db_url: str, dest_db_url: str, log_level: str
1514+
):
1515+
"""Migrates a session database to the latest schema version."""
1516+
logs.setup_adk_logger(getattr(logging, log_level.upper()))
1517+
try:
1518+
migration_runner.upgrade(source_db_url, dest_db_url)
1519+
click.secho("Migration check and upgrade process finished.", fg="green")
1520+
except Exception as e:
1521+
click.secho(f"Migration failed: {e}", fg="red", err=True)
1522+
1523+
14881524
@deploy.command("agent_engine")
14891525
@click.option(
14901526
"--api_key",

src/google/adk/cli/fast_api.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,13 @@ def get_fast_api_app(
106106
base_dir=agents_dir,
107107
session_service_uri=session_service_uri,
108108
session_db_kwargs=session_db_kwargs,
109-
per_agent=True, # Multi-agent mode
110109
)
111110

112111
# Build the Artifact service
113112
try:
114113
artifact_service = create_artifact_service_from_options(
115114
base_dir=agents_dir,
116115
artifact_service_uri=artifact_service_uri,
117-
per_agent=True, # Multi-agent mode
118116
)
119117
except ValueError as exc:
120118
raise click.ClickException(str(exc)) from exc

src/google/adk/cli/service_registry.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,18 +271,14 @@ def gcs_artifact_factory(uri: str, **kwargs):
271271

272272
kwargs_copy = kwargs.copy()
273273
kwargs_copy.pop("agents_dir", None)
274+
kwargs_copy.pop("per_agent", None)
274275
parsed_uri = urlparse(uri)
275276
bucket_name = parsed_uri.netloc
276277
return GcsArtifactService(bucket_name=bucket_name, **kwargs_copy)
277278

278-
def file_artifact_factory(uri: str, **kwargs):
279+
def file_artifact_factory(uri: str, **_):
279280
from ..artifacts.file_artifact_service import FileArtifactService
280281

281-
per_agent = kwargs.get("per_agent", False)
282-
if per_agent:
283-
raise ValueError(
284-
"file:// artifact URIs are not supported in multi-agent mode."
285-
)
286282
parsed_uri = urlparse(uri)
287283
if parsed_uri.netloc not in ("", "localhost"):
288284
raise ValueError(

src/google/adk/cli/utils/local_storage.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,27 +58,20 @@ def create_local_database_session_service(
5858

5959

6060
def create_local_artifact_service(
61-
*, base_dir: Path | str, per_agent: bool = False
61+
*, base_dir: Path | str
6262
) -> BaseArtifactService:
6363
"""Creates a file-backed artifact service rooted in `.adk/artifacts`.
6464
6565
Args:
6666
base_dir: Directory whose `.adk` folder will store artifacts.
67-
per_agent: Indicates whether the service is being used in multi-agent mode.
6867
6968
Returns:
7069
A `FileArtifactService` scoped to the derived root directory.
7170
"""
7271
manager = DotAdkFolder(base_dir)
7372
artifact_root = manager.artifacts_dir
7473
artifact_root.mkdir(parents=True, exist_ok=True)
75-
if per_agent:
76-
logger.info(
77-
"Using shared file artifact service rooted at %s for multi-agent mode",
78-
artifact_root,
79-
)
80-
else:
81-
logger.info("Using file artifact service at %s", artifact_root)
74+
logger.info("Using file artifact service at %s", artifact_root)
8275
return FileArtifactService(root_dir=artifact_root)
8376

8477

0 commit comments

Comments
 (0)