What are collections, objects, and properties in memory?

Short answer: An object is one memory entry; collections group objects; properties hold the typed fields on each object.

Each fact, preference, or summary is typically one object with an id, properties, and usually a vector. Collections organize many objects and keep their own vector spaces. A schema defines property names and types so structure does not drift from typos or unexpected values. Not every memory needs identical rigidity, but Engram uses this object-collection-schema stack so targeted questions stay answerable as stores grow.

Everything covered up to this point has treated memory largely as content: facts, summaries, preferences, extracted and searched by meaning. Underneath every one of those memories, though, sits a much more basic structural question: how does that memory actually get organized as data, stored, retrieved, and related to everything else a system knows? This Part turns to that structural layer directly, starting with the three building blocks nearly every memory system’s underlying storage rests on.

What Does It Actually Mean to Store a Memory as an Object?

An object is a single stored entry, one discrete unit of information with a unique identifier, a set of properties holding its actual data, and typically a vector embedding capturing its meaning. Every individual memory a system stores, one fact, one preference, one summary, corresponds to one object, in exactly the way a single row corresponds to one entry in a more traditional database table. An object’s properties are simply named fields holding whatever specific values that memory needs to carry: a piece of text, a timestamp, a category label, a user identifier, whatever the memory actually needs recorded alongside its core content.

How Do Collections Organize Many Individual Objects Into Something Coherent?

A collection groups together objects that share a common structure, the same set of properties, the same general shape, in much the way a table in a relational database groups together rows that all follow one shared column layout. A memory system storing many different kinds of information, conversation summaries, extracted facts, tool-use logs, might reasonably use several separate collections, each shaped around the specific properties that particular kind of memory actually needs. Grouping objects this way isn’t just tidiness, each collection maintains its own indexes and its own vector space, meaning objects in different collections are searched, and compared for similarity, independently of one another.

Why Does It Matter That Every Collection Maintains Its Own Independent Vector Space?

Because a collection’s vector space is entirely its own, two objects living in different collections are never directly compared against each other in a similarity search, even if their underlying content happens to be related. This has a direct, practical consequence for how a memory system should actually be divided into collections in the first place: content that genuinely needs to be searched together, compared against the same query in the same pass, belongs in the same collection, while content serving a fundamentally different purpose can reasonably live in its own, separately organized space without that separation causing any real loss.

What Role Does a Schema Actually Play in Holding All of This Together?

A schema is the formal definition of a collection’s structure, specifying exactly which properties exist, what data type each one holds, and how the collection’s vectors and indexes should behave. Without an explicit schema, a system can still infer structure automatically from whatever data happens to arrive, but that inferred structure is more fragile, a small typo in a property name or an unexpected data type in an otherwise well-formed memory can quietly create an unintended, inconsistent property rather than raising an error a person would actually notice. An explicitly defined schema catches exactly this kind of quiet drift before it has a chance to corrupt how memory gets organized over time.

Does Every Memory Genuinely Need the Same Rigid Structure to Be Useful?

Not entirely. A schema defines a consistent shape for a collection’s core properties, but memory content itself is often naturally variable, a preference might carry different supporting details than a factual note, even though both belong to the same general collection. Properties can be optional, left empty for a given object where they simply don’t apply, without breaking the schema’s overall consistency for the properties that do matter uniformly across every object in that collection. This flexibility matters considerably for memory specifically, since the whole point of a memory system is capturing genuinely varied, real-world information, not forcing every stored fact into an identical, rigid template that doesn’t actually fit what’s being remembered.

How Does Weaviate Engram Apply This Object, Collection, and Schema Structure to Real Memory?

Weaviate Engram is built directly on top of Weaviate’s collection and object model, storing every memory as an object with defined properties inside a collection shaped specifically for that kind of memory. Consider a municipal parks and recreation department’s facility-booking assistant, helping staff track reservations, maintenance notes, and community feedback across dozens of public facilities:

from engram import EngramClient

client = EngramClient(api_key=os.environ["ENGRAM_API_KEY"])

client.memories.add(
    "The main pavilion at Riverside Park has a recurring issue with its sound system cutting out during outdoor events, reported by three separate groups over the past two months.",
    properties={"facility_id": "riverside-park-pavilion", "category": "maintenance"},
)

Each memory added this way becomes a distinct object, carrying its own content alongside structured properties like the facility it concerns and the category of note it represents, letting staff later narrow a search to exactly the right slice of accumulated facility knowledge:

results = client.memories.search(
    query="Any recurring problems reported at the Riverside Park pavilion?",
    properties={"facility_id": "riverside-park-pavilion", "category": "maintenance"},
)

Because every facility’s memories share the same underlying property structure, staff can run this exact same kind of scoped search consistently across any facility in the department’s portfolio, rather than needing separate, ad hoc handling for each one. This is exactly the value the object, collection, and schema structure this chapter has described actually delivers in practice: consistent, well-organized storage that makes a specific, targeted question answerable reliably, no matter how many facilities, or how many months of accumulated notes, actually stand behind it.

Objects, collections, and schemas give memory its basic shape, but shape alone doesn’t determine whether that shape is actually a good fit for a specific system’s real needs. Designing that shape well, deciding which properties belong together, how finely to split memory across collections, and how much structure to impose upfront, is a deliberate design discipline in its own right. Our next chapter, How should you design a schema for a memory system?, takes up exactly that discipline.