Skip to main content

Event-driven memory validity layer for AI agents

Project description

Revok Revok

Revok

The memory validity layer for AI agents.

Every memory system updates beliefs from conversation.
None listen to the world changing around them. Revok does.

License: AGPL v3 Python Status Async PRs welcome

Quick start · How it works · Examples · Roadmap


Table of contents


The problem

Your agent tells a customer the item is in stock. It sold out 20 minutes ago.

Your agent has no idea — because no memory system listens to the world.

Memory layers today — Mem0, Zep, and the rest — track when a memory was stored, not whether it is still true. The moment reality changes, your agent is confidently wrong.

Stale memory ships bugs everywhere agents touch a changing world:

  • 🛒 Commerce — "it's in stock" → sold out
  • 💰 SaaS — quotes old pricing → undercharges the deal
  • 🎫 Support — "you're eligible for a refund" → policy changed last week
  • 📅 Scheduling — "that slot is open" → booked an hour ago
  • 🔐 Access — "you're on the free plan" → upgraded yesterday

Revok fixes this.


The solution

Revok sits between your agent and its memory store as a transparent HTTP proxy. It listens for real-world signals, resolves which memories are affected using a causal graph, and attaches a confidence score at retrieval time.

Minimal integration required. Point Revok in front of Mem0 and your existing memory writes are enriched automatically. Confidence is retrieved with one explicit call when your agent needs it.

# Step 1 — your existing memory search, completely unchanged
memories = mem0.search(query, user_id=user_id)

# Step 2 — get live confidence with one explicit call
response = requests.get(
    f"http://localhost:7771/v1/entities/{entity_key}"
)
confidence = response.json()["score"]         # live, time-recovered
status     = response.json()["confidence_status"] # fresh/degraded/stale

# Step 3 — agent decides what to do
if status == "fresh":
    answer_from_memory(memories)
elif status == "degraded":
    answer_with_caveat(memories)
else:  # stale
    re_verify_from_source()

Reads bypass Revok entirely — zero added read latency. Confidence is retrieved via a separate explicit call to GET /v1/entities/{key} when needed.


"But my system is context-aware"

Maybe you already do context engineering — RAG, live tool calls, fresh retrieval injected at prompt time. Good. That brings new data into the context window.

It still doesn't tell you whether the stored beliefs your agent reasons over are still valid.

Bringing the change into context ≠ knowing what the change invalidated.

Concretely:

  • RAG fetches a fresh document — but the agent's memory still holds a summary from last week, and nothing reconciles the two. Which one does it trust?
  • A tool call returns live data — but only for the one entity you queried. The signal that "supplier pricing changed" should also degrade the cached ROI, the quote, and the comparison — every downstream belief it touches.
  • You re-embed and re-index — that updates retrieval relevance, not truth. A confidently retrieved, perfectly relevant memory can still be stale.

Context engineering answers "what's relevant right now?" Revok answers "is what I already believe still true?" — and propagates a single real-world signal across every memory it invalidates via the causal graph. The two are complementary: keep your retrieval, add a validity layer underneath it.


Features

  • 🔌 Drop-in proxy — sits in front of Mem0 over HTTP; memory writes enriched automatically.
  • 🧠 Live confidence on demandGET /v1/entities/{key} returns a time-recovered score, never a frozen snapshot.
  • 🌐 World-aware — ingests external signals (CDC, webhooks, streams) that invalidate beliefs.
  • 🕸️ Causal graph — one signal can degrade every downstream memory it affects (NetworkX BFS).
  • ⏱️ Time decay + pressure — confidence recovers over time and drops under signal pressure.
  • Async, low-latency — built on asyncio + aiohttp; reads are never blocked.
  • 💾 Durable state — SQLite WAL with an in-memory hot layer.
  • 🧩 Flexible entity matching — catalog aliases, regex patterns, or X-Revok-Entity headers.

Quick start

Prerequisites

  • Python 3.11+
  • A running Mem0 instance (or use the Docker demos below)

Install

# Clone
git clone https://github.com/robertopc1/revok.git
cd revok

# Create a virtual environment and install
python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\Activate.ps1
pip install -e ".[dev]"

Configure

cp config/revok.example.yaml revok.yaml
# Edit revok.yaml — point `upstream.mem0_url` at your Mem0 instance
# and register the entities you want to track.

Run

revok --config revok.yaml
# → Revok listening on http://127.0.0.1:8080

Point your agent's Mem0 client at the Revok URL instead of Mem0 directly. That's it.

Or run with Docker

docker pull robertopc2/revok:latest

docker run -v ./revok.yaml:/config/revok.yaml \
  -p 7771:7771 \
  robertopc2/revok:latest

How confidence retrieval works

Revok uses three separate paths that never block each other:

Write path — Revok intercepts:

Agent writes memory → Revok proxy → extracts entities → scores updated → forwarded to Mem0

Read path — Revok not involved:

Agent reads memory → directly to Mem0 → returned unchanged

Reads bypass Revok entirely. Zero added read latency.

Confidence path — explicit call:

Agent checks confidence → GET /v1/entities/{entity_key} → returns live time-recovered score

The score returned by GET /v1/entities/{key} is always live — it reflects both the last signal received and time elapsed since then via decay_at(). It is never a frozen snapshot.


How Revok differs from TTL-based systems

TTL- and age-based approaches (session expiry, forgetting by max age, keep-top-N eviction):

  • Time passing drives memory lifecycle — sessions expire, old memories are pruned
  • No awareness of why something became stale
  • A memory can expire while still true, or survive while no longer true

Revok:

  • Time alone never causes staleness
  • Only external signals cause confidence to drop
  • Time passing after a signal causes recovery toward fresh
  • A memory with no signals stays fresh indefinitely
  • Staleness is always causally linked to a real-world event

Revok is complementary to lifecycle management, not a replacement for it. TTL and forgetting policies manage how long memories live. Revok manages whether they are still true. Use both.


Sending signals to Revok

When something changes in the real world, send a signal to the dedicated endpoint:

curl -X POST http://localhost:7771/signals \
  -H "Content-Type: application/json" \
  -d '{
    "entity_refs": ["redis-enterprise-pricing"],
    "severity": "high",
    "source": "webhook",
    "payload": {}
  }'

Revok returns 202 Accepted immediately and processes the signal asynchronously — zero impact on your agent read or write latency.

In production, wire this endpoint to an Azure Function trigger, a CDC pipeline, or any webhook-capable system.


How it works

A real-world signal arrives, Revok figures out which memories it touches, and the next time those memories are read they come back with a confidence score.

flowchart TD
    A[External signal] --> B[POST /signals]
    B --> C[AsyncioQueueBus]
    C --> D[Entity resolver]
    D -->|YAML registry / X-Revok-Entity| E[Scoring engine]
    E -->|exponential decay × pressure| F[State store]

    G[Agent memory write] --> H[Revok proxy]
    H -->|enrich| I[Mem0]

    J[Agent memory read] -->|bypasses Revok| I

    K[Agent confidence check] --> L[GET /v1/entities/key]
    L --> F

Three separate paths — signal ingestion, memory writes, and confidence reads — never block each other. Signal processing is async. Memory reads bypass Revok entirely.


Architecture

External signal
      ↓
Signal normalizer
      ↓
Entity resolver   ←  YAML entity registry / X-Revok-Entity header
      ↓
Causal graph      ←  NetworkX BFS traversal
      ↓
Scoring engine    ←  exponential decay × signal pressure
      ↓
State store       ←  SQLite WAL + in-memory hot layer
      ↓
Metadata writer   →  confidence score in memory metadata

Configuration

Revok is configured with a single YAML file. A minimal example:

server:
  host: "127.0.0.1"
  port: 8080

upstream:
  mem0_url: "http://localhost:8000"
  write_methods: ["POST", "PUT", "PATCH"]
  write_paths: ["/v1/memories"]

entity_matcher:
  entities:
    - id: "apex_hoodie"
      display_name: "Apex Fleece Hoodie"
      aliases: ["Apex Hoodie", "apex fleece", "SKU-1042"]

scoring:
  half_life_seconds: 86400      # confidence recovers to 0.5 after 24h
  signal_strength: 0.4          # how much each signal subtracts
  score_cap: 1.0

See config/revok.example.yaml for the fully documented configuration, including pattern mode and header-tagged mode for large catalogs.


HTTP API

Revok forwards everything to Mem0 transparently, and adds a small read-only API for inspecting confidence state:

Method Path Description
POST /signals Submit an external world-signal (202 async)
GET /v1/entities Paginated list of all entity records
GET /v1/entities/{entity_key} Live time-recovered confidence score
DELETE /v1/entities/{entity_key} Remove an entity record
* /{any other path} Transparently proxied to Mem0

To attach a signal to a write, send the entity with the request header:

X-Revok-Entity: apex_hoodie

Confidence states

Status Score Meaning
fresh > 0.7 Memory is reliable
degraded 0.3–0.7 Use with caution
stale < 0.3 Do not trust

Examples

Runnable end-to-end demos live in examples/:

Demo What it shows
mem0_basic Revok proxying Mem0: a pricing change fires a signal and confidence degrades.
langgraph_pricing A LangGraph agent that re-verifies from the live DB when memory goes stale, with a live dashboard.
crewai_pricing The same stale-memory scenario built on CrewAI.

Each demo ships with a docker compose setup and a step-by-step walkthrough in its own README.


Roadmap

Memory adapters

Adapter Status
Mem0 ✅ v0.1.0
Zep 🔜 v0.2.0
Agent Memory Server 🔜 v0.3.0

Signal sources

Source Tier
Webhooks OSS
Redis Streams OSS
Azure Event Hubs Enterprise
AWS EventBridge Enterprise
Google Pub/Sub Enterprise

The Enterprise tier adds multi-tenancy, managed cloud signal sources, SSO/RBAC, audit logging, and a SaaS dashboard.


Contributing

Contributions are welcome! To get started:

pip install -e ".[dev]"
pytest                 # run the test suite
ruff check .           # lint
mypy revok             # type-check

Please open an issue to discuss substantial changes before sending a PR.


License

AGPL v3. Enterprise licensing available — contact [robertopc@gmail.com].


Legal

Revok is licensed under AGPL v3. Core mechanisms are patent pending.

Status

v0.1.1 — MVP. Mem0 adapter. Production use at your own risk. Feedback welcome.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

revok-0.2.0.tar.gz (80.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

revok-0.2.0-py3-none-any.whl (56.1 kB view details)

Uploaded Python 3

File details

Details for the file revok-0.2.0.tar.gz.

File metadata

  • Download URL: revok-0.2.0.tar.gz
  • Upload date:
  • Size: 80.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for revok-0.2.0.tar.gz
Algorithm Hash digest
SHA256 b9c90fca598b4d7e109dc0b372d182d2a150539a6d2e744977119f8b87fcdb36
MD5 94608566b26ff4e5128b5e0947784fb8
BLAKE2b-256 eea8b921f02a60b8fd51b60bd70348f7eebe27119554a80cd89ad2c6a314eaf1

See more details on using hashes here.

File details

Details for the file revok-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: revok-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 56.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for revok-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 012b0a7a0803beab4b1063f14708efcf71956ac954979d7df174f64ebdcdfbee
MD5 cf9809cee6f795bceeba09a3a2038ac6
BLAKE2b-256 0e3df86dfaf4ecba2901989f80f42fe6fa568527e3fc09da857f10392f4cea31

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page