Zep and Graphiti, agent memory with a time axis
Zep is a memory layer for agents built on a knowledge graph where every fact carries a validity period. The graph engine is called Graphiti, ships under the Apache 2.0 licence, and can be used on its own.
The idea separating this from an ordinary vector store is singular and worth understanding whether or not you end up using this particular product. Facts about people change, and a record ignoring that forces an agent to choose between two contradictory truths with no hint about which is current.
The problem it solves
Take a simple situation. In March a user wrote that they work at company A. In September they wrote they had changed jobs and are now at company B.
A vector store now holds two sentences. Both resemble the question "where do they work", so both can reach the context, and the model receives a contradiction with no information about order. The answer depends on which sentence ranked higher in search results, meaning on chance.
You can work around it by adding dates to metadata and sorting by them. That holds until there are more than a handful of facts and they start relating to each other, since sorting by write date says nothing about whether a newer fact invalidates an older one or supplements it.
The answer applied here is that a graph relation carries two timestamps: when it became true and when it stopped being so. New employment information does not delete the old one, it closes its validity period. A question about the current state returns one thing; a question about history returns both, in order.
How it works underneath
The input is an episode: a conversation message, a system event, or an observation an agent recorded.
The engine decomposes it into graph elements. Entities become nodes, relations between them become edges, and each edge receives a validity period and a confidence assessment. Along the way it checks whether the new information conflicts with something already in the graph, and if so the older edge receives a closing date.
That decomposition costs. Every episode requires model calls to extract entities and relations, so writing to memory is neither free nor instant. With many events it pays to do it off the main answer path, since otherwise the user waits for something that does not concern them.
Reading is fast in return, and that is the right trade. The work happens once on write, and on every question the agent receives a prepared set of facts rather than raw conversation fragments to analyse.
Search combines three routes: semantic similarity, textual matching, and traversal along graph edges. The last is what a vector store cannot do. A question about the team somebody works in can be resolved by moving from person to company and on to team, even where no single sentence in the conversation held all three.
The end of Community Edition
This is the change to know about, since it invalidates a good share of the guides online.
Until April 2025 there was a variant meant to run on your own infrastructure, in one package, database included. That variant was retired.
Self hosting today means reaching for the graph engine alone and assembling the rest yourself: a graph database, a layer calling a model to extract entities, a queue for processing episodes in the background, error handling. The supported databases are Neo4j, FalkorDB, and Amazon Neptune. A Kuzu driver still ships, but the README marks it deprecated and slated for removal, since the Kuzu project itself is being archived by its authors and its site no longer responds.
The practical consequence is clear. The engine itself is Apache 2.0 licensed and free to use, while what you get is a library rather than a finished product. The difference between "I run a container" and "I assemble a system from four pieces" is usually a few days of work plus maintenance.
Worth knowing, though, that the product itself did not vanish from your own infrastructure entirely, it moved behind a commercial gate. The vendor lists three deployment variants today: the hosted service, the hosted service with encryption keys held on your side, and BYOC, meaning an install inside your own virtual network. That third one is what most people asking about self hosting are after, and it takes a conversation about the Enterprise plan.
So if you meet a text describing free self hosting of this product whole, check its date. The approach described before April 2025 no longer exists.
Graphiti on its own
That variant deserves consideration, since it is sometimes a better answer than the whole product.
The engine attaches to your own application as a Python library. You get graph building from episodes, temporal invalidation, and combined search, while keeping control over the database and infrastructure.
That route suits teams required to keep data on their own hardware, and those wanting to understand what happens rather than call a service. The price is operational work: a graph database needs maintenance, backups, and a considered answer to what happens when it is unavailable.
Know also that the library calls a model on every write, so a token cost exists regardless of whether you pay for a service. With many episodes that bill can exceed the hosted variant's fee, and that is a number worth computing before deciding.
Two time axes and what the second one is for
Two things deserve separating, since mixing them leads to wrong conclusions when diagnosing an answer.
The first axis is the time a fact held in reality: since when somebody works at a given company, since when a given price applies. The second is the time the system learned about it.
Those two axes diverge more often than people assume. A user may mention in September that they changed jobs in March. The fact holds from March, the system has known it since September, and both moments turn out to be needed. The question "what did we know in April" has a different answer from "what was true in April", and when analysing why an agent answered as it did back then, the first one is what counts.
There are two practical uses. The first is reconstructing what happened when a complaint arrives: the agent answered badly because at that moment it did not yet hold the information, not because something is broken. The second is compliance, where you have to demonstrate the system's state of knowledge at a given moment.
Bear in mind, though, that the mechanism will not guess a validity date absent from the content. The sentence "I changed jobs" with no date yields a fact holding from the moment of writing, and that is usually a good approximation. The sentence "I changed jobs in March" allows the correct start to be set, provided the model extracts that date while decomposing the episode.
What this means for the prompt
A memory layer is useful exactly to the degree that it slots into the prompt well, and that is the part easiest to neglect.
The returned set of facts needs describing, because a model dropped into a list of sentences with no context will treat them as equal in standing to the user's question. A section with a heading stating plainly that these are known facts about the person, and a separate section with the current question, produce markedly better results than gluing everything into one block.
The second thing is the number of facts. Dropping in everything memory returned is tempting, yet twenty facts distract the model more than they help, especially when some of them do not concern the question. Limiting it to the few most relevant usually improves answers and lowers cost at the same time.
The third concerns historical facts. If you also retrieve those whose validity period has closed, mark them clearly as out of date. A model handed an old and a new fact without that distinction is in the same position as with an ordinary vector store, meaning the entire advantage of this approach disappears at the last step.
Zep against the alternatives
| Option | Memory model | Self hosting | Pick it when |
|---|---|---|---|
| Zep | Graph with a time axis | Engine alone, or BYOC on Enterprise | Facts change over time |
| Mem0 | Facts with vectors | Yes | A simpler case, less infrastructure |
| Letta | Memory blocks the agent edits | Yes, through App Server | The agent should decide what it remembers |
| A vector store | Text fragments | Yes | Document search rather than memory |
| History in a database | Full conversation record | Yes | Short conversations, no need to summarise |
The last row deserves honest consideration before adding anything. With an assistant holding conversations of a dozen or so messages, the whole history fits in the model's context and no memory layer is needed. The problem starts with conversations stretching over weeks and hundreds of users who cannot all sit in context at once.
The difference between the first two rows comes down to whether you need relations and time. If you remember preferences of the "likes coffee without sugar" kind, the simpler option suffices. If you must answer questions requiring movement between entities, or distinguish current from historical state, a graph does something a list of facts will not.
The third row is a different class of solution, and mixing it with the first two leads to poor conclusions. There the model manages memory itself, calling tools that rewrite its own blocks, so you are not adding a layer to your agent but building an agent inside someone else's runtime. Its authors described that project's Python server as deprecated and maintained on an emergency basis in July 2026, moving development to an npm package, so tutorials written before that date describe a deployment that no longer exists.
Published effectiveness comparisons on test sets favour the graph approach, though they come from the authors and measure tasks chosen to suit the method. Treat them as an indication rather than a settlement, and check against your own conversations.
Pricing and what to compute
There is a free tier and several paid ones, and individual figures get quoted differently across third party material, so check the vendor's current price list before deciding.
More important than the rate is understanding what generates cost. Writing an episode requires model calls to extract entities and relations, so the bill grows with the number of events recorded rather than the number of questions. An application recording every conversation message costs several times more than one recording a summary once a thread closes.
That is a lever worth using. Recording everything is tempting and almost always unnecessary. Choosing which events reach memory does more for the bill than choosing a vendor.
The second line is graph storage, growing over time. Know from the start whether there is a way to delete a user's data, since under personal data requirements a deletion request has to cover agent memory as well as the main database.
Deployment in practice
A few things save trouble if the memory layer is to stay.
Separate writing from answering. Extracting entities from an episode takes time and need not happen before the user gets a reply. A queue or a background job settles that once.
Decide what counts as an episode. Every message separately produces a graph full of noise and a high bill. A thread summary or a business event, an order being placed for instance, produces a graph where something is visible.
Do not put everything a user wrote into memory. Sensitive data recorded in the graph stays there and returns in context on later conversations, so a filter before writing is cheaper than cleaning up afterwards.
Check what actually reaches the prompt. A memory layer returns a set of facts, and answer quality depends on whether they are the right facts. Without visibility into what was retrieved, diagnosing bad answers is guesswork, so wire in a tracing tool early, Arize Phoenix for instance.
The last item is behaviour on empty memory. A new user has no history, and an agent built assuming something is there behaves oddly on a first conversation. That case deserves testing separately.
Common mistakes
The first is relying on guides predating April 2025 for self hosting. The single package variant they describe no longer exists.
The second is recording every message as a separate episode. The bill grows linearly and the graph fills with facts of no consequence.
The third is performing the write on the answer path. The user then waits for processing that does not concern them.
The fourth is treating memory as document search. Those are two different things: memory holds facts about the person you are talking to, search finds fragments in a knowledge base, and mixing them produces a context where the model loses one in the other.
The fifth is having no way to delete a user's data. A deletion request has to cover the graph, not only the main database.
The sixth is trusting published results without checking against your own conversations. Test sets measure tasks chosen to suit the method, and your conversations look different.
FAQ
How does Zep differ from an ordinary vector store?
In its data model. A vector store holds text fragments and returns ones resembling the question, so two contradictory facts come back together with no hint about which is current. Here a fact is a graph edge with a validity period, so a question about the current state returns one answer.
Can Zep run on my own infrastructure?
Not as a free package. The community variant was retired in April 2025, so free of charge today means using the Graphiti engine alone together with your own graph database, Neo4j, FalkorDB, or Amazon Neptune for instance. A paid route exists separately: on the Enterprise plan the vendor lists a BYOC variant, the service stood up inside your own virtual network, alongside the hosted version and one using your own encryption keys.
What is Graphiti?
The temporal knowledge graph engine underneath this product, available separately under the Apache 2.0 licence. It builds a graph from episodes, closes the validity period of facts superseded by newer ones, and supports search combining semantic similarity with edge traversal.
How does it differ from Mem0?
In the richness of the data model. Mem0 holds facts and retrieves them by similarity, which suffices for user preferences. The graph approach adds relations and time, so it handles questions requiring movement between entities and the distinction between current and historical state, at the cost of more complexity.
What does it cost?
There is a free tier and paid ones, and the figures are worth checking in the current price list, since third party sources differ. More importantly, cost grows with the number of episodes recorded rather than questions asked, so choosing what reaches memory affects the bill more than choosing a vendor.
Documentation sits on the product site, and the engine's code in the Graphiti repository.