Skip to content

Repository files navigation

Pain Memory

AI agents are amnesic. Every session starts from zero. Yesterday's hard-won lesson — the one that took twenty failed commands to learn — is gone this morning.

Pain Memory gives any AI agent a memory of its own failures — automatically detecting failures after each step, matching them against past pain, and injecting behavioral rules (problem → fix) that stop the repeat.

One engine, four ways to plug in: MCP server (Claude Code, Cursor, Codex CLI, Windsurf, Zed...), Claude Code hooks, a universal CLI wrapper, or a plain Python SDK.

Tool call → pre-filter (exit≠0? stderr?) → embed → cosine match verified pain
   ├─ hit  → inject the behavioral rule into the agent's context
   └─ miss + error → independent LLM judge → write new (speculative) memory
                     └─ Layer 2: clusters recurrences into pattern rules
                        └─ Layer 3: distills rules into principles → feed back

Why not just "save the error to a file"?

Notes / RAG memory Pain Memory
Trigger manual or chat-time after every tool call
Content information ("remember that...") behavior rules (WHAT → HOW → WHY)
Trust everything is kept severity × recurrence × similarity; new memories start quarantined
Cost main-session tokens embedding + matching run out-of-band; zero main-session cost
Evolution static 3-layer self-evolution: memories → patterns → principles

The hard problem isn't remembering — it's knowing whether to trust what you remember. That's why memory writing is gated by an independent LLM judge, unverified memories are quarantined until they recur 3 times, and write-side dedup turns near-identical failures into recurrence events instead of duplicates.

Quickstart

pip install pain-memory          # numpy is the only hard dependency
pm init --with-seeds             # optional: 8 hand-verified starter memories

1. Any MCP-capable agent (recommended)

claude mcp add pain-memory -- pain-memory-mcp
# Cursor/Codex/Windsurf: point the MCP server command at `pain-memory-mcp`

The agent gets pain_check (after each step), pain_retrieve (at task start), pain_report, pain_add, pain_stats, pain_grow, pain_mine — memories are scoped per project automatically.

2. Claude Code hooks (zero-interaction mode)

pm install-hooks --claude-dir ~/.claude

This registers a PostToolUse hook (detect + inject after every tool call) and a UserPromptSubmit hook (task-entry retrieval). No agent cooperation needed — the memory loop just runs.

3. Universal shell wrapper — works for humans, CI, and any agent

pm exec -- npm run build          # runs the command, detects pain, injects on stderr
pm exec -- python train.py        # exit code is propagated unchanged

4. Python SDK

from painmemory import open_engine, Observation

engine = open_engine()
injection = engine.check(Observation(
    tool="Bash", command="npm run build",
    exit_code=1, stderr="npm ERR! missing script"))
if injection:
    print(injection.text)   # behavior rule(s) to show the agent

The three self-evolution layers

Layer Runs What it does
1 · Detect & inject every tool call pre-filter → embed → cosine-match verified memories → inject rules; unmatched errors → LLM judge → write-back
2 · Pattern grower pm grow / pain_grow clusters chains with pairwise cosine > 0.82; ≥3 members condense into a pattern rule with confidence = mean pairwise similarity
3 · Principle miner pm mine / pain_mine merges rules into principles (cosine > 0.85) or creates new ones; expands principle coverage; principles re-enter Layer 1 retrieval at 2× weight
pm stats                 # store health
pm list                  # all memories with severity × recurrence
pm log                   # activity: inject / judge / dedup events
pm grow && pm mine       # run layers 2+3 manually

Trust model

Every memory carries a confidence chain:

  • verified — human-confirmed (seeds, pm add, MCP pain_add)
  • speculative — written by the LLM judge; quarantined from task-entry retrieval until it recurs 3× (frequency substitutes for verification)
  • dedup — a near-identical failure (cosine > 0.88) appends a recurrence event instead of creating a duplicate

Injection is always labeled with similarity, trust, and recurrence — the agent decides, never blindly obeys.

Providers (all pluggable, all with fallback)

Embeddings — tried in order, first healthy wins: local persistent server (BGE, ~50ms/embed) → OpenAI-compatible API → Ollama → sentence-transformers → char-ngram hashing (zero-dep lexical semantics, multilingual) → deterministic hash mock (always works).

LLM judge — any OpenAI-compatible endpoint:

# painmemory.toml
[judge]
base_url = "https://api.deepseek.com/v1"   # or OpenAI, GLM, vLLM, ...
model = "deepseek-chat"

[embedder]
model = "BAAI/bge-base-zh-v1.5"
locale = "en"        # "zh" restores the original Chinese injection style

Environment equivalents: PAIN_MEMORY_JUDGE_BASE_URL / PAIN_MEMORY_JUDGE_MODEL / PAIN_MEMORY_JUDGE_API_KEY (or the DEEPSEEK_API_KEY shortcut). No judge configured? Memory injection still works; nothing new is written.

Memory scoping

Memories live in ~/.painmemory/stores/<scope>/ — the scope is a stable hash of the project root, so different projects never pollute each other. Override with PAIN_MEMORY_SCOPE, or point PAIN_MEMORY_HOME anywhere. The file formats are backward compatible with the original ~/.claude/tools/pain-memory/memory directory.

Repository

painmemory/
├── engine.py            # Layer 1: check() / retrieve() / write-back
├── embedder.py          # provider chain incl. zero-dep n-gram backend
├── judge.py             # independent LLM judge (OpenAI-compatible)
├── prefilter.py         # exit-code / stderr / hard-error detection
├── grower.py            # Layer 2: cluster → pattern rules
├── miner.py             # Layer 3: rules → principles
├── store.py             # JSON + npz persistence, per-project scoping
├── config.py            # defaults < toml < env < args
├── cli.py               # pm ...
└── adapters/
    ├── mcp_server.py    # stdio MCP server (stdlib-only JSON-RPC)
    ├── claude_code.py   # PostToolUse / UserPromptSubmit hooks
    └── exec_runner.py   # pm exec -- <any command>

examples/demo.py runs the whole loop offline — no API keys, no model downloads:

python examples/demo.py

Development

pip install -e .[dev]
pytest              # 45 tests, fully offline

Design history and the complete architecture document: DESIGN.md. Chinese readme: README.zh-CN.md.

License

MIT

About

Self-evolving pain memory for AI agents: detect tool-call failures, match past pain via local embedding, inject behavioral rules to avoid repeats.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages