Skip to content

Commit 6f5325a

Browse files
jsondaicopybara-github
authored andcommitted
chore: GenAI Client(evals) - fix AgentConfig.from_agent AttributeError for workflow / non-LlmAgent root agents
PiperOrigin-RevId: 929976190
1 parent bf32f5e commit 6f5325a

3 files changed

Lines changed: 35 additions & 2 deletions

File tree

agentplatform/_genai/types/evals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def _get_tool_declarations_from_agent(agent: Any) -> genai_types.ToolListUnion:
8383
The tool declarations of the agent.
8484
"""
8585
tool_declarations: genai_types.ToolListUnion = []
86-
for tool in agent.tools:
86+
for tool in getattr(agent, "tools", None) or []:
8787
# ADK tools (e.g. AgentTool, VertexAiSearchTool) own their declaration
8888
# via _get_declaration(). A None result means the tool has no function
8989
# declaration (e.g. built-in retrieval tools). In both cases, skip the

tests/unit/agentplatform/genai/test_evals.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5979,6 +5979,39 @@ def run(self, query: "Optional[str]" = None): # noqa: F821
59795979

59805980
assert agent_info.agents["mock_agent"].tools == []
59815981

5982+
@mock.patch.object(genai_types.FunctionDeclaration, "from_callable_with_api_option")
5983+
def test_load_from_agent_workflow_root_without_tools(self, mock_from_callable):
5984+
def my_search_tool(query: str) -> str:
5985+
"""Searches for information."""
5986+
return f"search result for {query}"
5987+
5988+
mock_function_declaration = mock.Mock(spec=genai_types.FunctionDeclaration)
5989+
mock_from_callable.return_value = mock_function_declaration
5990+
5991+
leaf_agent = mock.Mock()
5992+
leaf_agent.name = "leaf"
5993+
leaf_agent.instruction = "do a step"
5994+
leaf_agent.description = "leaf description"
5995+
leaf_agent.tools = [my_search_tool]
5996+
leaf_agent.sub_agents = []
5997+
5998+
root_agent = mock.Mock(spec=["name", "sub_agents"])
5999+
root_agent.name = "pipeline"
6000+
root_agent.sub_agents = [leaf_agent]
6001+
assert not hasattr(root_agent, "tools")
6002+
6003+
agent_info = agentplatform_genai_types.evals.AgentInfo.load_from_agent(
6004+
agent=root_agent,
6005+
)
6006+
6007+
assert agent_info.name == "pipeline"
6008+
assert agent_info.root_agent_id == "pipeline"
6009+
assert agent_info.agents["pipeline"].tools == []
6010+
assert len(agent_info.agents["leaf"].tools) == 1
6011+
assert agent_info.agents["leaf"].tools[0].function_declarations == [
6012+
mock_function_declaration
6013+
]
6014+
59826015

59836016
class TestValidateDatasetAgentData:
59846017
"""Unit tests for the _validate_dataset_agent_data function."""

vertexai/_genai/types/evals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def _get_tool_declarations_from_agent(agent: Any) -> genai_types.ToolListUnion:
8383
The tool declarations of the agent.
8484
"""
8585
tool_declarations: genai_types.ToolListUnion = []
86-
for tool in agent.tools:
86+
for tool in getattr(agent, "tools", None) or []:
8787
# ADK tools (e.g. AgentTool, VertexAiSearchTool) own their declaration
8888
# via _get_declaration(). A None result means the tool has no function
8989
# declaration (e.g. built-in retrieval tools). In both cases, skip the

0 commit comments

Comments
 (0)