EPI — Evidence for AI agents
Record. Seal. Verify offline. The answer is a file.
pip install epi-recorder
epi demo --no-browser # record → seal → verify (no API key)
60-second path · What a .epi is · CLI · Docs & pilot · Standards
When someone asks what your agent did six months ago,
the answer should be a.epifile — not a dashboard login and a shrug.
epi-recorder captures agent decisions into a portable, signed, offline-verifiable artifact.
No phone-home required to open or verify.
Open a sealed .epi offline — epi view run.epi
Forensic case view of a sealed run. Sample artifact: docs/assets/readme-demo.epi
60-second path
Works without any LLM API key:
# demo.py
from epi_recorder import record, get_current_session
with record("demo.epi", goal="show the golden path"):
s = get_current_session()
s.log("tool.call", tool="lookup", id="A-1")
s.log("tool.response", ok=True, balance=250)
s.log("decision", action="approve", reason="within limit")
python demo.py
epi verify demo.epi
epi-register demo.epi
epi view demo.epi
| Step | Command | What you get |
|---|---|---|
| Record + seal | python demo.py |
Signed demo.epi (secrets redacted by default) |
| Verify | epi verify demo.epi |
Integrity + signature checks offline |
| Register | epi-register demo.epi |
Transparency ledger receipt embedded in .epi |
| View | epi view demo.epi |
Self-contained browser viewer (screenshot above) |
Typical first-run verify:
| Check | Result |
|---|---|
| Integrity (SHA-256) | Valid |
| Signature (Ed25519) | Valid |
| Identity | Often LOCAL / UNKNOWN until you pin trust |
| Secrets | Redacted by default (redact=True) |
First-run WARN / LOCAL identity is normal — seal integrity and signature can still pass.
Identity is separate from seal. Pin withepi keys trust <name>when you mean it.
Policy / “did the run break our rules?” is separate again:epi analyze— see docs/POLICY-AND-FAULT-ANALYZER.md.
That’s the product. Everything below is optional depth.
With OpenAI
from openai import OpenAI
from epi_recorder import record, wrap_openai
client = wrap_openai(OpenAI()) # needs OPENAI_API_KEY
with record("agent.epi", goal="Answer a user question"):
client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
python agent.py
epi verify agent.epi
epi view agent.epi
API keys in prompts/headers are redacted automatically before they land in the file.
What a .epi file is
Every .epi uses the Envelope v2 container format — a polyglot HTML+ZIP
binary that opens natively in any browser and can be extracted programmatically.
demo.epi
├── manifest.json # Ed25519 signature + SHA-256 file hashes
├── steps.jsonl # Timeline (hash-linked steps)
├── environment.json # Runtime snapshot (sensitive env redacted)
├── analysis.json # Fault / policy analysis (when generated at seal)
├── viewer.html # Offline forensic UI
└── VERIFY.txt # Plain-text auditor instructions
| Guarantee | How |
|---|---|
| Integrity | SHA-256 over every sealed member |
| Authenticity | Ed25519 signature on the manifest |
| Chain | Each step’s prev_hash links the timeline |
| Privacy | Default secret redaction (API keys, tokens, PII) |
Samples: docs/assets/SAMPLES.md · try docs/assets/readme-demo.epi.
Integrations
| Stack | How |
|---|---|
| OpenAI | wrap_openai(OpenAI()) |
| Anthropic | wrap_anthropic(Anthropic()) |
| LangChain | EPICallbackHandler |
| LiteLLM | EPICallback |
| pytest | pytest --epi |
| Microsoft AGT | epi import agt <file> |
# LangChain (canonical adapter)
from epi_recorder import record
from epi_recorder.adapters.langchain import EpiCallbackHandler
with record("run.epi") as session:
handler = EpiCallbackHandler(session)
llm = ChatOpenAI(model="gpt-4o-mini", callbacks=[handler])
llm.invoke("…")
# pytest — attach evidence to failing tests
pytest --epi
More: docs/FRAMEWORK-INTEGRATIONS-5-MINUTES.md
CLI
| Command | Purpose |
|---|---|
epi demo |
Guided demo: record → seal → verify |
epi verify <file.epi> |
Offline integrity + signature check |
epi-register <file.epi> |
Register artifact on transparency ledger & embed receipt |
epi view <file.epi> |
Open offline viewer (screenshot above) |
epi analyze <file.epi> |
Fault / policy summary from sealed analysis |
epi policy init |
Create epi_policy.json rulebook |
epi run <script.py> |
Run a script under recording |
epi keys generate / list / trust |
Local signing keys |
epi enterprise setup / pack |
Org kit + auditor pack |
epi scitt register <file.epi> |
SCITT transparency anchor (advanced) |
epi import agt <path> |
Import Microsoft AGT evidence |
Policy + fault analyzer guide: docs/POLICY-AND-FAULT-ANALYZER.md
Security defaults
- Redaction is on (
redact=True). Keys/tokens/PII become placeholders. - Prefer not using
redact=Falsein production (it warns). - Verification is local — no network required for integrity/signature.
- First-run identity WARN / LOCAL is expected until you trust a key.
- Seal ≠ identity ≠ policy. Verify proves the file; analyze grades the run against rules/heuristics.
Docs & pilot
| Topic | Link |
|---|---|
| Docs map | docs/README.md |
| Guided pilot pack | docs/PILOT.md |
| Enterprise in 15 minutes | docs/ENTERPRISE-15-MINUTES.md |
| Enterprise capability (honest) | docs/ENTERPRISE-CAPABILITY.md |
| Policy + fault analyzer | docs/POLICY-AND-FAULT-ANALYZER.md |
| Known limitations | docs/KNOWN_LIMITATIONS.md |
| CLI deep dive | docs/CLI.md |
| Auditors guide | docs/AUDITORS-GUIDE.md |
Standards & compliance
EPI produces evidence files that help with audit trails. It is not a compliance guarantee and does not provide legal advice. Whether evidence satisfies a specific regulatory threshold is for the auditor or notified body to determine.
| Topic | Docs |
|---|---|
| EU AI Act Annex IV | docs/ANNEX-IV.md |
| AIUC-1 domains | docs/standards/aiuc-1-evidence.md |
| SCITT | docs/standards/scitt-predicate.md |
epi verify agent.epi --aiuc1 # optional domain scoring
Troubleshooting
| Symptom | Fix |
|---|---|
epi: command not found |
Same venv as pip install, or python -m epi_cli |
| First verify WARN / LOCAL identity | Normal if seal OK — pin with epi keys trust … when ready |
Integrity: FAILED |
File changed after seal — re-record |
epi analyze says heuristic only |
Add epi_policy.json via epi policy init, re-run from that folder |
| Share / portal fails | Hosted needs backend; local record/verify never depends on it |
Trust-model note: Integrity checks whether the sealed record was altered since sealing — not that every real-world action was captured.
Project layout (contributors)
| Path | Role |
|---|---|
epi_recorder/ |
Python SDK (record, wrappers) |
epi_core/ |
Container, crypto, redaction, verify, fault analyzer |
epi_cli/ |
epi command |
website/ |
Public site source of truth (epilabs.org) |
website-v2/ |
Sandbox redesign (not production deploy) |
verify_portal/ |
Hosted verify/auth API (optional) |
docs/ |
Start at docs/README.md |
tests/test_core_loop_golden.py |
Golden path regression |
Website edits: only under website/, then python scripts/sync_website.py. See docs/SITE.md.
License
MIT — see LICENSE.
Site: epilabs.org · Issues: GitHub Issues
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file epi_recorder-4.4.0.tar.gz.
File metadata
- Download URL: epi_recorder-4.4.0.tar.gz
- Upload date:
- Size: 11.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b6728d4849a2954ae77bd3a7253c6c7b68c1fa3393e24e8838827298cc6cd84
|
|
| MD5 |
179c3c0d22ccc68d5df54ecbe88463ab
|
|
| BLAKE2b-256 |
f17cbc27ea4c6063276e638a45d0fcc61bc2bedf15a0ee8039a684bf69903b3b
|
File details
Details for the file epi_recorder-4.4.0-py3-none-any.whl.
File metadata
- Download URL: epi_recorder-4.4.0-py3-none-any.whl
- Upload date:
- Size: 11.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6e157abd7b67e47e30e040709309a82eb45c227e34e1673984dacffa7717cc3
|
|
| MD5 |
10cdb53f0d5a2ee2dfb1225bdac95cc9
|
|
| BLAKE2b-256 |
2c4af691cf7498af48a910b8a322e4ee5bb4b370a244a2963f558d3ee06f477e
|