googleapis / googleapis/python-aiplatform

evals: AgentConfig.from_agent raises AttributeError for workflow / non-LlmAgent root agents (no 'tools' field)

未关闭
#6,865 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
api: vertex-ai
主要语言
Python
星标
905
派生
465
平均合并
1 天 13 小时
30 天内合并 PR
44

描述

### Environment

- `google-cloud-aiplatform`: 1.156.0
- `google-adk`: 2.2.0
- Python: 3.12

### Summary

`vertexai.types.evals.AgentConfig.from_agent()` raises `AttributeError` when the root agent is a workflow / non-`LlmAgent` agent — i.e. any `BaseAgent` subclass such as `SequentialAgent`, `ParallelAgent`, `LoopAgent`, or a custom `BaseAgent`. Those agents do not define a `tools` field; only `LlmAgent` does.

`_get_tool_declarations_from_agent` reads `agent.tools` directly (no default), whereas the sibling fields in `from_agent` (`description`, `instruction`, `sub_agents`) all use `getattr(agent, ..., default)`. As a result, introspection fails **before any inference runs**, which makes client-side eval impossible for any multi-agent system whose root is an orchestrator.

This affects every public entry point that introspects a live agent:
- `client.evals.run_inference(agent=...)` → `AgentConfig.from_agent(agent)`
- `types.evals.AgentInfo.load_from_agent(agent=...)` → `AgentData.get_agents_map(agent)` → `AgentConfig.from_agent(agent)`

### Reproduction

```python
from google.adk.agents import LlmAgent, SequentialAgent
from vertexai import types

leaf = LlmAgent(name="step", model="gemini-2.5-flash", instruction="do a step")
wf = SequentialAgent(name="pipeline", sub_agents=[leaf])

types.evals.AgentConfig.from_agent(wf)
```

### Actual behavior

```
Traceback (most recent call last):
File ".../vertexai/_genai/types/evals.py", line 128, in from_agent
tools=AgentConfig._get_tool_declarations_from_agent(agent),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".../vertexai/_genai/types/evals.py", line 86, in _get_tool_declarations_from_agent
for tool in agent.tools:
^^^^^^^^^^^
File ".../pydantic/main.py", line 1042, in __getattr__
raise AttributeError(f'{type(self).__name__!r} object has no attribute {item!r}')
AttributeError: 'SequentialAgent' object has no attribute 'tools'
```

The same failure occurs via `client.evals.run_inference(agent=wf)` and `types.evals.AgentInfo.load_from_agent(agent=wf)`, since both reach `AgentConfig.from_agent`.

### Expected behavior

`from_agent` should treat a missing `tools` field as "no tools", consistent with how it already handles `instruction` and `sub_agents`. A workflow root with `LlmAgent` leaves should produce an `AgentConfig` with empty `tools` for the root and recurse into `sub_agents` normally.

### Suggested fix

In `_get_tool_declarations_from_agent` (`vertexai/_genai/types/evals.py`, and the mirrored `agentplatform/_genai/types/evals.py` copy), iterate over a guarded value:

```python
for tool in getattr(agent, "tools", None) or []:
...
```

This mirrors the existing `getattr(...)` usage for the other fields in `from_agent`.

### Related

Distinct from #6861 / #6862, which addressed a `TypeError` for toolset elements *within* `tools` (e.g. `McpToolset`). Here the `tools` attribute is absent entirely. Both point at the same fragile extraction path.

### Workaround

Inject an empty list before introspection:

```python
if not hasattr(root_agent, "tools"):
object.__setattr__(root_agent, "tools", [])
```

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。