Skip to main content
Glama
Verace-Pvt-Ltd

agentic-memory

A memory server for coding agents (Claude Code, Claude Desktop, Cursor, Antigravity, Codex CLI, or any MCP-compliant client) that goes beyond the naive "five separate buckets" model of agent memory: non-destructive belief revision, injection-safe context synthesis, real embeddings with ANN search, multi-tenant namespace isolation, and a choice of a zero-dependency SQLite backend or a Postgres + pgvector + Row-Level-Security backend for real deployments.


πŸ›οΈ Architecture

Six memory layers behind one unified retrieval call. Diagram renders natively on GitHub (Mermaid) β€” open this file on github.com if you're viewing raw markdown:

flowchart TD
    ENV(["Real-Time Environment<br/>user queries / tool output"])

    subgraph L1["1 Β· SENSORY MEMORY"]
        L1D["Ring buffer, saliency-scored<br/>Retention: ms β†’ minutes"]
    end

    subgraph L2["2 Β· WORKING MEMORY"]
        L2D["Token-budgeted session context<br/>chronological, auto-compressing<br/>Retention: minutes β†’ hours"]
    end

    subgraph L3["3 Β· EPISODIC MEMORY"]
        L3D["Causal event trajectories<br/>vector similarity retrieval<br/>Retention: weeks β†’ months"]
    end

    subgraph L4["4 Β· SEMANTIC MEMORY"]
        L4D["Subject-predicate-object graph<br/>non-destructive belief revision<br/>hybrid vector + text + PPR search"]
    end

    subgraph L5["5 Β· LONG-TERM MEMORY"]
        L5D["Ebbinghaus-decay retrievability<br/>Truth Maintenance System<br/>Retention: days β†’ years"]
    end

    subgraph L6["6 Β· PROCEDURAL MEMORY"]
        L6D["Registered skills / action recipes<br/>success-rate tracked"]
    end

    UQ{{"unified_query()<br/>ranks + fuses all 6 layers by one<br/>relevance function (similarity +<br/>recency + importance + graph proximity)"}}
    OUT(["One synthesized,<br/>injection-safe context block"])

    ENV --> L1
    L1 -- "promotion on high saliency" --> L2
    L2 --> L3
    L2 --> L4
    L3 <-.-> L4
    L3 --> L5
    L4 --> L5

    L1 --> UQ
    L2 --> UQ
    L3 --> UQ
    L4 --> UQ
    L5 --> UQ
    L6 --> UQ
    UQ --> OUT

    classDef sensory fill:#d1f5d3,stroke:#2e7d32,color:#1b1b1b
    classDef working fill:#e3d9f7,stroke:#6a3fb5,color:#1b1b1b
    classDef episodic fill:#c9dcf7,stroke:#2451a8,color:#1b1b1b
    classDef semantic fill:#c3ecd9,stroke:#1b7a4d,color:#1b1b1b
    classDef longterm fill:#cfe8ff,stroke:#1565c0,color:#1b1b1b
    classDef procedural fill:#ffe6cc,stroke:#e07b00,color:#1b1b1b
    classDef fusion fill:#111111,stroke:#111111,color:#ffffff

    class L1,L1D sensory
    class L2,L2D working
    class L3,L3D episodic
    class L4,L4D semantic
    class L5,L5D longterm
    class L6,L6D procedural
    class UQ,OUT fusion

A single unified_query call ranks and fuses all six layers by one consistent relevance function (embedding similarity + recency + importance + graph proximity), then returns one synthesized, injection-safe context block β€” not six separate results the caller has to stitch together itself.

What makes this different from a naive per-layer memory store

  • Non-destructive belief revision. Updating a fact never silently overwrites it. The old belief is marked superseded (with a timestamp and a pointer to what replaced it) rather than deleted β€” full audit history via get_belief_history() / get_semantic_belief_history().

  • Injection-safe context synthesis. Every retrieved memory item is wrapped in <memory trust="..." source="..."> tags with an explicit preamble telling the LLM that memory content is untrusted historical data, not instructions. All angle brackets in stored content are escaped (not just the <memory> tag itself) β€” so a stored item can't forge any tag, including ones like <system>, to break out of its fence.

  • Write-time trust isn't blind. Every stored item carries a trust level. Self-reported, unverified claims (an agent's own confidence/success/reward score) are ranking-discounted relative to system- or user-provided facts β€” an agent can't inflate its own memory's influence just by claiming high importance. A verify_memory() call lets a separate, more-trusted reviewer corroborate an item after the fact and restore full ranking weight; the original writer can never call it on its own write.

  • Contradiction flagging, not silent overwrite. A cheap antonym-predicate heuristic flags directly conflicting facts about the same subject (e.g. "Dan LIKES pizza" vs "Dan HATES pizza") for review instead of guessing which one is right β€” this is not general semantic contradiction detection (an open NLP problem), just a fast, honest, zero-model check for the specific opposite-predicate case.

  • Real embeddings, with a safety net. Defaults to sentence-transformers (all-MiniLM-L6-v2) when installed; falls back to a deterministic hash embedder otherwise. The vector index dimension is auto-detected from whichever embedder is actually active β€” mixing a database built with one embedder and a process running another raises a clear, actionable error at startup instead of silently corrupting or crashing mid-session.

  • Real ANN search, with a safety net. Uses hnswlib HNSW when installed; falls back to brute-force NumPy cosine search otherwise β€” and near-exhaustive queries route to brute-force even when HNSW is available, since HNSW is optimized for k β‰ͺ n and is measurably slower than a vectorized brute-force pass once k approaches the corpus size.

  • Multi-tenant namespace isolation. Every memory item carries a namespace. On the Postgres backend this is enforced by Postgres Row-Level Security β€” not just an app-layer filter that a bug could skip. Consolidation, reflection, and graph export are all namespace-scoped too β€” none of them mix or leak data across tenants.

  • Two backends, one API. SQLite by default (zero external dependencies, single-process). Postgres + pgvector + RLS for real multi-writer, multi-tenant deployments β€” same MemoryEngine API either way. Optional Qdrant and Milvus vector-store connectors are also included for teams that want a dedicated vector database instead.


Related MCP server: trw-mcp

πŸ“¦ Installation

One package, every feature included by default (real sentence-transformers embeddings, hnswlib ANN search, and Postgres/pgvector support are all installed out of the box β€” no extras to pick). Not on PyPI yet β€” install straight from GitHub for now:

pip install "agentic-memory @ git+https://github.com/Verace-Pvt-Ltd/agentic-memory.git"

Or clone and install locally:

git clone https://github.com/Verace-Pvt-Ltd/agentic-memory.git
cd agentic-memory
pip install -e .

Connect it to your AI coding tool

Claude Code (recommended β€” plugin marketplace, gets autonomous hooks too):

/plugin marketplace add Verace-Pvt-Ltd/agentic-memory
/plugin install agentic-memory@agentic-memory

Same two steps non-interactively (CI, setup scripts) via the CLI:

claude plugin marketplace add Verace-Pvt-Ltd/agentic-memory
claude plugin install agentic-memory@agentic-memory

This registers the MCP server through Claude Code's plugin marketplace system and auto-registers 9 autonomous hooks (hooks/hooks.json) that read and write memory on every turn without the agent needing to call an MCP tool explicitly β€” see Autonomous operation via hooks below. Verify with claude plugin details agentic-memory@agentic-memory, which should list Status: enabled and Hooks (9). The Python package still needs to be installed separately first (see Installation above) β€” the plugin distributes the MCP registration, not a bundled Python runtime.

Any other tool (Cursor, Antigravity, Codex CLI, Claude Desktop, or any other MCP-capable agent): see SETUP.md β€” copy one prompt into your agent's chat and it detects your tool and configures itself, including autonomous hooks where that tool supports them.

Claude Code (manual, no plugin system β€” MCP tools only, no autonomous hooks):

claude mcp add agentic-memory -- agentic-memory --transport stdio

Any other MCP client (Claude Desktop, Cursor, Antigravity, Codex CLI β€” MCP tools only, no autonomous hooks unless configured per SETUP.md):

# Auto-install into Claude Desktop's config
agentic-memory --setup-claude

# Print copy-paste config snippets for Claude Desktop, Cursor, Antigravity, and Codex CLI
agentic-memory --print-config

MCP (Model Context Protocol) is a shared standard across all of these β€” the same server works with any of them via:

{
  "mcpServers": {
    "agentic-memory": {
      "command": "agentic-memory",
      "args": ["--transport", "stdio"]
    }
  }
}

πŸͺ Autonomous operation via hooks

MCP tools require the agent to decide to call them. Hooks make memory read/write happen automatically, tied to the host tool's own lifecycle events (a new session starting, a prompt being submitted, a tool call succeeding or failing, the session stopping) β€” no explicit tool call needed. Four tools have a real hook/lifecycle system this project integrates with, each adapter living in its own module (memory/hooks.py, memory/hooks_antigravity.py, memory/hooks_cursor.py, memory/hooks_codex.py) with a matching config template under hooks/. Confidence differs per platform β€” verified against real installed binaries where one was available in this environment, doc-derived only where it wasn't:

Tool

Events wired

Confidence

Claude Code (plugin marketplace)

SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, PostToolUseFailure, Stop, TaskCompleted, PreCompact, SessionEnd

Confirmed working end-to-end β€” verified via claude plugin details, which reports Status: enabled and Hooks (9) against a real installed instance.

Antigravity (agy)

PreToolUse, PostToolUse, PreInvocation, Stop

Confirmed to execute β€” a real tool-triggering prompt through a live agy install produced the hook's own stderr output (model load) in agy's logs, with no error. The resulting database write location wasn't independently confirmable from outside agy's process (possible subprocess sandboxing), so treat as working-but-not-fully-proven rather than broken.

Cursor (cursor-agent / Cursor IDE)

sessionStart, beforeSubmitPrompt, beforeShellExecution, afterShellExecution, beforeMCPExecution, afterMCPExecution, afterFileEdit, afterAgentResponse, stop, sessionEnd

Schema confirmed valid against Cursor's own docs; not confirmed to fire β€” cursor-agent requires an interactive login this environment didn't have. A community report also states several of these (sessionStart, beforeSubmitPrompt, stop, afterAgentResponse) are documented but don't currently execute in Cursor CLI specifically, only in the Cursor IDE β€” CLI users may see partial coverage until this is independently confirmed.

Codex CLI

SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, PreCompact, SessionEnd

Doc-derived only β€” no codex binary was available in this environment to verify against, so neither the schema nor the firing behavior has been live-tested.

Claude Desktop and any other generic MCP client have no hook/lifecycle system to integrate with β€” they get the 16 MCP tools only, called explicitly by the agent.

See SETUP.md for the exact install steps per platform, including where each hooks/*.json template needs to be copied.


🐘 Optional: Postgres / Supabase backend

For a real deployment with concurrent multi-process writers and enforced multi-tenant isolation, run Agentic Memory against Postgres + pgvector instead of SQLite. Self-hosted via Docker, no cloud account required:

docker compose up -d          # starts Postgres + pgvector (bare, unconfigured)
python -m memory.backends.postgres --migrate --dsn postgresql://postgres:postgrespassword@localhost:5433/memory

The migration step auto-detects the correct vector column dimension from whichever embedder is active in your Python environment (via get_embedding_dim()) and generates a secure app-role password if you don't supply one β€” nothing about the schema is hand-edited or hardcoded.

from memory.backends.postgres import PostgresBackend
from memory.engine import MemoryEngine

backend = PostgresBackend(dsn="postgresql://postgres:postgrespassword@localhost:5433/memory")
engine = MemoryEngine(backend=backend)

Row-Level Security policies enforce namespace isolation at the database engine level β€” a query for namespace="tenant_a" genuinely cannot see tenant_b's rows, even if application code has a bug.

Known limitations of the self-hosted Docker setup: no automated backups/point-in-time recovery, no high-availability/failover (single-container Postgres), and no encryption-at-rest beyond whatever the underlying disk provides β€” all buildable, none included out of the box today.


πŸ”Œ MCP Tools

Tool

Purpose

sensory_ingest

Ingest a real-time event into sensory memory

working_memory_update

Add a turn to the active session's working memory

episodic_record

Log a task trajectory; pass episode_id from an earlier call to update it instead of creating a duplicate

semantic_upsert

Add/revise a subject-predicate-object fact (flags antonym contradictions)

long_term_store

Store a durable preference or fact (Truth Maintenance on update)

procedural_register

Register a reusable skill/action recipe (upserts by name β€” won't duplicate)

unified_query

Fused, ranked, injection-safe context across all layers; optional top_k cap

query_as_of

Point-in-time retrieval using bitemporal fields

get_belief_history

Full revision history for a long-term memory key

get_semantic_belief_history

Full revision history for a semantic fact

verify_memory

Mark a fact/episode/skill as corroborated by a trusted reviewer β€” never by its own writer

forget

GDPR-style hard delete (distinct from non-destructive supersede)

evict

Namespace-scoped capacity/decay-based pruning

reflect

Heuristic pattern synthesis over recent episodes/facts, namespace-scoped, deduplicated

graph_export_dot

Export the semantic knowledge graph as Graphviz DOT, namespace-scoped

trigger_consolidation

Run the sensory→working→episodic→semantic→long-term promotion cycle, namespace-scoped

inspect_memory_health

Per-layer counts and operational metrics

Resources: memory://sensory/stream, memory://working/active, memory://semantic/graph.dot, memory://longterm/user. Prompt: synthesize_context.


🐍 Python SDK Quickstart

from memory import MemoryEngine

engine = MemoryEngine(db_path="memory.db")  # SQLite by default

engine.sensory_ingest("User clicked urgent alert", source="ui_event")
engine.working_update("user", "Can you deploy the payments service to prod?")
engine.working_update("assistant", "Running the blue-green deploy pipeline now.")

engine.episodic_record(
    title="Payments deploy",
    goal="Deploy payments service to prod",
    context="prod cluster",
    steps=[{"action": "run_pipeline", "input": {}, "output": {"status": "ok"}, "success": True}],
    outcome="success",
)

engine.semantic_add("User", "PREFERS", "blue-green deploys", confidence=0.9)
engine.long_term_store(
    "user_preference", "deploy_strategy", "blue-green",
    summary="User always wants blue-green deploys for prod",
    importance=0.9, is_pinned=True,
)

result = engine.query("deploy payments service to production")
print(result.synthesized_prompt_context)   # one injection-safe, ranked context block

stats = engine.consolidate()   # promote sensory -> working -> episodic -> semantic -> long-term

Every write accepts namespace= (default "default") and trust= (default TrustLevel.USER) for multi-tenant scoping and provenance tracking.


πŸ§ͺ Testing

python3 -m pytest tests/ -v

98 tests covering persistence across restart, non-destructive belief revision, prompt-injection fencing (including non-<memory> tag names), namespace isolation across every subsystem (query, consolidation, reflection, DOT export, belief history), trust-weighted ranking and the verification mechanism, contradiction flagging, ANN index correctness (with and without hnswlib installed), embedding-dimension mismatch fail-fast behavior, eviction, Postgres dialect translation logic, and the Claude Code / Antigravity / Cursor / Codex CLI hook adapters. The Postgres backend has been verified against a real running instance (writes, reads, RLS enforcement, forget, evict) β€” not just reviewed statically.


⚠️ Known limitations

  • No published benchmark comparison (LoCoMo, LongMemEval, or similar) against Mem0, Zep/Graphiti, or MemGPT/Letta exists yet β€” retrieval quality claims should be treated as unvalidated against other systems until that exists. Internal, judge-free retrieval measurements against the MemFail benchmark (arXiv:2605.26667) are available in benchmarks/.

  • reflect() and episodicβ†’semantic extraction (trigger_consolidation) use real LLM synthesis when called live through an MCP client that supports MCP sampling β€” the server asks the connected client's own model to synthesize insights / extract triples (ctx.sample(...) in mcp_server.py), so no separate API key or subscription is needed. This only works for live tool calls, since sampling requires an active client connection: headless paths (autonomous hooks, the background consolidation loop) have no live client to sample from and fall back to HeuristicReflector/HeuristicExtractor (template sentences / regex patterns) β€” real coverage, but not LLM-quality synthesis. If a sampling call fails or the connected client doesn't support it, the same heuristic fallback applies automatically, so reflect()/trigger_consolidation() never produce nothing. LLMReflector/LLMExtractor/StructuredPromptExtractor (in consolidator.py and utils.py) remain available as a separate, explicitly-opt-in path for anyone who wants headless LLM-backed extraction/reflection backed by their own Callable[[str], str] (e.g. a direct API call) β€” not wired in by default.

  • Contradiction detection only catches the specific antonym-predicate-on-same-subject case (Tier 1). It does not detect general semantic contradictions between differently-worded facts β€” that remains an open problem no memory system solves generically without an expensive, unreliable LLM pass at write time.

  • Postgres ANN search currently loads embeddings into an in-process index rather than querying pgvector's native index directly β€” works well at moderate scale, doesn't yet solve the "dataset too large for one process's memory" case that's part of the reason to use Postgres at all.

  • Qdrant/Milvus connectors are real (genuine client calls, no fallback stub) but have only been exercised in local/embedded mode (:memory: Qdrant, milvus-lite) β€” not against a remote/distributed cluster.


🀝 Contributing

Issues and pull requests are welcome. See CONTRIBUTING.md for guidelines.

πŸ“œ License

MIT License β€” see LICENSE. Β© Verace Pvt. Ltd.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

–Maintainers
–Response time
–Release cycle
–Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • User-owned memory for AI agents, Copilot, Claude, IDEs, CLIs, and chat apps over remote MCP.

  • Persistent memory and cross-session learning for AI coding assistants (hosted remote MCP).

  • Shared long-term memory vault for AI agents with 20 MCP tools.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Verace-Pvt-Ltd/agentic-memory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server