From 15a423ad3ca262997efd50bb92ca0961bc2e1214 Mon Sep 17 00:00:00 2001 From: Greyson LaLonde Date: Thu, 21 May 2026 01:09:30 +0800 Subject: [PATCH] fix: rebind MemoryScope/MemorySlice to fresh Memory after checkpoint restore --- lib/crewai/src/crewai/crew.py | 28 ++++++++++++++++++++++++++++ lib/crewai/src/crewai/flow/flow.py | 5 +++++ 2 files changed, 33 insertions(+) diff --git a/lib/crewai/src/crewai/crew.py b/lib/crewai/src/crewai/crew.py index e2e67368e..1b2d0095a 100644 --- a/lib/crewai/src/crewai/crew.py +++ b/lib/crewai/src/crewai/crew.py @@ -484,8 +484,36 @@ class Crew(FlowTrackable, BaseModel): if self.checkpoint_train is not None: self._train = self.checkpoint_train + self._rebind_memory_views() self._restore_event_scope() + def _rebind_memory_views(self) -> None: + """Reattach a live ``Memory`` to restored ``MemoryScope``/``MemorySlice`` views. + + Checkpoint JSON omits the live ``Memory`` dependency on scope/slice + views, so after restore they raise ``RuntimeError`` on first use. + Build a fresh ``Memory`` and bind it to any unbound views on the + crew and its agents. + """ + from crewai.memory.memory_scope import MemoryScope, MemorySlice + from crewai.memory.unified_memory import Memory + + fresh: Memory | None = None + + def _ensure(view: Any) -> None: + nonlocal fresh + if not isinstance(view, MemoryScope | MemorySlice): + return + if view._memory is not None: + return + if fresh is None: + fresh = Memory() + view.bind(fresh) + + _ensure(self.memory) + for agent in self.agents: + _ensure(agent.memory) + def _restore_event_scope(self) -> None: """Rebuild the event scope stack from the checkpoint's event record.""" from crewai.events.base_events import set_emission_counter diff --git a/lib/crewai/src/crewai/flow/flow.py b/lib/crewai/src/crewai/flow/flow.py index 5b71a2fbd..ef9658128 100644 --- a/lib/crewai/src/crewai/flow/flow.py +++ b/lib/crewai/src/crewai/flow/flow.py @@ -1098,6 +1098,11 @@ class Flow(BaseModel, Generic[T], metaclass=FlowMeta): } if self.checkpoint_state is not None: self._restore_state(self.checkpoint_state) + if ( + isinstance(self.memory, MemoryScope | MemorySlice) + and self.memory._memory is None + ): + self.memory.bind(Memory()) restore_event_scope(()) reset_last_event_id()