google / google/adk-python

`bypass_multi_tools_limit` on `VertexAiSearchTool` is a leaky abstraction: unexpected dependencies, silent shift from inbuilt RAG to tool calling, and prompt fragility

Đang mở
#7,100 2 bình luận 0 reaction 1 người được giao Được @llalitkumarrr nhận Xem trên GitHub
request clarification tools
Ngôn ngữ chính
Python
Star
21.5k
Fork
4k
Merge trung bình
1 ngày 14 giờ
Pull request đã merge (30 ngày)
37

Mô tả

The `bypass_multi_tools_limit=True` flag on `VertexAiSearchTool` is presented as a convenient boolean toggle to allow using Vertex AI Search alongside other tools. In practice, this flag is implemented as a hidden class replacement (`VertexAiSearchTool` → `DiscoveryEngineSearchTool`) that breaks the developer experience in three major ways:

1. **Unexpected runtime dependency:** Silently requires `google-cloud-discoveryengine` (`google-adk[gcp]`), failing at runtime with a `ModuleNotFoundError`.
2. **Silent shift from inbuilt RAG to client tool calling:** Transparent, citation-backed model retrieval is secretly replaced with an explicit client-side function call.
3. **Hardcoded tool naming and prompt fragility:** The substituted tool is hardcoded as `discovery_engine_search`. Because developers write instructions for their domain (e.g., "use the knowledge base"), the model naturally hallucinates calling `search(...)` instead, causing runtime crashes (`ValueError: Tool 'search' not found`).

This breaks the illusion that setting `bypass_multi_tools_limit=True` is a clean, seamless configuration switch.

---

## Minimal Reproduction

Consider a minimal agent combining a knowledge base search with a single custom helper function:

```python
from google.adk.agents import Agent
from google.adk.tools import VertexAiSearchTool

def get_user_tier() -> str:
"""Returns the loyalty tier of the current user."""
return "Platinum"

search_tool = VertexAiSearchTool(
data_store_id="projects/my-project/locations/global/collections/default_collection/dataStores/my-store",
max_results=10,
bypass_multi_tools_limit=True,
)

agent = Agent(
name="support_agent",
model="gemini-flash-lite-latest",
static_instruction="You are a helpful support assistant. Answer user questions using the knowledge base.",
tools=[search_tool, get_user_tier],
)
```

---

## The Issues

### 1. Undeclared Runtime Dependency (`google-adk[gcp]`)

When `bypass_multi_tools_limit=False` (or when the agent has only one tool), `VertexAiSearchTool` works with the base `google-adk` package using the Gemini API's built-in grounding (`types.Tool(retrieval=...)`).

However, the moment a second tool is added and `bypass_multi_tools_limit=True` is set, ADK's internal resolver ([`llm_agent.py`](file:///Users/kvadakattu/Documents/code/adkbook/.venv/lib/python3.12/site-packages/google/adk/agents/llm_agent.py)) silently swaps `VertexAiSearchTool` for `DiscoveryEngineSearchTool`. This class imports `google.cloud.discoveryengine`, immediately crashing with:

```text
ModuleNotFoundError: No module named 'google.cloud.discoveryengine'
```

There is no warning at agent instantiation time indicating that setting this flag requires the `[gcp]` extra.

### 2. Silent Paradigm Shift: Inbuilt RAG Grounding → Tool Calling

Developers choose `VertexAiSearchTool` because it integrates natively with Gemini's retrieval capability:
- Grounding happens transparently inside the model generation turn.
- The model returns grounded responses with citations and `groundingMetadata`.
- The model does not need to decide *whether* to execute a function call, construct JSON arguments, or wait for a second inference round-trip.

Flipping `bypass_multi_tools_limit=True` quietly transforms this into a client-side function calling tool:
- The model must now generate a structured tool call.
- A local API client executes an RPC to Discovery Engine.
- The raw JSON results are piped back into the conversation context for a second LLM turn.

This fundamental architectural shift is completely hidden behind what appears to be a minor transport flag.

### 3. Leaky Tool Naming & Prompt Fragility (`discovery_engine_search`)

In [`discovery_engine_search_tool.py`](file:///Users/kvadakattu/Documents/code/adkbook/.venv/lib/python3.12/site-packages/google/adk/tools/discovery_engine_search_tool.py), the substituted tool inherits from `FunctionTool` and registers `self.discovery_engine_search`:

```python
class DiscoveryEngineSearchTool(FunctionTool):
def __init__(self, ...):
super().__init__(self.discovery_engine_search)
```

This creates two critical problems:
1. **The name cannot be customized:** The function name is hardcoded to `"discovery_engine_search"` with the docstring `"Search through Vertex AI Search's discovery engine search API."` Neither `VertexAiSearchTool` nor `DiscoveryEngineSearchTool` accepts a `name` or `description` parameter.
2. **The model fails to call it:** Prompts written naturally (e.g. *"Answer user questions using the knowledge base"*) give the model no reason to suspect the tool is called `discovery_engine_search`. LLMs (especially lightweight models like `gemini-flash-lite`) guess generic names like `search(query=...)`, leading directly to:
```text
ValueError: Tool 'search' not found.
Available tools: discovery_engine_search, get_user_tier
```

To make the agent work, developers are forced to leak internal Google Cloud plumbing into user-facing prompts:
```text
"Answer user questions using the knowledge base by calling discovery_engine_search."
```

---

## Suggested Improvements

1. **Allow Custom Tool Naming and Description:**
If `VertexAiSearchTool` is going to be transformed into a client `FunctionTool`, it must accept `name` and `description` parameters (e.g., `name="knowledge_base_search"`), forwarding them to `DiscoveryEngineSearchTool` so the tool declaration matches the domain instructions.

2. **Handle Common Name Aliases / Fuzzy Resolution:**
When `DiscoveryEngineSearchTool` is the only search tool present, ADK should either register `search` as an alias or allow flexible resolution rather than failing with a hard `ValueError`.

3. **Explicit Tooling over Magic Flags:**
Rather than hiding a completely different execution model and dependency set behind `bypass_multi_tools_limit=True`, consider deprecating the flag in favor of:
- Providing `DiscoveryEngineSearchTool` directly as a first-class, documented tool when client-side search is desired.
- Documenting the sub-agent pattern (`AgentTool` / `sub_agents`) as the recommended architectural pattern when combining native search retrieval grounding with function tools.

4. **Fail Fast with Clear Dependency Errors:**
If `bypass_multi_tools_limit=True` is used without `google-cloud-discoveryengine` installed, raise a clear error during `Agent.__init__` instructing the user to install `google-adk[gcp]`.

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.