Skip to content

Find a component

Loading the directory…

↑ ↓ to select · Enter to open · Esc to closeBrowse all →
Contributor login

Convex Supermemory

Give your Convex app long-term, searchable memory with Supermemory. Reactive local state, backed by direct REST calls.

Upstream source
git clone https://github.com/sholajegede/convex-supermemory.git
cd convex-supermemory

This upstream package has not been adapted or qualified for Bijection. Read the original documentation before adopting it.

Description

Give your Convex app long-term, searchable memory with Supermemory. Reactive local state, backed by direct REST calls.

Explore the package README for API concepts, configuration, and examples. Check the Bijection source for adaptation-specific setup.

Available to evaluate

Review the source and its dependencies before adopting this package. Source availability does not establish npm publication or runtime qualification.

Getting started

  1. Get the source at the revision above and read its package documentation.
  2. Check the required Bijection SDK version, dependencies, and external service credentials.
  3. Follow the package setup instructions and the guide to using components.
  4. Exercise the component in your deployment according to your project’s verification rules.

Open source

Maintained source: sholajegede/convex-supermemory. License: See repository. Consult the repository for license terms, notices, and contributor attribution.

From the upstream publisher

Give your Convex app long-term, semantically searchable memory with Supermemory. Reactive local memory and document state, direct REST integration.

Explore the demo ↗

Upstream overview

From the upstream package documentation.

convex-supermemory integrates Supermemory's memory API into Convex applications, providing semantic search over stored facts and documents without running a separate vector database. It mirrors everything written to Supermemory into local Convex tables, so memory state is reactively queryable via standard Convex queries. The component handles both short discrete facts via addMemory() and larger content via addDocument(), which goes through Supermemory's async chunking and embedding pipeline.

Use cases

From the upstream package documentation.

  • Adding per-user long-term memory to an AI agent so it recalls preferences, history, or facts across separate sessions
  • Scoping memory to individual users or workspaces using containerTag and running semantic search against only that container
  • Ingesting large documents (transcripts, notes, documentation) and querying them later with hybrid RAG search without managing embeddings
  • Building a reactive UI that displays a user's stored memories and documents using Convex queries without extra API calls
  • Implementing a forgetting mechanism to remove specific memories or documents from both Supermemory and local Convex state in sync

How it works

From the upstream package documentation.

Setup requires three steps: adding convexSupermemory to convex.config.ts via app.use(), setting SUPERMEMORY_API_KEY as a Convex environment variable, and instantiating new Supermemory(components.convexSupermemory, { apiKey }) in a Convex module. The instance is then imported into any Convex action that needs to read or write memory.

The component exposes two write paths. addMemory() stores a single fact immediately with no processing delay and accepts options like isStatic, forgetAfter, and arbitrary metadata. addDocument() sends larger content through Supermemory's extraction and chunking pipeline asynchronously; status progresses through queued, extracting, chunking, embedding, indexing, and done. Callers must poll status manually using refreshDocument(), for example from a Convex scheduled function or cron.

Every memory and document written is mirrored into Convex tables (memories and documents), making them available through reactive query methods: listMemories(), listDocuments(), getMemory(), getDocument(), and getStats(). Semantic search via search() calls Supermemory live and is not cached locally, since results are a ranked view over the underlying data rather than durable records.

Deletion is handled by forgetMemory() and deleteDocument(), both of which update local Convex state to match what Supermemory removes. deleteDocument() throws on a 409 if the document is still processing, so callers should wait for a terminal status before attempting deletion.

Upstream package FAQ

What is the difference between addMemory and addDocument in convex-supermemory?

addMemory() is for short, discrete facts that are immediately available for search with no processing delay. addDocument() is for longer content that needs chunking and embedding; processing is asynchronous and moves through stages (queued, extracting, chunking, embedding, indexing, done). Use addMemory() for conversational facts and addDocument() for transcripts, documentation pages, or other multi-paragraph content.

Does convex-supermemory cache search results in Convex tables?

No. The search() method in convex-supermemory always calls the Supermemory API live and does not mirror results into Convex tables. Memories and documents are mirrored locally, but search results are a ranked view over that data and are intentionally not persisted.

How does containerTag work in convex-supermemory?

Every write, search, and profile operation in convex-supermemory is scoped to a containerTag string you provide. Container tags are exact-match scopes, not fuzzy. A common convention is one containerTag per user ID or one per agent workspace. Search only looks within the containerTag you pass, so tags must be consistent between writes and reads.

What happens when you call forgetMemory or deleteDocument in convex-supermemory?

forgetMemory() asks Supermemory to remove the memory scoped by both containerTag and memoryId, then updates the local Convex record's forgotten field to match the response. deleteDocument() removes the document from Supermemory and from the local Convex table, but will throw if Supermemory returns a 409 because the document is still processing. You should wait until refreshDocument() reports a terminal status before deleting.

What Convex version and Node.js version does convex-supermemory require?

convex-supermemory requires Convex v1.33.1 or later and Node.js 18 or later. You also need a Supermemory API key starting with sm_, which you set as the SUPERMEMORY_API_KEY environment variable in your Convex deployment.

Use with agents and CLI

Give your coding agent the component’s source identity and setup guidance.

agent-prompt.md
Help me integrate Convex Supermemory with Bijection.

Read: https://bijection.com/components/convex-supermemory/SKILL.md

Check SDK compatibility and dependency availability.
Follow this project's execution and verification rules.

Upstream README.md

View repository ↗

Documentation from sholajegede/convex-supermemory, recorded October 23, 2026. APIs and setup may differ in the Bijection adaptation.

convex-supermemory

Give your Convex app long-term, semantically searchable memory with Supermemory. Reactive local memory and document state, direct REST integration.

const supermemory = new Supermemory(components.convexSupermemory, {
  apiKey: process.env.SUPERMEMORY_API_KEY!,
});

// Store a fact about a user
const { memoryId } = await supermemory.addMemory(ctx, {
  containerTag: userId,
  content: "Prefers dark mode and terse responses",
});

// Recall it later with semantic search
const { results } = await supermemory.search({
  containerTag: userId,
  query: "how does this user like responses formatted?",
});

What this does

An AI agent is only as good as what it remembers between calls. Supermemory is a memory API purpose-built for this: you write facts and documents into a containerTag (typically one per user or agent), and it handles embedding, chunking, and semantic search so you can recall the right context later — without you running your own vector database.

This component wraps Supermemory's REST API directly (no SDK dependency) and mirrors everything you write into Convex tables, so you get:

  • Fast-path memory — addMemory() stores a single fact immediately, no processing pipeline
  • Document ingestion — addDocument() sends larger content through Supermemory's extraction/chunking pipeline, with refreshDocument() to poll status
  • Semantic search — search() proxies Supermemory's hybrid RAG + memory search live
  • Reactive local state — every memory and document is queryable from Convex without an extra API call
  • Forgetting — forgetMemory() / deleteDocument() keep local state in sync with what Supermemory actually removes

Table of Contents

Install

npm install convex-supermemory

Requirements: Convex v1.33.1 or later, Node.js 18+, a Supermemory API key

Quick Start

Three steps to add memory to your Convex app.

1. Add the component

In convex/convex.config.ts:

import { defineApp } from "convex/server";
import convexSupermemory from "convex-supermemory/convex.config";

const app = defineApp();
app.use(convexSupermemory);

export default app;

2. Set environment variables

npx convex env set SUPERMEMORY_API_KEY sm_xxxxxxxxxxxx

3. Initialize the client

In convex/memory.ts:

import { components } from "./_generated/api";
import { Supermemory } from "convex-supermemory";

export const supermemory = new Supermemory(components.convexSupermemory, {
  apiKey: process.env.SUPERMEMORY_API_KEY!,
});

Import supermemory from this file in any Convex action that needs to read or write memory.

Usage

Remember a fact

export const remember = action({
  args: { userId: v.string(), fact: v.string() },
  handler: async (ctx, args) => {
    return await supermemory.addMemory(ctx, {
      containerTag: args.userId,
      content: args.fact,
      isStatic: true, // long-term fact, not a fading conversational detail
    });
  },
});
// Returns: { memoryId }

Recall with semantic search

export const recall = action({
  args: { userId: v.string(), query: v.string() },
  handler: async (ctx, args) => {
    return await supermemory.search({
      containerTag: args.userId,
      query: args.query,
      limit: 5,
    });
  },
});
// Returns: { results: [{ documentId, score, summary, chunks, ... }], total }

Forget a memory

containerTag is required here too — Supermemory scopes the delete by it, not just by memoryId.

export const forget = action({
  args: { userId: v.string(), memoryId: v.string() },
  handler: async (ctx, args) => {
    return await supermemory.forgetMemory(ctx, {
      containerTag: args.userId,
      memoryId: args.memoryId,
    });
  },
});
// Returns: { forgotten: boolean }

List a user's memories reactively

export const getMemories = query({
  args: { userId: v.string() },
  handler: async (ctx, args) => {
    return await supermemory.listMemories(ctx, { containerTag: args.userId });
  },
});

Memories vs. Documents

Supermemory exposes two ways to write content, and this component exposes both:

  • addMemory() — for short, discrete facts ("the user is on the Pro plan", "prefers metric units"). No processing delay; usable in search immediately.
  • addDocument() — for longer content (a support transcript, a page of documentation, a whole conversation) that needs to be chunked and embedded. Processing is asynchronous — call refreshDocument() to check on status (queued → extracting → chunking → embedding → indexing → done).

API Reference

MethodKindDescription
addMemory(ctx, args)actionStores a single fact immediately
forgetMemory(ctx, args)actionRequests Supermemory forget a memory (scoped by containerTag)
addDocument(ctx, args)actionIngests larger content through the chunking pipeline
refreshDocument(ctx, args)actionPulls the latest status/title/summary for a document
deleteDocument(ctx, args)actionDeletes a document from Supermemory and locally
search(args)plain asyncLive semantic search — not cached locally
getMemory(ctx, args)queryFetch one memory by id
listMemories(ctx, args)queryList a container's memories, newest first
getDocument(ctx, args)queryFetch one document by id
listDocuments(ctx, args)queryList a container's documents, newest first
getStats(ctx)queryAggregate memory/document counts for a small dashboard
listRecentMemories(ctx, args?)queryEvery memory, newest first, regardless of containerTag
listRecentDocuments(ctx, args?)queryEvery document, newest first, regardless of containerTag

Type Reference

type AddMemoryArgs = {
  containerTag: string;
  content: string;
  isStatic?: boolean;
  metadata?: Record<string, unknown>;
  forgetAfter?: number;   // ms epoch
  forgetReason?: string;
};

type AddDocumentArgs = {
  containerTag: string;
  content: string;
  customId?: string;
  metadata?: Record<string, unknown>;
};

type SearchArgs = {
  containerTag: string;
  query: string;
  limit?: number;
  rerank?: boolean;
  includeFullDocs?: boolean;
};

type SearchResponse = {
  results: Array<{
    documentId: string;
    title: string | null;
    score: number;
    summary: string | null;
    content: string | null;
    chunks: Array<{ content: string; score: number; position: number; isRelevant: boolean }>;
  }>;
  total: number;
  timing?: number; // ms, when Supermemory reports it
};

Database Schema

memories: {
  memoryId, containerTag, content, isStatic, metadata?,
  forgetAfter?, forgetReason?, forgotten,
  createdAt, updatedAt,
}

documents: {
  documentId, containerTag, content?, customId?, metadata?, status,
  title?, summary?,
  createdAt, updatedAt,
}

getStats(), listRecentMemories(), and listRecentDocuments() read across these tables directly with a full scan — fine for a dashboard or history view, not intended as a high-volume production query path.

Container Tags

Supermemory scopes everything — writes, search, and profiles — by containerTag. Use one per user for personal memory, or one per agent/workspace for shared memory. Search only ever looks within the container tag you pass, so pick a convention early (this component doesn't enforce one).

Testing

npm run test

Component logic is tested with convex-test in src/component/lib.test.ts. Import convex-supermemory/test in your own app to register this component's schema against your test instance.

Example App

example/ is a full Vite + React demo that exercises the entire component end to end against your own Supermemory account:

  • Memories — add a fact with addMemory() (with suggestion chips to try), forget it with forgetMemory(), all reactive.
  • Documents — ingest longer content with addDocument(), poll status with refreshDocument(), remove it with deleteDocument().
  • Search — run search() against whichever containerTag is selected, showing result score, matching chunks, and Supermemory's own reported total/timing.
  • containerTag switcher — a row of chips lets you flip between a few demo users live, so you can see the exact same actions land in completely separate memory spaces.
  • History — every memory and document ever written in the deployment, newest first, across every containerTag. Expand a row for full detail, or hit Recreate live to replay it as a brand-new memory/document.
  • Activity console — a side-docked live log of every call this app makes into the Supermemory client, including real API errors (e.g. Supermemory returns 409 if you try to delete a document that's still processing).

Run it from the repo root:

npm install --legacy-peer-deps
npx convex env set SUPERMEMORY_API_KEY sm_xxxxxxxxxxxx
npm run dev

npm run dev starts the Convex backend and the Vite frontend together — there's no need to cd example or run either one separately.

Limitations

  • search() always calls Supermemory live — results are not cached or mirrored into Convex tables, since they're a ranked view over the underlying memories/documents rather than durable records themselves.
  • Document processing is asynchronous; this component does not poll for you. Call refreshDocument() on a schedule (e.g. a Convex cron or scheduled function) if you need status without a user-triggered refresh.
  • forgetMemory() reflects whatever forgotten value Supermemory returns — if Supermemory forgets asynchronously, the local record may briefly still show forgotten: false.
  • deleteDocument() throws if Supermemory reports the document is still processing (409) — retry after the document reaches a terminal status (done/failed).

Troubleshooting

401/403 from Supermemory — confirm SUPERMEMORY_API_KEY is set and starts with sm_.

Search returns nothing — confirm you're searching the same containerTag you wrote memories/documents into; container tags are exact-match scopes, not fuzzy. If the document was ingested moments ago, give it a few seconds to finish indexing even after refreshDocument() reports done.

Document stuck in queued/extracting — large documents can take longer to process; call refreshDocument() again after a short delay.

Deleting a document fails with a "still processing" error — Supermemory returns 409 for a document that hasn't reached a terminal status yet; wait for refreshDocument() to report done or failed, then delete.

Contributing

See CONTRIBUTING.md.

Changelog

See CHANGELOG.md.

Keywords