googleapis / googleapis/python-aiplatform

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

Đang mở
#6,865 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
api: vertex-ai
Ngôn ngữ chính
Python
Star
905
Fork
465
Merge trung bình
1 ngày 13 giờ
Pull request đã merge (30 ngày)
44

Mô tả

### 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", [])
```

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.