Memory #1155
Replies: 12 comments
|
Agent generated spec idea, non-normative Paperclip Memory Service PlanGoalDefine a Paperclip memory service and surface API that can sit above multiple memory backends, while preserving Paperclip's control-plane requirements:
This plan is based on the external landscape summarized in
Recommendation In One SentencePaperclip should not embed one opinionated memory engine into core. It should add a company-scoped memory control plane with a small normalized adapter contract, then let built-ins and plugins implement the provider-specific behavior. Product Decisions1. Memory is company-scoped by defaultEvery memory binding belongs to exactly one company. That binding can then be:
No cross-company memory sharing in the initial design. 2. Providers are selected by keyEach configured memory provider gets a stable key inside a company, for example:
Agents and services resolve the active provider by key, not by hard-coded vendor logic. 3. Plugins are the primary provider pathBuilt-ins are useful for a zero-config local path, but most providers should arrive through the existing Paperclip plugin runtime. That keeps the core small and matches the current direction that optional knowledge-like systems live at the edges. 4. Paperclip owns routing, provenance, and accountingProviders should not decide how Paperclip entities map to governance. Paperclip core should own:
5. Automatic memory should be narrow at firstAutomatic capture is useful, but broad silent capture is dangerous. Initial automatic hooks should be:
Everything else should start explicit. Proposed ConceptsMemory providerA built-in or plugin-supplied implementation that stores and retrieves memory. Examples:
Memory bindingA company-scoped configuration record that points to a provider and carries provider-specific config. This is the object selected by key. Memory scopeThe normalized Paperclip scope passed into a provider request. At minimum:
Memory source referenceThe provenance handle that explains where a memory came from. Supported source kinds should include:
Memory operationA normalized write, query, browse, or delete action performed through Paperclip. Paperclip should log every operation, whether the provider is local or external. Required Adapter ContractThe required core should be small enough to fit export interface MemoryAdapterCapabilities {
profile?: boolean;
browse?: boolean;
correction?: boolean;
asyncIngestion?: boolean;
multimodal?: boolean;
providerManagedExtraction?: boolean;
}
export interface MemoryScope {
companyId: string;
agentId?: string;
projectId?: string;
issueId?: string;
runId?: string;
subjectId?: string;
}
export interface MemorySourceRef {
kind:
| "issue_comment"
| "issue_document"
| "issue"
| "run"
| "activity"
| "manual_note"
| "external_document";
companyId: string;
issueId?: string;
commentId?: string;
documentKey?: string;
runId?: string;
activityId?: string;
externalRef?: string;
}
export interface MemoryUsage {
provider: string;
model?: string;
inputTokens?: number;
outputTokens?: number;
embeddingTokens?: number;
costCents?: number;
latencyMs?: number;
details?: Record<string, unknown>;
}
export interface MemoryWriteRequest {
bindingKey: string;
scope: MemoryScope;
source: MemorySourceRef;
content: string;
metadata?: Record<string, unknown>;
mode?: "append" | "upsert" | "summarize";
}
export interface MemoryRecordHandle {
providerKey: string;
providerRecordId: string;
}
export interface MemoryQueryRequest {
bindingKey: string;
scope: MemoryScope;
query: string;
topK?: number;
intent?: "agent_preamble" | "answer" | "browse";
metadataFilter?: Record<string, unknown>;
}
export interface MemorySnippet {
handle: MemoryRecordHandle;
text: string;
score?: number;
summary?: string;
source?: MemorySourceRef;
metadata?: Record<string, unknown>;
}
export interface MemoryContextBundle {
snippets: MemorySnippet[];
profileSummary?: string;
usage?: MemoryUsage[];
}
export interface MemoryAdapter {
key: string;
capabilities: MemoryAdapterCapabilities;
write(req: MemoryWriteRequest): Promise<{
records?: MemoryRecordHandle[];
usage?: MemoryUsage[];
}>;
query(req: MemoryQueryRequest): Promise<MemoryContextBundle>;
get(handle: MemoryRecordHandle, scope: MemoryScope): Promise<MemorySnippet | null>;
forget(handles: MemoryRecordHandle[], scope: MemoryScope): Promise<{ usage?: MemoryUsage[] }>;
}This contract intentionally does not force a provider to expose its internal graph, filesystem, or ontology. Optional Adapter SurfacesThese should be capability-gated, not required:
What Paperclip Should PersistPaperclip should not mirror the full provider memory corpus into Postgres unless the provider is a Paperclip-managed local provider. Paperclip core should persist:
For external providers, the memory payload itself can remain in the provider. Hook ModelAutomatic hooksThese should be low-risk and easy to reason about:
Explicit hooksThese should be tool- or UI-driven first:
Not automatic in the first version
Agent UX RulesPaperclip should give agents both automatic recall and explicit tools, with simple guidance:
This keeps memory available without forcing every agent prompt to become a memory-management protocol. Browse And Inspect SurfacePaperclip needs a first-class UI for memory, otherwise providers become black boxes. The initial browse surface should support:
When a provider supports richer browsing, the plugin can add deeper views through the existing plugin UI surfaces. Cost And EvaluationEvery adapter response should be able to return usage records. Paperclip should roll up:
It should also record evaluation-oriented metrics where possible:
This is important because a memory system that "works" but silently burns budget is not acceptable in Paperclip. Suggested Data Model AdditionsAt the control-plane level, the likely new core tables are:
Provider-specific long-form state should stay in plugin state or the provider itself unless a built-in local provider needs its own schema. Recommended First Built-InThe best zero-config built-in is a local markdown-first provider with optional semantic indexing. Why:
The design should still treat that built-in as just another provider behind the same control-plane contract. Rollout PhasesPhase 1: Control-plane contract
Phase 2: One built-in + one plugin example
Phase 3: UI inspection
Phase 4: Automatic hooks
Phase 5: Rich capabilities
Open Questions
Bottom LineThe right abstraction is:
That gives Paperclip a stable "memory service" without locking the product to one memory philosophy or one vendor. |
Thoughts on the memory landscape surveyGreat survey — the two-layer model you have landed on feels right. A few thoughts from tinkering with this problem: Start with markdown as the zero-config built-inThe core provider should ship without any setup requirements — no embedding model, no API key, no GPU, no running service. Markdown files fit this perfectly: plain text, inspectable on disk, versionable, and trivially ingestable by any memory plugin you install later. The This also gives a natural upgrade path: start with markdown, drop in a mem0 or OpenViking plugin when the team needs richer retrieval. Plugin architecture over committed providersThe memory landscape is moving fast enough that committing to a fixed set of providers at the core level would be a mistake. The right bet is on the interface contract. Your proposed portable core (ingest, search, forget, provenance, browse) is the right shape — small enough to implement against any provider, expressive enough to not flatten away useful differences. Scoping: add team as a first-class scopeCompany → project → agent covers most cases, but there is a natural gap for cross-agent collaboration within an org structure. A Proposed hierarchy: Sequence suggestion
The discussion already has the hard parts figured out. The risk is trying to standardize everything at once. |
|
Great thread. Really informative. I personally had tested several openclaw memory plugins and built a few memory systems myself. It's quite the rabbit hole that I am (somewhat) glad to be out of now. Where I ended up in my reasoning and journey was that I thought the best bet would be on on solutions from openai / anthropic / google, at least for deployments that are already leveraging services from the frontier providers, and the last system I was testing was this plugin to connect to Vertex Memory Bank (Google). Here's the OpenClaw plugin which also takes in interesting approach at how it utilizes the memory bank. I 100% agree that a completely local, ideally dependency free option should be available. I also think that there should be an option that would utilize the existing Postgres for those who don't want to run multiple DBs. |
|
This is a good framing. The trap with “memory abstraction” is usually making it so generic that it becomes useless, or so opinionated that every provider has to fake half the contract. I’d strongly consider defining two layers on purpose: 1. Retrieval contract (lowest common denominator)
2. Provider-native extras (not flattened away)
The key is that the control plane should reason over the first layer, but never pretend the second layer does not exist. Two practical suggestions:
I’d also add a test rule for new providers: the provider should be able to round-trip a memory with provenance + budget fields intact. That catches a lot of “looks compatible but actually drops the useful bits” problems early. |
|
Adding in one more approach to the conversation https://www.losslesscontext.ai |
|
Plan seems Okay for me. would be cool if we can get this shipped for the next release because agents forget regularly their previous runs |
|
We run 14 agents in production (7 claude_local + 5 openclaw_gateway + 2 mixed) and have been operating a markdown-first memory system for several weeks. Sharing what we learned — hopefully useful for the design. Our architecture (3 layers)Each memory file has frontmatter: ---
name: Panel Clientes Multi-Marca
description: White-label client panel — Laravel 11, 3 brands, 139 tables
type: project # project | reference | feedback | user
---Types serve different purposes:
What actually works in production1. The index is everything
2. Cross-references prevent orphaned knowledgeEvery memory file ends with a 3. Session briefings are the highest-value patternEach agent has a 4. Automated maintenance is non-negotiableWe run a weekly
Without this, memory rots within 2-3 weeks. Stale memories are worse than no memory — agents act on outdated information. 5. Memory sync to agentsA cron ( 6. What NOT to storeThis was learned the hard way:
Memory should capture what cannot be derived from current state: decisions, context, relationships, preferences. What doesn't work
Suggestion for the Paperclip contractBased on our experience, the minimum viable memory contract needs: The We'd be happy to share our implementation details or contribute a markdown-first provider as a starting point for the built-in baseline. |
|
The control-plane framing is the right one. I would avoid designing Paperclip memory as a universal memory engine and instead define the minimum contract needed to govern several backends safely. A good split is three tiers: raw observations, promoted facts, and policy-governed recall. Raw observations keep provenance to runs, issues, comments, and documents. Promoted facts carry The |
|
Hi! Is this being actively worked on? since memory would be an extremely valuable feature |
|
Hi all, wondering if such memory managment be on the release roadmap for the project? |
|
Answering "is this being worked on?" from the provider side: we built one. foldcrumbs (https://github.com/vcnngr/foldcrumbs) is a local markdown-first memory store — file-per-memory on disk, stdlib-only core, no cloud, no API key, no vector DB — with a Paperclip provider bridge that implements the portable core sketched in this discussion: https://github.com/vcnngr/foldcrumbs/blob/main/docs/paperclip.md (merged to main; Mapping to the concerns raised here:
Honest limits, stated up front: On integration shape: we read the ruling on #1092 (memory providers live in their own repos) and built accordingly — the bridge is a stdlib Python surface an adapter shells into ( |
|
Update on the foldcrumbs side: the provider bridge mentioned above is now merged into foldcrumbs main, and there is an installable Paperclip plugin: https://github.com/vcnngr/paperclip-plugin-foldcrumbs (v0.1.0) What it does, in terms of this thread's requirements:
It follows the placement policy from #1092: the provider lives in an external repo we maintain; the plugin talks to Paperclip only through documented surfaces ( If the Memory API contract in this discussion firms up, we'll adapt the plugin to conform — the bridge already isolates the storage layer behind a small JSON contract, so provider-side churn is cheap. Happy to take feedback here or in the plugin's issues. |
Uh oh!
There was an error while loading. Please reload this page.
A report on the memory landscape:
Memory Landscape
Date: 2026-03-17
This document summarizes the memory systems referenced in task
PAP-530and extracts the design patterns that matter for Paperclip.What Paperclip Needs From This Survey
Paperclip is not trying to become a single opinionated memory engine. The more useful target is a control-plane memory surface that:
The question is not "which memory project wins?" The question is "what is the smallest Paperclip contract that can sit above several very different memory systems without flattening away the useful differences?"
Quick Grouping
Hosted memory APIs
mem0supermemoryMemoriThese optimize for a simple application integration story: send conversation/content plus an identity, then query for relevant memory or user context later.
Agent-centric memory frameworks / memory OSes
MemOSmemUEverMemOSOpenVikingThese treat memory as an agent runtime subsystem, not only as a search index. They usually add task memory, profiles, filesystem-style organization, async ingestion, or skill/resource management.
Local-first memory stores / indexes
nuggetsmemsearchThese emphasize local persistence, inspectability, and low operational overhead. They are useful because Paperclip is local-first today and needs at least one zero-config path.
Per-Project Notes
remember,recall,forget, fact promotion intoMEMORY.mdadd,search,getAll,get,update,delete,deleteAll; entity partitioning viauser_id,agent_id,run_id,app_idadd,profile,search.memories,search.documents, document upload, settings; automatic profile building and forgettingentity_id+process_id, sessions, cloud + BYODBindex,search,watch, transcript parsing, plugin hooksCommon Primitives Across The Landscape
Even though the systems disagree on architecture, they converge on a few primitives:
ingest: add memory from text, messages, documents, or transcriptsquery: search or retrieve memory given a task, question, or scopescope: partition memory by user, agent, project, process, or sessionprovenance: carry enough metadata to explain where a memory came frommaintenance: update, forget, dedupe, compact, or correct memories over timecontext assembly: turn raw memories into a prompt-ready bundle for the agentIf Paperclip does not expose these, it will not adapt well to the systems above.
Where The Systems Differ
These differences are exactly why Paperclip needs a layered contract instead of a single hard-coded engine.
1. Who owns extraction?
mem0,supermemory, andMemoriexpect the provider to infer memories from conversations.memsearchexpects the host to decide what markdown to write, then indexes it.MemOS,memU,EverMemOS, andOpenVikingsit somewhere in between and often expose richer memory construction pipelines.Paperclip should support both:
2. What is the source of truth?
memsearchandnuggetsmake the source inspectable on disk.OpenVikingandmemUtreat hierarchy itself as part of the memory model.Paperclip should not require a single storage shape. It should require normalized references back to Paperclip entities.
3. Is memory just search, or also profile and planning state?
mem0andmemsearchcenter search and CRUD.supermemoryadds user profiles as a first-class output.MemOS,memU,EverMemOS, andOpenVikingexpand into tool traces, task memory, resources, and skills.Paperclip should make plain search the minimum contract and richer outputs optional capabilities.
4. Is memory synchronous or asynchronous?
Paperclip needs both direct request/response operations and background maintenance hooks.
Paperclip-Specific Takeaways
Paperclip should own these concerns
Providers should own these concerns
The control-plane contract should stay small
Paperclip does not need to standardize every feature from every provider. It needs:
Recommended Direction
Paperclip should adopt a two-layer memory model:
Memory binding + control plane layerPaperclip decides which provider key is in effect for a company, agent, or project, and it logs every memory operation with provenance and usage.
Provider adapter layerA built-in or plugin-supplied adapter turns Paperclip memory requests into provider-specific calls.
The portable core should cover:
Optional capabilities can cover:
That is enough to support:
memsearchmem0,supermemory, orMemoriMemOSorOpenVikingwithout forcing Paperclip itself to become a monolithic memory engine.
All reactions