AI Engineer World's Fair 2025
Stop Using RAG as Memory
Read the talk
Stop Using RAG as Memory
A media assistant that recalls a dog named Melody when asked for favorite tunes exposes the gap between semantic similarity and domain-aware agent memory.
From a talk by Daniel Chalef
Before you start: Familiarity with embeddings, agent tools and basic TypeScript will help you follow the retrieval and schema examples.
What should an assistant remember?
What should a media assistant remember about its user? The answer depends on what the assistant is supposed to do. Memory needs a business domain: a useful representation for a media player will differ from one for a financial coach.
Graphiti, Zep’s open-source temporal graph framework, supports custom entities and edges that represent a domain’s business objects. Daniel Chalef demonstrates how Zep exposes that approach to developers working in Python, TypeScript or Go. The developer supplies the kinds of things the application needs to remember, rather than treating every extracted fact as equally useful memory.
Chalef starts with a relevance problem he has observed in ChatGPT: memory can surface arbitrary personal facts, contributing to inaccurate responses or hallucinations. His media-assistant example makes the problem concrete. Jazz, NPR podcasts and The Daily are useful listening preferences. But conversation—and potentially incidental speech picked up by a voice agent—also supplies facts such as waking up at 7 AM and having a dog named Melody. Those facts describe the same person without necessarily helping the media player perform its job.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Why Melody appears among favorite tunes
The failure follows from a straightforward memory pipeline: extract facts, store them in a vector database or Redis, and retrieve facts that are semantically similar to the next request. That pipeline gives retrieval a similarity criterion, but no explicit account of which facts belong to the application’s domain.
In Chalef’s illustration, asking for favorite tunes retrieves useful listening preferences alongside the dog named Melody. The word has a musical association; the fact concerns a pet. A plausible semantic match has crossed the application’s relevance boundary.
Semantic similarity is not business relevance. Chalef describes vectors as projections into an embedding space: proximity does not itself establish an explicit causal or relational connection between the represented facts. Improving similarity ranking alone does not supply the missing domain model. The proposed remedy is domain-aware memory, with structure that lets the application distinguish the kinds of information it needs. Semantic search can still serve retrieval within those boundaries.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Give the finance coach explicit business objects
The recorded demonstration switches to a finance coach. The user wants to buy a house, so the assistant asks about annual earnings and student-loan debt. Beside the conversation, Zep’s memory contains explicit business objects: financial goals, debts and income sources. These are developer-defined categories, giving the application a vocabulary for the information its advice depends on.
Developers can express these schemas using Pydantic, Zod or Go structs. Chalef opens a TypeScript financial-goal schema built with Zep’s SDK, then shows how entity descriptions and field descriptions express what should be extracted and what values fields should contain. These descriptions guide extraction; describing a business rule is distinct from enforcing it through application validation.
For a house-purchase goal, a small Zod schema illustrates that separation. Descriptions explain the fields’ meaning, while .positive() supplies a concrete validation constraint when the application parses a value:
typescript
import { z } from "zod";
const FinancialGoal = z.object({
description: z.string().describe(
"The financial objective, such as buying a house"
),
targetAmount: z.number().positive().optional().describe(
"The amount needed for the goal, when stated by the user"
),
}).describe("A financial objective the user wants to achieve");
type FinancialGoal = z.infer<typeof FinancialGoal>;
const goal: FinancialGoal = FinancialGoal.parse({
description: "Buy a house",
});
The optional amount allows the goal to exist before the user supplies a target. The demonstrated schema view extends this descriptive approach to assets and income sources, including income type, monthly amount and reliability.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Retrieve by type, then register the ontology
With typed objects available, the agent’s financial-snapshot tool runs multiple Zep searches concurrently and filters each search by a specific node type. The displayed code searches for financial goals, expense categories and debt accounts. Each search has a defined category of eligible results instead of relying on one broad similarity query to separate every kind of fact.
Concurrency and filtering solve different problems. Concurrency lets the independent searches proceed together; node-type filters narrow what each search can return. An agent can then assemble the separate results into a financial snapshot while preserving their meanings as goals, expenses and debts.
The next code view supplies the setup that makes those types available: at application startup, the developer registers the business objects with Zep so it knows which ontology to build in the graph. Schema definitions establish the vocabulary; registration makes that vocabulary available to the memory system; typed retrieval uses it to select context for the agent.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Follow a new expense into memory
Chalef adds a monthly amount of $5,000, describing it as rent and then qualifying that with “I think it’s rent.” In the prerecorded demonstration, Chalef reports that Zep parses the new message and captures the $5,000 amount within a few seconds. The visible result is a memory panel whose Expenses section shows a monthly amount of $5,000 beside the conversation. That timing describes this demonstration, with no measured workload or independent latency test supplied.
He then opens Zep’s front end to inspect the user’s knowledge graph. It contains a debt-account entity with developer-defined fields. This graph view demonstrates the structured representation; it does not establish that the debt account is the newly entered rent expense.
The practical endpoint is control over retrieval: once memory has explicit types and fields, the application can filter tightly for the objects a task needs. Chalef closes by pointing viewers to a paper explaining the system. The demonstration ends with the full connection in place—from a conversational message, to structured memory, to selective retrieval for the next agent action.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
Open-source framework for temporal knowledge graphs, with installation instructions and examples for ingestion and hybrid retrieval.
Further reading
Daniel Chalef's introduction to domain-specific entity schemas and type-filtered retrieval, with Python examples and SDK support details.
Research paper describing Zep's temporal graph architecture and evaluations of conversational memory retrieval.
Updates since the talk
Current instructions for defining and registering entity and edge types, filtering retrieval, and configuring strict ontology extraction.
Read the complete timestamped transcript
- 0:00
[upbeat music] I'm here today to tell you that there's w- no one-size-fits-all memory. [coughs]
- 0:20
Um, and why you need to model your memory after your business domain. So if you saw me a little bit earlier and I was talking about Graphiti, Zep's open source temporal graph framework,
- 0:36
um, you might have seen me just speak to how you can build custom entities and edges in the Graphiti graph for your particular business domain. So business objects from your business domain. [coughs]
- 0:51
What I'm gonna demo today is actually how Zep implements that and how e- easy it is to use from Python, TypeScript or Go.
- 1:00
And what we've done here is we've solved a fundamental problem plaguing memory,
- 1:05
and we're enabling developers to build out memory that is far more cogent and capable for many different use cases. So I'm gonna just show you a quick example of
- 1:22
where things go really wrong. So many of you might have used ChatGPT before. It generates facts about you in memory, and you might have noticed that it really struggles with relevance.
- 1:34
Sometimes it just pulls out all sorts of arbitrary facts about you. And unfortunately, when you store arbitrary facts and retrieve them as memory, you get inaccurate responses or hallucinations.
- 1:47
And the same problem happens when you're building your own agents. So here we go. We have an ex-example media assistant, and it should remember things about jazz music, NPR podcasts, The Daily, et cetera.
- 2:01
All the things that I like to listen to. But unfortunately, because I'm in conversation with the agent, or it's picking up my voice when I'm, you know, it's a voice agent, um, it's learning all sorts of irrelevant things.
- 2:13
Like, I wake up at seven AM, my dog's name is Melody, et cetera. And the point here is that irrelevant facts pollute memory. They're not specific to the media player business domain.
- 2:28
And so the technical reality here is as well that many frameworks take this really simplistic approach, approach to generating facts. If you're using a framework that has memory capabilities, agent framework, it's generating facts and throwing it into a vector database.
- 2:45
And unfortunately, the facts dumped into the vector database or Redis mean that when you're recalling that memory, it's difficult to differentiate what should be returned. We're gonna return what is semantically similar.
- 2:58
And here we have, um, a bunch of facts that are semantically similar to my request for my favorite tunes. Um, we have some good things, and unfortunately, Melody is there as well because Melody is a dog named Melody, and that might be something to do with tunes.
- 3:16
Um, and so bl- bunch of irrelevant stuff.
- 3:23
So basically, semantic similarity is not business relevance,
- 3:29
and this is not un-unexpected. I was speaking a little bit earlier about how vectors and are just basically projections into an embedding space. There's no causal or relational, uh, relations between them.
- 3:44
And so we need a solution. We need domain-aware memory, not better semantic search.
- 3:52
So with that, I am going to unfortunately be showing you a video because the wifi has been absolutely terrible. Um- [laughs]
- 4:04
And let me bring up the video. [clears throat] Okay. So
- 4:13
I built a little application here, and it is a finance coach. And I've told it I wanna buy a house. [clears throat]
- 4:23
And it's asking me, well, how much do I earn a year? It's asking me about what student loan debt I might have. And we'll see that on the right-hand side, what is stored in Zep's memory are some very explicit c-
- 4:44
business objects. We have financial goals, debts, income sources, et cetera. These are defined by the developer, and they're defined in a way which is really simple to understand.
- 4:59
We can use Pydantic or Zod or Go structs, and we can apply business rules. So let's go take a look at some of the code here. We have a TypeScript financial goal schema using Zep's underlying SDK.
- 5:15
We can define these entity types. We can give a description to the entity type. Uh, we can even define fields, the business rules for those fields, so the values that they take on.
- 5:27
And then we can bu-build tools for our agent to retrieve a financial snapshot, which runs multiple Zep searches at the same time concurrently and filters by specific node types.
- 5:43
And when we start our Zep application, what we're gonna do is we're gonna register these particular goals, uh, sorry, objects, with, uh, Zep, so it knows to build this ontology in the graph.
- 5:58
So let's do a quick little addition here.
- 6:03
I'm gonna say that I have five thousand dollar a month rent.
- 6:08
I think it's rent. And in a few seconds, we see that Zep's already parsed that new message and has captured that five thousand dollars. And we can go look at the chart, the graph.
- 6:21
This is the, the Zep front end. And we can see the knowledge graph for this user has got a debt account entity. It's got fields on it, um, that we've defined as a developer.
- 6:35
And so again, we can really get really tight about what we retrieve from Zep by filtering. Okay, so we're at time. So just very quickly, we wrote a paper about how this, all of this works.
- 6:47
You can get to it, uh, by that link below, and appreciate your time today.
- 6:54
You can look me up afterwards. [upbeat music]