Collections
A collection is LangMem's default way of keeping memories: many separate memory documents, each with its own id, that grows as later conversations add to it.
Last updated: 30 Sep, 2026 · LangMem 0.0.30
One conversation gave one memory in Extracting memories. A customer comes back many times, so memories have to accumulate. A collection is that list; for each new conversation the manager decides whether to add a memory or change one it already has.
Syntax:
first = manager.invoke({"messages": conversation})
existing = [(m.id, m.content) for m in first]
later = manager.invoke({"messages": new_conversation, "existing": existing})Passing what you already have
existing is a list of (id, content) pairs. The manager returns the whole collection after the conversation, old memories included, so you replace your list with the result.
existing = [(memory.id, memory.content) for memory in first]A second conversation about a different order
later = manager.invoke({
"messages": [{"role": "user", "content": "Order A-1002 is three days late."}],
"existing": existing,
})Two conversations with a single-call manager
from langchain.chat_models import init_chat_model
from langmem import create_memory_manager
model = init_chat_model("groq:openai/gpt-oss-120b", temperature=0)
manager = create_memory_manager(
model,
instructions="Extract what helps support this customer. Record everything in a single Memory call.",
)
first = manager.invoke({"messages": [
{"role": "user", "content": "Hi, I'm Asha. Order A-1001 arrived broken. Please email me."},
]})
existing = [(memory.id, memory.content) for memory in first]
later = manager.invoke({
"messages": [{"role": "user", "content": "Order A-1002 is three days late."}],
"existing": existing,
})
for memory in later:
status = "kept id" if memory.id in dict(existing) else "new id"
print(f"{status:8} | {memory.content.content}")kept id | Customer Asha reported that order A-1001 arrived broken and requested to be contacted via email. Additionally, order A-1002 is three days late.
Why the collection did not grow
- kept id, and only one line. The second conversation did not add a memory. The model patched the existing one and appended "Additionally, order A-1002 is three days late."
- The instructions caused it. They asked for everything in a single
Memorycall, and the model kept everything in a single memory. It works like a single profile document, as in Profiles, and it only grows longer. - Runs differ in how they merge. Another run wrote the merged text as a new memory next to the old one, which leaves a near-duplicate. Either way, A-1002 did not get a memory of its own.
Instructions that keep topics apart
The manager does what the instructions say, and "record everything in a single Memory call" reads as "keep one memory". Say how memories should be split, and a new order gets its own memory while the call stays single:
manager = create_memory_manager(
model,
instructions="Extract what helps support this customer. Record everything in a single Memory call. A new order or a new topic gets a new memory; do not merge it into an existing one.",
)A new order in a new memory
from langchain.chat_models import init_chat_model
from langmem import create_memory_manager
model = init_chat_model("groq:openai/gpt-oss-120b", temperature=0)
manager = create_memory_manager(
model,
instructions="Extract what helps support this customer. Record everything in a single Memory call. A new order or a new topic gets a new memory; do not merge it into an existing one.",
)
first = manager.invoke({"messages": [
{"role": "user", "content": "Hi, I'm Asha. Order A-1001 arrived broken. Please email me."},
]})
existing = [(memory.id, memory.content) for memory in first]
later = manager.invoke({
"messages": [{"role": "user", "content": "Order A-1002 is three days late."}],
"existing": existing,
})
for memory in later:
status = "kept id" if memory.id in dict(existing) else "new id"
print(f"{status:8} | {memory.content.content}")new id | Order A-1002 is three days late. kept id | Customer Asha reported that Order A-1001 arrived broken and requested to be contacted via email.
What the collection holds now
- new id for A-1002. The late order became its own memory, so the collection now holds two.
- kept id for A-1001: the memory from the first conversation is still there, under its own id.
- Only the instructions changed between this example and the one above; the model still made one tool call per reply.
Several rounds with max_steps
LangMem's reference documents a second way to get more memories out of one conversation: a max_steps key in the input. The manager then calls the model up to that many times; after each round it tells the model which memories were saved, and from the second round it adds a Done tool the model calls when it has finished. Each round is one more model call.
memories = manager.invoke({"messages": conversation, "max_steps": 3})A conversation with nothing new
A collection only stays useful if nothing is saved twice. Send small talk with the existing memory and count:
from langchain.chat_models import init_chat_model
from langmem import create_memory_manager
model = init_chat_model("groq:openai/gpt-oss-120b", temperature=0)
manager = create_memory_manager(
model,
instructions="Extract what helps support this customer. Record everything in a single Memory call.",
)
first = manager.invoke({"messages": [
{"role": "user", "content": "Hi, I'm Asha. Order A-1001 arrived broken. Please email me."},
]})
existing = [(memory.id, memory.content) for memory in first]
chat = manager.invoke({
"messages": [{"role": "user", "content": "Thanks! Lovely weather in Pune today."}],
"existing": existing,
})
print(len(existing), "before,", len(chat), "after")
for memory in chat:
print(memory.content.content)1 before, 2 after Customer Asha reported that order A-1001 arrived broken and requested to be contacted via email. Customer Asha reported that order A-1001 arrived broken and requested to be contacted via email.
1 before, 2 after. Nothing in the message was worth keeping, yet the manager returned a second memory, a word-for-word copy of the first with a new id. When existing memories are passed, LangMem's extractor binds the tools with tool_choice="any", so the model has to call one; here it re-created the memory it already had.
Collection vs profile
| Collection | Profile | |
|---|---|---|
| Shape | Many memory documents | One document with fixed fields |
| Grows | Without limit | Never; fields are overwritten |
| Good for | Events, issues, anything open-ended | Current preferences and settings |
| Recall | Search, in Semantic search | Read the one document |
When a collection fits
- A customer's order problems, one memory per problem, kept even after the next one arrives.
- Notes a research assistant collects across many sessions.
- Anything where you cannot list the fields in advance.
Related
- Previous: Chat models
- Next: Updates and deletes
- Reference: create_memory_manager reference, with max_steps
- Run the second conversation without
existingand compare the ids. - Send a third conversation about order A-1001 and see whether the manager adds a memory or patches one.
- Send the small-talk message with the instructions "Save nothing if the message has no new facts" and count again.
Every expert started right here.