DEV Community

Cover image for Vertex AI Agent + Google Search Grounding: Real-Time Facts with ADK and Terraform πŸ“š
Suhas Mallesh
Suhas Mallesh

Posted on

Vertex AI Agent + Google Search Grounding: Real-Time Facts with ADK and Terraform πŸ“š

An agent without grounding hallucinates about current events. Google Search Grounding and Vertex AI Search give your ADK agent real-time web data and private document access with source citations. Here's how to wire both up with Terraform.

Through this series, we've built ADK agents that can reason, call tools, and coordinate with other agents. But ask one about today's stock prices or your company's internal policies, and it either hallucinates or admits it doesn't know. The model's training data has a cutoff, and it has no access to your documents.

Grounding fixes this with two built-in ADK tools: Google Search Grounding connects your agent to real-time web data - current events, live prices, recent news. Vertex AI Search Grounding connects your agent to your private documents - company policies, product specs, internal knowledge bases. Both return source-attributed responses with citations. 🎯

πŸ—οΈ Two Grounding Approaches

Tool Data Source Best For
Google Search Public web (Google Search index) Current events, live data, general facts
Vertex AI Search Your private documents (indexed datastore) Company policies, internal docs, product info

You can use one or both. Google Search handles what's public and current. Vertex AI Search handles what's private and specific to your organization.

πŸ”§ Google Search Grounding

The simplest grounding option. Add the built-in google_search tool to your agent:

# agent_source/agent.py

from google.adk.agents import Agent
from google.adk.models.vertexai import VertexAi

model = VertexAi(model=config["model_id"])

search_agent = Agent(
    name="search-grounded-agent",
    model=model,
    instruction="""You are a helpful assistant that provides accurate,
    current information. When answering questions about recent events, 
    current data, or anything that requires up-to-date information,
    use Google Search to ground your response. Always cite your sources.""",
    tools=["google_search"],
)
Enter fullscreen mode Exit fullscreen mode

That's it. One line: tools=["google_search"]. The agent automatically searches the web when it determines the question needs current information.

What the Response Looks Like

When the agent uses Google Search, the response includes groundingMetadata with source URLs, search queries executed, and confidence scores per segment:

async for event in runner.run_async(
    user_id="user-123",
    session_id=session.id,
    new_message=types.Content(
        role="user",
        parts=[types.Part(text="What were today's major tech news?")]
    )
):
    if event.content and event.content.parts:
        for part in event.content.parts:
            if hasattr(part, "text") and part.text:
                print(part.text)

    # Access grounding metadata for citations
    if hasattr(event, "grounding_metadata"):
        for chunk in event.grounding_metadata.grounding_chunks:
            print(f"Source: {chunk.web.uri} - {chunk.web.title}")
Enter fullscreen mode Exit fullscreen mode

Important: When using Google Search Grounding in production, you must display the Search Suggestions provided in the response metadata. This is a requirement from Google's terms of service.

πŸ”§ Vertex AI Search Grounding (Private Documents)

For grounding against your own documents, use the VertexAiSearchTool:

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

# Your Vertex AI Search datastore path
DATASTORE_PATH = (
    f"projects/{config['project_id']}/locations/global"
    f"/collections/default_collection"
    f"/dataStores/{config['datastore_id']}"
)

doc_agent = Agent(
    name="doc-grounded-agent",
    model=model,
    instruction="""You are a company policy expert. Answer questions 
    about internal policies, procedures, and guidelines using the 
    provided document store. Always cite the source document.""",
    tools=[VertexAiSearchTool(data_store_id=DATASTORE_PATH)],
)
Enter fullscreen mode Exit fullscreen mode

The agent queries your indexed documents, retrieves relevant chunks with semantic search, and generates a response grounded in your actual content. Source attributions include document titles and URIs.

Tool Limitation

Both google_search and VertexAiSearchTool are exclusive tools - they cannot be combined with other tools in the same agent instance. To use grounding alongside custom function tools, wrap the grounded agent as a sub-agent or use AgentTool:

from google.adk.tools import AgentTool

# Grounded agent as a tool for the main agent
search_assistant = Agent(
    name="searcher",
    model=model,
    instruction="Search the web for current information when asked.",
    tools=["google_search"],
)

doc_assistant = Agent(
    name="doc_lookup",
    model=model,
    instruction="Look up company policies and internal documents.",
    tools=[VertexAiSearchTool(data_store_id=DATASTORE_PATH)],
)

# Main agent uses grounded agents as tools alongside custom tools
main_agent = Agent(
    name="assistant",
    model=model,
    instruction="""You are a helpful assistant.
    Use the searcher for current events and live data.
    Use doc_lookup for company policies and internal info.
    Use get_exchange_rate for currency conversions.""",
    tools=[
        AgentTool(search_assistant),
        AgentTool(doc_assistant),
        get_exchange_rate,
    ],
)
Enter fullscreen mode Exit fullscreen mode

This is the production pattern: dedicated grounding agents wrapped as tools for a main orchestrator agent.

πŸ”§ Terraform: Infrastructure for Grounding

APIs and Vertex AI Search Datastore

# grounding/apis.tf

resource "google_project_service" "grounding" {
  for_each = toset([
    "aiplatform.googleapis.com",
    "discoveryengine.googleapis.com",  # For Vertex AI Search
    "storage.googleapis.com",
  ])
  project = var.project_id
  service = each.value
}
Enter fullscreen mode Exit fullscreen mode

Vertex AI Search Datastore (for Private Docs)

# grounding/datastore.tf

resource "google_discovery_engine_data_store" "docs" {
  location                    = "global"
  data_store_id               = "${var.environment}-company-docs"
  display_name                = "Company Documents"
  industry_vertical           = "GENERIC"
  content_config              = "CONTENT_REQUIRED"
  solution_types              = ["SOLUTION_TYPE_SEARCH"]
  create_advanced_site_search = false
  project                     = var.project_id
}
Enter fullscreen mode Exit fullscreen mode

IAM for Grounding

# grounding/iam.tf

# Agent SA needs Discovery Engine access for Vertex AI Search
resource "google_project_iam_member" "discovery_viewer" {
  project = var.project_id
  role    = "roles/discoveryengine.viewer"
  member  = "serviceAccount:${google_service_account.agent.email}"
}
Enter fullscreen mode Exit fullscreen mode

Config with Datastore ID

# grounding/config.tf

resource "local_file" "agent_config" {
  filename = "${path.module}/agent_source/config.json"
  content = jsonencode({
    project_id   = var.project_id
    location     = var.region
    model_id     = var.agent_model.id
    agent_name   = "${var.environment}-grounded-agent"
    datastore_id = google_discovery_engine_data_store.docs.data_store_id
    instruction  = var.agent_instruction
  })
}
Enter fullscreen mode Exit fullscreen mode

πŸ“ Combining Google Search + Vertex AI Search

The production pattern uses both grounding sources through the sub-agent approach:

# Public data: current events, live information
web_agent = Agent(
    name="web_search",
    model=model,
    instruction="Search the public web for current, real-time information.",
    tools=["google_search"],
)

# Private data: company documents, internal policies
docs_agent = Agent(
    name="doc_search",
    model=model,
    instruction="Search company documents for internal policies and procedures.",
    tools=[VertexAiSearchTool(data_store_id=DATASTORE_PATH)],
)

# Orchestrator decides which source to use
grounded_assistant = Agent(
    name="grounded_assistant",
    model=model,
    instruction="""You are a knowledgeable assistant.
    For current events or public information, use web_search.
    For company policies or internal documents, use doc_search.
    For general knowledge questions, answer directly.""",
    tools=[
        AgentTool(web_agent),
        AgentTool(docs_agent),
    ],
)
Enter fullscreen mode Exit fullscreen mode

The orchestrator routes to the right grounding source based on the question type. Public questions go to Google Search. Internal questions go to Vertex AI Search. General knowledge questions get answered directly without grounding.

⚠️ Gotchas and Tips

Exclusive tool limitation. google_search and VertexAiSearchTool can't be mixed with other tools in the same agent. Use the AgentTool wrapper pattern shown above.

Search Suggestions display requirement. When using Google Search Grounding in production, you must display the searchEntryPoint HTML/CSS from the response metadata. This is not optional.

Datastore indexing time. Vertex AI Search datastores need time to index your documents after upload. Don't test grounding immediately after creating the datastore - wait for indexing to complete.

Grounding adds latency. Each grounded response involves a search query plus retrieval. Expect 1-3 seconds of additional latency compared to non-grounded responses.

Confidence scores. The groundingMetadata includes confidence scores per response segment. Use these to flag low-confidence answers for human review in production.

⏭️ Series Complete!

This is Post 4 of the GCP AI Agents with Terraform series, and the final GCP post of the entire multi-cloud series.


Your agent is now grounded in reality. Google Search for real-time web data. Vertex AI Search for your private documents. Source citations on every response. No hallucinations, just facts. πŸ“š

Thanks for following the full series! Follow for what comes next. πŸ’¬

Top comments (0)