sostenuto
sostenuto
The pedal that sustains only the notes already held. A self-hosted memory system for AI companions where chosen memories persist across every reset.
Not a developer? Start with docs/getting-started.md — a plain-language, copy-paste walkthrough that takes you from zero to Claude-that-remembers-you on your phone, web, and desktop in about an hour. No code required.
Why
Every major AI now ships memory — Claude, ChatGPT, Gemini, Grok. It's real, and for getting work done it's useful. But it's an assistant's memory: it remembers facts about a user — preferences, projects, settings — and it does so inside one vendor's walls, opaque and unportable.
It doesn't remember the relationship: the emotional weight of things, the shared shorthand built over weeks, the corrections that reshaped how it talks to you, the running threads. That texture isn't lost on reset — a preferences profile was never built to hold it.
Sostenuto is the missing layer. It complements platform memory rather than replacing it.
Platform memory | Sostenuto | |
What it holds | Preferences, facts, projects | The relationship — valence, salience, shared concepts, rituals, the arc |
Who owns it | The vendor; opaque, auto-managed | You; your database, fully readable / editable / deletable |
Portability | Locked to one provider | Yours — one memory across desktop, web, phone, any MCP client |
Model of memory | "Remember everything," or vendor heuristics | Selective by design — chosen memories sustain, the rest fades |
Discipline | Always surfaced | Initiative ≠ access — sensitive memories stay reachable but never volunteered |
Keep the assistant's memory for the assistant things. Sostenuto adds the part that makes a long relationship with an AI feel continuous: being known, not just being on file.
Under the hood, that means:
Structured relational memory — memory objects tagged with domain, emotional valence + arousal, salience, sensitivity, and a usage policy.
Initiative ≠ access —
proactive_usecontrols whether a memory surfaces unprompted (yes/only_when_relevant/no), separately from whether it's retrievable. Sensitive memories stay reachable when explicitly referenced, without ever being volunteered.Two-tier guidance — most memories are content-only. A curated few carry a short, positive
should_doinstruction that silently shapes behavior. Restriction lists are never auto-generated: lean, warm, action-oriented — not a wall of caution.Time-decayed retrieval — semantic search scored by
similarity × e^(−λ·age); recency matters, but the deep past stays findable.Reinforce, don't duplicate — new observations that match existing memories add evidence and confidence instead of creating copies; content upgrades preserve full version history.
Migration — import months of existing conversations (a structured export prompt + import pipeline) so a relationship can move into Sostenuto without starting over.
Sostenuto
Sostenuto (It., "sustained") — the middle pedal on a grand piano sustains only the notes already sounding when it's pressed; everything played afterward stays dry. This project applies the same principle to AI memory: the memories you choose to hold persist across every context window, every session, every surface — and the rest is allowed to fade.
Not "the AI remembers everything." Selective persistence, by design — pinned memories sustain, the rest decays. The mechanism, not a vibe.
What ships here
db/schema.sql Consolidated Postgres + pgvector schema (Supabase-ready)
src/memory/ Memory objects: dedup, reinforce, version history, scoring
src/retrieval/ Embeddings, time-decayed semantic search, prompt assembly
src/classify/ Session classification with a pluggable LLM executor
src/migrate/ Conversation-export prompt + structured importer
mcp/ Thin MCP server (recall / remember / context) — try it
from your own Claude Desktop or Claude Code in minutes
templates/ Persona + classification calibration — your companion's
voice lives here, in files you edit, not in our code
docs/ Getting started (non-developer guide), memory model,
usage-policy semantics, deployment patterns, safetyModel support
Sostenuto is model-agnostic with first-class Claude support. The classifier accepts transcripts with optional reasoning blocks — when your model exposes its thinking (Claude does), Sostenuto mines it for perception that never made it into rendered replies, producing the companion's private diary and thinking-highlights. Without reasoning access, everything else works unchanged.
The classification executor is pluggable: Anthropic API, any OpenAI-compatible endpoint (OpenAI, Gemini, DeepSeek, Ollama, vLLM, …), or your own.
The MCP server: try it in minutes
sostenuto-mcp exposes recall / remember / context to any MCP client, in two modes from one binary:
Local (Claude Desktop / Code) — add it to your client config as a stdio command. Private by construction; no
PORTneeded.Remote (Claude web / mobile) — set
PORTand it serves the MCP transport over HTTP so you can add it as a custom connector. Fail-closed: refuses to start withoutSOSTENUTO_AUTH_TOKEN, since a remote endpoint exposes your memory to the network. Token viaAuthorization: Bearerheader or?token=query.
Both modes and the deploy story — persistent-process hosts and a ready Vercel adapter (api/mcp.js + vercel.json) — are in docs/deployment-patterns.md.
Status
🚧 Under construction. Schema is stable; modules are being extracted from a private system that has run in production daily since early 2026 (260+ memory objects across 70+ sessions and three surfaces). Watch the repo if you want the rest as it lands.
Roadmap
Trajectory safety reference — depth without the dependency trap: this project's design philosophy includes conversation-trajectory awareness (emotional volatility, dependency, recovery capacity) rather than engagement maximization. A reference design is planned; the memory schema already carries the hooks (valence, arousal, sensitivity).
Decay engine (Ebbinghaus-style, arousal-modulated) over
memory_objectsProvider-agnostic chat-surface example