One memory layer. Every agent framework.
Works with
OpenClaw · Nanobot · ZeroClaw · NanoClaw · PicoClaw · Claude Code · Cursor · Qwen-Agent · DeerFlow · LangGraph
— any MCP-compatible runtime. One endpoint. Zero lock-in.
The autonomous era needs more than execution. Agents hallucinate facts. They drift from their values. They forget who they are. OpenStinger is the memory, reasoning, and alignment infrastructure that keeps them grounded — exposed as 30 MCP tools any agent calls natively.
Built on FalkorDB (bi-temporal graph + vector) and PostgreSQL (operational audit DB), served over Model Context Protocol. No SDK changes. No vendor lock-in.
OpenStinger works alongside any *Claw framework's built-in memory — or replaces it entirely. Three adoption modes, zero switching cost:
| Mode | How | When |
|---|---|---|
| Alongside | Both OpenStinger + native memory active. Agent has all tools. | Day 1 — add OpenStinger, change nothing |
| Primary | System prompt: query OpenStinger first, fall back to native if empty | After ~1,000 episodes are ingested |
| Exclusive | Disable native memory. OpenStinger is the only backend. | Full commitment — cleanest setup |
Start alongside. Go primary when ready. No framework migration required.
→ Full integration modes guide with per-framework configs
| Framework | MCP | Integration Guide |
|---|---|---|
| OpenClaw | ✅ via mcporter | View guide |
| DeerFlow | ✅ v0.7 adapter | View guide |
| Qwen-Agent | ✅ v0.7 adapter | View guide |
| LangGraph | ✅ MCP native | View guide |
| Nanobot | ✅ confirmed Feb 2026 | View guide |
| ZeroClaw | ✅ swappable trait | View guide |
| NanoClaw | ✅ Agent SDK native | View guide |
| PicoClaw | ✅ v0.8 | View guide |
| Claude Code | ✅ MCP native | Point at http://localhost:8766/sse |
| Cursor | ✅ MCP native | Point at http://localhost:8766/sse |
Three additive tiers. Start with Tier 1 and unlock the rest as data accumulates.
| Tier | Name | Tools | What it gives your agent |
|---|---|---|---|
| Tier 1 | Memory Harness | 11 | Bi-temporal episodic memory. Every session ingested automatically. Hybrid BM25 + vector semantic search. Date filtering. Numeric/IP search. Delete and update stored memories. |
| Tier 2 | StingerVault | 11 | Autonomous distillation of sessions into structured self-knowledge: identity, domain, methodology, preferences, constraints. External document ingestion (URL, PDF, YouTube). |
| Tier 3 | Gradient | 8 | Synchronous alignment evaluation before every response. Drift detection. Correction engine. 3 new observability tools (v0.7). Starts in observe-only mode. |
⚡ Tier 3 ships in
observe_onlymode. It evaluates every response and logs alignment scores — but never blocks or corrects anything until you switch it on. This is intentional: let it calibrate against real sessions first. Runopenstinger-cli progressto see readiness, then setobserve_only: falseinconfig.yamland restart.
Requirements: Python 3.10+, Docker Desktop, one API key (Anthropic or any OpenAI-compatible provider)
git clone https://github.com/srikanthbellary/openstinger.git
cd openstinger
python -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows (Git Bash)
source .venv/Scripts/activate
# Windows (cmd / PowerShell)
.venv\Scripts\activate
pip install -e "."cp .env.example .env
cp config.yaml.example config.yamlEdit .env — add your API keys:
# Anthropic (for LLM — entity extraction, dedup, conflict resolution)
ANTHROPIC_API_KEY=sk-ant-...
# OpenAI (for embeddings) — OR use any OpenAI-compatible provider
OPENAI_API_KEY=sk-...
# FalkorDB password — leave blank for local dev (simplest)
FALKORDB_PASSWORD=
# PostgreSQL password (used by docker compose)
POSTGRES_PASSWORD=your_postgres_password
⚠️ Password gotcha: If you setFALKORDB_PASSWORD, do NOT use#in it..envfiles treat#as a comment —myPass#2026becomesmyPass. Use only alphanumeric characters:myPass2026is safe.
Edit config.yaml — the only required change:
ingestion:
sessions_dir: "/path/to/your/agent/sessions" # path to your agent's JSONL session filesdocker compose up -dTier 1 only (memory, 11 tools):
python -m openstinger.mcp.serverAll tiers (memory + vault + alignment, 30 tools):
python -m openstinger.gradient.mcp.serverOpenStinger speaks MCP over SSE. The config is identical across all supported frameworks:
{
"mcpServers": {
"openstinger": {
"baseUrl": "http://localhost:8766/sse"
}
}
}See integrations/ for framework-specific setup guides (OpenClaw, DeerFlow, Qwen-Agent, LangGraph, Nanobot, ZeroClaw, NanoClaw, PicoClaw).
Then your agent can call:
mcporter call openstinger.memory_query \
--args '{"query": "what did we work on last week", "limit": 5}'OpenStinger works with any OpenAI-compatible API for both LLM and embeddings — no OpenAI account required.
# config.yaml
llm:
provider: openai
model: deepseek/deepseek-v3.2
llm_base_url: "https://api.novita.ai/v3/openai"
embedding_model: qwen/qwen3-embedding-8b
embedding_provider: openai
embedding_base_url: "https://api.novita.ai/v3/openai"Set OPENAI_API_KEY in .env to your Novita (or other) API key.
Run embeddings entirely on-device — no cloud API key, no network calls, no cost per token. Full local operation for air-gapped environments or privacy-sensitive deployments.
Supported models:
| Model | Dimensions | Pull command |
|---|---|---|
nomic-embed-text |
768 | ollama pull nomic-embed-text |
mxbai-embed-large |
1024 | ollama pull mxbai-embed-large |
all-minilm |
384 | ollama pull all-minilm |
Setup via interactive init (recommended):
openstinger-cli init
# → When prompted for "Embedding provider", select "ollama"
# → Select model — dimensions are auto-populatedOr configure manually in config.yaml:
llm:
embedding_provider: ollama
embedding_model: nomic-embed-text
ollama_host: http://localhost:11434 # default; change if Ollama runs elsewhere
falkordb:
vector_dimensions: 768 # must match the model's native output sizeIn .env, set OPENAI_API_KEY=ollama (the client requires a non-empty value; Ollama ignores it):
OPENAI_API_KEY=ollamaBreaking change warning:
vector_dimensionsmust match the embedding model's native output size. If you switch models after data has been ingested, you must wipe and re-create the FalkorDB vector indices:docker compose down -v && docker compose up -dThen re-ingest your sessions. Embeddings from different dimension sizes are not compatible.
| Tool | What it does |
|---|---|
memory_add |
Store an episode manually |
memory_query |
Hybrid BM25 + vector search. Returns unified ranked results. Supports after_date / before_date. |
memory_search |
Smart keyword search with automatic fallbacks: numeric/IP detection, temporal queries, fuzzy entity matching |
memory_get_entity |
Fetch an entity and its current relationships by UUID |
memory_get_episode |
Fetch a specific episode by UUID |
memory_job_status |
Check ingestion job status |
memory_ingest_now |
Trigger immediate session ingestion |
memory_namespace_status |
Health stats: episode / entity / edge counts |
memory_list_agents |
List all registered agent namespaces |
memory_delete |
Permanently delete an episode and prune orphaned entities (v0.8) |
memory_update |
Update episode content and re-index with new embedding (v0.8) |
vault_status · vault_sync_now · vault_stats · vault_promote_now · vault_note_list · vault_note_get · knowledge_ingest · namespace_create · namespace_list · namespace_archive
| Tool | What it does |
|---|---|
gradient_status |
Gradient health, profile state, observe_only flag |
gradient_alignment_score |
Evaluate a response — returns score + verdict |
gradient_drift_status |
Rolling window alignment stats |
gradient_alignment_log |
Recent alignment evaluation log |
gradient_alert |
Current drift alert status |
ops_status ⭐ |
Single-call dashboard: vault notes + gradient pass rate + drift state |
gradient_history ⭐ |
Last N alignment verdicts with scores from PostgreSQL |
drift_status ⭐ |
Behavioral window drift history from PostgreSQL |
ops_status — what one call returns:
{
"vault": {
"total_notes": 42,
"active_notes": 38,
"stale_notes": 4,
"categories": ["IDENTITY", "EXPERTISE", "BOUNDARY", "PREFERENCE"]
},
"gradient": {
"profile_loaded": true,
"observe_only": true,
"pass_rate_7d": 0.94,
"drift_alert": false,
"last_evaluated": "2026-02-28T06:44:12Z"
},
"memory": {
"total_episodes": 1847,
"entities_known": 63,
"last_ingested": "2026-02-28T06:40:00Z"
}
}memory_query(query="Quinn was fired")
# Finds episodes containing "Quinn terminated", "Quinn dismissed", etc.memory_query(query="trading decisions", after_date="2026-02", before_date="2026-03")
memory_search(query="bot crash", search_type="episodes", after_date="2026-02-15")memory_search(query="203.0.113.42") # IP address — CONTAINS fallback auto-triggered
memory_search(query="$50 funding round") # prices/amounts
memory_search(query="wallet 0xDeadBeef") # hex/wallet addressesmemory_search(query="Qinn", search_type="entities")
# Finds "Quinn" via vector similarity fallback when BM25 returns nothingOpenStinger runs beside your agent — never inside it. Your agent calls MCP tools. OpenStinger reads session files in the background.
OpenClaw's built-in memory system and the broader ecosystem of agent memory services each solve part of the problem. OpenStinger uses a different approach for a different set of guarantees. Three concrete differences:
- One stack, not many. Other memory services typically require multiple separate components — a graph store, a separate embedding service, and your own reporting layer stitched together. OpenStinger ships as two containers (FalkorDB + PostgreSQL) with everything included and unified.
- SQL-queryable operational database. Every ingestion job, entity merge, vault classification, and alignment event is logged to PostgreSQL. OpenClaw's native memory and most other services have no equivalent audit trail. Connect any BI tool — Metabase, Grafana, Superset — with zero additional instrumentation.
- Alignment evaluation that survives memory compaction. OpenClaw's
SOUL.mdis a static file injected at session start. If compaction or context pruning drops it mid-session, alignment is gone. OpenStinger's Gradient evaluates every response against the agent's own vault-derived profile — it survives any context operation.
Broader ecosystem reference: Mem0, Graphiti, Cognee, Zep — each with different tradeoffs.
OpenClaw ──┐
Nanobot ──┤
ZeroClaw ──┤
NanoClaw ──┼── MCP / SSE · http://localhost:8766/sse
PicoClaw ──┤
DeerFlow ──┤ ▼
Qwen-Agent ──┤ OpenStinger MCP Server (Python · port 8766)
LangGraph ──┤
Claude Code ──┤
Cursor ──┘
├── Tier 1 memory_query · memory_add ··········· 11 tools
├── Tier 2 vault_promote_now · vault_note_get 11 tools
└── Tier 3 gradient_alignment_score · ops_status 8 tools
│ ─────────────────
│ 30 tools total
├── FalkorDB (graph · vectors · episodic memory)
├── PostgreSQL (jobs · alignment events · registry)
└── vault/ (notes · SHA-256 synced · auditable)
Session files are read-only. OpenStinger never writes to your agent's files.
OpenClaw format (session_format: openclaw):
OpenStinger parses OpenClaw v3 JSONL files, extracting user messages and assistant responses. Thinking blocks, tool calls, and metadata are skipped.
DeerFlow format (session_format: deerflow):
OpenStinger parses DeerFlow 2.0 thread.json conversation files via the DeerFlowSessionReader adapter (v0.7+). Configure sessions_dir to point at your DeerFlow project's threads/ directory.
Qwen-Agent format (session_format: qwen_agent):
OpenStinger parses Qwen-Agent JSONL session files written by QwenSessionWriter (v0.7+). Each file is a per-session conversation log. Configure sessions_dir to match the session_dir path in your OpenStingerQwenAgent config.
Simple format (session_format: simple):
One JSON object per line — works with any runtime that can write JSONL:
{"content": "conversation text here", "source": "conversation", "valid_at": 1234567890}| URL | Tool | Start command |
|---|---|---|
http://localhost:3000 |
FalkorDB Browser (visual graph) | docker compose up -d (auto-starts) |
http://localhost:8080 |
Adminer (PostgreSQL inspector) | docker compose up -d (auto-starts) |
FalkorDB Browser login: host host.docker.internal · port 6379 · password: whatever you set in .env (blank = no password)
Adminer login: System: PostgreSQL · Server: host.docker.internal · Username/Password/Database: use values from your .env and config.yaml
Use
host.docker.internalNOTlocalhost— both UIs run inside Docker.
Tier 1 python -m openstinger.mcp.server ← start here
↓ (~1,000+ episodes ingested — usually 1–2 days)
Tier 2 python -m openstinger.scaffold.mcp.server ← vault activates
↓ (vault builds identity + constraint notes — ~1–2 weeks)
Tier 3 python -m openstinger.gradient.mcp.server ← alignment activates (observe-only first)
Each tier includes all lower tiers. Running Tier 3 gives you all 30 tools.
agent_name: main # your agent's name
agent_namespace: main # namespace for graph isolation
falkordb:
host: localhost
port: 6379
password: "" # leave blank for local dev
operational_db:
provider: postgresql # postgresql (default, v0.6+) | sqlite
postgresql_url: "postgresql+asyncpg://your_user:your_password@localhost:5432/your_db"
# sqlite_path: ".openstinger/openstinger.db" # uncomment to use SQLite instead
llm:
provider: anthropic # anthropic | openai (for OpenAI-compatible)
model: claude-sonnet-4-6
fast_model: claude-haiku-4-5-20251001
embedding_model: text-embedding-3-small
# For Novita / DeepSeek / other OpenAI-compatible:
# provider: openai
# llm_base_url: "https://api.novita.ai/v3/openai"
# embedding_base_url: "https://api.novita.ai/v3/openai"
ingestion:
sessions_dir: "/path/to/sessions" # REQUIRED: path to your agent's JSONL session files
session_format: openclaw # openclaw | simple
poll_interval_seconds: 10
concurrency: 5 # parallel episode processing (v0.5+)
vault: # Tier 2
classification_interval_seconds: 300
gradient: # Tier 3
enabled: false
observe_only: true # always start in observe mode
mcp:
transport: sse # sse (recommended) | stdio
tcp_port: 8766 # default production port (8765 may be reserved on Windows)Server exits immediately after starting
Check the log (.openstinger/openstinger.log). Common causes:
- FalkorDB not reachable: verify
docker ps | grep falkordband test withdocker exec openstinger_falkordb redis-cli ping - Port in use: change
mcp.tcp_portinconfig.yamlto a free port
FalkorDB password issue
If you set FALKORDB_PASSWORD in .env and FalkorDB starts without auth anyway, the password contains #. Rename the password to avoid # characters and recreate the container:
docker compose down
docker volume rm openstinger_falkordb_data
docker compose up -dPort already in use (WinError 10048 / 10013) Windows may have the port reserved (Hyper-V, elevated process). Simply use a different port:
mcp:
tcp_port: 8766 # or 8767, 8768 — whatever is freeUpdate your MCP client config to match.
Semantic search not working ("fired" doesn't find "terminated")
memory_query (not memory_search) runs vector search. Use memory_query for semantic recall. All episodes ingested with v0.4+ have vector embeddings.
"February 2026" returns nothing
Use the after_date / before_date parameters in memory_query:
memory_query(query="decisions", after_date="2026-02", before_date="2026-03")Episodes from v0.4+ also have valid_at_human BM25-indexed for date keyword search.
# Without FalkorDB (fast)
pytest tests/ -m "not integration"
# Full suite (FalkorDB must be running)
pytest tests/
# Specific tier
pytest tests/ -m tier1
pytest tests/ -m tier2
pytest tests/ -m tier336+ tests passing across all tiers.
OpenStinger is the only *Claw-compatible memory system with a queryable operational database.
Every episode, entity, classification decision, and alignment event is logged to PostgreSQL — ready for dashboards, audits, and compliance reports. Not exported on request. Always on. Always queryable.
Connect any BI tool — Metabase, Grafana, Superset, or psql — and get full operational visibility with zero additional instrumentation. OpenStinger logs everything to a 12-table schema from the moment it starts.
-- Who has this agent's memory touched? (PII / people audit)
SELECT name, entity_type, episode_count
FROM entity_registry
WHERE entity_type = 'PERSON'
ORDER BY episode_count DESC;
-- Alignment verdict distribution this week
SELECT verdict, COUNT(*) AS count
FROM alignment_events
WHERE evaluated_at > EXTRACT(EPOCH FROM NOW() - INTERVAL '7 days')
GROUP BY verdict;
-- Knowledge confidence by category (vault health)
SELECT category,
COUNT(*) FILTER (WHERE stale = false) AS active_notes,
ROUND(AVG(confidence)::numeric, 2) AS avg_confidence
FROM vault_notes GROUP BY category;
-- Episode volume per day (ingestion health)
SELECT DATE(TO_TIMESTAMP(created_at)) AS day, COUNT(*) AS episodes
FROM episode_log GROUP BY day ORDER BY day DESC LIMIT 7;Adminer (bundled in
docker compose) gives a point-and-click interface to every table athttp://localhost:8080.
Your agent changes. The memory doesn't have to.
OpenStinger stores everything in two Docker volumes:
falkordb_data— the temporal knowledge graph: all entities, relationships, episodespostgres_data— the operational database: vault notes, alignment events, registry
Both are standard Docker volumes. Export, move, import — full memory transfers to a new host, a new runtime, or a new cloud provider. The agent framework is irrelevant because memory is decoupled from it.
# FalkorDB snapshot (atomic — run first)
docker exec openstinger_falkordb redis-cli BGSAVE
# Export both volumes
docker run --rm -v openstinger_falkordb_data:/data -v $(pwd):/backup \
alpine tar czf /backup/falkordb.tar.gz /data
docker run --rm -v openstinger_postgres_data:/data -v $(pwd):/backup \
alpine tar czf /backup/postgres.tar.gz /datadocker run --rm -v openstinger_falkordb_data:/data -v $(pwd):/backup \
alpine tar xzf /backup/falkordb.tar.gz -C /
docker run --rm -v openstinger_postgres_data:/data -v $(pwd):/backup \
alpine tar xzf /backup/postgres.tar.gz -C /
docker compose up -d # starts with full memory intact| Scenario | Result |
|---|---|
| Agent migration | Move from Mac Mini to cloud VM — full memory, vault, alignment history preserved |
| Runtime swap | Switch from OpenClaw to NanoClaw — OpenStinger memory transfers completely |
| Agent cloning | Snapshot production into dev — test against real accumulated knowledge |
| Multi-agent bootstrap | Clone a senior agent's vault into a new specialist — starts with wisdom, not zero |
| Emergency recovery | Host fails — restore volumes on any new machine, agent resumes |
| Memory rollback | Snapshot before risky vault changes — restore if classification results degrade |
No other *Claw memory system separates memory from the runtime cleanly enough to make this possible.
OpenStinger runs anywhere Python and Docker run. Deploy on a cloud VM and all your agents — on-prem, edge devices, other cloud instances — connect via MCP SSE.
[Mac Mini agent] ──HTTP SSE──►
[EC2 agent] ──HTTP SSE──► OpenStinger (cloud VM · port 8766)
[PicoClaw on $10 device] ──HTTP SSE──►
[NanoClaw swarm agent] ──HTTP SSE──►
For remote agents that generate session files locally, use the memory_add MCP tool to write episodes directly — no local file path required.
MIT — see LICENSE
