Skip to content

[BUG] When executing Runners(of which agent contains stateful toolset) in parallel, toolset is being released when only one of them has finished #4045

Description

@challenger71498

Describe the bug

When you configure root agent able to call same AgentTool which is configured with MCP toolset in parallel, and one of them finishes first, the rest of them fails.

To Reproduce

Before we go..
  • Any stateful toolset(which means that its close() method does something) may cause this error.
  • Since I encountered this is when using McpToolset, I will explain the step to reproduce using McpToolset.
  • It is more likely to reproduce the issue if:
    • The execution time of AgentTool is fairly long(about >10s).
    • The execution time of AgentTool is random.
    • These will cause the invocation of AgentTools not to finish at the same time, making a certain call to finish at first.

You may reproduce this issue by 2 ways.

First case: call Runner which shares same Agent concurrently.

  1. A root agent, configured with an McpToolset.
  2. Execute two runners simultaneously.
  3. When any runner finishes first, the rest of runner fails, raises exception(related to resource exhaution).

Second case: call AgentTool with McpToolset in parallel.

  1. A root agent, configured with an AgentTool.
  2. This AgentTool consists of an agent, which has a MCP toolset.
  3. Write an instruction to trigger root agent to call AgentTools in parallel. (e.g. You must call 10 'search_item' tool in parallel.)
  4. Execute the root agent.
  5. When any AgentTool finishes first, the rest of AgentTool fails, raises exception(related to resource exhaution).

Expected behavior

Even if one of the runner has finished first, the rest of runners should not fail.

Screenshots

None, but I could reproduce both case by adding 2 test sample agent setups. You may look into it this PR #4046.

Desktop (please complete the following information):

  • OS: macOS
  • Python version(python -V): 3.13
  • ADK version(pip show google-adk): 1.9.0

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: gemini-2.5-flash

Additional context

This happens due to the early release of shared resource in runner, especially when the toolset is stateful.

First case: call `Runner` which shares same `Agent` concurrently

Starting with the first case, I described the initial state to a diagram as below.
Note that 2 runners are connected to a single toolset, demonstrates that the runner will close the toolset after it finishes since both runners are based on the same agent.

Image

Assume that Runner 1 is done first, cleaning up the toolset by calling self.close().

Image

Now the toolset has been closed. But Runner 2 is not finished yet. Therefore, tool call throws exception, making the runner to fail.

Image
Second case: call `AgentTool` with `McpToolset` in parallel.

Same thing goes on with the second case. The initial state is quite complicated, but the configuration is basically same: 2 runners are being executed concurrently.

Image

And as you expected, same problem occurs.

Image

IMO users usually do not use runner explicitly, I think first case would not occur frequently.

The second will occur quite frequently since calling same AgentTool in parallel is common(and useful!), e.g.

  • RAG search in parallel (this is my case)
  • run PR review bot in parallel
  • fetch data chunks in parallel

Also, calling tool in parallel is decided by LLM, and from what I know is that LLM usually calls tool in parallel. We could controll this behaviour only by restricting LLM to call tools sequentially, which is not deterministic(99% maybe, but not 100%).

I made a PR to address the second issue, adding AgentToolManager which functions as reference-count for agent when using AgentTool.

Activity

  1. added
    core[Component] This issue is related to the core interface and implementation
    on Dec 30, 2025
  2. added theissue type on Dec 30, 2025
  3. self-assigned this
    on Dec 30, 2025
  4. adk-bot commented on Jan 7, 2026

    @adk-bot
    Collaborator

    Notification: The author has updated the issue description. Maintainers, please review.

  5. surajksharma07 commented on Jan 9, 2026

    @surajksharma07
    Collaborator

    @challenger71498 This issue stems from toolsets lacking reference counting when shared across parallel Runners.

    The runner.close() call in agent_tool.py:187 (added in commit fa5c546 to fix MCP async context errors) now closes shared toolsets prematurely when AgentTools execute in parallel.

    Your PR #4046 with AgentToolManager looks like the right direction - it implements reference counting for AgentTool scenarios.

    As a workaround until the fix merges, you can instruct the LLM to execute tools sequentially (though this isn't 100% reliable) or use separate toolset instances per agent to avoid resource sharing.

    Thanks!

  6. added
    answered[Status] This issue has been answered by the maintainer
    on Jan 9, 2026
  7. surajksharma07 commented on Mar 26, 2026

    @surajksharma07
    Collaborator

    @Jacksunwei Please have a look into it once.

  8. claxman commented on Sep 7, 2026

    @claxman
    Contributor

    Two Runners sharing one LlmAgent with a CountingToolset: after r1.close() the toolset close_count is already 1 while r2 is still open. After r2.close() it is 2. I will refcount toolsets on Runner so close() only releases the toolset when the last holder is gone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

answered[Status] This issue has been answered by the maintainercore[Component] This issue is related to the core interface and implementation

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions