feat: Add progressive streaming for run_async via ProgressiveTool (partial progress + final result) #2698
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Linked Issue
Closes: #2014
Summary
This PR introduces progressive streaming support for non-live runs (
run_async).partial function_responseevents.function_responseis injected back into the model.Rationale
Users need progress visibility for long-running tools during
run_async, without switching to the live APIs.This feature mirrors live runner ergonomics while remaining opt-in and ensuring model reasoning is unchanged (only final outputs affect the model).
New API
google.adk.tools.progressive_function_tool.ProgressiveFunctionTool(abstract base)google.adk.tools.progressive_tool.ProgressiveTool(convenience wrapper)Supported patterns:
yield→ partial; lastyield→ finalprogressorprogress_callback: injected reporter emits partials; return value → finalChanges
src/google/adk/flows/llm_flows/base_llm_flow.py_postprocess_handle_function_calls_asyncupdated to handle progressive tools (stream partials + final).src/google/adk/flows/llm_flows/functions.pyiter_progressive_function_calls_async(...)to stream partials and yield a finalfunction_response.src/google/adk/tools/progressive_function_tool.pysrc/google/adk/tools/progressive_tool.py_ignore_params).src/google/adk/tools/__init__.pyProgressiveTool.Backward Compatibility
Testing Plan
Unit Tests (added)
Tools:
tests/unittests/tools/test_progressive_tool.pyprogress,progress_callback)run_asyncreturns last yieldFlows:
tests/unittests/flows/llm_flows/test_progressive_flow.pyProgressiveToolProgressiveFunctionToolsupportedFunctions:
tests/unittests/flows/llm_flows/test_functions_progressive_unit.pyCommands:
# Run only progressive tool/flow tests pytest -q tests/unittests/tools/test_progressive_tool.py \ tests/unittests/flows/llm_flows/test_progressive_flow.py \ tests/unittests/flows/llm_flows/test_functions_progressive_unit.pyManual End-to-End (E2E)
Minimal script with
InMemoryRunner+ProgressiveTool(export_report)(async generator).Observed output (truncated):
Partial events:
{"status": "started", "country": "Germany"} {"status": "progress", "percent": 20} ... {"status": "progress", "percent": 100} {"status": "completed", "url": "https://example.com/germany.pdf"}Model Reply
The report for Germany has been exported and can be accessed at https://example.com/germany.pdfDocumentation
No user-facing docs changed in this PR.
A follow-up PR to
adk-docswill add a short usage guide forProgressiveTool.