MemoryRouterMemoryRouter

Quickstart: Add memory to your AI app

Add private persistent memory to every user in a multi-user AI product.

Quickstart: Add memory to your AI app

This guide shows the production shape: your app owns users, MemoryRouter owns user-scoped memory.

user.id → memoryKey → private vault → AI requests with memory

1. Provision a Memory Key for each user

Give every user their own Memory Key so their memory stays in a private vault. Create the key when a user signs up, starts their first AI session, or upgrades into a memory-enabled tier, then store it mapped to your internal user_id.

You have two ways to create keys.

Create keys programmatically

POST /v1/keys mints a new Memory Key. Authenticate the request with an existing Memory Key from your account. The new key belongs to your account and inherits any provider keys you have stored, so you can mint one key per end user from your backend.

async function getOrCreateMemoryKey(userId: string) {
  const existing = await db.memoryKeys.findUnique({ where: { userId } })
  if (existing) return existing.memoryKey

  // Mint a new key, authenticated with your account's Memory Key.
  // Keep MEMORYROUTER_ACCOUNT_KEY server-side only.
  const res = await fetch('https://api.memoryrouter.ai/v1/keys', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.MEMORYROUTER_ACCOUNT_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ name: `user:${userId}` })
  })

  const { key } = await res.json() // -> { key, name, created_at }

  // Store only the Memory Key mapped to your internal user id.
  await db.memoryKeys.create({ data: { userId, memoryKey: key } })

  return key
}

Response shape:

{
  "key": "mk_xxxxxxxxxxxxxxxx",
  "name": "user:42",
  "created_at": "2026-06-05T21:00:00.000Z"
}

Create keys in the dashboard

For lower volume, or to issue a key by hand, create Memory Keys at app.memoryrouter.ai and paste them into your config. The dashboard is also where you store the provider keys that newly minted keys inherit.

Keep the key you authenticate with (MEMORYROUTER_ACCOUNT_KEY) server-side only. Never expose it to the browser or ship it to clients.

2. Choose your integration mode

MemoryRouter supports two production shapes:

ModeYour app doesMemoryRouter does
Proxy modeSends the model request to MemoryRouterRetrieves memory, calls the provider, stores memory
Local inference modeCalls the provider directlyRetrieves memory with /memory/prepare, stores memory with /memory/ingest

Use proxy mode when you want the fastest integration. Use local inference mode when your app already owns provider routing, streaming, retries, evals, or model observability.

3. Proxy mode: send the AI request through MemoryRouter

Use the Memory Key as the API key for requests from that user.

import OpenAI from 'openai'

const client = new OpenAI({
  apiKey: process.env.MEMORYROUTER_PLACEHOLDER_KEY,
  baseURL: 'https://api.memoryrouter.ai/v1'
})

export async function answerUser(user: { id: string }, messages: any[]) {
  const memoryKey = await getOrCreateMemoryKey(user.id)

  const response = await client.chat.completions.create(
    {
      model: 'openai/gpt-5.5',
      messages
    },
    {
      headers: {
        Authorization: `Bearer ${memoryKey}`
      }
    }
  )

  return response.choices[0]?.message?.content
}

You can also instantiate one client per request:

const memoryKey = await getOrCreateMemoryKey(user.id)

const userClient = new OpenAI({
  apiKey: memoryKey,
  baseURL: 'https://api.memoryrouter.ai/v1'
})

const response = await userClient.chat.completions.create({
  model: 'openai/gpt-5.5',
  messages
})

4. Local inference mode: retrieve, call provider, ingest

If you do not want MemoryRouter to proxy provider calls, call the memory endpoints directly.

const memoryKey = await getOrCreateMemoryKey(user.id)

const prepared = await fetch('https://api.memoryrouter.ai/v1/memory/prepare', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${memoryKey}`,
    'Content-Type': 'application/json',
    'X-Session-ID': session.id
  },
  body: JSON.stringify({ messages })
}).then((r) => r.json())

const response = await openai.chat.completions.create({
  model: 'gpt-5.5',
  messages: [
    {
      role: 'system',
      content: prepared.context
        ? `Relevant user memory:\n${prepared.context}`
        : 'No relevant user memory found.'
    },
    ...messages
  ]
})

await fetch('https://api.memoryrouter.ai/v1/memory/ingest', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${memoryKey}`,
    'Content-Type': 'application/json',
    'X-Session-ID': session.id
  },
  body: JSON.stringify({
    model: 'openai/gpt-5.5',
    messages: [...messages, response.choices[0].message]
  })
})

In this mode, your provider request never goes through MemoryRouter. MemoryRouter only retrieves memory before inference and stores the completed exchange after inference.

Read Local inference mode for the full flow.

5. Keep the key stable

The Memory Key is the durable pointer to the user's vault. Keep it stable across:

  • plan changes
  • device changes
  • email changes
  • workspace changes
  • billing migrations

If the key changes, the user starts using a different vault unless you migrate or reattach their data.

6. Use provider keys

MemoryRouter supports two provider-key patterns:

Stored provider keys

Add provider keys in the dashboard. Then send requests with the Memory Key only.

const client = new OpenAI({
  apiKey: memoryKey,
  baseURL: 'https://api.memoryrouter.ai/v1'
})

BYOK pass-through

Pass your provider key on the request and identify the user vault with X-Memory-Key.

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
  baseURL: 'https://api.memoryrouter.ai/v1',
  defaultHeaders: {
    'X-Memory-Key': memoryKey
  }
})

7. Test memory

await userClient.chat.completions.create({
  model: 'openai/gpt-5.5',
  messages: [{ role: 'user', content: 'Remember that I prefer concise coaching and train at 6am.' }]
})

const response = await userClient.chat.completions.create({
  model: 'openai/gpt-5.5',
  messages: [{ role: 'user', content: 'How should we adjust tomorrow?' }]
})

The second call can retrieve relevant context from the same user's vault. A different user's Memory Key searches a different vault.

Next

On this page