Skip to content

Google Search Tool does not return grounding metadata in ADK Runner events #1693

@robert-h-dss

Description

@robert-h-dss

** Please make sure you read the contribution guide and file the issues in the right place. **
Contribution guide.

Describe the bug
When utilizing the Google Search tool within an ADK Runner flow, the event objects emitted by the Runner do not contain the expected grounding_metadata. This metadata, crucial for understanding the source and reliability of information, is absent from the event representing the tool's output.

While grounding_metadata appears to be logged elsewhere (e.g., in debug or info logs), it is not accessible directly within the Runner's event stream after the tool execution, which prevents programmatic access to provenance information.

To Reproduce

Steps to reproduce the behavior:

  1. Configure the ADK agents with the structure shown below, which includes an orchestrator_agent using a chat_agent, which in turn uses a google_search_agent as a tool:

    from google.adk.agents.llm_agent import LlmAgent
    from google.adk.tools import agent_tool
    from google.adk.tools import google_search
    
    orchestrator_agent = LlmAgent(
        model=_settings.google_llm_model,
        name="ai_assistant",
        instruction=(prompt.INSTRUCTION_PROMPT),
        sub_agents=[
          chat_agent,
          # ... other sub_agents
        ],
    )
    
    chat_agent = LlmAgent(
        model=_settings.google_llm_model,
        name="chat_ai_assistant",
        instruction=(prompt.INSTRUCTION_PROMPT),
        global_instruction=(prompt.GLOBAL_PROMPT),
        tools=[
            agent_tool.AgentTool(agent=google_search_agent, skip_summarization=True),
        ],
        sub_agents=[
            faq_agent,
            # ... other sub_agents
        ],
    )
    
    google_search_agent = LlmAgent(
        model=_settings.google_llm_model,
        name="google_search_agent",
        instruction=prompt.GOOGLE_SEARCH_PROMPT,
        tools=[
            google_search
        ],
    )
    
    faq_agent = LlmAgent(
        model=_settings.google_llm_model,
        name="faq_agent",
        instruction=prompt.FAQ_PROMPT,
        tools=(
            [
              faq_tool
            ]
        ),
    )
  2. Implement a process_message function that uses the Runner to interact with the orchestrator agent and iterates through its events:

    async def process_message(
        self, query: str, session_id: str, user_id: str, dtr_token: str
      ) -> str:
        """Process a message and get the agent's response.
    
        Args:
          query: The user's query
          session_id: The session ID
    
        Returns:
          str: The agent's response
        """
        try:
          # Ensure session exists
          self.get_or_create_session(session_id, user_id, dtr_token)
    
          # Create runner
          runner = Runner(
            agent=orchestrator_agent,
            app_name=self.app_name,
            session_service=self.session_service,
          )
    
          # Prepare user message
          content = types.Content(role="user", parts=[types.Part(text=query)])
    
          # Default response
          final_response_text = "Agent did not produce a final response."
    
          # Run agent and get response
          async for event in runner.run_async(
            user_id=user_id, session_id=session_id, new_message=content
          ):
            # Observe 'event' objects here.
            # print(f"Received event: {event}") # Add this to inspect events
            if event.is_final_response():
              if event.content and event.content.parts:
                if event.content.parts[0].function_response:
                  final_response_text = event.content.parts[
                    0
                  ].function_response.response["result"]
                elif event.content.parts[0].text:
                  final_response_text = event.content.parts[0].text
                else:
                  final_response_text = event.content.parts[1].text
              elif event.actions and event.actions.escalate:
                final_response_text = f"Agent escalated: {event.error_message or 'No specific message.'}"
              break
    
          return final_response_text
    
        except Exception as e:
          logger.error(f"Error processing message: ") # Consider adding {e} to the log message
          raise
  3. Call process_message with a query that prompts the chat_agent to use the google_search_agent tool.

  4. Examine the event objects yielded by runner.run_async(). Observe that the event pertaining to the google_search tool's result lacks grounding_metadata.

Expected behavior
The event object corresponding to the google_search tool's output should include grounding_metadata. This metadata should be accessible directly within the event structure (e.g., event.content.parts[0].tool_output.grounding_metadata or a similar path) to allow downstream processing of sourced information.

It is suspected that an intermediary event object might be missing between the AgentTool call event and its eventual result event that should contain this metadata.

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

  • OS: macOS 15.5
  • Python version(python -V): 3.13.2
  • ADK version(pip show google-adk): 1.3.0

Model Information:
gemini-2.5-flash

Additional context
The described agent structure (orchestrator -> chat_agent -> google_search_agent) is intended to fully leverage the Google Search tool. However, the current event emission by the Runner prevents direct access to grounding information.

Additionally, related functionalities such as skip_summarization (when set on the AgentTool) and general tool callback mechanisms also do not appear to function as expected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bot triaged[Bot] This issue is triaged by ADK bottracing[Component] This issue is related to OpenTelemetry tracing

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions