LangMemLangMem 0.0.30 · LangGraph 1.2 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
18 small wins to finish your pathNext lesson

Background memory with ReflectionExecutor

Extracting after every message is slow and wasteful. ReflectionExecutor runs a store manager in the background, after a delay that restarts when new messages arrive.

Example
asha = {"configurable": {"user_id": "asha", "thread_id": "chat-1"}}
with ReflectionExecutor(manager, store=store) as executor:
    future = executor.submit({"messages": [{"role": "user", "content": "My name is Asha. I moved to Pune."}]}, config=asha, after_seconds=1)
    print("right after submit:", len(store.search(("memories", "asha"))))
    future.result()
    print("after it ran:", len(store.search(("memories", "asha"))))

submit returns at once with a Future. The work runs on a worker thread after after_seconds, so the reply to the customer is not delayed. future.result() waits for it, which a real app would not do.

Debouncing

Submits are keyed by thread_id. A new submit for the same thread before the delay ends cancels the pending one, so a customer typing five quick messages causes one extraction over the full conversation, not five. Pick a delay longer than the gap between messages in a normal conversation, often minutes.

Two details the source shows

  • Outside a LangGraph node, submit needs config= with the ids; inside a graph it reads the current config itself.
  • The worker is a normal thread, not a daemon, so a script that never calls shutdown() waits for it at exit. The with block shuts it down.
Try it yourself
  • Submit twice for the same thread within the delay and check how many times extraction ran.
  • Remove future.result() and print the count at the end of the with block.
  • Submit for two different thread_ids.

This is what real progress feels like.