Task sub-agent attempts to execute the parent coordinator's delegation FunctionCall when resumability is enabled
Describe the bug
When an LLM coordinator delegates work to a sub-agent configured with mode="task", the task sub-agent attempts to execute the coordinator's delegation FunctionCall itself.
For example, after the coordinator delegates to the order_collector task agent, the order_collector appears to receive or observe the parent's delegation call named order_collector and attempts to execute it as one of its own tools.
This fails because order_collector is a delegation function exposed to the coordinator, not a tool registered on the child agent.
The resulting error is:
ValueError: Tool 'order_collector' not found.
Available tools: transfer_to_agent, confirmation, finish_task
Possible causes:
- LLM hallucinated the function name - review agent instruction clarity
- Tool not registered - verify agent.tools list
Name mismatch - check for typos
The problem occurs when resumability is enabled on the application:
app = App(
name="test",
root_agent=root_agent,
resumability_config=ResumabilityConfig(
is_resumable=True,
),
)
Disabling resumability prevents the issue. The same agent setup works when using:
app = App(
name="test",
root_agent=root_agent,
)
or:
app = App(
name="test",
root_agent=root_agent,
resumability_config=ResumabilityConfig(
is_resumable=False,
),
)
This suggests that the issue is related to resumable task-agent dispatch or event isolation rather than the agent instructions or tool registration.
Steps to reproduce
Create an order_collector agent using mode="task".
Add the task agent to an LLM coordinator through sub_agents.
Add a confirmation tool to the task agent.
Enable resumability on the ADK App.
Start the application using adk web.
Ask the coordinator about the menu or place a food order.
Let the coordinator delegate the request to order_collector.
Minimal reproduction
from future import annotations
from google.adk import Agent
from google.adk.agents.llm_agent import LlmAgent
from google.adk.models.lite_llm import LiteLlm
from google.adk.tools.function_tool import FunctionTool
from google.adk.apps.app import App, ResumabilityConfig
from pydantic import BaseModel
from pydantic import Field
from .adk_workaround import install_task_delegation_workaround
install_task_delegation_workaround()
class OrderItem(BaseModel):
name: str = Field(description="Name of the food item ordered")
quantity: int = Field(description="Quantity ordered")
class PaymentInfo(BaseModel):
"""Output schema for the payment collection task."""
credit_card_number: str
cvv: str
def place_order(orders: list[OrderItem], payment_info: PaymentInfo) -> str:
"""Mock an order placement operation."""
total_items = sum(item.quantity for item in orders)
return f"Successfully placed order for {total_items} items."
def confirmation() -> str:
"""Confirm proceeding with the order."""
return "Proceeding with order."
order_collector = Agent(
name="order_collector",
mode="task",
output_schema=list[OrderItem],
instruction=("""
You are an order collection assistant for a food delivery service.
Our menu today has exactly 3 items: 1. Pizza, 2. Burger, 3. Salad.
Ask the user what they would like to order and collect their choice and quantity.
Do not offer anything else.
If the combined quantity of items exceeds 5, you MUST use the confirmation tool to get user's confirmation before proceeding.
Do not ask for confirmation in natural language, always use the confirmation tool.
Once you have their final order and confirmation if needed, finish your task.
"""),
description="Collects the food order from the user.",
tools=[FunctionTool(confirmation, require_confirmation=True)],
)
payment_collector = Agent(
name="payment_collector",
mode="task",
output_schema=PaymentInfo,
instruction=("""
You are a payment collection assistant.
Ask the user for their credit card number and CVV.
Once you have both pieces of information, finish your task.
"""),
description="Collects credit card and CVV from the user.",
)
root_agent = LlmAgent(
model=LiteLlm("openai/gemma4unc:31b"),
name="coordinator",
sub_agents=[order_collector, payment_collector],
tools=[place_order],
instruction="""
You are a helpful coordinator for a food delivery service.
You need both order and payment information to place an order.
""",
)
app = App(
name="test",
root_agent=root_agent,
resumability_config=ResumabilityConfig(
is_resumable=True,
),
)
The model configuration has been omitted from this reproduction because the issue appears to be related to task dispatch and event isolation rather than a specific model provider.
Reproducing with ADK Web
The easiest way to reproduce the issue is to start the application with:
Then open the test application in the ADK Web UI and ask the coordinator about the available menu or place a simple food order, for example:
or:
I would like to order one pizza.
The coordinator delegates the request to the order_collector task agent.
Shortly after the delegation, the task agent attempts to execute the coordinator's delegation function call named order_collector, resulting in:
ValueError: Tool 'order_collector' not found.
Available tools: transfer_to_agent, confirmation, finish_task
The issue occurs consistently when is_resumable=True.
Repeating the same test after disabling resumability works as expected and does not produce the invalid tool call.
Expected behavior
The coordinator's delegation FunctionCall should remain part of the parent agent's execution context.
The child task agent should receive only:
its reconstructed task input;
relevant task-agent conversation events;
its own registered tools;
resumability information belonging to its task execution.
The child should not receive or attempt to execute the parent's delegation FunctionCall.
Enabling resumability should not change which function calls are visible to or executable by the child task agent.
Observed behavior
The coordinator correctly creates a delegation FunctionCall for the task agent.
After the task agent starts, it appears to receive the parent coordinator's delegation call in its own runner event list. It then attempts to execute the delegation call named order_collector.
Because the task agent only has access to its own tools, ADK raises:
Tool 'order_collector' not found.
Available tools: transfer_to_agent, confirmation, finish_task
The order_collector name is the task-agent delegation function exposed to the parent coordinator. It is not supposed to be executed by the child agent itself.
The behavior changes when resumability is disabled:
is_resumable=True -> Child attempts to execute order_collector and fails
is_resumable=False -> Delegation works as expected
Possible cause
The child task agent may be receiving the coordinator's delegation event as part of its own runner event list when resumability is enabled.
It appears that the parent delegation call is not sufficiently isolated from the child task-agent execution context. The child then interprets the parent's delegation FunctionCall as a pending function call that it must execute itself.
Environment details
ADK Library Version: 2.4.0
Desktop OS: Linux
Python Version: 3.14
Execution interface: adk web
Resumability enabled: Yes
Frequency: Always, 100%
Optional information
Regression
I have not verified whether this worked in an earlier ADK version.
Logs
ValueError: Tool 'order_collector' not found.
Available tools: transfer_to_agent, confirmation, finish_task
Possible causes:
- LLM hallucinated the function name - review agent instruction clarity
- Tool not registered - verify agent.tools list
Name mismatch - check for typos
Workaround
Disabling resumability prevents the issue:
app = App(
name="test",
root_agent=root_agent,
resumability_config=ResumabilityConfig(
is_resumable=False,
),
)
A local workaround that forces task-agent dispatch into a separate sub-branch also prevents the parent delegation call from being executed by the child. However, that workaround modifies private ADK runtime APIs and is therefore not suitable as a permanent solution.
How often has this issue occurred?
Task sub-agent attempts to execute the parent coordinator's delegation FunctionCall when resumability is enabled
Describe the bug
When an LLM coordinator delegates work to a sub-agent configured with
mode="task", the task sub-agent attempts to execute the coordinator's delegationFunctionCallitself.For example, after the coordinator delegates to the
order_collectortask agent, theorder_collectorappears to receive or observe the parent's delegation call namedorder_collectorand attempts to execute it as one of its own tools.This fails because
order_collectoris a delegation function exposed to the coordinator, not a tool registered on the child agent.The resulting error is:
The problem occurs when resumability is enabled on the application:
Disabling resumability prevents the issue. The same agent setup works when using:
or:
This suggests that the issue is related to resumable task-agent dispatch or event isolation rather than the agent instructions or tool registration.
Steps to reproduce
Create an
order_collectoragent usingmode="task".Add the task agent to an LLM coordinator through
sub_agents.Add a confirmation tool to the task agent.
Enable resumability on the ADK
App.Start the application using
adk web.Ask the coordinator about the menu or place a food order.
Let the coordinator delegate the request to
order_collector.Minimal reproduction
The model configuration has been omitted from this reproduction because the issue appears to be related to task dispatch and event isolation rather than a specific model provider.
Reproducing with ADK Web
The easiest way to reproduce the issue is to start the application with:
Then open the
testapplication in the ADK Web UI and ask the coordinator about the available menu or place a simple food order, for example:or:
The coordinator delegates the request to the
order_collectortask agent.Shortly after the delegation, the task agent attempts to execute the coordinator's delegation function call named
order_collector, resulting in:The issue occurs consistently when
is_resumable=True.Repeating the same test after disabling resumability works as expected and does not produce the invalid tool call.
Expected behavior
The coordinator's delegation
FunctionCallshould remain part of the parent agent's execution context.The child task agent should receive only:
its reconstructed task input;
relevant task-agent conversation events;
its own registered tools;
resumability information belonging to its task execution.
The child should not receive or attempt to execute the parent's delegation
FunctionCall.Enabling resumability should not change which function calls are visible to or executable by the child task agent.
Observed behavior
The coordinator correctly creates a delegation
FunctionCallfor the task agent.After the task agent starts, it appears to receive the parent coordinator's delegation call in its own runner event list. It then attempts to execute the delegation call named
order_collector.Because the task agent only has access to its own tools, ADK raises:
The
order_collectorname is the task-agent delegation function exposed to the parent coordinator. It is not supposed to be executed by the child agent itself.The behavior changes when resumability is disabled:
is_resumable=True -> Child attempts to execute order_collector and failsis_resumable=False -> Delegation works as expected
Possible cause
The child task agent may be receiving the coordinator's delegation event as part of its own runner event list when resumability is enabled.
It appears that the parent delegation call is not sufficiently isolated from the child task-agent execution context. The child then interprets the parent's delegation
FunctionCallas a pending function call that it must execute itself.Environment details
ADK Library Version:
2.4.0Desktop OS: Linux
Python Version:
3.14Execution interface:
adk webResumability enabled: Yes
Frequency: Always, 100%
Optional information
Regression
I have not verified whether this worked in an earlier ADK version.
Logs
Workaround
Disabling resumability prevents the issue:
A local workaround that forces task-agent dispatch into a separate sub-branch also prevents the parent delegation call from being executed by the child. However, that workaround modifies private ADK runtime APIs and is therefore not suitable as a permanent solution.
How often has this issue occurred?
Always, 100%