Skip to content

Parallel tool calls: state_delta list values silently overwritten during merge #5190

Description

@thequantumquirk

Description

When multiple tool calls run in parallel and each writes to the same state_delta key containing a list value, merge_parallel_function_response_events silently drops all but the last value.

Root Cause

deep_merge_dicts in flows/llm_flows/functions.py (line ~822) only recurses into dict values. Lists hit the else branch and get overwritten:

defdeep_merge_dicts(d1: dict, d2: dict) ->dict:
forkey, valueind2.items():
ifkeyind1andisinstance(d1[key], dict) andisinstance(value, dict):
d1[key] =deep_merge_dicts(d1[key], value)
else:
d1[key] =value# <-- lists are overwritten herereturnd1

Reproduction

  1. Create a tool that appends to a list in tool_context.state:
defmy_tool(tool_context, item):
items=tool_context.state.get("items") or []
items=list(items)
items.append(item)
tool_context.state["items"] =items
  1. Have the LLM call this tool multiple times in a single response (parallel execution via asyncio.gather in handle_function_calls_live)
  2. Each parallel call gets its own ToolContext with a separate state_delta
  3. Tool A's delta: {"state_delta": {"items": ["a"]}}
  4. Tool B's delta: {"state_delta": {"items": ["b"]}}
  5. After merge: {"state_delta": {"items": ["b"]}} — item "a" is lost

Impact

Any application that accumulates list state across parallel tool calls loses data. In our case, drafting multiple emails in a single agent turn results in only ~2 out of 10 emails persisting.

Suggested Fix

deep_merge_dicts should concatenate lists instead of overwriting:

defdeep_merge_dicts(d1: dict, d2: dict) ->dict:
forkey, valueind2.items():
ifkeyind1andisinstance(d1[key], dict) andisinstance(value, dict):
d1[key] =deep_merge_dicts(d1[key], value)
elifkeyind1andisinstance(d1[key], list) andisinstance(value, list):
d1[key] =d1[key] +valueelse:
d1[key] =valuereturnd1

Environment

  • google-adk 1.18.0
  • Python 3.12
  • Using DatabaseSessionService with LiteLLM + OpenAI models

Metadata

Metadata

Labels

core[Component] This issue is related to the core interface and implementationneeds review[Status] The PR/issue is awaiting review from the maintainer

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions