Skip to content

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

Description

@vadakattu

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 (VertexAiSearchToolDiscoveryEngineSearchTool) 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:

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) silently swaps VertexAiSearchTool for DiscoveryEngineSearchTool. This class imports google.cloud.discoveryengine, immediately crashing with:

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, the substituted tool inherits from FunctionTool and registers self.discovery_engine_search:

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:
    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:

"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].

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

request clarification[Status] The maintainer need clarification or more information from the authortools[Component] This issue is related to tools

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions