Skip to content

Commit 332c99d

Browse files
authored
Merge branch 'main' into fix/handle-circular-refs
2 parents 632e15f + 223d9a7 commit 332c99d

File tree

65 files changed

+4916
-1332
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+4916
-1332
lines changed

.github/workflows/python-unit-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
run: |
4444
uv venv .venv
4545
source .venv/bin/activate
46-
uv sync --extra test --extra eval --extra a2a
46+
uv sync --extra test
4747
4848
- name: Run unit tests with pytest
4949
run: |
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Agent Registry Sample
2+
3+
This sample demonstrates how to use the `AgentRegistry` client to discover agents and MCP servers registered in Google Cloud.
4+
5+
## Setup
6+
7+
1. Ensure you have Google Cloud credentials configured (e.g., `gcloud auth application-default login`).
8+
2. Set the following environment variables:
9+
10+
```bash
11+
export GOOGLE_CLOUD_PROJECT=your-project-id
12+
export GOOGLE_CLOUD_LOCATION=global # or your specific region
13+
```
14+
15+
3. Obtain the full resource names for the agents and MCP servers you want to use. You can do this by running the sample script once to list them:
16+
17+
```bash
18+
python3 agent.py
19+
```
20+
21+
Alternatively, use `gcloud` to list them:
22+
23+
```bash
24+
# For agents
25+
gcloud alpha agent-registry agents list --project=$GOOGLE_CLOUD_PROJECT --location=$GOOGLE_CLOUD_LOCATION
26+
27+
# For MCP servers
28+
gcloud alpha agent-registry mcp-servers list --project=$GOOGLE_CLOUD_PROJECT --location=$GOOGLE_CLOUD_LOCATION
29+
```
30+
31+
4. Replace `AGENT_NAME` and `MCP_SERVER_NAME` in `agent.py` with the last part of the resource names (e.g., if the name is `projects/.../agents/my-agent`, use `my-agent`).
32+
33+
## Running the Sample
34+
35+
Run the sample script to list available agents and MCP servers:
36+
37+
```bash
38+
python3 agent.py
39+
```
40+
41+
## How it Works
42+
43+
The sample uses `AgentRegistry` to:
44+
- List registered agents using `list_agents()`.
45+
- List registered MCP servers using `list_mcp_servers()`.
46+
47+
It also shows (in comments) how to:
48+
- Get a `RemoteA2aAgent` instance using `get_remote_a2a_agent(name)`.
49+
- Get an `McpToolset` instance using `get_mcp_toolset(name)`.
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: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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+
"""Sample agent demonstrating Agent Registry discovery."""
16+
17+
import os
18+
19+
from google.adk.agents.llm_agent import LlmAgent
20+
from google.adk.integrations.agent_registry import AgentRegistry
21+
22+
# Project and location can be set via environment variables:
23+
# GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION
24+
project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
25+
location = os.environ.get("GOOGLE_CLOUD_LOCATION", "global")
26+
27+
# Initialize Agent Registry client
28+
registry = AgentRegistry(project_id=project_id, location=location)
29+
30+
print(f"Listing agents in {project_id}/{location}...")
31+
agents = registry.list_agents()
32+
for agent in agents.get("agents", []):
33+
print(f"- Agent: {agent.get('displayName')} ({agent.get('name')})")
34+
35+
print(f"\nListing MCP servers in {project_id}/{location}...")
36+
mcp_servers = registry.list_mcp_servers()
37+
for server in mcp_servers.get("mcpServers", []):
38+
print(f"- MCP Server: {server.get('displayName')} ({server.get('name')})")
39+
40+
# Example of using a specific agent or MCP server from the registry:
41+
# (Note: These names should be full resource names as returned by list methods)
42+
43+
# 1. Using a Remote A2A Agent as a sub-agent
44+
# TODO: Replace AGENT_NAME with your agent name
45+
remote_agent = registry.get_remote_a2a_agent(
46+
f"projects/{project_id}/locations/{location}/agents/AGENT_NAME"
47+
)
48+
49+
# 2. Using an MCP Server in a toolset
50+
# TODO: Replace MCP_SERVER_NAME with your MCP server name
51+
mcp_toolset = registry.get_mcp_toolset(
52+
f"projects/{project_id}/locations/{location}/mcpServers/MCP_SERVER_NAME"
53+
)
54+
55+
root_agent = LlmAgent(
56+
model="gemini-2.5-flash",
57+
name="discovery_agent",
58+
instruction=(
59+
"You have access to tools and sub-agents discovered via Registry."
60+
),
61+
tools=[mcp_toolset],
62+
sub_agents=[remote_agent],
63+
)

contributing/samples/bigquery/README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ distributed via the `google.adk.tools.bigquery` module. These tools include:
5555
`ARIMA_PLUS` model and then querying it with
5656
`ML.DETECT_ANOMALIES` to detect time series data anomalies.
5757

58-
11. `search_catalog`
59-
Searches for data entries across projects using the Dataplex Catalog. This allows discovery of datasets, tables, and other assets.
60-
6158
## How to use
6259

6360
Set up environment variables in your `.env` file for using
@@ -162,4 +159,3 @@ the necessary access tokens to call BigQuery APIs on their behalf.
162159
* which tables exist in the ml_datasets dataset?
163160
* show more details about the penguins table
164161
* compute penguins population per island.
165-
* are there any tables related to animals in project <your_project_id>?

contributing/samples/skills_agent/agent.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from google.adk import Agent
2020
from google.adk.skills import load_skill_from_dir
2121
from google.adk.skills import models
22-
from google.adk.tools import skill_toolset
22+
from google.adk.tools.skill_toolset import SkillToolset
2323

2424
greeting_skill = models.Skill(
2525
frontmatter=models.Frontmatter(
@@ -44,15 +44,12 @@
4444
pathlib.Path(__file__).parent / "skills" / "weather_skill"
4545
)
4646

47-
my_skill_toolset = skill_toolset.SkillToolset(
48-
skills=[greeting_skill, weather_skill]
49-
)
47+
my_skill_toolset = SkillToolset(skills=[greeting_skill, weather_skill])
5048

5149
root_agent = Agent(
5250
model="gemini-2.5-flash",
5351
name="skill_user_agent",
5452
description="An agent that can use specialized skills.",
55-
instruction=skill_toolset.DEFAULT_SKILL_SYSTEM_INSTRUCTION,
5653
tools=[
5754
my_skill_toolset,
5855
],

pyproject.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ dependencies = [
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
40-
"google-cloud-dataplex>=1.7.0,<3.0.0", # For Dataplex Catalog Search tool
4140
"google-cloud-discoveryengine>=0.13.12, <0.14.0", # For Discovery Engine Search Tool
4241
"google-cloud-pubsub>=2.0.0, <3.0.0", # For Pub/Sub Tool
4342
"google-cloud-secret-manager>=2.22.0, <3.0.0", # Fetching secrets in RestAPI Tool
@@ -49,13 +48,13 @@ dependencies = [
4948
"httpx>=0.27.0, <1.0.0", # HTTP client library
5049
"jsonschema>=4.23.0, <5.0.0", # Agent Builder config validation
5150
"mcp>=1.23.0, <2.0.0", # For MCP Toolset
52-
"opentelemetry-api>=1.36.0, <1.40.0", # OpenTelemetry - keep below 1.40.0 to reduce risk of breaking changes around log-signal APIs.
51+
"opentelemetry-api>=1.36.0, <1.39.0", # OpenTelemetry - keep below 1.39.0 due to current agent_engines exporter constraints.
5352
"opentelemetry-exporter-gcp-logging>=1.9.0a0, <2.0.0",
5453
"opentelemetry-exporter-gcp-monitoring>=1.9.0a0, <2.0.0",
5554
"opentelemetry-exporter-gcp-trace>=1.9.0, <2.0.0",
5655
"opentelemetry-exporter-otlp-proto-http>=1.36.0",
5756
"opentelemetry-resourcedetector-gcp>=1.9.0a0, <2.0.0",
58-
"opentelemetry-sdk>=1.36.0, <1.40.0",
57+
"opentelemetry-sdk>=1.36.0, <1.39.0",
5958
"pyarrow>=14.0.0",
6059
"pydantic>=2.7.0, <3.0.0", # For data validation/models
6160
"python-dateutil>=2.9.0.post0, <3.0.0", # For Vertext AI Session Service
@@ -125,7 +124,7 @@ test = [
125124
"kubernetes>=29.0.0", # For GkeCodeExecutor
126125
"langchain-community>=0.3.17",
127126
"langgraph>=0.2.60, <0.4.8", # For LangGraphAgent
128-
"litellm>=1.75.5, <1.80.17", # For LiteLLM tests
127+
"litellm>=1.75.5, <2.0.0", # For LiteLLM tests
129128
"llama-index-readers-file>=0.4.0", # For retrieval tests
130129
"openai>=1.100.2", # For LiteLLM
131130
"opentelemetry-instrumentation-google-genai>=0.3b0, <1.0.0",
@@ -157,7 +156,7 @@ extensions = [
157156
"docker>=7.0.0", # For ContainerCodeExecutor
158157
"kubernetes>=29.0.0", # For GkeCodeExecutor
159158
"langgraph>=0.2.60, <0.4.8", # For LangGraphAgent
160-
"litellm>=1.75.5, <1.80.17", # For LiteLlm class. Currently has OpenAI limitations. TODO: once LiteLlm fix it
159+
"litellm>=1.75.5, <2.0.0", # For LiteLlm class. Currently has OpenAI limitations. TODO: once LiteLlm fix it
161160
"llama-index-readers-file>=0.4.0", # For retrieval using LlamaIndex.
162161
"llama-index-embeddings-google-genai>=0.3.0", # For files retrieval using LlamaIndex.
163162
"lxml>=5.3.0", # For load_web_page tool.

src/google/adk/agents/agent_config.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616

1717
from typing import Annotated
1818
from typing import Any
19-
from typing import get_args
2019
from typing import Union
2120

2221
from pydantic import Discriminator
2322
from pydantic import RootModel
2423
from pydantic import Tag
2524

26-
from ..utils.feature_decorator import experimental
25+
from ..features import experimental
26+
from ..features import FeatureName
2727
from .base_agent_config import BaseAgentConfig
2828
from .llm_agent_config import LlmAgentConfig
2929
from .loop_agent_config import LoopAgentConfig
@@ -68,6 +68,6 @@ def agent_config_discriminator(v: Any) -> str:
6868

6969
# Use a RootModel to represent the agent directly at the top level.
7070
# The `discriminator` is applied to the union within the RootModel.
71-
@experimental
71+
@experimental(FeatureName.AGENT_CONFIG)
7272
class AgentConfig(RootModel[ConfigsUnion]):
7373
"""The config for the YAML schema to create an agent."""

src/google/adk/agents/base_agent.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@
4040

4141
from ..events.event import Event
4242
from ..events.event_actions import EventActions
43+
from ..features import experimental
44+
from ..features import FeatureName
4345
from ..telemetry import tracing
4446
from ..telemetry.tracing import tracer
4547
from ..utils.context_utils import Aclosing
46-
from ..utils.feature_decorator import experimental
4748
from .base_agent_config import BaseAgentConfig
4849
from .callback_context import CallbackContext
4950

@@ -70,7 +71,7 @@
7071
SelfAgent = TypeVar('SelfAgent', bound='BaseAgent')
7172

7273

73-
@experimental
74+
@experimental(FeatureName.AGENT_STATE)
7475
class BaseAgentState(BaseModel):
7576
"""Base class for all agent states."""
7677

@@ -618,7 +619,7 @@ def __set_parent_agent_for_sub_agents(self) -> BaseAgent:
618619

619620
@final
620621
@classmethod
621-
@experimental
622+
@experimental(FeatureName.AGENT_CONFIG)
622623
def from_config(
623624
cls: Type[SelfAgent],
624625
config: BaseAgentConfig,
@@ -642,7 +643,7 @@ def from_config(
642643
return cls(**kwargs)
643644

644645
@classmethod
645-
@experimental
646+
@experimental(FeatureName.AGENT_CONFIG)
646647
def _parse_config(
647648
cls: Type[SelfAgent],
648649
config: BaseAgentConfig,

src/google/adk/agents/base_agent_config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@
2626
from pydantic import ConfigDict
2727
from pydantic import Field
2828

29-
from ..utils.feature_decorator import experimental
29+
from ..features import experimental
30+
from ..features import FeatureName
3031
from .common_configs import AgentRefConfig
3132
from .common_configs import CodeConfig
3233

3334
TBaseAgentConfig = TypeVar('TBaseAgentConfig', bound='BaseAgentConfig')
3435

3536

36-
@experimental
37+
@experimental(FeatureName.AGENT_CONFIG)
3738
class BaseAgentConfig(BaseModel):
3839
"""The config for the YAML schema of a BaseAgent.
3940

0 commit comments

Comments
 (0)