Skip to content

perf(flows): Resolve agent tool unions in parallel#5875

Open
wenzhaoy-google wants to merge 1 commit into
google:mainfrom
wenzhaoy-google:parallelize-tool-union-resolution
Open

perf(flows): Resolve agent tool unions in parallel#5875
wenzhaoy-google wants to merge 1 commit into
google:mainfrom
wenzhaoy-google:parallelize-tool-union-resolution

Conversation

@wenzhaoy-google
Copy link
Copy Markdown

perf(flows): Resolve agent tool unions in parallel

_process_agent_tools previously walked agent.tools serially,
awaiting _convert_tool_union_to_tools for each entry in turn. For
toolsets this calls get_tools_with_prefix, which can perform I/O
(e.g. MCP list_tools over the network), so the total wall-clock cost
stacks linearly with the number of toolsets.

Dispatch every _convert_tool_union_to_tools call concurrently via
asyncio.gather so those listings overlap. The subsequent
process_llm_request calls are intentionally kept serial and in the
original agent.tools order: several built-in tools read or write
llm_request state (e.g. GoogleSearchTool writes
llm_request.model; ComputerUseToolset performs an idempotency
check on llm_request.config.tools) and rely on observing the
post-state of earlier tools.

Add two unit tests pinning down the new contract: one asserts
concurrent dispatch via a shared asyncio.Event gate (would hang if
still serial); the other asserts process_llm_request invocation
order still matches agent.tools order even when later unions
resolve first.

`_process_agent_tools` previously walked `agent.tools` serially,
awaiting `_convert_tool_union_to_tools` for each entry in turn. For
toolsets this calls `get_tools_with_prefix`, which can perform I/O
(e.g. MCP `list_tools` over the network), so the total wall-clock cost
stacks linearly with the number of toolsets.

Dispatch every `_convert_tool_union_to_tools` call concurrently via
`asyncio.gather` so those listings overlap. The subsequent
`process_llm_request` calls are intentionally kept serial and in the
original `agent.tools` order: several built-in tools read or write
`llm_request` state (e.g. `GoogleSearchTool` writes
`llm_request.model`; `ComputerUseToolset` performs an idempotency
check on `llm_request.config.tools`) and rely on observing the
post-state of earlier tools.

Add two unit tests pinning down the new contract: one asserts
concurrent dispatch via a shared `asyncio.Event` gate (would hang if
still serial); the other asserts `process_llm_request` invocation
order still matches `agent.tools` order even when later unions
resolve first.
@adk-bot adk-bot added the core [Component] This issue is related to the core interface and implementation label May 28, 2026
@google google deleted a comment from wenzhaoy-google May 28, 2026
@DeanChensj
Copy link
Copy Markdown
Collaborator

Could you fix the mypy failure?

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

Labels

core [Component] This issue is related to the core interface and implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants