Schemas and profiles
A schema is a Pydantic model for your memories. With enable_inserts=False the manager keeps exactly one of it, a profile that updates field by field.
from pydantic import BaseModel
from langmem import create_memory_manager
from memory_model import MemoryModel
class Profile(BaseModel):
"""What we know about the customer."""
name: str | None = None
contact: str | None = None
city: str | None = Noneprofiler = create_memory_manager(MemoryModel(), schemas=[Profile], enable_inserts=False)
profile = profiler.invoke({"messages": [{"role": "user", "content": "My name is Asha, please email me."}]})
print(profile[0].content)schemas=[Profile] gives the model a Profile tool with the model's fields, so it fills in fields instead of writing sentences. The docstring becomes the tool's description. enable_inserts=False means: once a profile exists, update it, never add a second one.
update = profiler.invoke({"messages": [{"role": "user", "content": "I moved to Pune last month."}], "existing": [(profile[0].id, profile[0].content)]})
print(update[0].id == profile[0].id, update[0].content)The same profile, same id, with city filled in by a JSON Patch on /city. The name and contact stayed. Your app can read profile.contact directly, no search needed.
Other schemas
class OrderIssue(BaseModel):
"""A problem a customer had with an order."""
order_id: str
problem: str
resolved: bool = False
manager = create_memory_manager("anthropic:claude-sonnet-4-5", schemas=[OrderIssue, Profile])Several schemas give the model several tools. With inserts enabled, OrderIssue would collect many records while typed fields keep them consistent. LangMem's docs use the same idea for episodes: a schema with the situation, the reasoning and the result of an interaction that went well.
- Add
order_ids: list[str] = []toProfileand extract. - Set
enable_inserts=Trueand send two separate names. - Print
Profile.model_json_schema(): that is the tool the model sees.
Slow is fine. Stopping is the only problem.