🛡️ DreamGuard
Reversible memory compilation for AI agents. Compress your agent's memory without losing the raw data, and roll back when recall drops.
The problem
Long-running agents compress their memory ("dreaming" / consolidation) to keep the context window small. The common approach rewrites memory in place: once a detail is summarised away, it is gone for good. If the summary dropped the one port number, ticket owner or ID the agent needs later, there is no way back.
The idea
DreamGuard treats memory like a build step:
- Raw episodes are never deleted.
- Every compressed fact is linked back to its source episodes (provenance).
- If recall quality drops,
rollback()restores the exact raw context.
record() ──► episodes (immutable)
│ dream()
▼
semantic_memories ──provenance──► episodes
│ rollback()
▼
compressed facts deactivated, raw context restored
Install
pip install dreamguard # core library, zero dependencies
pip install "dreamguard[groq]" # + Groq LLM compressor
pip install "dreamguard[server]" # + dashboard, API and Groq support
Requires Python 3.10+.
Quick start
from dreamguard import MemoryEngine, HeuristicCompressor
mem = MemoryEngine(HeuristicCompressor(retention=0.7), destructive=False)
mem.record(1, "api_port=8421")
mem.record(2, "region=ap-south-1")
mem.dream() # compress; raw episodes + provenance are kept
print(mem.context()) # what your agent sees: the compressed digest
mem.rollback() # back to the exact raw episodes
print(mem.context())
MemoryEngine accepts any compressor with a compress(lines: list[str]) -> str method, so you can plug in any LLM.
Auto-rollback with canary questions
Pick facts that must never be lost, test them after every compression, and roll back automatically if recall falls below a threshold:
from dreamguard import MemoryEngine, GroqCompressor # pip install "dreamguard[groq]"
# export GROQ_API_KEY=gsk_... (and optionally GROQ_MODEL=openai/gpt-oss-120b)
mem = MemoryEngine(GroqCompressor(), destructive=False)
CANARIES = [("Which port does redis use?", "6391"), ("Who approved r-1093?", "tomas berg")]
THRESHOLD = 0.85
def guarded_dream(mem, ask):
"""ask(memory_text, [questions]) -> [answers]; your LLM call."""
mem.dream()
answers = ask(mem.context(), [q for q, _ in CANARIES])
score = sum(exp in a.lower() for (_, exp), a in zip(CANARIES, answers)) / len(CANARIES)
if score < THRESHOLD:
mem.rollback() # compression rejected, raw memory restored
return score
Dashboard and CLI
pip install "dreamguard[server]"
dreamguard serve # dashboard at http://localhost:8000
dreamguard benchmark # offline simulation in your terminal
dreamguard benchmark --auto # auto-rollback when accuracy < 85%
The dashboard has two pages:
/is the offline simulation: a 50-turn chart plus a hands-on memory panel (record, dream, rollback)./liveruns a real LLM through the flow. SetGROQ_API_KEY(and optionallyGROQ_MODEL) in your environment or a.envfile, then click Load scenario → Evaluate → Dream → Evaluate → Rollback → Evaluate.
In /live, an LLM compresses 12 engineering-log episodes, then answers 8 factual questions from each system's remaining memory. Answers are graded against known ground truth. In one example run, recall fell to 50% after compression; after rollback DreamGuard returned to 100% while in-place memory stayed at 50%. LLM output varies by model and run, but the rollback guarantee does not, because it restores the raw text.
How it works
| Table | Purpose |
|---|---|
episodes |
Raw, append-only memory (turn, content) |
semantic_memories |
Compressed digests, with an active flag |
provenance |
memory_id → episode_id links from each digest to its sources |
| Method | What it does |
|---|---|
record(turn, content) |
Append a raw episode |
dream() |
Compress episodes not yet covered by an active digest |
rollback() |
Deactivate digests so raw episodes become the context again |
context() |
Active digests plus any uncovered raw episodes |
snapshot() |
Episodes, facts and provenance as dicts |
evaluate(truth) |
Fraction of key=value details recoverable from the context |
With destructive=True the engine mimics in-place dreaming: it deletes raw data and re-compresses digests together with new episodes, so loss compounds and cannot be undone. Use it as a baseline for comparisons.
Benchmark methodology
The built-in benchmark is a synthetic simulation, not a measurement of any production system:
- Each turn records one exact detail, e.g.
param_7=48213. - Every 10 turns memory is compressed with a seeded lossy compressor that keeps each value with probability 0.7.
- After every turn, recall is the fraction of all details seen so far that appear verbatim in the agent's visible context.
It shows that if compression is lossy, an irreversible design loses information permanently while a design that keeps raw data can restore it. It does not show how any specific LLM or product behaves.
Trade-off: after a rollback the agent context is raw again and therefore larger. You trade the size benefit of compression for recall until the next dream.
REST API (with [server])
| Method | Path | Description |
|---|---|---|
| POST | /api/record |
{"content": "..."} record an episode |
| POST | /api/dream |
Compress uncovered episodes |
| POST | /api/rollback |
Deactivate compressed memory |
| GET | /api/memory |
Episodes, facts, provenance, context size |
| GET | /api/benchmark |
Run the simulation (seed, retention, auto_rollback, rollback_at) |
Interactive docs at /docs.
Roadmap
- Selective rollback (restore only the episodes behind a specific fact)
- Built-in guarded dream with canary checks
- Pluggable storage backends (Postgres, vector DBs)
- Rollback triggers driven by task-level eval signals
Contributing
Issues and PRs are welcome at github.com/manojkumar16122/dreamguard.
git clone https://github.com/manojkumar16122/dreamguard
cd dreamguard
pip install -e ".[dev,server]"
pytest
License
MIT. Built by Manojkumar V.
Metadata
Release files for dreamguard 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| dreamguard-0.1.1.tar.gz | 22.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dreamguard-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.5 kB
Release files / dreamguard-0.1.1.tar.gz
| Download URL | dreamguard-0.1.1.tar.gz |
|---|---|
| Size | 22.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6d48b2edaa5982459ccd49ed3fedebb20dda4ae00b226b681e95e3ddf696e6bb
|
|
BLAKE2b-256 checksum How to use checksums |
e38a53d7c0236ef455161cef00175957cd696ac8e90ac0cdba915e0f7f81c78d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.6
|
Release files / dreamguard-0.1.1-py3-none-any.whl
| Download URL | dreamguard-0.1.1-py3-none-any.whl |
|---|---|
| Size | 22.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
53a3dbef1bed1712defdc1143fb18fbd9e552d5a58fa532bc6e18186bada8262
|
|
BLAKE2b-256 checksum How to use checksums |
893a06d00f5b18abf705f4bec1fd681834aee66559901e18789a41ac9d59049b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.6
|
Security for dreamguard 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.