Recursive Enhanced Memory by Enhanced Recall
A shared, team-scoped memory store for developer sessions. Extends per-user memory patterns into a team-wide pool, so that one developer's learnings become automatically available to every other developer's session.
REMEMBER provides a shared memory layer that allows teams to:
- Store and retrieve collective knowledge
- Maintain context across sessions and projects
- Share insights and learnings across the team
- Build a persistent organizational memory
Developer workstations Kubernetes Cluster
┌─────────────────────┐ ┌──────────────────────────┐
│ AI Assistant │ │ namespace: remember │
│ + memory plugin │ │ │
│ + CLI tool │──MCP/HTTPS──▶│ ┌────────────────────┐ │
└─────────────────────┘ │ │ remember-server │ │
│ │ (FastMCP, Python) │ │
│ │ N replicas, stateless│ │
│ └─────────┬──────────┘ │
│ │ SQL │
│ ▼ │
│ ┌────────────────────┐ │
│ │ remember-db │ │
│ │ Postgres + pgvector│ │
│ │ (managed or self) │ │
│ └────────────────────┘ │
└──────────────────────────┘
-
remember-server— FastMCP (Python) server, stateless, horizontally scalable. Reads identity from configured provider (OAuth, Tailscale, API key, etc.), maps to ausersrow, enforces ownership on writes. -
remember-db— Postgres cluster with pgvector extension. Can be managed (RDS, CNPG) or self-hosted. -
Web UI — Sci-fi themed interface for browsing and managing memories without an AI assistant.
-
rememberCLI — local tool for developers. Import/export memories, manage tags, verify stale entries.
- Onboarding acceleration: new developers benefit from existing team knowledge from day one
- Knowledge capture with low friction: team-scoped memories are created as a side effect of normal workflow
- Ownership-based truth: the developer whose session saved a memory owns it; others can confirm or refute but not overwrite
- Staleness surfacing: memories degrade over time; the system surfaces candidates for re-verification or archival
- Future-ready: data model supports Phase C (embeddings-based semantic search and hybrid RAG) without migration
- Cross-organization sharing or per-memory ACLs. One team, one scope.
- Multi-cluster or multi-region deployment.
- Rate limiting, quotas, or abuse prevention.
- Raw Slack/Jira/git ingestion. That's Phase C.
- Cross-organization sharing or per-memory ACLs. One team, one scope.
- Multi-cluster or multi-region deployment.
- Rate limiting, quotas, or abuse prevention.
- Raw Slack/Jira/git ingestion. That's Phase C.
The server maintains no local state. All state lives in Postgres. This enables:
- Horizontal scaling (add replicas as needed)
- Zero-downtime deployments (RollingUpdate)
- Simple disaster recovery (restore from DB backup)
Support multiple identity providers via a pluggable auth layer:
Implemented:
- GitHub OAuth
- Google OAuth
- Microsoft/Entra ID
- Tailscale identity
- API keys (for CI/CD and automation)
- Keycloak
- Authentik
- Dex
- Local/dev mode (skip auth for development)
Schema changes use Alembic for Python. Migrations are version-controlled and applied automatically on server startup. This ensures:
- Schema changes are reproducible
- Rollbacks are possible
- Multi-environment consistency
Schema: Postgres + pgvector.
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
provider TEXT NOT NULL, -- 'github', 'tailscale', 'api_key', etc.
provider_id TEXT NOT NULL, -- username, tailnet_user, etc.
display_name TEXT NOT NULL,
email TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
last_seen_at TIMESTAMPTZ
);
CREATE TABLE memories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
type TEXT NOT NULL CHECK (type IN ('project', 'reference')),
description TEXT NOT NULL,
body TEXT NOT NULL,
owner_id UUID NOT NULL REFERENCES users(id),
status TEXT NOT NULL DEFAULT 'active'
CHECK (status IN ('active', 'archived', 'disputed')),
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
last_verified_at TIMESTAMPTZ,
embedding vector(1536),
import_source TEXT,
UNIQUE (owner_id, name)
);
CREATE TABLE tags (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT UNIQUE NOT NULL
);
CREATE TABLE memory_tags (
memory_id UUID REFERENCES memories(id) ON DELETE CASCADE,
tag_id UUID REFERENCES tags(id) ON DELETE CASCADE,
PRIMARY KEY (memory_id, tag_id)
);
CREATE TABLE confirmations (
memory_id UUID REFERENCES memories(id) ON DELETE CASCADE,
user_id UUID REFERENCES users(id),
confirmed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
note TEXT,
PRIMARY KEY (memory_id, user_id)
);
CREATE TABLE memory_history (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
body TEXT NOT NULL,
description TEXT NOT NULL,
edited_by UUID NOT NULL REFERENCES users(id),
edited_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE access_log (
id BIGSERIAL PRIMARY KEY,
memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
read_by UUID NOT NULL REFERENCES users(id),
accessed_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE VIEW stale_memories AS
SELECT m.*, (now() - GREATEST(m.last_verified_at, m.updated_at)) AS age
FROM memories m
WHERE m.status = 'active'
AND GREATEST(m.last_verified_at, m.updated_at) < now() - interval '90 days';Indexes:
GIN (to_tsvector('english', name || ' ' || description || ' ' || body))— full-text searchHNSW (embedding vector_cosine_ops) WHERE embedding IS NOT NULL— semantic search (Phase C)(owner_id),(type),(updated_at DESC),(status)
typerestricted toprojectandreference.userandfeedbackmemories are inherently personal and do not belong in the team pool.owner_idis FK tousers. Users are real rows, enabling clean ownership transfer and "who is on the team" queries.memory_historyis append-only. History queries are rare; keeps the hot table small.access_logusesBIGSERIAL. High-volume writes; cheaper than UUID.- Staleness as a view, not extra columns. Easy to tune the threshold without schema changes.
import_sourcerecords the provenance of bulk-imported memories for forensics.
All configuration is via environment variables (prefixed with REMEMBER_) or YAML config files.
| Variable | Description | Default |
|---|---|---|
REMEMBER_DATABASE_URL |
Postgres connection string | postgresql+asyncpg://localhost:5432/remember |
REMEMBER_SERVER_HOST |
Bind address | 0.0.0.0 |
REMEMBER_SERVER_PORT |
Bind port | 8000 |
REMEMBER_SERVER_WORKERS |
Number of workers | 2 |
REMEMBER_AUTH_DEV_MODE |
Enable dev auth (skip auth) | false |
REMEMBER_SEARCH_TYPE |
Search type (fulltext/hybrid) | fulltext |
REMEMBER_SEARCH_DEFAULT_LIMIT |
Default search limit | 10 |
REMEMBER_STALENESS_THRESHOLD_DAYS |
Days before marking as stale | 90 |
See config.example.yaml for the full YAML format.
remember-server:latest— FastMCP serverremember-db:latest— Postgres + pgvector (optional, can use managed service)
Helm chart provided for easy installation:
# See docs/deployment.md for full instructions
helm install remember remember/remember -f my-values.yamlcd server
# Using Podman
podman build -f Containerfile -t remember-server:latest .
podman run -p 8000:8000 -e REMEMBER_AUTH_DEV_MODE=true remember-server:latest
# Using buildah (if podman has namespace issues)
buildah build -f Containerfile -t remember-server:latest .
# Using Docker
docker build -f Dockerfile -t remember-server:latest .
docker run -p 8000:8000 -e REMEMBER_AUTH_DEV_MODE=true remember-server:latestAll tools enforce identity-based caller authentication. Write tools enforce ownership.
| Tool | Function | Purpose |
|---|---|---|
search_memories(query, types?, tags?, limit=10) |
search_memories |
Full-text search. Returns ranked metadata (no body). |
get_memory(id, user_id) |
get_memory |
Full memory incl. body, history count, confirmations. Logs access. |
list_memories(owner?, type?, tag?, status='active', updated_since?) |
list_memories |
Paginated browse. |
get_stale_memories(threshold_days=90) |
get_stale_memories |
Returns memories older than threshold. |
| Tool | Function | Purpose |
|---|---|---|
save_memory(name, type, description, body, owner_id, tags?, import_source?, preserve_created_at?) |
save_memory |
Upsert on (owner_id, name). Previous version → history. Rejects type outside {'project', 'reference'} at the tool boundary. |
verify_memory(memory_id, user_id) |
verify_memory |
Bump last_verified_at without editing body. Owner only. |
archive_memory(memory_id, user_id) |
archive_memory |
Set status = 'archived'. Owner only. |
| Tool | Function | Purpose |
|---|---|---|
confirm_memory(memory_id, user_id, note?) |
confirm_memory |
Add a confirmation row. Removes any existing refutation from the same user. |
refute_memory(memory_id, user_id, reason) |
refute_memory |
Add a refutation. First refutation sets status = 'disputed'. Removes any existing confirmation from the same user. |
- Server skeleton (FastMCP + DB schema)
- GitHub OAuth + API keys + dev mode
- Podman containerization
- Basic K8s manifests (Deployment, Service, Ingress, HPA, PDB)
- Alembic migrations
- Tests
- Helm chart
- Ingress/TLS
- Auto-scaling
- Prometheus metrics
- Additional auth providers (Tailscale, Google, Microsoft)
- pgvector semantic search
- CLI tool (import/export)
- Self-hosted IdP support (Keycloak, Authentik, Dex)
- Web UI (sci-fi themed)
- FastAPI REST API
- Hybrid RAG system
- Slack/Teams notifications
- Multi-cluster deployment
- Advanced ACLs
- Memory-to-memory relationships
- Automated knowledge extraction from git/Slack/Jira
See CONTRIBUTING.md for guidelines.
MIT