v1

Introduction

Memra gives your AI app a memory. When a user talks to your AI, Memra saves the conversation. Next time that user comes back, your AI remembers what they said — their name, preferences, what they were working on. Everything.

How it works in 30 seconds:

  1. User says “My name is Wais” → your AI replies → Memra saves both messages
  2. User comes back tomorrow, asks “What's my name?”
  3. Your app calls memory.getContext() → gets back “My name is Wais”
  4. You put that in the system prompt → AI answers “Your name is Wais!”
1

Save

After each AI response, save the exchange with memory.save(). Two lines of code.

2

Retrieve

Before the next response, call memory.getContext(). It returns recent chat + relevant older memories.

3

Inject

Put the memories in your system prompt. Your AI now remembers everything.

Installation

Install the Memra client package. Works with any JavaScript/TypeScript project — Next.js, Express, anything.

bash
npm install @memra-client/client

Then get your API key from the dashboard (starts with mk_mem_).

Quick start

This is all you need. Four steps: create the client, get context, call your AI, save the exchange.

handler.ts
import { MemoryClient } from '@memra-client/client'

const memory = new MemoryClient({ apiKey: 'mk_mem_...' })

export async function chat(userId: string, userMessage: string) {
  // 1. Get recent conversation + relevant older memories
  const { recentHistory, relevantMemories } = await memory.getContext(
    userId,
    userMessage
  )

  // 2. Build a system prompt that includes BOTH
  let memoryText = ''
  if (recentHistory.length > 0) {
    memoryText += 'Recent conversation:\n'
    memoryText += recentHistory
      .map(m => `[${m.role}]: ${m.content}`)
      .join('\n')
    memoryText += '\n\n'
  }
  if (relevantMemories.length > 0) {
    memoryText += 'Relevant older memories:\n'
    memoryText += relevantMemories
      .map(m => `[${m.role}]: ${m.content}`)
      .join('\n')
  }

  const systemPrompt = memoryText
    ? `You are a helpful assistant with memory.
${memoryText}
Use this to give personalized responses.`
    : 'You are a helpful assistant.'

  // 3. Call your AI provider (works with any: OpenAI, Groq, etc.)
  const aiReply = await yourAI.chat.completions.create({
    messages: [
      { role: 'system', content: systemPrompt },
      { role: 'user',   content: userMessage  },
    ],
  })

  // 4. Save this exchange so AI remembers it next time
  await memory.save(userId, userMessage, aiReply)

  return aiReply
}

💡 Tip

recentHistory gives the AI the last 10 messages in order — so it always knows the recent conversation. relevantMemoriesgives it related messages from older chats. Together they fix the “what's my name?” problem.

Full working example

A complete Next.js API route you can copy-paste. This is exactly how the demo works.

app/api/chat/route.ts
// Complete working example — Next.js API route
import { NextResponse } from 'next/server'
import MemoryClient from '@memra-client/client'

const memory = new MemoryClient({
  apiKey: process.env.MEMRA_API_KEY || '',
})

export async function POST(req: Request) {
  const { query } = await req.json()

  // Step 1: Get memories (recent chat + relevant older ones)
  const { recentHistory, relevantMemories } = await memory.getContext(
    'user_123', query, { limit: 5, recentLimit: 10 }
  )

  // Step 2: Build the system prompt
  let memorySection = ''
  if (recentHistory.length > 0) {
    memorySection += 'Recent conversation:\n'
      + recentHistory.map(m => `[${m.role}]: ${m.content}`).join('\n')
      + '\n\n'
  }
  if (relevantMemories.length > 0) {
    memorySection += 'Relevant older memories:\n'
      + relevantMemories.map(m => `[${m.role}]: ${m.content}`).join('\n')
  }

  const systemPrompt = memorySection
    ? `You are a helpful assistant with memory.\n${memorySection}\nUse ALL of this to answer.`
    : 'You are a helpful assistant.'

  // Step 3: Call any AI provider
  const aiResponse = await fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'gpt-4',
      messages: [
        { role: 'system', content: systemPrompt },
        { role: 'user', content: query },
      ],
    }),
  })
  const data = await aiResponse.json()
  const reply = data.choices[0].message.content

  // Step 4: Save so AI remembers next time
  await memory.save('user_123', query, reply)

  return NextResponse.json({ reply })
}
class

MemoryClient

Create one instance and reuse it. Don't create a new one for every request.

Constructor

typescript
import { MemoryClient } from '@memra-client/client'

const memory = new MemoryClient({
  apiKey: 'mk_mem_...',                          // required — from your dashboard
  baseUrl: 'https://memra-rho.vercel.app/api'    // optional — this is the default
})

Options

ParameterTypeDescription
apiKeyreqstringYour Memory API key from the dashboard. Starts with mk_mem_
baseUrlstringAPI base URL. Default: https://memra-rho.vercel.app/api
methodPOST /memory/save

memory.save()

Call this after every AI response. It saves both the user message and AI reply to memory. Each message gets turned into a vector embedding so it can be found later with semantic search.

Signature

typescript
memory.save(
  userId: string,       // your end-user's identifier
  userMessage: string,  // the user's message text
  aiReply: string,      // the assistant's response text
  options?: {
    agentId?: string    // isolate memory per bot or context (default: 'default')
  }
): Promise<{ success: boolean; saved: number }>

Parameters

ParameterTypeDescription
userIdreqstringYour user's ID. Each user gets their own isolated memory — they can't see each other's data.
userMessagereqstringWhat the user said.
aiReplyreqstringWhat your AI replied.
options.agentIdstringIf your app has multiple bots (e.g. support-bot, coding-bot), use this to keep their memories separate. Default: 'default'

Example

typescript
// After your AI replies, save the exchange
const result = await memory.save(
  'user_abc123',
  'What is my current plan?',
  'You are on the Free plan — 500 memory slots available.',
  { agentId: 'support-bot' }
)
// => { success: true, saved: 2 }
methodGET /memory/context

memory.getContext()

This is the most important method. Call it before every AI response. It returns two things:

recentHistory

The last 10 messages in chronological order. The AI always knows what was just said.

relevantMemories

Semantically similar messages from older conversations. Found via vector search.

Signature

typescript
memory.getContext(
  userId: string,
  query: string,           // the current message — used for semantic search
  options?: {
    agentId?: string       // filter to a specific agent (default: 'default')
    limit?: number         // max semantic results (default: 5)
    recentLimit?: number   // max recent messages (default: 10)
  }
): Promise<ContextResponse>

Parameters

ParameterTypeDescription
userIdreqstringThe user whose memories to search.
queryreqstringThe current user message. Used to find related older memories.
options.agentIdstringFilter to a specific bot's memories. Default: 'default'
options.limitnumberHow many semantic results to return. Default: 5
options.recentLimitnumberHow many recent messages to return. Default: 10

Response types

typescript
interface ContextResponse {
  recentHistory: Memory[]      // last N messages chronologically
  relevantMemories: Memory[]   // semantic matches from older conversations
  context: Memory[]            // backwards compat — same as semantic results
  count: number
  latencyMs: number            // end-to-end latency, added client-side
}

interface Memory {
  id: string
  content: string
  role: 'user' | 'assistant'
  createdAt: string
  similarity?: number  // 0–1 cosine score (only on semantic results)
}

Example

typescript
// This is the key method — call it before every AI response
const { recentHistory, relevantMemories } = await memory.getContext(
  'user_abc123',
  'What plan am I on?',
  { limit: 5, recentLimit: 10 }
)

// recentHistory = last 10 messages in order (always includes recent chat)
// relevantMemories = semantically similar older messages (deduplicated)

// Use BOTH in your system prompt:
const systemPrompt = `You remember everything.
Recent: ${recentHistory.map(m => m.content).join(' | ')}
Related: ${relevantMemories.map(m => m.content).join(' | ')}`

⚠️ Warning

Always put memory in the system prompt, not the user message. If you put it in the user message, the AI treats it as something the user said — not as context it should use.
methodGET /memory/history

memory.getHistory()

Returns the complete chat history for a user — every message they ever sent and received. Use this to show past conversations in your UI. You don't need your own database for chat storage — Memra stores it all.

Signature

typescript
memory.getHistory(
  userId: string,
  options?: {
    agentId?: string     // filter by agent (omit = all agents)
    limit?: number       // omit to get ALL messages
    order?: 'asc'|'desc' // default: 'asc' (oldest first)
    before?: string      // ISO date — get messages before this time
    after?: string       // ISO date — get messages after this time
  }
): Promise<{
  history: Memory[]     // every message for this user
  total: number         // total message count
  count: number         // messages in this response
}>

Parameters

ParameterTypeDescription
userIdreqstringThe user whose history to fetch.
options.agentIdstringFilter by bot. Omit to get all bots' messages together.
options.limitnumberOmit to get ALL messages. Set a number to limit.
options.order'asc' | 'desc''asc' = oldest first (default, good for chat UI). 'desc' = newest first.
options.beforestringISO date. Get messages before this time (for pagination).
options.afterstringISO date. Get messages after this time (for pagination).

Example

typescript
// Get ALL chat history for a user (for showing in your UI)
const { history, total } = await memory.getHistory('user_abc123')

console.log('Total messages stored:', total)
history.forEach(m => {
  console.log('[' + m.role + '] ' + m.content)
})

// With filters:
const recent = await memory.getHistory('user_abc123', {
  agentId: 'support-bot',
  order: 'desc',   // newest first
  limit: 20,       // just the last 20
})

Real-world usage — API route for chat history

Create an API route in your app that fetches a user's complete chat history. Your frontend calls this to display past conversations — like a chat sidebar or message list.

app/api/history/route.ts
// app/api/history/route.ts — API route to fetch chat history
import { NextResponse } from 'next/server'
import MemoryClient from '@memra-client/client'

const client = new MemoryClient({
  apiKey: process.env.MEMRA_API_KEY || '',
})

export async function GET() {
  // Returns ALL messages for this user, oldest first
  const { history, total } = await client.getHistory('user_123', {
    order: 'asc',
  })
  return NextResponse.json({ history, total })
}

// Then in your frontend:
// const res = await fetch('/api/history')
// const { history, total } = await res.json()
// history.forEach(msg => renderMessage(msg.role, msg.content))

💡 Tip

You don't need your own database for chat storage. Memra stores every message when you call save(). Call getHistory() to get them all back — sorted, filtered, and ready to display. Use getContext() separately before AI responses to inject the right memories into the prompt.
methodDELETE /memory/forget

memory.forget()

Permanently deletes memories. Use this for GDPR compliance, when a user asks to be forgotten, or when you want to start fresh. This cannot be undone.

Signature

typescript
memory.forget(
  userId: string,
  options?: {
    agentId?: string   // omit to delete ALL memories for this user
  }
): Promise<{ success: boolean; deleted: number }>

Parameters

ParameterTypeDescription
userIdreqstringThe user whose memories to delete.
options.agentIdstringOnly delete this bot's memories. Omit to delete ALL memories for this user.

Example

typescript
// Clear only this agent's memory
await memory.forget('user_abc123', { agentId: 'support-bot' })

// Clear ALL memories for a user across every agent
const result = await memory.forget('user_abc123')
// => { success: true, deleted: 124 }
HTTP

REST API

Don't want to use the npm package? Call the API directly with curl, Python, Go — any language. All endpoints need your API key in the x-api-key header.

Base URL

https://memra-rho.vercel.app/api

MethodEndpointDescription
POST/memory/saveSave a user message + AI reply
GET/memory/contextGet recent chat + relevant older memories
GET/memory/historyGet complete chat history for a user
DELETE/memory/forgetDelete memories

POST /memory/save

ParameterTypeDescription
userIdreqstringYour user's ID.
userMessagereqstringWhat the user said.
aiReplyreqstringWhat the AI replied.
agentIdstringBot namespace. Default: 'default'
bash
curl -X POST https://memra-rho.vercel.app/api/memory/save \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: mk_mem_...' \
  -d '{
    "userId": "user_123",
    "userMessage": "What is my plan?",
    "aiReply": "You are on the Free plan.",
    "agentId": "support-bot"
  }'
json
{ "success": true, "saved": 2 }

GET /memory/context

ParameterTypeDescription
userIdreqstringUser to search.
queryreqstringThe search query.
agentIdstringFilter by bot. Default: 'default'
limitnumberMax semantic results. Default: 5
recentLimitnumberMax recent messages. Default: 10
bash
curl 'https://memra-rho.vercel.app/api/memory/context?userId=user_123&query=account+plan&limit=5&recentLimit=10' \
  -H 'x-api-key: mk_mem_...'
json
{
  "recentHistory": [
    { "id": "clx1", "content": "What is my plan?", "role": "user", "createdAt": "..." },
    { "id": "clx2", "content": "You are on Free.", "role": "assistant", "createdAt": "..." }
  ],
  "relevantMemories": [
    { "id": "clx0", "content": "I signed up yesterday", "role": "user", "similarity": 0.72 }
  ],
  "context": [...],
  "count": 1
}

GET /memory/history

ParameterTypeDescription
userIdreqstringUser whose history to fetch.
agentIdstringFilter by bot. Omit for all.
limitnumberOmit to get ALL messages.
order'asc'|'desc'Default: asc (oldest first).
beforestringISO date for pagination.
afterstringISO date for pagination.
bash
# Get ALL messages for a user (no limit)
curl 'https://memra-rho.vercel.app/api/memory/history?userId=user_123' \
  -H 'x-api-key: mk_mem_...'

# With pagination
curl 'https://memra-rho.vercel.app/api/memory/history?userId=user_123&limit=20&order=desc' \
  -H 'x-api-key: mk_mem_...'
json
{
  "history": [
    { "id": "clx1", "content": "Hello", "role": "user", "createdAt": "..." },
    { "id": "clx2", "content": "Hi! How can I help?", "role": "assistant", "createdAt": "..." }
  ],
  "total": 142,
  "count": 142
}

DELETE /memory/forget

ParameterTypeDescription
userIdreqstringUser whose memories to delete.
agentIdstringDelete only this bot's memories. Omit to delete everything.
bash
curl -X DELETE https://memra-rho.vercel.app/api/memory/forget \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: mk_mem_...' \
  -d '{ "userId": "user_123", "agentId": "support-bot" }'
json
{ "success": true, "deleted": 14 }

Error codes

When something goes wrong, the API returns a JSON object with an error field. The SDK throws an error automatically — wrap calls in try/catch.

StatusWhat went wrongHow to fix
400Missing required fieldCheck that you're sending userMessage, aiReply, query, etc.
401Bad API keyCheck your mk_mem_ key is correct and active in the dashboard.
403Wrong key typeYou're using an extension key (mk_ext_) on a memory endpoint. Use mk_mem_ instead.
429Memory limit reachedYour plan's storage is full. Delete old memories or upgrade.

429 — Limit reached

json
{
  "error": "Memory limit reached",
  "limit": 100,
  "plan": "free",
  "upgrade": "https://memra-rho.vercel.app/pricing"
}