From 7a57c9b0e788e8462ee183e884b159b04c9ad244 Mon Sep 17 00:00:00 2001 From: citizen204 Date: Thu, 25 Jun 2026 21:29:10 +0930 Subject: [PATCH] fix(state): use merge_dicts reducer for scratchpad to prevent key loss When multiple save_note tool calls run in the same executor_tools superstep, they all read the same base state and each produce a full merged-scratchpad update. The previous take_last reducer discarded all but the last update, silently losing keys written by earlier tool calls. merge_dicts accumulates every key across all concurrent updates, preserving all writes. Fixes #208 --- minitap/mobile_use/graph/state.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/minitap/mobile_use/graph/state.py b/minitap/mobile_use/graph/state.py index 85d66691..f465d399 100644 --- a/minitap/mobile_use/graph/state.py +++ b/minitap/mobile_use/graph/state.py @@ -17,6 +17,11 @@ def take_last(a, b): return b +def merge_dicts(a, b): + """Merge two dicts; keys in b overwrite keys in a.""" + return {**a, **b} + + class State(BaseModel): messages: Annotated[list[AnyMessage], "Sequential messages", add_messages] remaining_steps: Annotated[int | None, "Remaining steps before the task is completed"] = None @@ -62,7 +67,7 @@ class State(BaseModel): scratchpad: Annotated[ dict[str, str], "Persistent key-value storage for notes the agent can save and retrieve", - take_last, + merge_dicts, ] = {} async def asanitize_update(