feat(samples): Add backend blocking poll pattern for HITL workflows #3224
+2,882
−4
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.
Summary
This PR adds a backend blocking poll pattern for human-in-the-loop (HITL) approval workflows as an alternative to the existing
LongRunningFunctionTool
pattern.Pattern Overview
The backend blocking poll pattern handles polling internally within the tool, allowing the agent to call the approval tool once and receive the final decision without manual intervention.
Key Benefits:
FunctionResponse
injection requiredGitHub Issues Addressed
This pattern directly addresses:
Issue #3184: Parent agent doesn't pause properly for sub-agent approvals
Direct Solution: This pattern eliminates the need for parent agents to pause and resume. The approval tool blocks internally while polling, and the agent naturally waits for the final decision.
Issue #1797: Need HITL event support
Alternative Provided: For systems that don't support webhooks (poll-only systems like Jira, ServiceNow), this pattern provides a simple alternative to webhook-based
LongRunningFunctionTool
.Files Added
All files in
contributing/samples/human_in_loop_blocking_poll/
:Core Implementation
blocking_poll_approval_example.py
- Synchronous version (standalone agents, low concurrency)blocking_poll_approval_example_async.py
- Asynchronous version (production, high concurrency)Testing Infrastructure
mock_approval_api.py
- FastAPI-based mock approval server with HTML dashboardtest_standalone.py
- Standalone sync integration test (no ADK dependencies)test_standalone_async.py
- Standalone async integration testtest_blocking_poll_core.py
- Unit tests with pytest (12 tests)Documentation
README.md
- Comprehensive documentation (359 lines) including:Test Results
100% Pass Rate (20 tests total):
Integration Tests
Unit Tests
All tests validated locally before submission.
Production Validation
This pattern has been validated in a production multi-agent RFQ approval system:
Real-World Use Case:
When to Use This Pattern
✅ Use Backend Blocking Poll When:
FunctionResponse
management)Design Decisions
Why Async + Sync Versions?
Why Mock API?
Provides complete testing infrastructure without external dependencies, allowing developers to validate the pattern locally.
Why Comprehensive Documentation?
The 359-line README includes:
LongRunningFunctionTool
to clarify differencesChecklist
Reviewer Notes
This contribution complements the existing
human_in_loop
sample by providing an alternative pattern for poll-only systems. It does not replaceLongRunningFunctionTool
but offers a simpler option when webhooks are not available.Related Samples:
contributing/samples/human_in_loop/
- Existing LongRunningFunctionTool patterncontributing/samples/a2a_human_in_loop/
- A2A human-in-the-loop exampleProduction Impact: