Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.maximem.ai/llms.txt

Use this file to discover all available pages before exploring further.

Add persistent, per-user memory to a Mastra agent in TypeScript. The integration ships a MastraMemory subclass for always-on memory and a pair of tools the model can call when it wants explicit control.
@maximem/synap-mastra wraps the JavaScript SDK, which in turn wraps the Python SDK as a subprocess. It requires a Python 3.11+ runtime on the host. Edge Runtime, Cloudflare Workers, Bun, Deno Deploy, and AWS Lambda Node-only runtimes are not supported. See Installation → JavaScript / TypeScript SDK.

Overview

This guide shows how to add Synap to a Mastra application to build agents that:
  • Recall and persist memory automatically on every generate call
  • Search and store memories on demand when the model decides it’s relevant
  • Mix and match — use the memory class alone, the tools alone, or both together
The Synap Mastra integration ships three exports — one memory class and two tool factories.
ExportMastra interfacePurpose
SynapMemoryMastraMemory subclassAlways-on memory: auto-recall + auto-store on every generate
synapSearchToolTool factoryReturns a Mastra-compatible tool for explicit memory search
synapStoreToolTool factoryReturns a Mastra-compatible tool for explicit memory storage

Setup

Install the package alongside Mastra:
npm install @maximem/synap-mastra @maximem/synap @mastra/core zod
Configure your API key. Generate one from the Synap Dashboard.
.env
SYNAP_API_KEY=synap_your_key_here
OPENAI_API_KEY=your-openai-api-key
Initialize the SDK once at application startup:
import { MaximemSynapSDK } from "@maximem/synap";

const sdk = new MaximemSynapSDK();
await sdk.initialize();
See SDK Initialization for the full lifecycle and configuration options.

Basic integration

The smallest useful integration plugs SynapMemory into an Agent. Every generate call automatically pulls relevant memories into the prompt and writes the new turn back out:
import { Agent } from "@mastra/core";
import { openai } from "@ai-sdk/openai";
import { SynapMemory } from "@maximem/synap-mastra";

const agent = new Agent({
  name: "MemoryAgent",
  instructions: "You are an agent with persistent memory.",
  model: openai("gpt-4o"),

  memory: new SynapMemory({
    sdk,
    userId: "alice",
    customerId: "acme",   // optional — required for B2B instances
  }),
});

const result = await agent.generate("What do you remember about my project deadlines?");
console.log(result.text);
The scoping triple is bound when SynapMemory is constructed — the model never sees the user identity. Memory reads degrade gracefully (empty context on failure); writes raise so silent data loss is impossible. To let the model decide when to recall or store (rather than running on every turn), use the tools below.

Core concepts

SynapMemory

SynapMemory extends Mastra’s MastraMemory and overrides the storage layer to route through Synap:
import { SynapMemory } from "@maximem/synap-mastra";

const memory = new SynapMemory({
  sdk,
  userId: "alice",
  customerId: "acme",       // optional
  conversationId: "t-001",  // optional — scopes to a single session
  maxResults: 8,
  mode: "fast",             // "fast" | "accurate"
});
The two retrieval modes trade latency against comprehensiveness:
fastaccurate
Latency50-100ms200-500ms
SearchVector similarityVector + graph + re-ranking
Best forReal-time chatMulti-entity queries
Method behavior:
MethodBehavior
remember(message)Ingests a message into Synap
recall(query, options)Semantic search; returns MemoryMessage[]
getMessages(threadId)Retrieves the message thread from Synap

synapSearchTool and synapStoreTool

The tool factories return Mastra-compatible tool objects with Zod schemas. They’re for agents that should decide when to query memory rather than running on every turn:
import { synapSearchTool, synapStoreTool } from "@maximem/synap-mastra";

const agent = new Agent({
  // ...
  tools: {
    synapSearch: synapSearchTool({
      sdk,
      userId: "alice",
      maxResults: 5,
      mode: "accurate",
    }),
    synapStore: synapStoreTool({ sdk, userId: "alice" }),
  },
});
synapSearchTool schema:
z.object({
  query: z.string().describe("What to search for in memory"),
  maxResults: z.number().optional().default(5),
})
synapStoreTool schema:
z.object({
  content: z.string().describe("The information to remember"),
  memoryType: z.string().optional().default("fact"),
})

Memory vs. tools

SynapMemoryTools
Context injectionAutomatic on every generateOn-demand when model calls the tool
Memory storageAutomatic after every responseOn-demand when model calls the tool
Best forAlways-on memory for every interactionAgents that decide when memory matters
Use both for maximum coverage: SynapMemory handles the always-on path and synapStoreTool lets the model bookmark new information explicitly when it sees something worth remembering.

Complete example: agent with memory + tools

The pattern below assembles all three exports. The agent has always-on memory via SynapMemory AND can call the search/store tools when it decides to:
import { Agent } from "@mastra/core";
import { openai } from "@ai-sdk/openai";
import {
  SynapMemory,
  synapSearchTool,
  synapStoreTool,
} from "@maximem/synap-mastra";

function buildAgent(sdk, userId: string, customerId?: string) {
  return new Agent({
    name: "PersonalAssistant",
    instructions: `You are a personal assistant with long-term memory.
Use synapSearch when you need older context not already in the prompt.
Use synapStore when the user shares a new fact, preference, or decision.`,
    model: openai("gpt-4o"),

    memory: new SynapMemory({
      sdk,
      userId,
      customerId,
      maxResults: 6,
      mode: "fast",
    }),

    tools: {
      synapSearch: synapSearchTool({ sdk, userId, customerId, maxResults: 5 }),
      synapStore: synapStoreTool({ sdk, userId, customerId }),
    },
  });
}


// Usage
const agent = buildAgent(sdk, "alice", "acme");

await agent.generate("I just upgraded to the Pro plan.");
// SynapMemory.remember persists the turn; the model may also call synapStore.

const reply = await agent.generate("What plan am I on?");
// SynapMemory.recall surfaces "Pro plan" automatically.
console.log(reply.text);  // → "You're on the Pro plan."
Three things to notice in this pattern:
  1. Memory and tools are complementary, not redundant. SynapMemory handles the always-on baseline; tools handle the explicit “I should look this up” path.
  2. Scope is per-agent. buildAgent(...) constructs a fresh agent per user, so each invocation has its scope baked in.
  3. The instructions are the policy. Telling the model when to use synapSearch and synapStore is what produces the explicit-memory behavior.

Advanced patterns

Multi-tenant scoping

All three exports accept the standard scoping triple — userId (required), optional customerId, optional conversationId. customerId is required on B2B Synap instances and ignored on single-tenant ones. See Memory Scopes.
const memory = new SynapMemory({
  sdk,
  userId: "alice",
  customerId: "acme",
});
For multi-tenant services, build agents per request rather than caching them — each agent should have its scope baked in.

Choosing between memory, tools, or both

  • SynapMemory only — always-on agents where every turn benefits from recall and ingestion.
  • Tools only — agents that should be selective about memory (e.g. research agents that should only remember important findings).
  • Both — production agents where automatic recall sets the baseline and tools let the model dig deeper or bookmark explicitly.

Failure semantics

The integration follows the Synap-wide contract:
  • SynapMemory.recall degrades gracefully — returns [] and logs on failure.
  • SynapMemory.remember surfaces failures — raises SynapIntegrationError.
  • synapSearchTool degrades gracefully — returns [] and logs on failure.
  • synapStoreTool surfaces failures — raises SynapIntegrationError.
This is by design: read failures shouldn’t break a user-facing turn, but silent write failures would let the memory drift away from reality.

Next steps

Vercel AI SDK

Model middleware for the Vercel AI SDK.

Claude Agent SDK

Hooks and MCP server for the Claude Agent SDK.

Context Fetch

The retrieval API behind SynapMemory and synapSearchTool.

Memory Scopes

How userId, customerId, and conversationId interact across reads.