Validated, private, shareable memory for your AI.
FaultLine adds persistent, validated memory to your local AI. Facts are stored in a structured knowledge graph — not summarised into text blobs, not guessed from documents. When you correct something, it updates. When you ask about it later, the answer is right.
Everything runs on your machine. Your conversations, your memories, your data — none of it leaves. No cloud sync, no accounts, no subscriptions.
FaultLine exposes an MCP server. That means the same memory store is available to OpenWebUI, Claude Desktop, or any other MCP-capable endpoint. Change your server IP in one conversation, every model sees the update.
RAG retrieves documents and asks the LLM to interpret them. The answer depends on wording, context, and luck. FaultLine validates facts before storing them and rejects hallucinations at the gate. Your AI knows "AlphaNode's IP is 10.44.5.20" — not "a document mentioned something about a server."
Facts are stored as typed relationships — person, age, occupation, network device, IP address, MAC, hostname. Corrections update the record cleanly; the old value is archived, not lost. Memory strengthens over time: things mentioned once are held lightly, confirmed facts become authoritative.
/expand networking teaches FaultLine how networking works before you mention your first device. /expand kubernetes online https://kubernetes.io/docs/concepts/ reads the actual docs and builds the ontology from them. You point it at the source, it learns the structure, and every fact you mention in that domain from then on is stored and retrieved in context — not as an isolated string. And everything it learns is still correctable by you.
You: "I'm a sysadmin. My main workstation is called DevBox, IP 10.0.1.5."
Next session:
You: "What do you know about DevBox?"
AI: "DevBox is your workstation, IP address 10.0.1.5."
You: "Actually DevBox moved to 10.0.1.10 after the network change."
Next session:
You: "What's DevBox's IP?"
AI: "DevBox has IP address 10.0.1.10."
You: /expand networking
Later, after mentioning your firewall:
AI: "Your firewall OPNsense is a networking device — I have that from earlier."
People, preferences, server IPs, MAC addresses, hostnames, relationships, corrections. Anything you tell it, stored and ready.
- Every message is scanned for facts worth keeping
- Facts go through a validation gate before storage — hallucinated details are rejected
- Relevant facts are injected into the conversation before the AI responds
- Memories strengthen with confirmation; corrections archive the old value cleanly
/expand <topic>teaches FaultLine how a domain is structured so facts about it land correctly
Most memory systems store facts. FaultLine can learn how a domain works — the structure, the relationships, the vocabulary — so that facts about it land correctly and mean something.
Without a domain expansion, "my firewall is OPNsense" is stored as a flat string. With /expand networking, FaultLine knows that a firewall is a type of network device, that it has IP addresses, that it sits between your LAN and WAN, and how it relates to switches, routers, and hosts. Every networking fact you mention after that is stored and retrieved in context.
The difference in practice:
Without /expand:
You: "OPNsense is at 10.0.0.1, the switch is at 10.0.0.2"
AI: "OPNsense has IP 10.0.0.1 and the switch has IP 10.0.0.2."
(two isolated facts, no relationship, no structure)
With /expand networking:
You: "OPNsense is at 10.0.0.1, the switch is at 10.0.0.2"
AI: "Your firewall OPNsense is at 10.0.0.1. Your switch is at 10.0.0.2,
downstream from it." (stored relationally — device types, roles, topology)
Point it at the actual documentation and it grounds the expansion in that material — not in what the LLM guesses the domain looks like:
/expand kubernetes online https://kubernetes.io/docs/concepts/
/expand tls online https://www.rfc-editor.org/rfc/rfc8446
/expand networking
/expand home lab
/expand kubernetes
Without a URL, it reasons from its training knowledge. With one, it reads the source and builds the ontology from it. You decide how authoritative you need it to be.
Everything /expand builds is subject to the same correction rules as any other fact. If it got the domain structure wrong, tell it — your correction wins and is stored as authoritative. The expansion is a starting point, not a constraint.
Expand once and every future conversation in that domain benefits automatically. New facts slot into the right relationships. Queries about that domain return structured, contextual answers instead of isolated strings. The more you use it, the more useful it gets.
| FaultLine | ChatGPT Memory | MemGPT / Letta | Mem0 | OpenWebUI RAG | |
|---|---|---|---|---|---|
| Self-hosted, fully private | ✅ | ❌ Cloud only | ✅ | ✅ | ✅ |
| Works with any local LLM | ✅ | ❌ OpenAI only | ✅ | ✅ | ✅ |
| MCP server — share across models | ✅ | ❌ | ❌ | Partial | ❌ |
| Write-validated (no hallucination storage) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Correctable — updates cleanly, archives old | ✅ | ❌ Overwrites | ❌ | ❌ | ❌ |
| Relational facts (not document chunks) | ✅ | ❌ | Partial | Partial | ❌ |
| Remembers server IPs, MACs, hostnames | ✅ | ❌ | ❌ | ❌ | ❌ |
| Remembers relationships & people | ✅ | ✅ | Partial | Partial | ❌ |
| Short → long-term promotion | ✅ | ❌ | Partial | ❌ | ❌ |
/expand topic learning |
✅ | ❌ | ❌ | ❌ | ❌ |
| Web-grounded learning | ✅ | ❌ | ❌ | ❌ | ❌ |
| Dead-naming / preferred name support | ✅ | ❌ | ❌ | ❌ | ❌ |
| Per-user private memory | ✅ | ✅ Account | ✅ | ✅ | ❌ Shared |
| Open source | ✅ Apache 2.0 | ❌ | ✅ MIT | Partial | ✅ MIT |
- Docker and Docker Compose
- OpenWebUI v0.9.5 or newer
- A local LLM via Ollama or LM Studio — Qwen2.5 recommended
- 8 GB RAM minimum, 16 GB recommended
git clone https://github.com/tkalevra/FaultLine.git
cd FaultLine
cp .env.example .env
# Open .env and point QWEN_API_URL at your Ollama or LM Studio endpoint
docker compose up -d
curl http://localhost:8000/health
# {"status": "ok", ...}The first start downloads the model used for extraction (~500 MB). Takes 3–5 minutes.
- Go to Workspace → Functions → + in OpenWebUI
- Paste the contents of
openwebui/faultline_function.py - Open Valves and set
FAULTLINE_URLtohttp://faultline:8000(orhttp://localhost:8000if not using Docker networking) - Enable the filter
Start a conversation — FaultLine begins learning immediately.
FaultLine's MCP server makes the same memory available to Claude Desktop or any MCP-capable client.
{
"mcpServers": {
"faultline": {
"url": "http://YOUR-HOST:8002/mcp",
"headers": { "Authorization": "Bearer YOUR_MCP_API_KEY" }
}
}
}Four tools: recall memory, store facts, retract facts, learn topic hierarchies — all backed by the same local store your OpenWebUI conversations write to.
# The two you'll almost certainly need to set
POSTGRES_DSN=postgresql://faultline:faultline@postgres:5432/faultline
QWEN_API_URL=http://host.docker.internal:11434/v1/chat/completions
# Everything else has sensible defaults
QDRANT_URL=http://qdrant:6333
MCP_API_KEY= # leave blank for no auth, or set a secret token
FAULTLINE_USER_ID= # optional — pins the MCP server to one user| File | What it is |
|---|---|
openwebui/faultline_function.py |
The OpenWebUI filter — drop this in and you're running |
src/api/main.py |
The backend API |
src/mcp/server.py |
The MCP tool server |
migrations/ |
Database schema — runs automatically on first start |
PostgreSQL · Qdrant · Redis · FastAPI · GLiNER2 · nomic-embed-text-v1.5 · OpenWebUI
Apache 2.0 — see LICENSE.
- New relationship types belong in the
rel_typesdatabase table, not in code - GLiNER2 zero-shot descriptions should never be modified to include extraction patterns
- No UUIDs in anything a user sees
- All tests pass:
pytest tests/