Repository navigation
A task-mode root agent loses its task input once it asks the user a question #7384
Description
Activity
Hi @lamberttraccard, thanks for the detailed reproduction and the minimal scripted-model case.
I’d like to investigate this issue, specifically the root
LlmAgent(mode="task")task-input lifecycle across a paused question/answer turn and the interaction between_build_task_input_user_content, task scopes, andinvocation_context.user_content.I’ll first reproduce the behavior against the reported version and trace how the initial root task input is stored, filtered, and reconstructed after the task pauses. Then I’ll look for a minimal fix that preserves the original task input across follow-up turns without changing the existing behavior for delegated task agents.
If the behavior is confirmed, I’ll add regression coverage for both the single paused task and the subsequent task in the same session before proposing the fix.
Reacted by Lambert Traccard and Romain N.- addedcore[Component] This issue is related to the core interface and implementation[Component] This issue is related to the core interface and implementation
on Oct 5, 2026 Your script reproduces this on 2.11.0 and main @lamberttraccard. It's actually a regression: 2.9.2 keeps "Revenue by country" on the follow-up turn. Bisected it to ddbb59e (v2.10.0) which now gives a task-mode root the fixed scope reporting@1.
A workaround worth trying: scope the root task as f"{node.name}@{ctx.invocation_id}" when ctx.node_path is empty (a small wrap of DynamicNodeScheduler._execute_step) and when there's no delegating FC build the task input from the user message that opened that scope. With that getting your expected call 1 and call 3 and the existing task/runner tests still pass. Happy to share the script.
Could you check whether it holds up behind to_a2a with LiteLLM on your side? Only tried it with the scripted model.
@vinitsonawane45 if you pick this up please test it against both turns of the repro and the peer-isolation case from ddbb59e (test_task_api_e2e.py) before opening a PR.
@vinitsonawane45 are you still working on this? If not, I'd be glad to pick it up following @surajksharma07's approach and test it against both repro turns and the
test_task_api_e2e.pypeer-isolation case.@ahlag thanks for offering. @vinitsonawane45 hasn't posted an update in a week so unless they reply here in the next day or two please go ahead, just leave a note when you start so no one duplicates the work.
For context: this still reproduces on current main (128faab) even after the recent workflow isolation changes (097ae1e) and the per-invocation root scope workaround still gives the expected call 1 and call 3 there.
Before opening a PR please test it against both turns of the repro, the peer-isolation case in test_task_api_e2e.py and ideally a to_a2a root since that's the path the reporter hits.
@lamberttraccard whenever you get a chance it'd still help to know whether the workaround holds up behind to_a2a with LiteLLM on your side.
Reacted by Chang Yong LikThanks @surajksharma07! I'll give @vinitsonawane45 until Oct 11 to reply and post a note here before I start.
Once I do, I'll cover both turns of the repro, the peer-isolation case in
test_task_api_e2e.py, and ato_a2aroot.Hi @surajksharma07, @ahlag, and @lamberttraccard — thanks for your patience.
I’ve implemented the root invocation-scoping fix and opened PR #7419. I’ve now also added an A2A client/server regression test covering clarification and resumption, and the targeted test passes locally.
Sorry for not posting an update sooner. I’m still following the issue and will respond to review feedback. The PR is open and awaiting review.
@ahlag, thanks for offering to pick this up. Since the PR is now open, please let me know if there’s any additional validation you’d like me to prioritize.
🔴 Required Information
Describe the Bug:
Runner.run_asyncdocuments a rootLlmAgent(mode="task")as fully supported, and it is the server shape theRemoteA2aAgenttask-mode guide puts behindto_a2a. Two things go wrong as soon as that root asks the user something before callingfinish_task.<agent>@1), which_find_active_task_scopealready counts as finished. The user's answer to a question in that later task is therefore not stamped with the scope, and it reaches the model only as the task input at the head of the contents. The history the model sees ends on its own question.Steps to Reproduce:
pip install google-adk==2.11.0Expected Behavior:
[('user', 'Revenue by country'), ('model', 'Which period?'), ('user', 'Q3')].('user', 'Desktop and mobile'), after('model', 'Which devices?').Observed Behavior:
Environment Details:
src/google/adk/flows/llm_flows/context/_contents.pyis unchanged onmain.Model Information:
BaseLlm. Production goes through LiteLLM.🟡 Optional Information
Regression:
Not known. A root
LlmAgent(mode="task")is what the reproduction exercises; it was not tried on earlier versions.Where it comes from:
isolation_scope, and the contents filter for scopereporting@1drops it._build_task_input_user_contentthen looks for a function call whose id is the scope, finds none (a root has no delegating call), and falls back toinvocation_context.user_content. When a message continues a paused task,_node_runner_utilsdeliberately leavesuser_contentas the new message ("A message that joins a paused task only borrowed that invocation's id"), so the fallback is the answer, not the request.reporting@1, so every task in the session shares one scope, and once one task has calledfinish_taskthat scope stays infinished_scopes.Impact:
Any multi-turn task served as a root, which includes every
to_a2aserver aRemoteA2aAgent(mode="task")delegates to: the remote agent asks a clarifying question, and on the next turn it no longer knows what it was asked to do.A chat coordinator that delegates to the same agent as a
tasksub-agent does not have the problem, because the delegating function call is in the session and its id is the scope.