Files
rohitg00__agentmemory/README.md
T
Rohit Ghumare 5d70ecfb3c feat: migrate agentmemory to iii v0.11 and add upgrade command (#116)
* feat: migrate agentmemory to iii v0.11 and add upgrade command

Migrate the codebase from legacy iii-sdk v0.3 APIs to v0.11 trigger/register patterns, update runtime configs, and align stream/state behavior with newer engine semantics. Add a new `agentmemory upgrade` CLI command so users can refresh dependencies and iii runtime components with one entrypoint.

* chore: remove pnpm lockfile from migration PR

Drop pnpm-lock.yaml from this branch to keep the migration PR focused on source and config changes only.

* fix(ci): sync npm lockfile with iii-sdk v0.11 dependency

Update package-lock.json so npm ci in CI matches package.json after the iii-sdk migration.

* fix(ci): resolve build parse errors after v0.11 migration

Fix malformed braces introduced during API migration in triggers/health/branch-aware files so tsdown build passes in CI.

* fix: harden migration follow-up fixes and audits

Apply the reviewed v0.11 follow-up fixes across runtime, docs, and tests by tightening validation, correcting upgrade/error handling, and adding missing audit coverage on state mutations. This also addresses stream fallback behavior, lock consistency, retention source-bucket cleanup, and test/mock alignment so build and test remain green.

* fix: address 9 unresolved CodeRabbit findings on iii v0.11 migration

CodeRabbit flagged 9 remaining issues on #116 — all real. Each was
verified against the current branch code before applying. Two
findings were deliberately skipped as policy/scope issues and are
documented at the bottom.

### Applied (9 real findings)

- src/triggers/api.ts — api.ts numeric query param validation:
  multiple sites forwarded `parseInt(params.limit)` result to the
  downstream function without a Number.isFinite check. A non-numeric
  query value produced NaN at the iii-sdk trigger boundary. Added
  parseOptionalInt and parseOptionalFloat helpers at the top of the
  file, wired into api::crystal-list, api::lesson-list, and
  api::insight-list (5 sites total).

- src/triggers/api.ts — api::observe, api::context, api::session::start,
  api::session::end were forwarding req.body verbatim to sdk.trigger
  with no validation. Added explicit type checks mirroring the existing
  api::search pattern, construct a sanitized payload object before
  triggering.

- src/cli.ts — p.confirm() can return a cancel Symbol on Ctrl+C, which
  is truthy, so the upgrade path ran even when the user cancelled.
  Added p.isCancel() check and explicit boolean comparison.

- src/cli.ts — removed dead `failed` flag in runUpgrade: every caller
  already calls process.exit(1) immediately, so the final `if (failed)`
  branch was unreachable. Simplified requireSuccess accordingly.

- src/functions/leases.ts — mem::lease-renew recorded audit events as
  "lease_acquire", which conflated renewals with first claims. Renamed
  the audit event to "lease_renew" so downstream audit filters can tell
  the two operations apart.

- src/functions/relations.ts — the pair lock
  `mem:${firstId}:${secondId}` serialized concurrent relate(A,B) calls
  with identical pairs, but did NOT protect concurrent relate(A,B) +
  relate(A,C). Both modify memory A's `relatedIds` array, which is a
  classic last-writer-wins race producing lost relation edges. Fixed
  by replacing the pair lock with nested per-entity locks in canonical
  sort order: withKeyedLock(mem:firstId) wrapping withKeyedLock(mem:secondId).
  Since the ids are sorted deterministically, no deadlock is possible.

- src/functions/sketches.ts + src/functions/summarize.ts + new
  src/functions/audit.ts safeAudit helper — recordAudit was awaited
  after kv.set calls. An audit write failure would reject and the
  caller would see an error even though the target state was already
  persisted. New safeAudit wrapper swallows audit errors and logs them
  via ctx.logger.warn, preserving the mutation's success. Applied to
  all 11 audit sites in sketches.ts and the single site in summarize.ts.

- src/mcp/server.ts — three issues in the MCP handler:
  1. memory_profile's refresh flag used `args.refresh === "true"`,
     ignoring boolean `true` from MCP clients that send proper types.
     Now accepts both.
  2. memory_sketch_create built sketchPayload with
     `asNonEmptyString(args.title)` which could return undefined,
     then forwarded that to the downstream function. Added explicit
     validation + 400 response at the MCP boundary.
  3. memory_recall, memory_team_feed, memory_audit_query used
     `(args.limit as number) || 10` which replaced an explicit 0 with
     10. Changed to typeof check so explicit 0 (rare but legal) is
     preserved.

- src/functions/governance.ts — mem::governance-bulk used Promise.all
  for the delete batch, which fails fast on the first error. The audit
  record still said `deleted: candidates.length` even if only half
  actually succeeded. Switched to Promise.allSettled, split results
  into successfulIds and failures arrays, record audit with both counts
  plus the per-failure details for traceability.

- src/functions/mesh.ts — mem::mesh-register, mem::mesh-sync,
  mem::mesh-receive, mem::mesh-remove all dereferenced `data.*` without
  checking that data was passed. A TypeError would bubble up on null
  payload. Added early null/type guards returning structured errors.

- src/functions/obsidian-export.ts — resolveVaultDir(data.vaultDir)
  was called without validating that vaultDir was a string, and
  `new Set(data.types)` without validating types was an array of
  strings. Added explicit validation returning 400-style error
  responses.

- src/functions/retention.ts — the eviction loop silently swallowed
  kv.delete errors via a bare `continue`. Added ctx.logger.warn on
  catch, included memoryId and sourceBucket in the log, and now
  returns `failed` count alongside `evicted` in the response.

- src/viewer/index.html — two WebSocket bugs:
  1. connectWs assigned to the mutable global state.ws before binding
     handlers, so old sockets could have their callbacks fire and
     mutate retry/direct state after state.ws was overwritten by a
     new socket. Fixed by creating a local `ws` variable, binding
     all handlers to it, only then assigning state.ws = ws. Each
     handler guards `if (state.ws !== ws) return` so stale callbacks
     are dropped.
  2. handleStreamEvent routed EVERY incoming event to routeWsMessage,
     so non-observation events (session.activity, etc.) were being
     treated as timeline observations and causing UI confusion. Added
     a looksLikeObservation helper + event_type gate that only routes
     real observation payloads.

- test/retention.test.ts — added an explicit sourceBucket eviction
  test that seeds a semantic memory at high age, runs retention-score,
  then runs retention-evict at high threshold and asserts BOTH
  KV.semantic and KV.memories are empty. Proves the candidate.sourceBucket
  branch added in this PR actually routes to the right bucket.

- src/types.ts — side fix: the ExportData.version union on line 254
  used comma separators instead of pipes in 3 positions (0.7.9,
  0.8.0, 0.8.1 → needed | between them). tsdown strips types so the
  build passed, but tsc --noEmit would have thrown and any IDE showed
  squiggles. Pre-existing latent bug, fixed while in the file.

### Deliberately skipped

- retention.ts eviction audit (CodeRabbit asked to add recordAudit
  to the eviction loop): policy change, not a bug fix. Verified:
  auto-forget.ts, evict.ts, retention-evict, remember-forget all
  skip audit by convention — only governance audits. Adding audit
  everywhere is a policy decision tracked in issue #125.

- file-index.ts sequential → parallel session lookup: micro-opt,
  the loop is already cache-backed, negligible savings, not worth
  the readability cost.

Tests: 655/655. Build clean.

* fix(api): harden request validation at HTTP boundaries

Validate and sanitize session, observe, and context inputs plus numeric query params before forwarding to memory functions, returning 400 for invalid values instead of propagating malformed payloads. Also remove duplicate CLI command registration introduced during merge resolution.

* fix: address 6 new CodeRabbit findings on iii v0.11 migration (#116 round 2)

CodeRabbit's second review pass on #116 flagged 6 real issues introduced
by the previous round of fixes (commit 3e3ac7e). Each was verified
against the current code before applying.

### Fixed

- src/functions/governance.ts — mem::governance-bulk switched to
  Promise.allSettled in the previous round but fanned out every
  kv.delete concurrently. The governance endpoint can target tens of
  thousands of memories in a single call; firing them all at once
  overwhelms the state worker. Batched with BATCH_SIZE=50 chunks,
  awaited serially while preserving the per-batch allSettled so a
  single failure doesn't abort the rest.
- src/functions/governance.ts — the recordAudit call AFTER the bulk
  delete is already committed was still using `await recordAudit`, so
  an audit write failure would bubble up as a "failed" response even
  though the rows were actually deleted. Switched to safeAudit so the
  deletes are reflected faithfully in the response regardless of
  audit health.
- src/functions/relations.ts — the mem::relate handler was emitting
  three recordAudit calls INTERLEAVED with three kv.set writes:
  relation → audit → source update → audit → target update → audit.
  A thrown audit in the middle would leave KV.relations and
  source/target.relatedIds in a partial state. Restructured to
  complete all three durable writes first, then emit a single
  safeAudit at the end. Also changed the operation from the generic
  "evolve" (which made audit queries indistinguishable from actual
  version evolutions) to a new "relation_create" event, added to the
  AuditEntry.operation union in src/types.ts.
- src/functions/retention.ts — mem::retention-score used
  `{ ...DEFAULT_DECAY, ...data.config }` which is only a shallow
  merge. A caller passing `{ config: { tierThresholds: { cold: 0.2 } } }`
  would drop the hot and warm thresholds, causing every downstream
  `s.score >= config.tierThresholds.hot` comparison to produce NaN
  and misclassify every tier bucket. Deep-merged tierThresholds
  explicitly.
- src/functions/retention.ts — mem::retention-evict previously
  used `candidate.sourceBucket || KV.memories` as the delete bucket.
  That's correct for new retention scores (which now store
  sourceBucket) but wrong for pre-migration scores whose sourceBucket
  is undefined: the fallback would try to delete semantic ids from
  KV.memories and silently no-op, leaving the real semantic memory
  alive. Fixed by splitting the delete path: if sourceBucket is set,
  use it; otherwise attempt both KV.memories and KV.semantic with
  individual .catch(() => {}) wrappers so whichever bucket actually
  contains the id succeeds and the other is a no-op. Legacy rows
  retire naturally on the next scoring run, which writes sourceBucket.
- src/triggers/api.ts — api::obsidian-export was validated at the
  downstream mem::obsidian-export layer in the previous round, but
  the API boundary handler was still forwarding body.vaultDir without
  a type check. Added the same 400 response pattern used by
  api::search / api::observe / api::context for consistency.

### Skipped from CodeRabbit's suggestions

- CodeRabbit's proposed fix for retention.ts:249 was
  `candidate.sourceBucket || KV.retentionScores` which would try to
  delete the memory from the retention scores namespace — that's
  where the scoring entry lives, not where the memory lives. That
  fix is wrong. The two-bucket fallback approach above is the
  correct one.

Tests: 655/655. Build clean.

* fix(agentmemory): harden deletion, relation, and API validation paths

Bound retention/governance side effects and make audit logging best-effort so successful state writes are not masked by telemetry failures. Also tighten boundary validation for MCP/API inputs, resolve relation lock edge cases, and align retention test mocks with v0.11 trigger/registerFunction call shapes.

* fix: address remaining CodeRabbit validation and eviction issues

Remove duplicate CLI help examples, harden eviction/delete bookkeeping, allow file-context without sessionId, sanitize governance failure output, validate retention-evict inputs with bounded limits, and tighten summarize/observations/obsidian-export input validation.

* fix(v0.11): align stream send payloads and migration docs

Use the engine-compatible stream payload key `type` for stream::send events and update docs/plugin examples to reflect v0.11 function registration and trigger request shapes.
2026-04-15 14:02:22 +01:00

35 KiB

agentmemory — Persistent memory for AI coding agents

Your coding agent remembers everything. No more re-explaining.
Persistent memory for Claude Code, Cursor, Gemini CLI, OpenCode, and any MCP client.

Design doc: 686 stars / 94 forks on the gist

The gist extends Karpathy's LLM Wiki pattern with confidence scoring, lifecycle, knowledge graphs, and hybrid search.
agentmemory is the implementation.

npm version CI License Stars

95.2% retrieval R@5 92% fewer tokens 43 MCP tools 12 auto hooks 0 external DBs 654 tests passing

agentmemory demo

Quick Start • Benchmarks • vs Competitors • Agents • How It Works • MCP • Viewer • Config • API


Works with every agent

agentmemory works with any agent that supports hooks, MCP, or REST API. All agents share the same memory server.

Claude Code
Claude Code
12 hooks + MCP + skills
OpenClaw
OpenClaw
MCP + plugin
Hermes
Hermes
MCP + plugin
Cursor
Cursor
MCP server
Gemini CLI
Gemini CLI
MCP server
OpenCode
OpenCode
MCP server
Codex CLI
Codex CLI
MCP server
Cline
Cline
MCP server
Goose
Goose
MCP server
Kilo Code
Kilo Code
MCP server
Aider
Aider
REST API
Claude Desktop
Claude Desktop
MCP server
Windsurf
Windsurf
MCP server
Roo Code
Roo Code
MCP server
Claude SDK
Claude SDK
AgentSDKProvider
REST API
Any agent
REST API

Works with any agent that speaks MCP or HTTP. One server, memories shared across all of them.


You explain the same architecture every session. You re-discover the same bugs. You re-teach the same preferences. Built-in memory (CLAUDE.md, .cursorrules) caps out at 200 lines and goes stale. agentmemory fixes this. It silently captures what your agent does, compresses it into searchable memory, and injects the right context when the next session starts. One command. Works across agents.

What changes: Session 1 you set up JWT auth. Session 2 you ask for rate limiting. The agent already knows your auth uses jose middleware in src/middleware/auth.ts, your tests cover token validation, and you chose jose over jsonwebtoken for Edge compatibility. No re-explaining. No copy-pasting. The agent just knows.

npx @agentmemory/agentmemory

New in v0.8.2 — Security hardening (default localhost, viewer CSP nonces, mesh auth), agentmemory demo command, benchmark comparison vs mem0/Letta/Khoj, OpenClaw gateway plugin, real-time token savings in CLI + viewer.


Benchmarks

Retrieval Accuracy

LongMemEval-S (ICLR 2025, 500 questions)

System R@5 R@10 MRR
agentmemory 95.2% 98.6% 88.2%
BM25-only fallback 86.2% 94.6% 71.5%

Token Savings

Approach Tokens/yr Cost/yr
Paste full context 19.5M+ Impossible (exceeds window)
LLM-summarized ~650K ~$500
agentmemory ~170K ~$10
agentmemory + local embeddings ~170K $0

Embedding model: all-MiniLM-L6-v2 (local, free, no API key). Full reports: benchmark/LONGMEMEVAL.md, benchmark/QUALITY.md, benchmark/SCALE.md. Competitor comparison: benchmark/COMPARISON.md — agentmemory vs mem0, Letta, Khoj, claude-mem, Hippo.


vs Competitors

agentmemory mem0 (53K ⭐) Letta / MemGPT (22K ⭐) Built-in (CLAUDE.md)
Type Memory engine + MCP server Memory layer API Full agent runtime Static file
Retrieval R@5 95.2% 68.5% (LoCoMo) 83.2% (LoCoMo) N/A (grep)
Auto-capture 12 hooks (zero manual effort) Manual add() calls Agent self-edits Manual editing
Search BM25 + Vector + Graph (RRF fusion) Vector + Graph Vector (archival) Loads everything into context
Multi-agent MCP + REST + leases + signals API (no coordination) Within Letta runtime only Per-agent files
Framework lock-in None (any MCP client) None High (must use Letta) Per-agent format
External deps None (SQLite + iii-engine) Qdrant / pgvector Postgres + vector DB None
Memory lifecycle 4-tier consolidation + decay + auto-forget Passive extraction Agent-managed Manual pruning
Token efficiency ~1,900 tokens/session ($10/yr) Varies by integration Core memory in context 22K+ tokens at 240 obs
Real-time viewer Yes (port 3113) Cloud dashboard Cloud dashboard No
Self-hosted Yes (default) Optional Optional Yes

Quick Start

Compatibility: this release targets stable iii-sdk ^0.11.0 and iii-engine v0.11.x.

Try it in 30 seconds

# Terminal 1: start the server
npx @agentmemory/agentmemory

# Terminal 2: seed sample data and see recall in action
npx @agentmemory/agentmemory demo

demo seeds 3 realistic sessions (JWT auth, N+1 query fix, rate limiting) and runs semantic searches against them. You'll see it find "N+1 query fix" when you search "database performance optimization" — keyword matching can't do that.

Open http://localhost:3113 to watch the memory build live.

Upgrade / Maintenance

Use the maintenance command when you intentionally want to update your local runtime:

npx @agentmemory/agentmemory upgrade

Warning: this command mutates the current workspace/runtime. It can update JavaScript dependencies, may run cargo install iii-engine --force, and may pull Docker images.

Implementation details live in src/cli.ts (see runUpgrade around the src/cli.ts:544-595 region).

Claude Code (one block, paste it)

Install agentmemory: run `npx @agentmemory/agentmemory` in a separate terminal to start the memory server. Then run `/plugin marketplace add rohitg00/agentmemory` and `/plugin install agentmemory` — the plugin registers all 12 hooks, 4 skills, AND auto-wires the `@agentmemory/mcp` stdio server via its `.mcp.json`, so you get 43 MCP tools (memory_smart_search, memory_save, memory_sessions, memory_governance_delete, etc.) without any extra config step. Verify with `curl http://localhost:3111/agentmemory/health`. The real-time viewer is at http://localhost:3113.
OpenClaw (paste this prompt)
Install agentmemory for OpenClaw. Run `npx @agentmemory/agentmemory` in a separate terminal to start the memory server on localhost:3111. Then add this to my OpenClaw MCP config so agentmemory is available with all 43 memory tools:

{
  "mcpServers": {
    "agentmemory": {
      "command": "npx",
      "args": ["-y", "@agentmemory/mcp"]
    }
  }
}

Restart OpenClaw. Verify with `curl http://localhost:3111/agentmemory/health`. Open http://localhost:3113 for the real-time viewer. For deeper 4-hook gateway integration, see integrations/openclaw in the agentmemory repo.

Full guide: integrations/openclaw/

Hermes Agent (paste this prompt)
Install agentmemory for Hermes. Run `npx @agentmemory/agentmemory` in a separate terminal to start the memory server on localhost:3111. Then add this to ~/.hermes/config.yaml so Hermes can use agentmemory as an MCP server with all 43 memory tools:

mcp_servers:
  agentmemory:
    command: npx
    args: ["-y", "@agentmemory/mcp"]

Verify with `curl http://localhost:3111/agentmemory/health`. Open http://localhost:3113 for the real-time viewer. For deeper 6-hook memory provider integration (pre-LLM context injection, turn capture, MEMORY.md mirroring, system prompt block), copy integrations/hermes from the agentmemory repo to ~/.hermes/plugins/memory/agentmemory.

Full guide: integrations/hermes/

Other agents

Start the memory server: npx @agentmemory/agentmemory

Then add the MCP config for your agent:

Agent Setup
Cursor Add to ~/.cursor/mcp.json: {"mcpServers": {"agentmemory": {"command": "npx", "args": ["-y", "@agentmemory/mcp"]}}}
OpenClaw Add to MCP config: {"mcpServers": {"agentmemory": {"command": "npx", "args": ["-y", "@agentmemory/mcp"]}}} or use the gateway plugin
Gemini CLI gemini mcp add agentmemory -- npx -y @agentmemory/mcp
Codex CLI Add to .codex/config.yaml: mcp_servers: {agentmemory: {command: npx, args: ["-y", "@agentmemory/mcp"]}}
OpenCode Add to opencode.json: {"mcp": {"agentmemory": {"type": "local", "command": ["npx", "-y", "@agentmemory/mcp"], "enabled": true}}}
Hermes Agent Add to ~/.hermes/config.yaml or use the memory provider plugin
Cline / Goose / Kilo Code Add MCP server in settings
Claude Desktop Add to claude_desktop_config.json: {"mcpServers": {"agentmemory": {"command": "npx", "args": ["-y", "@agentmemory/mcp"]}}}
Aider REST API: curl -X POST http://localhost:3111/agentmemory/smart-search -d '{"query": "auth"}'
Any agent (32+) npx skillkit install agentmemory

From source

git clone https://github.com/rohitg00/agentmemory.git && cd agentmemory
npm install && npm run build && npm start

This starts agentmemory with a local iii-engine if iii is already installed, or falls back to Docker Compose if Docker is available. REST, streams, and the viewer bind to 127.0.0.1 by default.

Install iii-engine manually:

  • macOS / Linux: curl -fsSL https://install.iii.dev/iii/main/install.sh | sh
  • Windows: download iii-x86_64-pc-windows-msvc.zip from iii-hq/iii releases, extract iii.exe, add to PATH

Or use Docker (the bundled docker-compose.yml pulls iiidev/iii:latest). Full docs: iii.dev/docs.

Windows

agentmemory runs on Windows 10/11, but the Node.js package alone isn't enough — you also need the iii-engine runtime (a separate native binary) as a background process. The official upstream installer is a sh script and there is no PowerShell installer or scoop/winget package today, so Windows users have two paths:

Option A — Prebuilt Windows binary (recommended):

# 1. Open https://github.com/iii-hq/iii/releases/latest in your browser
# 2. Download iii-x86_64-pc-windows-msvc.zip
#    (or iii-aarch64-pc-windows-msvc.zip if you're on an ARM machine)
# 3. Extract iii.exe somewhere on PATH, or place it at:
#    %USERPROFILE%\.local\bin\iii.exe
#    (agentmemory checks that location automatically)
# 4. Verify:
iii --version

# 5. Then run agentmemory as usual:
npx -y @agentmemory/agentmemory

Option B — Docker Desktop:

# 1. Install Docker Desktop for Windows
# 2. Start Docker Desktop and make sure the engine is running
# 3. Run agentmemory — it will auto-start the bundled compose file:
npx -y @agentmemory/agentmemory

Option C — standalone MCP only (no engine): if you only need the MCP tools for your agent and don't need the REST API, viewer, or cron jobs, skip the engine entirely:

npx -y @agentmemory/agentmemory mcp
# or via the shim package:
npx -y @agentmemory/mcp

Diagnostics for Windows: if npx @agentmemory/agentmemory fails, re-run with --verbose to see the actual engine stderr. Common failure modes:

Symptom Fix
iii-engine process started then did not become ready within 15s Engine crashed on startup — re-run with --verbose, check stderr
Could not start iii-engine Neither iii.exe nor Docker is installed. See Option A or B above
Port conflict netstat -ano | findstr :3111 to see what's bound, then kill it or use --port <N>
Docker fallback skipped even though Docker is installed Make sure Docker Desktop is actually running (system tray icon)

Note: there is no cargo install iii-engine — iii is not published to crates.io. The only supported install methods are the prebuilt binary above, the upstream sh install script (macOS/Linux only), and the Docker image.


Why agentmemory

Every coding agent forgets everything when the session ends. You waste the first 5 minutes of every session re-explaining your stack. agentmemory runs in the background and eliminates that entirely.

Session 1: "Add auth to the API"
  Agent writes code, runs tests, fixes bugs
  agentmemory silently captures every tool use
  Session ends -> observations compressed into structured memory

Session 2: "Now add rate limiting"
  Agent already knows:
    - Auth uses JWT middleware in src/middleware/auth.ts
    - Tests in test/auth.test.ts cover token validation
    - You chose jose over jsonwebtoken for Edge compatibility
  Zero re-explaining. Starts working immediately.

vs built-in agent memory

Every AI coding agent ships with built-in memory — Claude Code has MEMORY.md, Cursor has notepads, Cline has memory bank. These work like sticky notes. agentmemory is the searchable database behind the sticky notes.

Built-in (CLAUDE.md) agentmemory
Scale 200-line cap Unlimited
Search Loads everything into context BM25 + vector + graph (top-K only)
Token cost 22K+ at 240 observations ~1,900 tokens (92% less)
Cross-agent Per-agent files MCP + REST (any agent)
Coordination None Leases, signals, actions, routines
Observability Read files manually Real-time viewer on :3113

How It Works

Memory Pipeline

PostToolUse hook fires
  -> SHA-256 dedup (5min window)
  -> Privacy filter (strip secrets, API keys)
  -> Store raw observation
  -> LLM compress -> structured facts + concepts + narrative
  -> Vector embedding (6 providers + local)
  -> Index in BM25 + vector + knowledge graph

SessionStart hook fires
  -> Load project profile (top concepts, files, patterns)
  -> Hybrid search (BM25 + vector + graph)
  -> Token budget (default: 2000 tokens)
  -> Inject into conversation

4-Tier Memory Consolidation

Inspired by how human brains process memory — not unlike sleep consolidation.

Tier What Analogy
Working Raw observations from tool use Short-term memory
Episodic Compressed session summaries "What happened"
Semantic Extracted facts and patterns "What I know"
Procedural Workflows and decision patterns "How to do it"

Memories decay over time (Ebbinghaus curve). Frequently accessed memories strengthen. Stale memories auto-evict. Contradictions are detected and resolved.

What Gets Captured

Hook Captures
SessionStart Project path, session ID
UserPromptSubmit User prompts (privacy-filtered)
PreToolUse File access patterns + enriched context
PostToolUse Tool name, input, output
PostToolUseFailure Error context
PreCompact Re-injects memory before compaction
SubagentStart/Stop Sub-agent lifecycle
Stop End-of-session summary
SessionEnd Session complete marker

Key Capabilities

Capability Description
Automatic capture Every tool use recorded via hooks — zero manual effort
Semantic search BM25 + vector + knowledge graph with RRF fusion
Memory evolution Versioning, supersession, relationship graphs
Auto-forgetting TTL expiry, contradiction detection, importance eviction
Privacy first API keys, secrets, <private> tags stripped before storage
Self-healing Circuit breaker, provider fallback chain, health monitoring
Claude bridge Bi-directional sync with MEMORY.md
Knowledge graph Entity extraction + BFS traversal
Team memory Namespaced shared + private across team members
Citation provenance Trace any memory back to source observations
Git snapshots Version, rollback, and diff memory state

Triple-stream retrieval combining three signals:

Stream What it does When
BM25 Stemmed keyword matching with synonym expansion Always on
Vector Cosine similarity over dense embeddings Embedding provider configured
Graph Knowledge graph traversal via entity matching Entities detected in query

Fused with Reciprocal Rank Fusion (RRF, k=60) and session-diversified (max 3 results per session).

Embedding providers

agentmemory auto-detects your provider. For best results, install local embeddings (free):

npm install @xenova/transformers
Provider Model Cost Notes
Local (recommended) all-MiniLM-L6-v2 Free Offline, +8pp recall over BM25-only
Gemini text-embedding-004 Free tier 1500 RPM
OpenAI text-embedding-3-small $0.02/1M Highest quality
Voyage AI voyage-code-3 Paid Optimized for code
Cohere embed-english-v3.0 Free trial General purpose
OpenRouter Any model Varies Multi-model proxy

MCP Server

43 tools, 6 resources, 3 prompts, and 4 skills — the most comprehensive MCP memory toolkit for any agent.

43 Tools

Core tools (always available)
Tool Description
memory_recall Search past observations
memory_save Save an insight, decision, or pattern
memory_smart_search Hybrid semantic + keyword search
memory_file_history Past observations about specific files
memory_sessions List recent sessions
memory_profile Project profile (concepts, files, patterns)
memory_export Export all memory data
Extended tools (43 total — set AGENTMEMORY_TOOLS=all)
Tool Description
memory_patterns Detect recurring patterns
memory_timeline Chronological observations
memory_relations Query relationship graph
memory_graph_query Knowledge graph traversal
memory_consolidate Run 4-tier consolidation
memory_claude_bridge_sync Sync with MEMORY.md
memory_team_share Share with team members
memory_team_feed Recent shared items
memory_audit Audit trail of operations
memory_governance_delete Delete with audit trail
memory_snapshot_create Git-versioned snapshot
memory_action_create Create work items with dependencies
memory_action_update Update action status
memory_frontier Unblocked actions ranked by priority
memory_next Single most important next action
memory_lease Exclusive action leases (multi-agent)
memory_routine_run Instantiate workflow routines
memory_signal_send Inter-agent messaging
memory_signal_read Read messages with receipts
memory_checkpoint External condition gates
memory_mesh_sync P2P sync between instances
memory_sentinel_create Event-driven watchers
memory_sentinel_trigger Fire sentinels externally
memory_sketch_create Ephemeral action graphs
memory_sketch_promote Promote to permanent
memory_crystallize Compact action chains
memory_diagnose Health checks
memory_heal Auto-fix stuck state
memory_facet_tag Dimension:value tags
memory_facet_query Query by facet tags
memory_verify Trace provenance

6 Resources · 3 Prompts · 4 Skills

Type Name Description
Resource agentmemory://status Health, session count, memory count
Resource agentmemory://project/{name}/profile Per-project intelligence
Resource agentmemory://memories/latest Latest 10 active memories
Resource agentmemory://graph/stats Knowledge graph statistics
Prompt recall_context Search + return context messages
Prompt session_handoff Handoff data between agents
Prompt detect_patterns Analyze recurring patterns
Skill /recall Search memory
Skill /remember Save to long-term memory
Skill /session-history Recent session summaries
Skill /forget Delete observations/sessions

Standalone MCP

Run without the full server — for any MCP client. Either of these works:

npx -y @agentmemory/agentmemory mcp   # canonical (always available)
npx -y @agentmemory/mcp                # shim package alias

Or add to your agent's MCP config:

Most agents (Cursor, Claude Desktop, Cline, etc.):

{
  "mcpServers": {
    "agentmemory": {
      "command": "npx",
      "args": ["-y", "@agentmemory/mcp"]
    }
  }
}

OpenCode (opencode.json):

{
  "mcp": {
    "agentmemory": {
      "type": "local",
      "command": ["npx", "-y", "@agentmemory/mcp"],
      "enabled": true
    }
  }
}

Real-Time Viewer

Auto-starts on port 3113. Live observation stream, session explorer, memory browser, knowledge graph visualization, and health dashboard.

open http://localhost:3113

The viewer server binds to 127.0.0.1 by default. The REST-served /agentmemory/viewer endpoint follows the normal AGENTMEMORY_SECRET bearer-token rules. CSP headers use a per-response script nonce and disable inline handler attributes (script-src-attr 'none').


Configuration

LLM Providers

agentmemory auto-detects from your environment. No API key needed if you have a Claude subscription.

Provider Config Notes
Claude subscription (default) No config needed Uses @anthropic-ai/claude-agent-sdk
Anthropic API ANTHROPIC_API_KEY Per-token billing
MiniMax MINIMAX_API_KEY Anthropic-compatible
Gemini GEMINI_API_KEY Also enables embeddings
OpenRouter OPENROUTER_API_KEY Any model

Environment Variables

Create ~/.agentmemory/.env:

# LLM provider (pick one, or leave empty for Claude subscription)
# ANTHROPIC_API_KEY=sk-ant-...
# GEMINI_API_KEY=...
# OPENROUTER_API_KEY=...

# Embedding provider (auto-detected, or override)
# EMBEDDING_PROVIDER=local
# VOYAGE_API_KEY=...

# Search tuning
# BM25_WEIGHT=0.4
# VECTOR_WEIGHT=0.6
# TOKEN_BUDGET=2000

# Auth
# AGENTMEMORY_SECRET=your-secret

# Ports (defaults: 3111 API, 3113 viewer)
# III_REST_PORT=3111

# Features
# AGENTMEMORY_AUTO_COMPRESS=false  # OFF by default (#138). When on,
                                   # every PostToolUse hook calls your
                                   # LLM provider to compress the
                                   # observation — expect significant
                                   # token spend on active sessions.
# AGENTMEMORY_INJECT_CONTEXT=false # OFF by default (#143). When on:
                                   # - SessionStart may inject ~1-2K
                                   #   chars of project context into
                                   #   the first turn of each session
                                   #   (this is what actually reaches
                                   #   the model — Claude Code treats
                                   #   SessionStart stdout as context)
                                   # - PreToolUse fires /agentmemory/enrich
                                   #   on every file-touching tool call
                                   #   (resource cleanup, not a token
                                   #   fix — PreToolUse stdout is debug
                                   #   log only per Claude Code docs)
                                   # Observations are still captured via
                                   # PostToolUse regardless of this flag.
# GRAPH_EXTRACTION_ENABLED=false
# CONSOLIDATION_ENABLED=true
# LESSON_DECAY_ENABLED=true
# OBSIDIAN_AUTO_EXPORT=false
# AGENTMEMORY_EXPORT_ROOT=~/.agentmemory
# CLAUDE_MEMORY_BRIDGE=false
# SNAPSHOT_ENABLED=false

# Team
# TEAM_ID=
# USER_ID=
# TEAM_MODE=private

# Tool visibility: "core" (7 tools) or "all" (43 tools)
# AGENTMEMORY_TOOLS=core

API

109 endpoints on port 3111. The REST API binds to 127.0.0.1 by default. Protected endpoints require Authorization: Bearer <secret> when AGENTMEMORY_SECRET is set, and mesh sync endpoints require AGENTMEMORY_SECRET on both peers.

Key endpoints
Method Path Description
GET /agentmemory/health Health check (always public)
POST /agentmemory/session/start Start session + get context
POST /agentmemory/session/end End session
POST /agentmemory/observe Capture observation
POST /agentmemory/smart-search Hybrid search
POST /agentmemory/context Generate context
POST /agentmemory/remember Save to long-term memory
POST /agentmemory/forget Delete observations
POST /agentmemory/enrich File context + memories + bugs
GET /agentmemory/profile Project profile
GET /agentmemory/export Export all data
POST /agentmemory/import Import from JSON
POST /agentmemory/graph/query Knowledge graph query
POST /agentmemory/team/share Share with team
GET /agentmemory/audit Audit trail

Full endpoint list: src/triggers/api.ts


Architecture

Built on iii-engine's three primitives — no Express, no Postgres, no Redis.

118 source files · ~21,800 LOC · 646 tests · 123 functions · 34 KV scopes

What iii-engine replaces
Traditional stack agentmemory uses
Express.js / Fastify iii HTTP Triggers
SQLite / Postgres + pgvector iii KV State + in-memory vector index
SSE / Socket.io iii Streams (WebSocket)
pm2 / systemd iii-engine worker management
Prometheus / Grafana iii OTEL + health monitor

Development

npm run dev               # Hot reload
npm run build             # Production build
npm test                  # 646 tests (~1.7s)
npm run test:integration  # API tests (requires running services)

Prerequisites: Node.js >= 20, iii-engine or Docker

License

Apache-2.0