Skip to content

fix: concatenate list values in deep_merge_dicts during parallel tool call merge#5191

Open
enjoykumawat wants to merge 5 commits into
google:mainfrom
enjoykumawat:fix/parallel-state-delta-list-merge
Open

fix: concatenate list values in deep_merge_dicts during parallel tool call merge#5191
enjoykumawat wants to merge 5 commits into
google:mainfrom
enjoykumawat:fix/parallel-state-delta-list-merge

Conversation

@enjoykumawat

Copy link
Copy Markdown
Contributor

Summary

  • Bug: When multiple tool calls run in parallel and each writes to the same state_delta key containing a list value, deep_merge_dicts silently drops all but the last value because lists hit the else branch and get overwritten.
  • Fix: Add a list-type check in deep_merge_dicts so list values are concatenated (d1[key] + value) instead of overwritten, preserving all entries from parallel function responses.
  • Tests: Added 5 unit tests covering list concatenation, scalar overwrite, nested dict merge, mixed-type handling, and an integration test for merge_parallel_function_response_events with state_delta lists.

Reproduction

# Tool A's delta: {"state_delta": {"items": ["a"]}}
# Tool B's delta: {"state_delta": {"items": ["b"]}}
# Before fix: {"state_delta": {"items": ["b"]}} — item "a" is lost
# After fix:  {"state_delta": {"items": ["a", "b"]}} — both preserved

Test plan

  • All 5 new unit tests pass (test_deep_merge_dicts_* and test_merge_parallel_function_response_events_merges_state_delta_lists)
  • All 32 existing tests in test_functions_simple.py pass (0 regressions)
  • Manual: create parallel tool calls that accumulate list state and verify no data loss

Fixes #5190

enjoykumawat and others added 2 commits April 7, 2026 18:08
… call merge

When multiple tool calls run in parallel and each writes to the same
state_delta key containing a list value, deep_merge_dicts silently drops
all but the last value because lists hit the else branch and get
overwritten.

Add a list-type check so that list values are concatenated instead of
overwritten, preserving all entries from parallel function responses.

Fixes google#5190

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move the tests to test_functions_parallel.py

@wuliang229 wuliang229 self-assigned this Apr 7, 2026
enjoykumawat and others added 2 commits April 7, 2026 23:41
…nctions_parallel

Move tests for deep_merge_dicts and merge_parallel_function_response_events
with list state_delta merging from test_functions_simple.py to
test_functions_parallel.py per reviewer feedback.
@enjoykumawat

Copy link
Copy Markdown
Contributor Author

Done! Moved all the deep_merge_dicts and state_delta list tests to test_functions_parallel.py in commit 4b3db55. Also merged latest main to pick up any upstream changes. CI is re-running now.

@enjoykumawat

Copy link
Copy Markdown
Contributor Author

Hi @wuliang229, just following up — the tests have been moved to test_functions_parallel.py as requested (commit 4b3db55) and CI is passing. Would you have a chance to re-review when you get a moment? Happy to make any additional changes if needed.

@rohityan rohityan added needs review [Status] The PR/issue is awaiting review from the maintainer core [Component] This issue is related to the core interface and implementation labels Apr 9, 2026
copybara-service Bot pushed a commit that referenced this pull request Jun 22, 2026
… call merge

Merge #5191

## Summary

- **Bug:** When multiple tool calls run in parallel and each writes to the same `state_delta` key containing a list value, `deep_merge_dicts` silently drops all but the last value because lists hit the `else` branch and get overwritten.
- **Fix:** Add a list-type check in `deep_merge_dicts` so list values are concatenated (`d1[key] + value`) instead of overwritten, preserving all entries from parallel function responses.
- **Tests:** Added 5 unit tests covering list concatenation, scalar overwrite, nested dict merge, mixed-type handling, and an integration test for `merge_parallel_function_response_events` with `state_delta` lists.

## Reproduction

```python
# Tool A's delta: {"state_delta": {"items": ["a"]}}
# Tool B's delta: {"state_delta": {"items": ["b"]}}
# Before fix: {"state_delta": {"items": ["b"]}} — item "a" is lost
# After fix:  {"state_delta": {"items": ["a", "b"]}} — both preserved
```

## Test plan

- [x] All 5 new unit tests pass (`test_deep_merge_dicts_*` and `test_merge_parallel_function_response_events_merges_state_delta_lists`)
- [x] All 32 existing tests in `test_functions_simple.py` pass (0 regressions)
- [ ] Manual: create parallel tool calls that accumulate list state and verify no data loss

Fixes #5190

Co-authored-by: George Weale <gweale@google.com>
COPYBARA_INTEGRATE_REVIEW=#5191 from enjoykumawat:fix/parallel-state-delta-list-merge 7425481
PiperOrigin-RevId: 936119923
@adk-bot

adk-bot commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Thank you @enjoykumawat for your contribution! 🎉

Your changes have been successfully imported and merged via Copybara in commit 1ff84eb.

Closing this PR as the changes are now in the main branch.

@adk-bot adk-bot added the merged [Status] This PR is merged label Jun 22, 2026
@adk-bot adk-bot closed this Jun 22, 2026
copybara-service Bot pushed a commit that referenced this pull request Jun 22, 2026
… call merge

Merge #5191

## Summary

- **Bug:** When multiple tool calls run in parallel and each writes to the same `state_delta` key containing a list value, `deep_merge_dicts` silently drops all but the last value because lists hit the `else` branch and get overwritten.
- **Fix:** Add a list-type check in `deep_merge_dicts` so list values are concatenated (`d1[key] + value`) instead of overwritten, preserving all entries from parallel function responses.
- **Tests:** Added 5 unit tests covering list concatenation, scalar overwrite, nested dict merge, mixed-type handling, and an integration test for `merge_parallel_function_response_events` with `state_delta` lists.

## Reproduction

```python
# Tool A's delta: {"state_delta": {"items": ["a"]}}
# Tool B's delta: {"state_delta": {"items": ["b"]}}
# Before fix: {"state_delta": {"items": ["b"]}} — item "a" is lost
# After fix:  {"state_delta": {"items": ["a", "b"]}} — both preserved
```

## Test plan

- [x] All 5 new unit tests pass (`test_deep_merge_dicts_*` and `test_merge_parallel_function_response_events_merges_state_delta_lists`)
- [x] All 32 existing tests in `test_functions_simple.py` pass (0 regressions)
- [ ] Manual: create parallel tool calls that accumulate list state and verify no data loss

Fixes #5190

PiperOrigin-RevId: 936249245
@GWeale GWeale reopened this Jun 23, 2026
@enjoykumawat

Copy link
Copy Markdown
Contributor Author

Hi @GWeale — I see this was reopened after the Copybara merge (commit 1ff84eb is already in main). Is there a follow-up you'd like from me, or was this reopened for internal tracking? Happy to help.

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 merged [Status] This PR is merged needs review [Status] The PR/issue is awaiting review from the maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parallel tool calls: state_delta list values silently overwritten during merge

5 participants