Skip to content

Conversation

@sarojrout
Copy link
Contributor

Implements real-time event streaming for AgentTool to propagate sub-agent events, addressing issue #3984.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

2. Or, if no issue exists, describe the change:

If applicable, please follow the issue templates to provide as much detail as
possible.

Problem:
When a coordinator agent delegates to a sub-agent via AgentTool, the sub-agent's execution acts as a "black box". No events are yielded during sub-agent execution, making the frontend appear unresponsive for the duration of sub-agent execution (which can be 20-30 seconds for complex tasks). Only the final result is returned after sub-agent completes, providing no visibility into intermediate steps, tool calls, or responses.

This creates a poor user experience for hierarchical multi-agent systems where users need real-time feedback about sub-agent progress.

Solution:
Implemented event streaming propagation for AgentTool to yield events from sub-agents in real-time to the parent Runner. This enables:

  1. Real-time visibility: Sub-agent events (model responses, tool calls, tool responses) are streamed immediately as they are generated
  2. Progressive feedback: Frontend receives events progressively, not all at once at the end
  3. Better UX: Users can see intermediate steps and progress, maintaining a responsive UI

Implementation Details:

  • Added run_async_with_events() method to AgentTool that yields events from sub-agent execution
  • Created handle_function_calls_async_with_agent_tool_streaming() helper function in functions.py to handle AgentTool event streaming
  • Modified _postprocess_handle_function_calls_async() in base_llm_flow.py to use the new streaming mechanism
  • Maintains backward compatibility - existing run_async() method still works as before

Testing Plan

Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes.

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Test Results:

tests/unittests/tools/test_agent_tool_event_streaming.py::test_agent_tool_run_async_with_events_yields_sub_agent_events PASSED
tests/unittests/tools/test_agent_tool_event_streaming.py::test_agent_tool_run_async_with_events_forwards_state_delta PASSED
tests/unittests/tools/test_agent_tool_event_streaming.py::test_agent_tool_event_streaming_in_runner PASSED

======================== 3 passed, 9 warnings in 8.07s =========================

Manual End-to-End (E2E) Tests:

Setup:

cd contributing/samples/agent_tool_event_streaming
adk web .

Test Steps:

  1. In the web UI, select agent_tool_event_streaming from the dropdown
  2. Ask: "Research the history of artificial intelligence"
  3. Observe the Events panel in real-time

Expected Behavior:

  • Coordinator agent's function call to research_agent appears immediately
  • Multiple events from research_agent stream progressively (not all at once)
  • Events include intermediate model responses showing step-by-step progress
  • Final function response event appears after all sub-agent events

Screenshots:
Screenshot 2025-12-20 at 11 20 12 PM
Screenshot 2025-12-20 at 11 20 23 PM
Screenshot 2025-12-20 at 11 21 47 PM

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

This PR will have merge conflicts with PR #3848 (streaming-tools-non-live) as both modify:

  • src/google/adk/flows/llm_flows/functions.py
  • src/google/adk/flows/llm_flows/base_llm_flow.py

if we are planning to merge this pr first, then i will have to rebase again and fix the conflicts of #3848

Note: These are separate features (PR #3848 handles streaming tools in non-live mode, while this PR handles AgentTool event streaming), but they touch the same code paths.

Sample Code:
A complete sample demonstrating the feature is available at:
contributing/samples/agent_tool_event_streaming/

Key Benefits:

  • Enables real-time visibility into sub-agent execution progress
  • Improves UX for hierarchical multi-agent systems
  • Maintains backward compatibility

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @sarojrout, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant enhancement to how AgentTool interacts with sub-agents, enabling real-time event propagation. The primary purpose is to transform the previously opaque execution of sub-agents into a transparent process, allowing users to observe the step-by-step progress of complex multi-agent tasks. This change dramatically improves the responsiveness and user experience of applications built with hierarchical agent systems by providing immediate feedback and visibility into intermediate operations.

Highlights

  • Real-time Event Streaming for AgentTool: Implemented a mechanism to stream events from sub-agents wrapped in AgentTool directly to the parent Runner, providing real-time visibility into sub-agent execution.
  • Improved User Experience: Addresses the "black box" problem of sub-agent execution by yielding intermediate events (model responses, tool calls, tool responses), making the frontend responsive and providing progressive feedback for hierarchical multi-agent systems.
  • Core Implementation Changes: Introduced run_async_with_events() in AgentTool, a new helper handle_function_calls_async_with_agent_tool_streaming() in functions.py, and modified _postprocess_handle_function_calls_async() in base_llm_flow.py to integrate the streaming logic.
  • Backward Compatibility & Testing: The existing run_async() method in AgentTool remains functional, and comprehensive unit and manual end-to-end tests have been added to verify the new streaming behavior.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@adk-bot adk-bot added live [Component] This issue is related to live, voice and video chat tools [Component] This issue is related to tools labels Dec 21, 2025
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a valuable feature for event streaming from AgentTool sub-agents, significantly improving the user experience for hierarchical agent systems by providing real-time feedback. The implementation is well-structured, adding a new run_async_with_events method and a corresponding streaming handler while maintaining backward compatibility. The inclusion of new unit tests and a sample application is commendable. I have a couple of suggestions to improve a test case for better validation and to remove a minor code redundancy.

Comment on lines 261 to 263
if not isinstance(tool_result, dict):
tool_result = {'result': tool_result}
agent_tool_results[function_call.id] = tool_result
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic to wrap tool_result in a dictionary is redundant here. The __build_response_event function, which is called later with this result, already handles wrapping non-dictionary results. Removing this logic will make the code cleaner and more consistent with the non-streaming tool execution path.

      agent_tool_results[function_call.id] = tool_result

@sarojrout
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a valuable feature for real-time event streaming from AgentTool sub-agents, significantly improving the user experience for hierarchical agent systems. The implementation is well-structured and includes thorough testing. My review focuses on opportunities to reduce code duplication and improve readability, which will enhance the long-term maintainability of this new functionality.

Comment on lines 21 to 22
cd contributing/samples
adk web .
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The command to run the demo appears to be incorrect. The PR description suggests running adk web . from within the agent_tool_event_streaming directory. To align with that and ensure the sample runs correctly, this path should be updated.

Suggested change
cd contributing/samples
adk web .
cd contributing/samples/agent_tool_event_streaming
adk web .

Comment on lines +689 to +697
if (
event.content
and event.content.parts
and any(
part.function_response
for part in event.content.parts
if part.function_response
)
):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This condition to check for a function response can be simplified by using the event.get_function_responses() helper method. This will make the code more concise and readable.

      if event.get_function_responses():

Comment on lines 261 to 262
if not isinstance(tool_result, dict):
tool_result = {'result': tool_result}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This check to ensure tool_result is a dictionary is redundant. The __build_response_event function, which is called later with this result, already performs the same check. Removing this duplicated validation will simplify the code.

@sarojrout
Copy link
Contributor Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a valuable feature for real-time event streaming from AgentTool sub-agents, which significantly improves the user experience for hierarchical agent systems by providing visibility into sub-agent execution. The implementation is well-structured, with a new streaming method in AgentTool, a dedicated handler in functions.py, and comprehensive unit tests and a sample application to validate the changes. My review includes a couple of suggestions to enhance maintainability by reducing code duplication and to improve performance by optimizing a list comprehension.

Comment on lines +264 to +270
parts=[
part
for part in (function_call_event.content.parts or [])
if part.function_call
and part.function_call.name
not in [fc.name for fc, _ in agent_tool_calls]
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The list comprehension used here to filter parts for regular_call_event re-evaluates [fc.name for fc, _ in agent_tool_calls] on each iteration. For improved performance, especially when dealing with many parts, it's more efficient to compute the set of agent tool names once before the list comprehension.

            agent_tool_names = {fc.name for fc, _ in agent_tool_calls}
            parts=[
                part
                for part in (function_call_event.content.parts or [])
                if part.function_call
                and part.function_call.name not in agent_tool_names
            ],

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

Labels

live [Component] This issue is related to live, voice and video chat tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Support Event Streaming propagation from AgentTool (Sub-agents) to Runner

2 participants