fix(samples): make a2a human-in-the-loop sample resume after confirmation#6187
Open
vaibhav-patel wants to merge 1 commit into
Open
fix(samples): make a2a human-in-the-loop sample resume after confirmation#6187vaibhav-patel wants to merge 1 commit into
vaibhav-patel wants to merge 1 commit into
Conversation
…tion The A2A human-in-the-loop sample never completed after the manager approved a reimbursement: the approval ran as a long-running tool on the remote approval_agent, but the root reimbursement_agent was exposed as a bare agent. When the user sent the approval (a FunctionResponse for the pending long-running call) the next turn was routed to the root agent instead of the remote approval_agent, because Runner._find_agent_to_run only re-routes a function-response turn back to the originating agent when the app is resumable. Resumability is disabled by default, so the pending tool was never resumed and the task only finished if the user explicitly asked to retry (which made the model transfer to the remote agent again, starting a fresh task). Expose the sample as an App with ResumabilityConfig(is_resumable=True) so the approval is delivered back to the remote approval_agent and the paused tool resumes, matching the documented flow. Also fix the stale paths in the README run commands (the sample lives under contributing/samples/a2a/) and document how to approve a pending request from the ADK Web UI. Fixes google#5871.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
Following the README for
contributing/samples/a2a/a2a_human_in_loop, the task never completes after the manager approves a reimbursement — it only finishes if the user explicitly asks to "retry". Fixes #5871.Root cause
The approval runs as a
LongRunningFunctionTool(ask_for_approval) on the remoteapproval_agent, which is a sub-agent of the local root agent. When the user approves, the approvalFunctionResponsemust be routed back to the remote agent so it can resume the paused tool.Runner._find_agent_to_runonly re-routes a function-response turn to the originating agent when the app is resumable, andResumabilityConfig.is_resumabledefaults toFalse. Underadk webthe bare agent is wrapped in anAppwith no resumability config, so the approval was delivered to the root agent — which has no pending call — and nothing happened. "retry" only worked because it made the model transfer to the remote agent again, starting a brand-new task.This is a sample-wiring issue; the framework resume path already works (see
tests/unittests/a2a/integration/test_client_server.py).Fix
AppwithResumabilityConfig(is_resumable=True)(the same pattern ascontributing/samples/hitl/human_tool_confirmation), so the approval is routed back to the remoteapproval_agentand the long-running tool resumes.contributing/samples/a2a/) and document how to approve a pending request from the ADK Web UI (send aFunctionResponsevia "Send another response", not a plain chat message).Verification
Verified the routing mechanism deterministically with fake models (no live model needed):
Fix applied: the sample's
app.resumability_config.is_resumable is True,app.root_agentintact.Runner._find_agent_to_runrouting — the exact decision the fix changes — driven with the session state the Web UI produces after approval (last event = the user's approvalFunctionResponsefor the long-running call previously emitted byapproval_agent):is_resumable=True(this fix)approval_agentis_resumable=Falsereimbursement_agent(root)App(upstream)reimbursement_agent(root)Confirmed identical in both a non-transferable
LlmAgentsub-agent and aBaseAgentsub-agent (the sample's real shape —RemoteA2aAgentis aBaseAgent). 8/8 assertions passed.Existing suites pass on the branch:
a2a/integration/test_client_server.py(12),test_runners.py(69 — includingtest_find_agent_to_run_uses_function_response_when_resumableand..._skips_function_response_when_not_resumable), plus the long-running-tool / resumability / apps suites — 122 passed, 1 skipped, 3 xfailed (the skip/xfail are pre-existing V2-resume markers, unrelated to this change).Note: no Gemini key was available, so the full two-server live run wasn't exercised; the routing decision the fix relies on is verified at the
Runnerlevel and corroborated by the existing unit tests.Fixes #5871.