ec2b666284
Continuous Integration / Pre-commit Linter (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.10) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.11) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.12) (push) Has been cancelled
Continuous Integration / Mypy Check (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.12) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / Unit Tests (Python 3.14) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.10) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.11) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.12) (push) Has been cancelled
Copybara PR Handler / close-imported-pr (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.13) (push) Has been cancelled
Continuous Integration / A2A v0.3 Tests (Python 3.14) (push) Has been cancelled
257 lines
9.2 KiB
Python
257 lines
9.2 KiB
Python
# Copyright 2026 Google LLC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Tests for TransferToAgentTool enum constraint functionality."""
|
|
|
|
from unittest.mock import patch
|
|
|
|
from google.adk.features import FeatureName
|
|
from google.adk.features._feature_registry import temporary_feature_override
|
|
from google.adk.tools.function_tool import FunctionTool
|
|
from google.adk.tools.transfer_to_agent_tool import TransferToAgentTool
|
|
from google.genai import types
|
|
import pytest
|
|
|
|
|
|
class TestTransferToAgentToolLegacy:
|
|
"""Tests for TransferToAgentTool when JSON_SCHEMA_FOR_FUNC_DECL is disabled."""
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def disable_feature_flag(self):
|
|
"""Disable the JSON_SCHEMA_FOR_FUNC_DECL feature flag for legacy tests."""
|
|
with temporary_feature_override(
|
|
FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, False
|
|
):
|
|
yield
|
|
|
|
def test_transfer_to_agent_tool_enum_constraint(self):
|
|
"""Test that TransferToAgentTool adds enum constraint to agent_name."""
|
|
agent_names = ['agent_a', 'agent_b', 'agent_c']
|
|
tool = TransferToAgentTool(agent_names=agent_names)
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
assert decl.name == 'transfer_to_agent'
|
|
assert decl.parameters is not None
|
|
assert decl.parameters.type == types.Type.OBJECT
|
|
assert 'agent_name' in decl.parameters.properties
|
|
|
|
agent_name_schema = decl.parameters.properties['agent_name']
|
|
assert agent_name_schema.type == types.Type.STRING
|
|
assert agent_name_schema.enum == agent_names
|
|
|
|
# Verify that agent_name is marked as required
|
|
assert decl.parameters.required == ['agent_name']
|
|
|
|
def test_transfer_to_agent_tool_single_agent(self):
|
|
"""Test TransferToAgentTool with a single agent."""
|
|
tool = TransferToAgentTool(agent_names=['single_agent'])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters.properties['agent_name']
|
|
assert agent_name_schema.enum == ['single_agent']
|
|
|
|
def test_transfer_to_agent_tool_multiple_agents(self):
|
|
"""Test TransferToAgentTool with multiple agents."""
|
|
agent_names = ['agent_1', 'agent_2', 'agent_3', 'agent_4', 'agent_5']
|
|
tool = TransferToAgentTool(agent_names=agent_names)
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters.properties['agent_name']
|
|
assert agent_name_schema.enum == agent_names
|
|
assert len(agent_name_schema.enum) == 5
|
|
|
|
def test_transfer_to_agent_tool_empty_list(self):
|
|
"""Test TransferToAgentTool with an empty agent list."""
|
|
tool = TransferToAgentTool(agent_names=[])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters.properties['agent_name']
|
|
assert agent_name_schema.enum == []
|
|
|
|
def test_transfer_to_agent_tool_preserves_parameter_type(self):
|
|
"""Test that TransferToAgentTool preserves the parameter type."""
|
|
tool = TransferToAgentTool(agent_names=['agent_a'])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters.properties['agent_name']
|
|
# Should still be a string type, just with enum constraint
|
|
assert agent_name_schema.type == types.Type.STRING
|
|
|
|
def test_transfer_to_agent_tool_no_extra_parameters(self):
|
|
"""Test that TransferToAgentTool doesn't add extra parameters."""
|
|
tool = TransferToAgentTool(agent_names=['agent_a'])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
# Should only have agent_name parameter (tool_context is ignored)
|
|
assert len(decl.parameters.properties) == 1
|
|
assert 'agent_name' in decl.parameters.properties
|
|
assert 'tool_context' not in decl.parameters.properties
|
|
|
|
|
|
# Shared/Common tests at module level
|
|
def test_transfer_to_agent_tool_preserves_description():
|
|
"""Test that TransferToAgentTool preserves the original description."""
|
|
tool = TransferToAgentTool(agent_names=['agent_a', 'agent_b'])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
assert decl.description is not None
|
|
assert 'Transfer the query to another agent' in decl.description
|
|
|
|
|
|
def test_transfer_to_agent_tool_maintains_inheritance():
|
|
"""Test that TransferToAgentTool inherits from FunctionTool correctly."""
|
|
tool = TransferToAgentTool(agent_names=['agent_a'])
|
|
|
|
assert isinstance(tool, FunctionTool)
|
|
assert hasattr(tool, '_get_declaration')
|
|
assert hasattr(tool, 'process_llm_request')
|
|
|
|
|
|
def test_transfer_to_agent_tool_handles_parameters_json_schema():
|
|
"""Test that TransferToAgentTool handles parameters_json_schema format."""
|
|
agent_names = ['agent_x', 'agent_y', 'agent_z']
|
|
|
|
# Create a mock FunctionDeclaration with parameters_json_schema
|
|
mock_decl = type('MockDecl', (), {})()
|
|
mock_decl.parameters = None # No Schema object
|
|
mock_decl.parameters_json_schema = {
|
|
'type': 'object',
|
|
'properties': {
|
|
'agent_name': {
|
|
'type': 'string',
|
|
'description': 'Agent name to transfer to',
|
|
}
|
|
},
|
|
'required': ['agent_name'],
|
|
}
|
|
|
|
# Temporarily patch FunctionTool._get_declaration
|
|
with patch.object(
|
|
FunctionTool,
|
|
'_get_declaration',
|
|
return_value=mock_decl,
|
|
):
|
|
tool = TransferToAgentTool(agent_names=agent_names)
|
|
result = tool._get_declaration()
|
|
|
|
# Verify enum was added to parameters_json_schema
|
|
assert result.parameters_json_schema is not None
|
|
assert 'agent_name' in result.parameters_json_schema['properties']
|
|
assert (
|
|
result.parameters_json_schema['properties']['agent_name']['enum']
|
|
== agent_names
|
|
)
|
|
assert (
|
|
result.parameters_json_schema['properties']['agent_name']['type']
|
|
== 'string'
|
|
)
|
|
# Verify required field is preserved
|
|
assert result.parameters_json_schema['required'] == ['agent_name']
|
|
|
|
|
|
class TestTransferToAgentToolWithJsonSchema:
|
|
"""Tests for TransferToAgentTool when JSON_SCHEMA_FOR_FUNC_DECL is enabled."""
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def enable_feature_flag(self):
|
|
"""Enable the JSON_SCHEMA_FOR_FUNC_DECL feature flag."""
|
|
with temporary_feature_override(
|
|
FeatureName.JSON_SCHEMA_FOR_FUNC_DECL, True
|
|
):
|
|
yield
|
|
|
|
def test_transfer_to_agent_tool_enum_constraint(self):
|
|
"""Test that TransferToAgentTool adds enum constraint to parameters_json_schema."""
|
|
agent_names = ['agent_a', 'agent_b', 'agent_c']
|
|
tool = TransferToAgentTool(agent_names=agent_names)
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
assert decl.name == 'transfer_to_agent'
|
|
assert decl.parameters_json_schema is not None
|
|
assert 'agent_name' in decl.parameters_json_schema['properties']
|
|
|
|
agent_name_schema = decl.parameters_json_schema['properties']['agent_name']
|
|
assert agent_name_schema['type'] == 'string'
|
|
assert agent_name_schema['enum'] == agent_names
|
|
assert decl.parameters_json_schema['required'] == ['agent_name']
|
|
|
|
def test_transfer_to_agent_tool_single_agent(self):
|
|
"""Test TransferToAgentTool with a single agent."""
|
|
tool = TransferToAgentTool(agent_names=['single_agent'])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters_json_schema['properties']['agent_name']
|
|
assert agent_name_schema['enum'] == ['single_agent']
|
|
|
|
def test_transfer_to_agent_tool_multiple_agents(self):
|
|
"""Test TransferToAgentTool with multiple agents."""
|
|
agent_names = ['agent_1', 'agent_2', 'agent_3', 'agent_4', 'agent_5']
|
|
tool = TransferToAgentTool(agent_names=agent_names)
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters_json_schema['properties']['agent_name']
|
|
assert agent_name_schema['enum'] == agent_names
|
|
assert len(agent_name_schema['enum']) == 5
|
|
|
|
def test_transfer_to_agent_tool_empty_list(self):
|
|
"""Test TransferToAgentTool with an empty agent list."""
|
|
tool = TransferToAgentTool(agent_names=[])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters_json_schema['properties']['agent_name']
|
|
assert agent_name_schema['enum'] == []
|
|
|
|
def test_transfer_to_agent_tool_preserves_parameter_type(self):
|
|
"""Test that TransferToAgentTool preserves the parameter type."""
|
|
tool = TransferToAgentTool(agent_names=['agent_a'])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
agent_name_schema = decl.parameters_json_schema['properties']['agent_name']
|
|
assert agent_name_schema['type'] == 'string'
|
|
|
|
def test_transfer_to_agent_tool_no_extra_parameters(self):
|
|
"""Test that TransferToAgentTool doesn't add extra parameters."""
|
|
tool = TransferToAgentTool(agent_names=['agent_a'])
|
|
|
|
decl = tool._get_declaration()
|
|
|
|
assert decl is not None
|
|
assert len(decl.parameters_json_schema['properties']) == 1
|
|
assert 'agent_name' in decl.parameters_json_schema['properties']
|
|
assert 'tool_context' not in decl.parameters_json_schema['properties']
|