googleapis / googleapis/python-aiplatform

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

Abierto
#6,865 1 comentario 0 reacciones 0 asignados Ver en GitHub
api: vertex-ai
Lenguaje dominante
Python
Estrellas
905
Forks
465
Merge medio
1 d 13 h
PR fusionados (30 d)
44

Descripción

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

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.