Repository navigation
Closed
Closed
Copy link
Labels
core[Component] This issue is related to the core interface and implementation[Component] This issue is related to the core interface and implementationneeds review[Status] The PR/issue is awaiting review from the maintainer[Status] The PR/issue is awaiting review from the maintainer
Description
Summary
When a sub-agent within a custom orchestrator agent calls a LongRunningFunctionTool, the FunctionResponse is routed directly to the sub-agent, bypassing the parent custom agent's _run_async_impl method entirely. This prevents custom agents from implementing proper workflow orchestration and continuation logic after long-running tool pauses.
Our Architecture
We have a custom orchestrator agent (DomainAgent) that manages multi-step workflows:
DomainAgent (custom orchestrator)
├── Router Agent (LlmAgent)
├── Planner Agent (LlmAgent)
└── Step Executor Agent (LlmAgent) ← calls long-running tool
Flow:
DomainAgent._run_async_impl()orchestrates the workflow- Calls router → planner → executes multiple steps sequentially
- Step Executor agent calls
ask_clarifications(LongRunningFunctionTool) - Frontend collects user input and sends
FunctionResponse - Problem: Runner routes directly to Step Executor, never re-enters
DomainAgent._run_async_impl()
The Issue
In runners.py, the _find_agent_to_run() method (line 1003-1055) determines which agent should handle the next message:
def _find_agent_to_run(self, session: Session, root_agent: BaseAgent) -> BaseAgent:
# If the last event is a function response, send to agent that made the function call
event = find_matching_function_call(session.events)
if event and event.author:
return root_agent.find_agent(event.author) # ← Returns sub-agent directly
# ... rest of logicWhat happens:
- Step Executor calls long-running tool → event.author = "step_executor"
- Frontend sends FunctionResponse via
run_async(invocation_id=..., new_message=FunctionResponse) _find_agent_to_run()finds the function call event with author="step_executor"- Returns Step Executor agent directly
- Runner calls
step_executor.run_async() - DomainAgent's orchestration logic is completely bypassed
Expected Behavior
The DomainAgent should be able to:
- Detect that a FunctionResponse is being processed
- Update workflow state
- Continue orchestration (e.g., move to next workflow step)
- Properly manage the entire workflow lifecycle
Questions
- Is this the intended behavior? Should long-running tools always route directly to the calling agent?
- Is there a supported way for custom orchestrator agents to intercept FunctionResponses for sub-agents?
- Could ADK provide a hook (e.g.,
can_handle_sub_agent_function_response()) to let parent agents opt-in to handling their sub-agents' function responses?
Environment
- ADK Version: [Latest from main]
- Python Version: 3.12
- Agent Type: Custom BaseAgent subclass with LlmAgent sub-agents
Additional Context
This limitation makes it difficult to implement:
- Multi-step workflows with human-in-the-loop
- Orchestrator agents that manage sub-agent lifecycles
- Complex state machines where parent agents coordinate sub-agent interactions
- Resume logic that requires parent-level context
Metadata
Metadata
Assignees
Labels
core[Component] This issue is related to the core interface and implementation[Component] This issue is related to the core interface and implementationneeds review[Status] The PR/issue is awaiting review from the maintainer[Status] The PR/issue is awaiting review from the maintainer
Activity
surajksharma07 commentedon Dec 25, 2025
@selimseker This behavior is intentional in
runners.py:1025-1031where_find_agent_to_run()routes FunctionResponses directly to the calling agent (needed for A2A credential requests).For custom orchestrators to intercept sub-agent FunctionResponses, ADK would need a new hook like
can_handle_sub_agent_function_response()that parent agents can implement.As a workaround, use SequentialAgent or avoid LongRunningFunctionTool in custom orchestrators.
This is a valid feature request for enhanced orchestration patterns.
Thanks!
surajksharma07 commentedon Jan 25, 2026
@wukath Please have a look into it once.
surajksharma07 commentedon Jan 25, 2026
This is still an open feature request - the routing behavior in
runners.py:1099-1105remains unchanged in v1.23.0.Adding orchestrator interception hooks (like
can_handle_sub_agent_function_response()) would require a design decision to balance with existing A2A credential patterns.We're tracking this for future consideration.
Team is looking more into it.
GWeale commentedon Aug 28, 2026
fixed on the v2 line. the functionresponse turn re-enters your orchestrator's _run_async_impl before the sub-agent runs, where on v1.21.0 it went straight to the sub-agent. we didn't add the can_handle_sub_agent_function_response hook you suggested, so reopen if the new default doesn't cover your workflow. 1.39.1 is unchanged.