Short answer: Profile memory is the current summary of who or what something is. Event memory is the growing record of things that happened.
A profile stays compact and up to date. Events accumulate as a history. Agents usually need both: a quick standing picture for personalization, and a timeline when the question is what occurred, when, and in what order.
Temporal memory dealt with a single fact changing while still describing the same underlying thing. A related but separate question is how a system should organize two very different kinds of information that both describe that same thing at once: a compact, always-current summary of what it is right now, and a growing record of individual things that have happened to it over time. Profile memory and event memory are the two answers to that question, and most real systems need both, held in genuinely different shapes.
What Distinguishes a Profile From a Set of Events?
A profile is a single, current snapshot: who or what something is, right now, distilled into one coherent picture. A user profile might state their role, their preferences, and their general context, updated in place whenever any of that changes. An event, by contrast, is a specific, timestamped occurrence: one particular thing that happened, worth preserving as its own distinct record rather than being folded into a running summary.
This maps directly onto the bounded-versus-unbounded distinction already covered, but it’s worth stating on its own terms because it comes up constantly in practice. A profile is naturally bounded, there should only ever be one current version. A stream of events is naturally unbounded, because each occurrence deserves to exist on its own, sitting alongside every other occurrence rather than replacing it.
Why Can’t a Profile Just Absorb Every Event as It Happens?
Folding every event straight into a profile would either bloat the profile until it’s no longer a quick, current snapshot, or force each new event to overwrite whatever was there before, destroying the individual record of what actually happened. Neither outcome is acceptable. A profile is valuable precisely because it stays compact and current, something that can be handed to an agent’s system prompt or read at a glance without wading through history. An event is valuable precisely because it preserves a specific moment in full, not compressed into a running average.
The right relationship is closer to derivation than absorption: individual events accumulate on their own, and a profile can be updated to reflect a pattern or conclusion drawn from them, without the profile itself becoming a container for every event that ever contributed to it. A profile that says “generally responsive within a day” is a conclusion drawn from a pattern of events, not a list of every past response time stapled together.
What Actually Goes Wrong When These Two Shapes Get Mixed Up?
Treating events as if they were profile updates causes a profile to lose its most recent event’s context entirely, since the update mechanism designed for a fact overwrites rather than preserves. If a system stores “last service was a brake replacement” as if it were a bounded profile field, and it gets overwritten by the next service event, the brake replacement itself is gone, along with whatever pattern it might have been part of. Anyone later asking “what maintenance has this asset had” gets an incomplete answer, not because the information didn’t exist, but because it was stored in a shape that couldn’t preserve it.
The opposite mistake, treating a profile fact as an event, causes the reverse problem: a stable fact ends up scattered across dozens of near-duplicate records instead of consolidating into one current answer, and retrieving “what’s currently true” means sorting through a pile of entries to find the most recent one rather than just fetching the single current value directly. Both mistakes are the same underlying error in different directions: assuming one shape can substitute for the other when the content genuinely calls for the opposite shape.
How Should a System Decide Which Facts Belong in the Profile and Which Belong as Events?
The test worth applying is whether a piece of information describes a current state or describes something that happened at a specific point in time. “Currently assigned to route 14” is a state, appropriate for the profile. “Had its brakes serviced on this specific date” is an occurrence, appropriate as an event. Some facts genuinely straddle the line, and in those cases, it’s worth asking whether the individual occurrences themselves carry information worth preserving beyond their conclusion. If every occurrence looks the same and only the aggregate matters, a profile field summarizing the pattern is enough. If the specific sequence and details of each occurrence matter, they need to stay as distinct events.
How Does Weaviate Engram Let Profile and Event Memory Coexist?
Weaviate Engram supports this directly by letting a bounded topic and an unbounded topic exist side by side within the same group, each configured for the shape of content it’s meant to hold. Consider a fleet-maintenance assistant tracking delivery vehicles, where a compact current profile needs to sit alongside a detailed history of individual service visits:
from engram import EngramClient
client = EngramClient(api_key=os.environ["ENGRAM_API_KEY"])
client.memories.add(
"Vehicle currently assigned to Route 14, mileage at last check-in was 82,340.",
properties={"vehicle_id": "van-2291"},
)
This is written to a bounded topic scoped by the vehicle’s identifier, so each new check-in rewrites the same profile entry rather than accumulating a growing pile of stale mileage readings. A specific service visit, by contrast, is written to a separate, unbounded topic, since each visit deserves to exist as its own distinct record:
client.memories.add(
"Service visit on this vehicle replaced the rear brake pads and topped off coolant; technician flagged the alternator belt for monitoring next visit.",
properties={"vehicle_id": "van-2291"},
)
profile = client.memories.search(
query="current vehicle status",
properties={"vehicle_id": "van-2291"},
topics=["VehicleProfile"],
retrieval_config=FetchRetrieval(limit=1),
)
history = client.memories.search(
query="What has happened during this vehicle's recent service visits?",
properties={"vehicle_id": "van-2291"},
topics=["ServiceEvents"],
retrieval_config=HybridRetrieval(limit=10),
)
The profile fetch returns exactly one current answer, the vehicle’s route and latest mileage, regardless of how many service visits have accumulated behind it. The event search, by contrast, can surface many individual visits, including the specific detail about the alternator belt flagged for future attention, a detail that would have been lost entirely if it had been squeezed into an overwritten profile field instead of preserved as its own event. Both searches are answering genuinely different questions, and neither shape could substitute for the other without losing something the fleet manager actually needs.
Profile and event memory both describe facts, whether current state or specific occurrence. A related but distinct category concerns something narrower: a specific kind of stable fact about how someone likes things done, which behaves a little differently from an ordinary semantic fact even though it’s built from the same underlying mechanism. Our next chapter, What is preference memory?, takes up exactly that distinction.