Memory Infrastructure for Mastra Agents

Mastra is a TypeScript-first framework for building AI agents and workflows. This guide integrates REM Labs as the persistent memory layer so your Mastra agents remember past interactions, share context across workflows, and retrieve with multi-signal fusion -- all in TypeScript.

Why Mastra Agents Need External Memory

Mastra provides a clean abstraction for building agents with tools, workflows, and RAG. But like most agent frameworks, conversation state lives in memory and resets between invocations. For production agents that handle real users over days and weeks, you need memory that persists outside the process.

Step 1: Install

npm install @remlabs/memory @mastra/core

Step 2: Create Memory Tools

import { createTool } from "@mastra/core"; import { RemMemory } from "@remlabs/memory"; import { z } from "zod"; const mem = new RemMemory({ apiKey: process.env.REM_API_KEY! }); const searchMemory = createTool({ id: "search-memory", description: "Search persistent memory for relevant context from past interactions", inputSchema: z.object({ query: z.string().describe("What to search for in memory"), }), execute: async ({ context }) => { const results = await mem.search(context.query, { namespace: "mastra-agent", limit: 5, }); if (!results.length) return "No relevant memories found."; return results.map((r: any) => `- ${r.value}`).join("\n"); }, }); const storeMemory = createTool({ id: "store-memory", description: "Store an important fact or observation for future reference", inputSchema: z.object({ value: z.string().describe("The fact or observation to remember"), tags: z.array(z.string()).optional().describe("Optional tags for categorization"), }), execute: async ({ context }) => { await mem.store({ value: context.value, namespace: "mastra-agent", tags: context.tags || [], }); return `Stored: ${context.value}`; }, });

The tools use Mastra's createTool API with Zod schemas for input validation. The agent can call these during any conversation to search or store memories.

Step 3: Attach to a Mastra Agent

import { Agent } from "@mastra/core"; const agent = new Agent({ name: "Support Agent", instructions: `You are a helpful support agent with persistent memory. At the start of each conversation, search memory for relevant context. When you learn important facts about a user, store them in memory.`, model: { provider: "OPEN_AI", name: "gpt-4o", }, tools: { searchMemory, storeMemory }, }); // First interaction const response1 = await agent.generate( "I'm Alex, CTO at Buildly. We're using your Pro plan." ); // Agent stores: "Alex is CTO at Buildly, on Pro plan" // Later interaction (even after restart) const response2 = await agent.generate( "What plan is the Buildly team on?" ); // Agent searches memory, finds the stored fact, responds accurately

Step 4: Memory in Mastra Workflows

import { Workflow, Step } from "@mastra/core"; const retrieveContext = new Step({ id: "retrieve-context", execute: async ({ context }) => { const results = await mem.search(context.triggerData.input, { namespace: "mastra-workflow", limit: 5, }); return { context: results.map((r: any) => r.value).join("\n") }; }, }); const generateResponse = new Step({ id: "generate-response", execute: async ({ context }) => { const result = await agent.generate( `Context: ${context.retrieve_context.context}\n\nQuestion: ${context.triggerData.input}` ); return { response: result.text }; }, }); const persistExchange = new Step({ id: "persist-exchange", execute: async ({ context }) => { await mem.store({ value: `Q: ${context.triggerData.input}\nA: ${context.generate_response.response}`, namespace: "mastra-workflow", tags: ["workflow-exchange"], }); return { stored: true }; }, }); const workflow = new Workflow({ name: "memory-chat" }) .step(retrieveContext) .then(generateResponse) .then(persistExchange); await workflow.execute({ triggerData: { input: "What was our last deployment target?" } });

The workflow retrieves context, generates a response, and stores the exchange -- building up institutional knowledge with every run.

Triple-Indexed Retrieval

Every memory stored through REM is automatically indexed with vector embeddings, full-text search, and entity graph extraction. Multi-signal fusion retrieval combines all three at query time, reaching 90% on LongMemEval.

TypeScript-native: The @remlabs/memory SDK is written in TypeScript with full type definitions. It uses standard fetch, so it works in Node.js, Bun, Deno, and edge runtimes.

Give your Mastra agents a memory

Free tier. No credit card. npm install and go.

Get started free →