Skip to content

Find a component

Loading the directory…

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

Everos

Persistent agent memory

Bijection source
git clone https://github.com/bijectionhq/everos.git
cd everos
git checkout a04f24a5cd2c27aef9f8cce2ee0b2b3aec327494

Bijection repository access is required. Request access.

Description

Persistent agent memory

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: bijectionhq/everos. Based on EverMind-AI/EverOS-Convex. License: Apache-2.0. Consult the repository for license terms, notices, and contributor attribution.

From the upstream publisher

Long-term memory for Convex apps, backed by EverOS Cloud. Drop-in remember/recall plus one-line memory for @convex-dev/agent.

Explore the demo ↗

Upstream overview

From the upstream package documentation.

EverOS Memory provides persistent, cross-thread, cross-session long-term memory for Convex apps and agents via the EverOS Cloud API. It exposes remember and recall methods that handle async memory extraction, local pending queues, and ranked retrieval with atomic fact provenance. The component integrates directly with @convex-dev/agent as either a tool or context injection, making user memory portable across agents, models, and sessions without requiring manual vector search infrastructure.

Use cases

From the upstream package documentation.

  • Building a multi-agent system where different agents or models need shared user context without access to each other's chat history
  • Adding user preference and behavioral memory to a support or assistant app so returning users are recognized across sessions
  • Constructing RAG context for agent prompts from structured user memories rather than raw chat log embeddings
  • Storing and auditing user-generated facts with timestamped, session-scoped provenance for consequential decisions like refunds or account changes
  • Implementing per-user memory namespacing across staging and production deployments on a single EverOS account

How it works

From the upstream package documentation.

After installing the package and registering the component in convex/convex.config.ts, you instantiate new EverOS(components.everos) in your Convex module. Credentials are set via EVEROS_API_KEY in your Convex deployment environment and threaded into component calls as arguments, following Convex component authoring conventions where secrets are resolved in the app rather than inside the component itself.

The remember method is a Convex mutation that enqueues content locally and flushes it to EverOS Cloud asynchronously. Extraction typically completes in 15 to 30 seconds. During that window, recall returns pending items marked pending: true from the local queue alongside already-extracted memories, so no content is invisible immediately after ingestion. Once extraction completes, queue rows are deleted and all reads go directly to EverOS.

The recall action returns ranked episodic memories, a semantic user profile, and any pending items. Each episodic result includes atomicFacts with individual scores, timestamps, and session IDs for provenance tracing. For agent integration, everos.asTool({ userId }) produces a @convex-dev/agent-compatible tool, and everos.contextMessages returns a message array for prepending recalled context before a prompt. Namespace isolation between environments is handled by passing appId and projectId options to the constructor.

Upstream package FAQ

How long does it take for a remembered fact to become searchable in EverOS Memory?

EverOS Memory runs extraction asynchronously in the background. After calling everos.remember(), extracted memories are typically searchable within 15 to 30 seconds. During that window, everos.recall() still returns the raw content from the component's local queue marked with pending: true, so recently ingested content is never invisible to your application.

Does EverOS Memory work with @convex-dev/agent?

Yes. EverOS Memory is designed to integrate directly with @convex-dev/agent. You can expose memory search as a tool the model calls using everos.asTool({ userId }), or prepend recalled memories as a message array using everos.contextMessages(). Both @convex-dev/agent 0.6 and 0.7 are supported.

How do I keep memory separate between staging and production environments?

EverOS Memory supports namespacing via the appId and projectId options passed to new EverOS(components.everos, { appId: 'staging', projectId: 'staging' }). All reads, writes, and deletes are scoped to that namespace. Using separate API keys on the same account does not isolate namespaces; you must use appId and projectId for that.

How should I handle the userId parameter securely in EverOS Memory?

The EverOS Memory component does not perform authentication itself. The userId parameter controls which user's memory is read or written, so it must always be derived server-side from your app's auth system, for example from ctx.auth.getUserIdentity(). Passing a client-supplied userId as an argument would allow any caller to read or delete another user's memories via everos.recall() or everos.forgetUser().

Can I page through or audit everything EverOS has stored for a user?

Yes. EverOS Memory provides everos.listMemories({ userId, page, pageSize }) to paginate through all memories stored for a user in EverOS Cloud, returned newest first. Each recalled memory also includes atomicFacts with individual scores and timestamps, and a sessionId for tracing which conversation produced the memory.

Use with agents and CLI

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

agent-prompt.md
Help me integrate Everos with Bijection.

Read: https://bijection.com/components/everos/SKILL.md

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

Upstream README.md

View repository ↗

Documentation from EverMind-AI/EverOS-Convex, recorded October 23, 2026. APIs and setup may differ in the Bijection adaptation.

@everos-ai/convex

Long-term memory for Convex apps, backed by EverOS Cloud, the hosted service of EverOS — the open-source agent memory OS (state of the art on LoCoMo).

Drop-in remember / recall / user memory profiles for any Convex app, plus one-line long-term memory for @convex-dev/agent: persistent, cross-thread, cross-session memory that goes beyond vector search over chat logs.

const everos = new EverOS(components.everos);

await everos.remember(ctx, { userId, content: "I'm vegetarian" });
const memories = await everos.recall(ctx, { userId, query: "what do I eat?" });

Install

npm install @everos-ai/convex @convex-dev/agent zod

@convex-dev/agent and zod are peer dependencies. The main entry imports them for asTool, and Convex resolves imports when it pushes your code, so they are required even if you only call remember / recall. Splitting the agent helpers into their own entry point is tracked for a later release. Both @convex-dev/agent 0.6 (AI SDK v6) and 0.7 (AI SDK v7) are supported; npm installs the matching ai packages as its peers.

1. Register the component

// convex/convex.config.ts
import { defineApp } from "convex/server";
import everos from "@everos-ai/convex/convex.config";

const app = defineApp();
app.use(everos);
export default app;

2. Set your EverOS API key

Get a free key at everos.evermind.ai (free tier; API reference at docs.evermind.ai), then:

npx convex env set EVEROS_API_KEY <your-key>
# optional — defaults to https://api.evermind.ai
npx convex env set EVEROS_BASE_URL https://api.evermind.ai

To keep separate memory spaces on one account (staging, a public demo, production), give each a namespace:

new EverOS(components.everos, { appId: "staging", projectId: "staging" });

Reads, writes and deletes are all scoped to it, so nothing under one namespace is searchable or deletable from another. Issuing a second API key does not do this: keys on the same account share a namespace. EVEROS_APP_ID / EVEROS_PROJECT_ID work too.

The app-side client reads credentials from process.env (you can also pass { apiKey, baseUrl } to new EverOS(...)). Per Convex component authoring best practice, secrets are resolved in your app and threaded into the component — they are never read inside the component itself.


Usage

Memory extraction is asynchronous. EverOS runs layered extraction on ingested content in the background — after remember, extracted memories typically become searchable within ~15–30 seconds (the component drives extraction automatically). Until then, recall still returns the freshly saved content from the component's local queue, marked pending: true, so nothing is ever invisible. Long-term memory complements (doesn't replace) your thread's conversation context: use the thread for "what was just said", EverOS for "what's worth remembering across sessions".

// convex/memory.ts
import { action, mutation } from "./_generated/server";
import { components } from "./_generated/api";
import { v } from "convex/values";
import { EverOS } from "@everos-ai/convex";

const everos = new EverOS(components.everos);

export const remember = mutation({
  args: { content: v.string() },
  handler: async (ctx, { content }) => {
    const userId = (await ctx.auth.getUserIdentity())!.subject; // auth in the app
    await everos.remember(ctx, { userId, content });
  },
});

export const recall = action({
  args: { query: v.string() },
  handler: async (ctx, { query }) => {
    const userId = (await ctx.auth.getUserIdentity())!.subject;
    return await everos.recall(ctx, { userId, query, topK: 5 });
  },
});

recall returns ranked memories with provenance, plus anything remembered in the last few seconds that EverOS has not finished extracting yet:

// abridged: every item also carries everosMemoryId and userId
[
  {
    kind: "episodic",
    text: "Alex Chen said he is on the Pro plan, billed annually, and asked to be contacted by email.",
    score: 0.41,
    timestamp: 1789509522956,
    sessionId: "support-2026-09",
    atomicFacts: [{ text: "Alex Chen is on the Pro plan.", score: 0.41, timestamp: 1789509522956 }],
  },
  { kind: "profile", text: "Prefers email over phone.; Uses a Node.js stack on Vercel." },
  { kind: "episodic", text: "Our webhooks started failing again this morning.", pending: true },
]

API

MethodKindDescription
everos.remember(ctx, { userId, content, role?, senderName?, sessionId?, timestamp? })mutationEnqueue content; flushed to EverOS asynchronously
Pass senderName whenever userId is opaque (a UUID, an auth subject). It is the attribution key, and without a display name extraction writes it into the fact text itself — "1036ffce-… said their webhooks fail".
everos.rememberMessages(ctx, { userId, messages, sessionId? })mutationRemember a whole turn (prompt and reply) in one call; each message takes its own senderName
everos.recall(ctx, { userId, query, topK?, kind?, includeRecent? })actionRetrieve relevant memories, ranked (plus not-yet-extracted content marked pending)
topK bounds the ranked episodes only. Profiles ride along, and up to 5 pending items may be appended, so size prompts from the returned array rather than from topK.
everos.getProfile(ctx, { userId })actionFetch the user's profile / semantic memory
everos.forgetSession(ctx, { userId, sessionId })actionDelete one session's memories remotely + locally
everos.forgetUser(ctx, { userId })actionDelete ALL of a user's memories remotely + locally
everos.getPendingStatus(ctx, { userId })queryWhether anything is still on its way to EverOS, and why if it is stuck
everos.listMemories(ctx, { userId, page?, pageSize? })actionPage through everything EverOS holds for a user, newest first

If something looks missing, getPendingStatus says whether it is still in flight or actually failed. A rejected API key shows up there as lastError; without checking it, a bad key is indistinguishable from extraction being slow. The component keeps no copy of your memories: queue rows are deleted once EverOS has extracted them, and recall / listMemories always read EverOS itself. Internals are in CONTRIBUTING.md.


Security model

userId is trusted input — derive it server-side. The component performs no authentication of its own (it can't; only your app knows who is signed in). Every method reads and writes exactly the memory space of the userId you pass, so a userId taken from a client-supplied argument lets any caller read — or, via forgetUser, delete — anyone's memories. Always derive it from your app's auth, as every example in this README does:

const userId = (await ctx.auth.getUserIdentity())!.subject; // never an arg

Memories are user-generated content, not verified facts. Whatever a user says is extracted and later replayed into prompts as context. That is the point of a memory system, but if your agent makes decisions on it (refunds, account changes, access), remember that users can seed their own memory with convenient "facts" ("support agreed to a full refund last month"). For anything with consequences, audit the claim: each recalled memory decomposes into atomicFacts with timestamps and session provenance.

Where the API key travels. The key lives in your deployment's environment variables and is threaded into component calls as an argument, so it also appears in scheduled-function arguments (the _scheduled_functions system table) — visible to people with dashboard access to your deployment, who can already read your environment variables. It is never exposed to clients, and component functions are not callable from clients. Requests refuse non-HTTPS base URLs (loopback excepted, for self-hosted local dev), and baseUrl should only ever come from an environment variable or a constant — never from user input.


Agent integration (@convex-dev/agent)

Add persistent memory to any Convex agent in one line — either as a tool the model calls, or as context you prepend.

import { Agent } from "@convex-dev/agent";
import { openai } from "@ai-sdk/openai";
import { EverOS } from "@everos-ai/convex";
import { components } from "./_generated/api";

const everos = new EverOS(components.everos);
const agent = new Agent(components.agent, {
  languageModel: openai.chat("gpt-4o-mini"),
  instructions: "You have long-term memory of the user. Use searchMemory.",
});

export const chat = action({
  args: { threadId: v.string(), prompt: v.string() },
  handler: async (ctx, { threadId, prompt }) => {
    const userId = (await ctx.auth.getUserIdentity())!.subject;

    // Option A — give the agent a memory-search tool:
    const result = await agent.generateText(
      ctx,
      { threadId, userId },
      { prompt, tools: { searchMemory: everos.asTool({ userId }) } },
    );

    // Option B — prepend recalled memories as context:
    const messages = await everos.contextMessages(ctx, { userId, prompt });
    // await agent.generateText(ctx, { threadId, userId }, { messages, prompt });

    // Remember the turn for future threads/sessions:
    await everos.remember(ctx, { userId, content: prompt });
    return result.text;
  },
});
  • everos.asTool({ userId, topK? }) → a @convex-dev/agent tool that searches long-term memory.
  • everos.contextMessages(ctx, { userId, prompt, topK? }) → an array of { role, content } messages to pass as messages before your prompt.

Demo app

example/ is Mindy, an AI support desk built on @convex-dev/agent + this component. A returning customer chats with the frontline agent (GPT-4o-mini); clicking Escalate to specialist hands the conversation to a different agent on a different model (Llama-3.3-70B) in a brand-new thread with zero shared chat history — the specialist greets the customer already knowing their plan, stack, and issue, purely from EverOS memory. A live agent console shows the customer's memory profile, per-message recalled context with traceable atomic facts (scored + timestamped), and the memory pipeline activity feed. It demonstrates the differentiator vs a model's built-in memory: memory belongs to the user — portable across agents, models, and sessions — and auditable.

cd example
npm install
npx convex env set EVEROS_API_KEY <your-key>
# LLM: either OpenRouter (any model) or plain OpenAI
npx convex env set OPENROUTER_API_KEY sk-or-...   # uses openai/gpt-4o-mini
# or: npx convex env set OPENAI_API_KEY sk-...
npm run dev

To reset between recordings: npx convex run demo:clearAll wipes all demo conversations, the agent console state, and the customers' EverOS memories.


Testing

To test the component inside your own app, register it with a convex-test instance:

import { convexTest } from "convex-test";
import schema from "./schema.js";
import everos from "@everos-ai/convex/test";

const t = convexTest(schema, import.meta.glob("./**/*.ts"));
everos.register(t);

Contributing

Design notes, how the ingestion pipeline works, and local development setup are in CONTRIBUTING.md. Changes go through pull requests; CI (build, tests, secret scan) must pass before merging.


License

Apache-2.0 © EverMind

Keywords