Metadata-Version: 2.4
Name: context-vault-ai
Version: 0.6.1
Summary: A temporal, governed context layer for agentic AI systems — bitemporal, attributed, permissioned Claims.
Project-URL: Homepage, https://github.com/RajdeepDas43/context-graph-vault
Project-URL: Documentation, https://github.com/RajdeepDas43/context-graph-vault/blob/main/docs/SPEC.md
Project-URL: Repository, https://github.com/RajdeepDas43/context-graph-vault
Project-URL: Issues, https://github.com/RajdeepDas43/context-graph-vault/issues
Project-URL: Changelog, https://github.com/RajdeepDas43/context-graph-vault/blob/main/CHANGELOG.md
Author: Paramind AI
License: MIT
License-File: LICENSE
Keywords: agent-memory,audit,bitemporal,context,governance,mcp,rag
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Requires-Python: >=3.11
Requires-Dist: anthropic>=0.40
Requires-Dist: httpx>=0.27
Requires-Dist: numpy>=1.26
Requires-Dist: pydantic>=2.6
Provides-Extra: agent-framework
Requires-Dist: agent-framework-core>=1.0; extra == 'agent-framework'
Provides-Extra: api
Requires-Dist: fastapi>=0.110; extra == 'api'
Requires-Dist: uvicorn>=0.29; extra == 'api'
Provides-Extra: audit-encryption
Requires-Dist: cryptography>=42; extra == 'audit-encryption'
Provides-Extra: audit-kms
Requires-Dist: boto3>=1.34; extra == 'audit-kms'
Requires-Dist: cryptography>=42; extra == 'audit-kms'
Provides-Extra: claude-agent-sdk
Requires-Dist: claude-agent-sdk>=0.2; extra == 'claude-agent-sdk'
Provides-Extra: confluence
Requires-Dist: atlassian-python-api>=3.41; extra == 'confluence'
Provides-Extra: crewai
Requires-Dist: crewai>=1.0; extra == 'crewai'
Provides-Extra: dev
Requires-Dist: asn1crypto>=1.5; extra == 'dev'
Requires-Dist: cryptography>=42; extra == 'dev'
Requires-Dist: filelock>=3.12; extra == 'dev'
Requires-Dist: httpx>=0.27; extra == 'dev'
Requires-Dist: hypothesis>=6.0; extra == 'dev'
Requires-Dist: pyjwt[crypto]>=2.8; extra == 'dev'
Requires-Dist: pytest-split>=0.10; extra == 'dev'
Requires-Dist: pytest-xdist>=3.5; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Provides-Extra: embeddings
Requires-Dist: sentence-transformers>=2.6; extra == 'embeddings'
Provides-Extra: federation
Requires-Dist: httpx>=0.27; extra == 'federation'
Requires-Dist: psycopg-pool>=3.2; extra == 'federation'
Requires-Dist: psycopg[binary]>=3.1; extra == 'federation'
Provides-Extra: langgraph
Requires-Dist: langchain-core>=0.3; extra == 'langgraph'
Requires-Dist: langgraph-checkpoint>=2.0; extra == 'langgraph'
Provides-Extra: llamaindex
Requires-Dist: llama-index-core>=0.12; extra == 'llamaindex'
Provides-Extra: mcp
Requires-Dist: mcp>=1.2; extra == 'mcp'
Provides-Extra: oidc
Requires-Dist: httpx>=0.27; extra == 'oidc'
Requires-Dist: pyjwt[crypto]>=2.8; extra == 'oidc'
Provides-Extra: redis
Requires-Dist: redis>=5.0; extra == 'redis'
Provides-Extra: self-host
Requires-Dist: neo4j>=5.26; extra == 'self-host'
Requires-Dist: psycopg-pool>=3.2; extra == 'self-host'
Requires-Dist: psycopg[binary]>=3.1; extra == 'self-host'
Provides-Extra: telemetry-collector
Requires-Dist: fastapi>=0.110; extra == 'telemetry-collector'
Requires-Dist: psycopg[binary]>=3.1; extra == 'telemetry-collector'
Requires-Dist: uvicorn>=0.29; extra == 'telemetry-collector'
Provides-Extra: tsa
Requires-Dist: asn1crypto>=1.5; extra == 'tsa'
Requires-Dist: cryptography>=42; extra == 'tsa'
Description-Content-Type: text/markdown

# Context Vault

_by Paramind AI_

<!-- mcp-name: io.github.RajdeepDas43/context-vault -->

[![PyPI](https://img.shields.io/pypi/v/context-vault-ai)](https://pypi.org/project/context-vault-ai/)
[![PyPI downloads](https://img.shields.io/pypi/dm/context-vault-ai)](https://pypistats.org/packages/context-vault-ai)
[![npm](https://img.shields.io/npm/v/context-vault-sdk)](https://www.npmjs.com/package/context-vault-sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue)](https://pypi.org/project/context-vault-ai/)

**Governed memory for AI agents** — every fact is stored as a versioned, time-bound, access-controlled, auditable claim. Agents retrieve what is *current*, *permitted*, and *traceable*. Conflicting facts are detected and reconciled, not silently overwritten.

> Other memory systems help your agent *remember more*.  
> Context Vault makes sure it remembers **what's true, what it's allowed to know, and proves what it knew**.

---

## Try it right now — no databases, no API key

```bash
pip install context-vault-ai
uvx --from context-vault-ai context-vault demo
```

That's it. The full governed-memory tour runs completely offline, in-memory, no setup required. You'll see conflict detection, time-travel queries, and the audit trail in action.

---

## Table of Contents

- [What it does](#what-it-does)
- [How it works](#how-it-works)
- [Installation](#installation)
- [Level 1 — Python (two minutes, no infrastructure)](#level-1--python-two-minutes-no-infrastructure)
- [Two memory models — don't reuse an id across them](#two-memory-models--dont-reuse-an-id-across-them)
- [Level 2 — Durable store + full Python SDK](#level-2--durable-store--full-python-sdk)
- [Level 3 — HTTP REST API](#level-3--http-rest-api)
- [Level 4 — MCP server (Claude, Cursor, any MCP client)](#level-4--mcp-server-claude-cursor-any-mcp-client)
- [Level 5 — Framework adapters](#level-5--framework-adapters)
- [Level 6 — Full self-hosted deployment (Docker)](#level-6--full-self-hosted-deployment-docker)
- [Level 7 — TypeScript / JavaScript SDK](#level-7--typescript--javascript-sdk)
- [Key concept: Claims and conflict detection](#key-concept-claims-and-conflict-detection)
- [Configuration reference](#configuration-reference)
- [CLI reference](#cli-reference)
- [Links](#links)

---

## What it does

Most AI memory systems are retrieval caches — smarter lookups over stored text. Context Vault is a **governed context graph**: every write goes through conflict detection, every fact carries a time window and an access label, and every operation is logged to a tamper-evident audit trail.

**Five operations — nothing outside them:**

| Operation | What it does |
|---|---|
| **Assert** | Write a new fact. Automatically checks for contradictions, supersessions, duplicates, and refinements against existing facts. Never silently overwrites. |
| **Resolve** | Read facts relevant to a query at a point in time, scoped to what the caller is allowed to see. Answers like "what did we believe about Priya on March 1st?" |
| **Reconcile** | Route conflicting facts to human review or auto-resolve by policy (recency, trust, confidence). |
| **Decay** | Age out or compress stale facts according to per-type policies. |
| **Audit** | Replay exactly what any principal saw at any time. Tamper-evident and exportable. |

**What you get out of the box:**
- Conflict detection with a 6-way taxonomy (not just "conflict / no conflict")
- Bitemporal queries: *valid time* (when a fact was true in the world) + *system time* (when you learned it)
- Deny-by-default access control — unlabeled facts are private to their asserter
- An immutable, tamper-evident audit log
- Multi-tenant workspaces — agents share nothing unless explicitly permitted
- GDPR erase: redact + archive, never hard-delete

---

## How it works

Every write is checked against what you already know: a new fact is classified against existing ones — contradiction, supersession, refinement, duplicate, independent, or unsure — *before* it is stored, so nothing is silently overwritten. Every fact carries a validity window (when it is true) and an access label (who may see it), and every operation is recorded to an immutable, tamper-evident audit trail. Reads return only what is currently true, permitted for the caller, and reconstructable at any past point in time.

---

## Installation

```bash
# Core — the engine, in-memory store, CLI demo. ~40 MB, no compile step.
pip install context-vault-ai

# With durable storage (Neo4j + Postgres)
pip install "context-vault-ai[self-host]"

# With the HTTP API server
pip install "context-vault-ai[api]"

# With the MCP server
pip install "context-vault-ai[mcp]"

# Everything you need to self-host the full stack
pip install "context-vault-ai[self-host,api,mcp]"

# With semantic embeddings (sentence-transformers; pulls PyTorch)
pip install "context-vault-ai[embeddings]"
```

**Which extras do you need?**

| You want to… | Extra |
|---|---|
| Try the offline demo | *(none — core only)* |
| Store facts in Python scripts (ephemeral) | *(none — uses in-memory store)* |
| Store facts durably (Neo4j + Postgres) | `self-host` |
| Run the REST API / serve over HTTP | `api` |
| Use the MCP server in Claude / Cursor | `mcp` |
| Semantic recall / KB-quality vector search | `embeddings` |
| Cluster-wide rate limiting | `redis` |
| Front an existing vector store (Qdrant, pgvector) | `federation` |
| LangGraph / LangChain integration | `langgraph` |
| CrewAI integration | `crewai` |
| LlamaIndex integration | `llamaindex` |
| Claude Agent SDK integration | `claude-agent-sdk` |
| OIDC / SSO | `oidc` |
| GDPR crypto-shred of audit payloads | `audit-encryption` |
| GDPR crypto-shred with a managed KMS (AWS) | `audit-kms` |

> **Recall quality needs `[embeddings]`.** Semantic (sentence-transformer) ranking — what makes
> `recall` and knowledge-base retrieval find the *right* facts — only runs when the `embeddings` extra
> is installed. The common `[self-host]` / `[api]` / `[mcp]` installs and the zero-DB MCP trial fall
> back to a deterministic **hash** embedder (lexical, offline, no PyTorch). Resolve results carry an
> `embedder` field (`"sentence-transformer"` vs `"hash"`) so you can tell which one ranked an answer.

---

## Level 1 — Python (two minutes, no infrastructure)

Install the core package. No databases, no API key required for the structured write path.

```python
import os
# set BEFORE importing context_vault (config is read at import):
os.environ.setdefault("VAULT_STORE", "memory")    # ephemeral in-memory store, no DB server
os.environ.setdefault("VAULT_EMBEDDER", "hash")   # offline embedder — no model download

from context_vault import Memory

m = Memory()

# Assert a structured fact (no API key needed). assert_claim_from takes the PRINCIPAL first
# (m.principal(user) is the read-only handle for that user), then subject, predicate, object.
me = m.principal("my-agent")
m.vault.assert_claim_from(me, "Priya", "job title", "VP of Sales")

# Resolve — asks "what do we know about Priya's job title right now?"
results = m.recall("what is Priya's job title?", user="my-agent")
print(results)
# → "- (Priya) --[job title]--> (VP of Sales) ..."

# Forget — archives the fact, never deletes it
m.forget("job title", user="my-agent")
```

> **Offline, you get the governed *shape*** — every fact is a time-bound, conflict-checked,
> auditable claim, recalled correctly across time on a tamper-evident log. **Measured correctness
> needs a key:** the 0.0% silent-corruption number is the **Claude judge**'s; offline the rule-based
> **heuristic** judge gives the governance shape, not that measured rate.

**With an Anthropic API key** — unlock free-text `remember` (the LLM extracts structured facts) and the measured-correctness LLM judge:

```python
import os
os.environ["ANTHROPIC_API_KEY"] = "sk-ant-..."
os.environ["VAULT_STORE"] = "memory"

from context_vault import Memory

m = Memory()
m.remember("Priya joined the enterprise plan and prefers Slack", user="priya")
print(m.recall("how should I contact Priya?", user="priya"))
```

**Conflict detection in action (keyless — the structured path):**

```python
agent = m.principal("agent")
m.vault.assert_claim_from(agent, "Alice", "works at", "Acme Corp")
m.vault.assert_claim_from(agent, "Alice", "works at", "Beta Inc")
# ↑ The second assert is automatically classified against the first by the conflict detector
# → no silent overwrite; the history is preserved and the current truth is governed
```

> The in-memory store is ephemeral — data is lost when the process exits. For durable storage, see Level 2.

---

## Two memory models — don't reuse an id across them

Context Vault exposes the same engine through **two principal models**. Pick one per identity; they are designed for different jobs:

| Model | Entry points | Principal semantics | Use it for |
|---|---|---|---|
| **Two-verb (private memory)** | `Memory` · `remember` / `recall` / `forget` (and the MCP `remember`/`recall` tools) | Each `user` is its **own private principal with empty labels** — deny-by-default, visible only to itself | Single-user / single-agent memory where nothing is shared |
| **Governed (team-shared, ACL'd)** | `context_vault.vault.Vault` · `VaultClient` · the MCP `vault_register_principal` tool with `visibility=[...]` | A principal you register **with labels / workspaces** — facts are shared across whoever holds a matching label | Team-shared knowledge, multi-agent governance, cross-tenant scoping |

As of **v0.5.1** the two models **compose safely**: the two-verb path is GET-OR-CREATE — if an id is already registered on the governed path (with labels/workspaces), `remember`/`recall` **adopt** that principal rather than clobbering it to empty labels. Still, the mental model matters: a `user` you only ever touch through `remember`/`recall` stays **private**. If you *want* a fact to be team-visible, register that principal on the governed path with `visibility` labels — don't expect the two-verb path to widen its audience for you.

---

## Level 2 — Durable store + full Python SDK

Start Neo4j and Postgres (one command), then use the full SDK:

```bash
docker compose up -d       # Neo4j on 7474/7687, Postgres on 5433
```

**Entry points.** `build_vault()` (from `context_vault.app`) constructs a wired `Vault`; the governed orchestrator class is `context_vault.vault.Vault`. The one-import `Memory` façade is the *only* thing exported at the top level (`from context_vault import Memory`) — `from context_vault import Vault` is intentionally **not** exported, because the governed `Vault` is meant to be built through `build_vault()` (or constructed explicitly), not imported as a bare class.

**Clean shutdown.** A durable `build_vault()` holds a Postgres connection pool; close it or interpreter exit stalls ~20s with "couldn't stop thread" warnings. Use it as a context manager (`with build_vault() as v:`) or call `v.close()` in a `finally` (both are no-ops on the in-memory trial backend):

```python
from context_vault.app import build_vault

with build_vault() as vault:   # auto-closes the pool on exit
    vault.init()
    ...
```

```python
from datetime import datetime, timezone

from context_vault.app import build_vault
from context_vault.sdk import VaultClient
from context_vault.models.principal import Principal

# Build the vault (connects to Neo4j + Postgres via env vars or defaults)
vault = build_vault()
vault.init()

# Create a principal (an agent identity with access labels)
principal = Principal(id="agent-sales", role="agent", labels=["team:sales"])

# Use the typed SDK client
client = VaultClient(vault, principal)

# Assert a time-bound fact — valid from 2024-01-01 onwards
client.assert_fact(
    subject="Priya",
    predicate="account tier",
    obj="Enterprise",
    valid_from=datetime(2024, 1, 1, tzinfo=timezone.utc),
)

# Resolve — ask a natural-language question, get ranked facts back
for claim in client.resolve("what tier is Priya on?"):
    print(claim.edge_str())
    # → Priya --[account tier]--> Enterprise  (2024-01-01 → open)

# Time-travel: what did we believe on 2023-12-01?
for claim in client.resolve("what tier is Priya on?", as_of=datetime(2023, 12, 1, tzinfo=timezone.utc)):
    print(claim.edge_str())
    # → (empty — fact wasn't asserted until 2024-01-01)
```

**Assert a structured claim directly:**

```python
from context_vault.models.claim import Claim
from datetime import datetime, timezone

# Construct the Claim, then assert it (Claim + Principal + transaction-time ts)
claim = Claim(
    subject="acme-contract-2025",
    predicate="renewal date",
    object="2025-09-30",
    valid_from=datetime(2025, 1, 1, tzinfo=timezone.utc),
    valid_to=datetime(2026, 1, 1, tzinfo=timezone.utc),
)
vault.assert_claim(claim, principal, ts=datetime(2025, 1, 1, tzinfo=timezone.utc))
```

**Audit replay — what did agent-sales see on March 1st?**

```python
log = vault.audit_replay(principal, as_of="2025-03-01")
for entry in log:
    print(entry)
```

---

## Level 3 — HTTP REST API

The HTTP API is the most complete interface — it includes auth, multi-tenancy, conflict detection, admin console, and a governance UI.

**Start the server:**

```bash
pip install "context-vault-ai[self-host,api]"
docker compose up -d                               # Neo4j + Postgres
uvicorn context_vault.http_api:app --port 8000     # API server
```

Or with the CLI:

```bash
context-vault serve --port 8000
```

**Sign up and get an API key (no admin dance):**

```bash
# Sign up — creates your org + admin account, returns a cv_... API key (shown once)
KEY=$(curl -s -X POST http://localhost:8000/signup \
  -H "content-type: application/json" \
  -d '{"org":"Acme","username":"admin@acme.test","password":"<choose-a-strong-password>"}' \
  | python -c 'import sys,json; print(json.load(sys.stdin)["api_key"])')

echo "Your key: $KEY"
```

**Assert a fact:**

```bash
curl -X POST http://localhost:8000/assert \
  -H "authorization: Bearer $KEY" \
  -H "content-type: application/json" \
  -d '{
    "subject": "Priya",
    "predicate": "lives in",
    "object": "London",
    "valid_from": "2024-06-01"
  }'
```

**Resolve — time- and permission-aware query:**

```bash
curl -X POST http://localhost:8000/resolve \
  -H "authorization: Bearer $KEY" \
  -H "content-type: application/json" \
  -d '{"query": "where does Priya live?", "as_of": "2026-06-01"}'
```

**Get a profile — everything known about a subject:**

```bash
curl "http://localhost:8000/profile?subject=Priya" \
  -H "authorization: Bearer $KEY"
```

**Mint a key for a new agent under your tenant:**

```bash
curl -X POST http://localhost:8000/keys \
  -H "authorization: Bearer $KEY" \
  -H "content-type: application/json" \
  -d '{"name": "agent-a", "labels": []}'
```

**Admin console:** open `http://localhost:8000/admin` in a browser — full governance UI with a live conflict detector, claims graph, audit chain viewer, and reconciliation queue.

**Ask UI (non-technical users):** open `http://localhost:8000/ask` — a plain-language interface for asking questions and adding facts, no code required.

**Full API reference:** every endpoint is documented at `http://localhost:8000/docs` (OpenAPI/Swagger).

---

## Level 4 — MCP server (Claude, Cursor, any MCP client)

Context Vault ships a full MCP server. Add it to Claude Desktop, Claude Code, or Cursor to give your AI assistant governed, time-aware memory.

**Add to your MCP config (Claude Desktop or Cursor):**

```json
{
  "mcpServers": {
    "context-vault": {
      "command": "uvx",
      "args": ["--from", "context-vault-ai[mcp]", "context-vault-mcp"]
    }
  }
}
```

For Claude Code, add this to `.mcp.json` in your project root.

**With an Anthropic API key** (enables free-text `remember`):

```json
{
  "mcpServers": {
    "context-vault": {
      "command": "uvx",
      "args": ["--from", "context-vault-ai[mcp]", "context-vault-mcp"],
      "env": {
        "ANTHROPIC_API_KEY": "sk-ant-..."
      }
    }
  }
}
```

**Tools available to the AI:**

| Tool | What it does |
|---|---|
| `remember` | Store a fact in free text — the LLM extracts structure and conflict-checks the write |
| `recall` | Ask a question, get governed, time-correct context back |
| `vault_assert` | Assert a structured `(subject, predicate, object)` claim — no API key needed |
| `vault_resolve` | Raw facts + claim IDs for a specific principal at a point in time |
| `vault_register_principal` | Set visibility labels for governed sharing across a team |
| `vault_audit_replay` | Replay exactly what a principal saw at/before a given time |

**With durable storage** (data persists across restarts):

```json
{
  "mcpServers": {
    "context-vault": {
      "command": "uvx",
      "args": ["--from", "context-vault-ai[mcp,self-host]", "context-vault-mcp"],
      "env": {
        "VAULT_STORE": "neo4j",
        "ANTHROPIC_API_KEY": "sk-ant-...",
        "NEO4J_URI": "bolt://localhost:7687",
        "NEO4J_PASSWORD": "<your-neo4j-password>",
        "VAULT_PG_DSN": "postgresql://<user>:<password>@localhost:5433/vault_audit"
      }
    }
  }
}
```

> **For semantic `recall` quality, add the `embeddings` extra** — `context-vault-ai[mcp,self-host,embeddings]` and set `"VAULT_EMBEDDER": "sentence-transformer"`. Without it (including the zero-DB trial above) the server falls back to the deterministic **hash** embedder and prints a one-time banner; `recall` results carry an `embedder` field so you can confirm which one ranked them.

The server is also listed on the **official MCP registry** as `io.github.RajdeepDas43/context-vault`.

---

## Level 5 — Framework adapters

Drop Context Vault into your existing agent stack as a governed memory backend. All adapters use the same `vault_tools(memory)` pattern — one line to wire in.

### LangGraph / LangChain

```bash
pip install "context-vault-ai[langgraph]"
```

```python
from context_vault import Memory
from context_vault.integrations.langgraph import vault_tools

memory = Memory()
tools = vault_tools(memory)   # returns [vault_remember, vault_recall] as LangChain tools

# Use tools in your LangGraph graph / agent
from langgraph.prebuilt import create_react_agent
agent = create_react_agent(llm, tools)
```

### CrewAI

```bash
pip install "context-vault-ai[crewai]"
```

```python
from context_vault import Memory
from context_vault.integrations.crewai import vault_tools

memory = Memory()
tools = vault_tools(memory)   # returns CrewAI Tool objects

from crewai import Agent, Task, Crew
agent = Agent(role="Researcher", tools=tools, ...)
```

### LlamaIndex

```bash
pip install "context-vault-ai[llamaindex]"
```

```python
from context_vault import Memory
from context_vault.integrations.llamaindex import vault_tools

memory = Memory()
tools = vault_tools(memory)   # FunctionTool objects for LlamaIndex agents
```

### Claude Agent SDK

```bash
pip install "context-vault-ai[claude-agent-sdk]"
```

```python
from context_vault import Memory
from context_vault.integrations.claude_agent_sdk import vault_tools

memory = Memory()
tools = vault_tools(memory)   # Claude Agent SDK tool definitions
```

### Microsoft Agent Framework (AutoGen successor)

```bash
pip install "context-vault-ai[agent-framework]"
```

```python
from context_vault import Memory
from context_vault.integrations.agent_framework import vault_tools

memory = Memory()
tools = vault_tools(memory)   # MAF FunctionTool objects
```

Each adapter wraps the same governed engine — conflict-checked writes, deny-by-default ACL, time-aware recall — with zero boilerplate.

### Back a framework's *native memory/state* with the vault

The `vault_tools(...)` adapters above expose the vault to an agent as **tools it calls**. Two
adapters instead sit *under* a framework, backing its native memory/state store with governed
claims — so the framework's own memory gains validity windows, deny-by-default ACL, the audit
trail, and bitemporal replay, with no agent-side changes:

```python
# CrewAI Storage adapter — backs ShortTerm + Entity memory with governed claims
from context_vault import Memory
from context_vault.integrations.crewai import vault_storage
from crewai.memory import ShortTermMemory

stm = ShortTermMemory(storage=vault_storage(Memory(), user="crew:acme"))
# save → governed Assert, search → governed recall, reset → archive (never hard-delete)
```

```python
# LangGraph BaseCheckpointSaver — graph state as per-(thread, step) governed claims,
# so an agent run can be reconstructed at a past time with Resolve@past.
from context_vault.integrations.langgraph import vault_checkpointer
from context_vault.sdk import VaultClient

saver = vault_checkpointer(client)   # ACL bound to client.principal
graph = builder.compile(checkpointer=saver)
```

Both need the matching extra (`[crewai]` / `[langgraph]`) and are imported lazily — `import
context_vault` never requires either framework.

---

## Level 6 — Full self-hosted deployment (Docker)

Run the API from the published package against your own Neo4j + Postgres — no source checkout required.

**1. Install the server:**

```bash
pip install "context-vault-ai[self-host,api]"
```

**2. Start the datastores.** Save this as `docker-compose.yml` and fill in your own passwords:

```yaml
services:
  neo4j:
    image: neo4j:5.26
    ports:
      - "7474:7474"   # browser
      - "7687:7687"   # bolt
    environment:
      NEO4J_AUTH: neo4j/<your-neo4j-password>

  postgres:
    image: postgres:16
    ports:
      - "5433:5432"
    environment:
      POSTGRES_USER: <your-postgres-user>
      POSTGRES_PASSWORD: <your-postgres-password>
      POSTGRES_DB: vault_audit
```

```bash
docker compose up -d
```

**3. Point the server at your datastores and run it:**

```bash
export VAULT_STORE=neo4j
export NEO4J_URI=bolt://localhost:7687
export NEO4J_PASSWORD=<your-neo4j-password>
export VAULT_PG_DSN=postgresql://<your-postgres-user>:<your-postgres-password>@localhost:5433/vault_audit
export VAULT_ADMIN_KEY=<set-a-strong-random-secret>   # gates the /admin/* endpoints
export ANTHROPIC_API_KEY=sk-ant-...                   # optional — enables the Claude judge

context-vault serve --port 8000
```

**Check everything is healthy:**

```bash
curl http://localhost:8000/ready
# {"ready":true,"neo4j":true,"postgres":true,"embedder":"hash"}
```

**Web interfaces:**
- `http://localhost:8000/admin` — full governance console (requires `VAULT_ADMIN_KEY`)
- `http://localhost:8000/ask` — plain-language interface (non-technical staff)
- `http://localhost:8000/console` — compliance / audit wizard
- `http://localhost:8000/docs` — interactive API documentation

> For semantic recall quality, install `context-vault-ai[self-host,api,embeddings]` and set
> `VAULT_EMBEDDER=sentence-transformer`. Otherwise the server uses the offline `hash` embedder.

---

## Level 7 — TypeScript / JavaScript SDK

```bash
npm install context-vault-sdk
```

```typescript
import { VaultClient } from "context-vault-sdk";

const client = new VaultClient({
  baseUrl: "http://localhost:8000",
  apiKey: "cv_...",    // from POST /signup or POST /keys
});

// Assert a fact
await client.assert({
  subject: "Priya",
  predicate: "account tier",
  object: "Enterprise",
  validFrom: "2024-01-01",
});

// Resolve — time- and permission-aware
const results = await client.resolve({
  query: "what tier is Priya on?",
  asOf: new Date().toISOString(),
});

// Get a full profile
const profile = await client.profile({ subject: "Priya" });
```

The TypeScript SDK targets the HTTP API and works in Node.js, Deno, and browser environments.

---

## Key concept: Claims and conflict detection

**A Claim is the atomic unit.** Every fact stored in Context Vault is a Claim:

```
(subject, predicate, object, valid_from, valid_to, confidence, visibility, provenance)
```

Example: `(Priya, works at, Acme Corp, 2024-01-01, 2025-06-01, 0.95, [team:sales], agent-crm)`

**What happens when you write a conflicting fact?**

Context Vault does not have a simple "conflict / no conflict" binary. On every assert, the new fact is compared against existing ones and classified into exactly one of six relations:

| Relation | Meaning | What happens |
|---|---|---|
| `CONTRADICTION` | Two claims are logically incompatible over overlapping time | Flagged for human review — never auto-resolved |
| `TEMPORAL_SUPERSESSION` | A functional fact updated over time (new role, new address) | Old fact is closed at today; new fact becomes current |
| `REFINEMENT` | More specific than an existing claim — both are true | Both are kept (branched) |
| `DUPLICATE` | Restates the same fact | Merged — corroboration count incremented |
| `INDEPENDENT` | Unrelated to existing facts | Stored as-is |
| `UNSURE` | Judge is not confident | Flagged — never auto-mutated |

Collapsing these into "conflict / no-conflict" is how a memory system silently corrupts itself. Context Vault measures a **silent-corruption rate**: the percentage of real contradictions or supersessions misclassified as independent or duplicate. The current rate on the 54-case adversarial gold set is **0.0%** (Claude judge, `sonnet-4-6`, 96.3% accuracy).

**Time-travel queries.** Every resolve query accepts two optional timestamps:

```python
# What was true on March 1st?
resolve("where does Priya live?", as_of="2025-03-01")

# What did we *believe* on March 1st (ignoring later corrections)?
resolve("where does Priya live?", as_of="2025-03-01", known_as_of="2025-03-01")
```

The second form is "bitemporal" — it reconstructs what the system believed at a past system time, not just what was true in the world. Useful for audits and debugging agent decisions.

---

## Configuration reference

All configuration is via environment variables. These are the handful you set to run the server:

| Variable | Default | Description |
|---|---|---|
| `VAULT_STORE` | `neo4j` | Storage backend: `neo4j` (durable), `memory` (ephemeral, no deps), `sqlite` (local file) |
| `ANTHROPIC_API_KEY` | *(none)* | Enables the Claude LLM judge + free-text extraction. Without it, the safe heuristic judge is used. |
| `VAULT_EMBEDDER` | `sentence-transformer` | Embedding backend: `sentence-transformer` (semantic, needs `[embeddings]`) or `hash` (offline). Falls back to `hash` when the extra is absent; Resolve results report which ran via an `embedder` field. |
| `NEO4J_URI` | `bolt://localhost:7687` | Neo4j connection URI (default user `neo4j`) |
| `NEO4J_PASSWORD` | *(set your own)* | Neo4j password — use a strong secret |
| `VAULT_PG_DSN` | `postgresql://<user>:<password>@localhost:5433/vault_audit` | Postgres connection string |
| `VAULT_ADMIN_KEY` | *(none)* | Required to access `/admin/*` endpoints. Set a strong random secret in production. |

**Minimal `.env`:**

```bash
VAULT_STORE=neo4j
ANTHROPIC_API_KEY=sk-ant-...                          # optional — enables the Claude judge
NEO4J_URI=bolt://localhost:7687
NEO4J_PASSWORD=<your-neo4j-password>
VAULT_PG_DSN=postgresql://<user>:<password>@localhost:5433/vault_audit
VAULT_ADMIN_KEY=<set-a-strong-random-secret>
```

---

## CLI reference

```bash
# Start the HTTP API + admin console
context-vault serve --port 8000

# Run the interactive offline demo
context-vault demo

# Assert a fact from the command line
context-vault assert \
  --principal agent-a \
  --subject Priya \
  --predicate "lives in" \
  --object London \
  --api-key cv_...

# Resolve — time-aware query
context-vault resolve \
  --principal agent-a \
  --query "where does Priya live?" \
  --as-of 2026-06-01 \
  --api-key cv_...

# Register a principal with visibility labels
context-vault register-principal \
  --id agent-a \
  --labels "team:sales" \
  --api-key cv_...

# Check telemetry (what would be sent — no network call)
context-vault telemetry --send --dry-run
```

---

## Links

- **[Quickstart](https://github.com/RajdeepDas43/context-graph-vault/blob/main/docs/QUICKSTART.md)** — zero to first governed retrieval in 5 minutes
- **[MCP setup](https://github.com/RajdeepDas43/context-graph-vault/blob/main/docs/MCP.md)** — register with Claude Desktop / Code / Cursor
- **[Changelog](https://github.com/RajdeepDas43/context-graph-vault/blob/main/CHANGELOG.md)** — what changed in each version
- **[GitHub Issues](https://github.com/RajdeepDas43/context-graph-vault/issues)** — bug reports and feature requests

---

*Context Vault is MIT licensed, built by Paramind AI — for the teams that need to know not just what their agents know, but what they were allowed to know, and prove it.*
