Issue adding metadata to memory threads for user/agent separation

Hi, we’re experiencing an issue when trying to add metadata to the memory threads. Our goal is to separate threads for each agent based on the user who is using it, so that every agent maintains isolated context per user. To achieve this, we’ve extended the Memory class in order to inject and manage custom metadata on the threads. However, we’re not sure if this is the correct or recommended approach within Mastra’s architecture. We’d like to know: Is it possible (or supported) to attach custom metadata directly to threads? Is extending the Memory class the right way to implement user-based thread separation, or is there a more suitable pattern? Are there any examples or best practices for handling per-user or per-agent memory isolation? Thanks in advance for your help!
2 Replies
_roamin_
_roamin_5d ago
Hi @Stefano Denti ! You can already attach metadata to a thread if you're using our default memory implementation. You can either do that when calling agent.generate/agent.stream
const result = await weatherAgent.generate(
"What's the weather like in New York today?",
{
memory: {
resource: "user-123",
thread: {
id: "thread-456",
metadata: {
organization: "org-789",
},
},
},
}
);

const memory = await weatherAgent.getMemory();

if (memory) {
const threads = await memory.getThreadById({ threadId: "thread-456" });
console.log("Thread metadata:", threads?.metadata);
}
const result = await weatherAgent.generate(
"What's the weather like in New York today?",
{
memory: {
resource: "user-123",
thread: {
id: "thread-456",
metadata: {
organization: "org-789",
},
},
},
}
);

const memory = await weatherAgent.getMemory();

if (memory) {
const threads = await memory.getThreadById({ threadId: "thread-456" });
console.log("Thread metadata:", threads?.metadata);
}
You can also handle the thread in a more manual way:
const memory = await weatherAgent.getMemory();

if (memory) {
// create a new thread with metadata
await memory.createThread({
threadId: "thread-456",
resourceId: "user-123",
metadata: {
organization: "org-789",
},
})

// retrieve the thread and its metadata
let thread = await memory.getThreadById({ threadId: "thread-456" });

if (!thread) {
throw new Error("Thread not found");
}

console.log("Thread metadata:", thread.metadata);

await memory.saveThread({
thread: {
...thread,
metadata: {
organization: "org-updated",
}
}
})

thread = await memory.getThreadById({ threadId: "thread-456" });

if (!thread) {
throw new Error("Thread not found");
}

console.log("Thread metadata:", thread.metadata);
}
const memory = await weatherAgent.getMemory();

if (memory) {
// create a new thread with metadata
await memory.createThread({
threadId: "thread-456",
resourceId: "user-123",
metadata: {
organization: "org-789",
},
})

// retrieve the thread and its metadata
let thread = await memory.getThreadById({ threadId: "thread-456" });

if (!thread) {
throw new Error("Thread not found");
}

console.log("Thread metadata:", thread.metadata);

await memory.saveThread({
thread: {
...thread,
metadata: {
organization: "org-updated",
}
}
})

thread = await memory.getThreadById({ threadId: "thread-456" });

if (!thread) {
throw new Error("Thread not found");
}

console.log("Thread metadata:", thread.metadata);
}
Stefano Denti
Stefano DentiOP4d ago
Ok, great — this is clear to me, even though this implementation requires me to handle the metadata from the frontend that calls the agent, but that’s fine, I get it. Now, however, I’d like to understand how I can filter threads to retrieve only those belonging to a specific organization, for example. Thanks for the answers!

Did you find this page helpful?