From 866c8009dcdd6349598d4a15948ba2e030aa1795 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Mon, 23 Jun 2025 17:21:07 -0700 Subject: [PATCH] Fix bug where Command(update=) could be ignored if there was a 2nd interrupt after it - writes from the null task (ie. from outside tasks) should be accummulated across invocations --- libs/langgraph/langgraph/pregel/loop.py | 24 ++++++++++++++++++------ libs/langgraph/tests/test_pregel.py | 12 +++++++++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/loop.py b/libs/langgraph/langgraph/pregel/loop.py index 4549d2244..9391fb3a9 100644 --- a/libs/langgraph/langgraph/pregel/loop.py +++ b/libs/langgraph/langgraph/pregel/loop.py @@ -313,10 +313,22 @@ class PregelLoop: # deduplicate writes to special channels, last write wins if all(w[0] in WRITES_IDX_MAP for w in writes): writes = list({w[0]: w for w in writes}.values()) - # remove existing writes for this task - self.checkpoint_pending_writes = [ - w for w in self.checkpoint_pending_writes if w[0] != task_id - ] + if task_id == NULL_TASK_ID: + # writes for the null task are accumulated + self.checkpoint_pending_writes = [ + w + for w in self.checkpoint_pending_writes + if w[0] != task_id or w[1] not in WRITES_IDX_MAP + ] + writes_to_save: WritesT = [ + w[1:] for w in self.checkpoint_pending_writes if w[0] == task_id + ] + list(writes) + else: + # remove existing writes for this task + self.checkpoint_pending_writes = [ + w for w in self.checkpoint_pending_writes if w[0] != task_id + ] + writes_to_save = writes # save writes self.checkpoint_pending_writes.extend((task_id, c, v) for c, v in writes) if self.checkpoint_during and self.checkpointer_put_writes is not None: @@ -337,7 +349,7 @@ class PregelLoop: self.submit( self.checkpointer_put_writes, config, - writes, + writes_to_save, task_id, task_path_str(task.path) if task else "", ) @@ -345,7 +357,7 @@ class PregelLoop: self.submit( self.checkpointer_put_writes, config, - writes, + writes_to_save, task_id, ) # output writes diff --git a/libs/langgraph/tests/test_pregel.py b/libs/langgraph/tests/test_pregel.py index 1ecc18466..5e8992e26 100644 --- a/libs/langgraph/tests/test_pregel.py +++ b/libs/langgraph/tests/test_pregel.py @@ -4909,7 +4909,7 @@ def test_interrupt_multiple(sync_checkpointer: BaseCheckpointSaver): assert [ event for event in graph.stream( - Command(resume="answer 1", update={"my_key": "foofoo"}), thread1 + Command(resume="answer 1", update={"my_key": " foofoo "}), thread1 ) ] == [ { @@ -4924,8 +4924,14 @@ def test_interrupt_multiple(sync_checkpointer: BaseCheckpointSaver): } ] - assert [event for event in graph.stream(Command(resume="answer 2"), thread1)] == [ - {"node": {"my_key": "answer 1 answer 2"}}, + assert [ + event + for event in graph.stream( + Command(resume="answer 2"), thread1, stream_mode="values" + ) + ] == [ + {"my_key": "DE foofoo "}, + {"my_key": "DE foofoo answer 1 answer 2"}, ]