agentcache / CLAUDE.md
Yash030's picture
feat: migrate agentmemory to agentcache namespace, endpoints, and tools
12a6c9a
|
Raw
History Blame Contribute Delete
4.87 kB
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What This Is
A Python REST + WebSocket + MCP memory server backed by SQLite. No Node.js, no Dolt. Agents use it to store observations scoped to `(folder_path, agent_id)` pairs and global long-term memories. The architecture is **folder-based** β€” sessions, lessons, slots, and actions are removed.
## Running
```bash
pip install -r requirements.txt
python src/app.py
# Server on http://localhost:3111
# Viewer at http://localhost:3111/viewer
```
No build step. SQLite file lives at `~/.agentcache/agentcache.db`. Config optionally loaded from `~/.agentcache/.env`.
## Running Tests
```bash
pip install -e ".[dev]"
pytest tests/ -v
```
## Key Environment Variables
| Variable | Default | Purpose |
|---|---|---|
| `III_REST_PORT` / `PORT` | `3111` | API server port |
| `GEMINI_API_KEY` / `GOOGLE_API_KEY` | β€” | Gemini vector search (priority 1) |
| `OPENAI_API_KEY` | β€” | OpenAI vector search (priority 2) |
| `AGENTCACHE_LOCAL_EMBEDDING_MODEL` | β€” | SentenceTransformer model (priority 3) |
| `AGENTCACHE_SECRET` | β€” | Bearer token auth on all endpoints |
| `AGENT_ID` | β€” | Default agent ID |
| `AGENTCACHE_AGENT_SCOPE=isolated` | β€” | Filter data to current `AGENT_ID` |
| `AGENTCACHE_CWD` | β€” | Fallback folder path for legacy clients |
| `MAX_OBS_PER_FOLDER` | `2000` | Hard cap on observations per (folder, agent) pair |
| `TOKEN_BUDGET` | `2000` | Context compilation cap |
| `GRAPH_EXTRACTION_ENABLED` | `false` | Knowledge graph extraction (needs LLM) |
| `CONSOLIDATION_ENABLED` | `false` | Memory consolidation (needs LLM) |
| `AGENTCACHE_AUTO_COMPRESS` | `false` | LLM-powered observation compression |
| `AGENTCACHE_CORS_ORIGINS` | see app.py | Comma-separated allowed CORS origins |
## Architecture
### `src/db.py` β€” Storage Layer
`StateKV` wraps SQLite with two tables:
- `kv_store(scope, key, value)` β€” all data as JSON, namespaced by scope
- `audit_log(id, ts, agent_id, message)` β€” write audit trail
Per-thread persistent connections via `threading.local()`. WAL checkpoint on shutdown.
Key scopes: `mem:folders` (index), `mem:folder:{path}:{agent}` (observations), `mem:foldermeta:{path}:{agent}` (metadata), `mem:obs_lookup` (O(1) reverse lookup), `mem:memories` (global), `mem:index:bm25:*` (search).
### `src/functions.py` β€” Business Logic
All core implementations. Key functions:
- `folder_observe(kv, payload)` β€” ingest a folder-scoped observation
- `folder_search(kv, query, limit, folder_path, agent_id)` β€” BM25+vector hybrid search
- `folder_timeline(kv, limit, folder_path, agent_id, before, after)` β€” activity feed
- `folder_graph_build(kv)` β€” build graph nodes + edges
- `remember(kv, data)` / `forget(kv, data)` β€” global memory management
- `health_check(kv)` β€” system stats
- `export_data(kv, data)` β€” v2 JSON export
- `migrate_sessions_to_folders(kv, dry_run)` β€” legacy migration
`src/memory/*` contains thin shim modules that re-export from here.
### `src/search.py` β€” Search Indexes
- `SearchIndex`: BM25 with Porter stemmer + synonym expansion. `_dirty` flag prevents unnecessary saves.
- `VectorIndex`: cosine similarity over embeddings as base64 float32. `_dirty` flag.
- `HybridSearch`: RRF fusion (k=60) of BM25 + vector.
- `GeminiEmbeddingProvider`, `OpenAIEmbeddingProvider`, `SentenceTransformerProvider`.
### `src/app.py` β€” Flask Factory
`create_app()`: init DB β†’ auto-select embedding provider β†’ init IndexPersistence β†’ backfill obs_lookup β†’ register blueprints β†’ setup WebSocket β†’ register CORS β†’ start background workers.
### `src/routes/` β€” Flask Blueprints
| Blueprint | Endpoints |
|-----------|-----------|
| `observations.py` | `/observe`, `/agent/observe`, `/folders`, `/folder/observations`, legacy session shims |
| `memories.py` | `/remember`, `/agent/remember`, `/memories`, `/forget` |
| `search.py` | `/search`, `/timeline` |
| `graph.py` | `/graph`, `/graph/stats`, `/graph/query`, `/graph/build` |
| `health.py` | `/livez`, `/health`, `/audit`, `/config/flags` |
| `mcp.py` | `/mcp/tools` GET+POST (12 tools) |
| `migration.py` | `/migrate` |
### `src/workers.py` β€” Background Threads
- Index rebuild thread (if BM25 index is empty or out of sync on boot)
- Auto-forget sweep loop (hourly)
- SIGTERM/SIGINT handlers: flush `IndexPersistence`, WAL checkpoint, exit 0
### `src/viewer/index.html` β€” Dashboard
Single-file HTML, served at `/viewer`. Tabs: **Folders**, **Memories**, **Graph**, **Timeline**. No build step.
## MCP Tools (12 active)
`agent_observe`, `agent_remember`, `memory_recall`, `memory_smart_search`, `memory_save`, `memory_export`, `memory_forget`, `memory_diagnose`, `memory_folders`, `memory_folder_observations`, `memory_timeline`
Full schema at `GET /agentcache/mcp/tools`.