A secure semantic memory layer for AI agents, with governance as a first-class property — demonstrated by one thin action agent built on top of it. v1 proves a principle, governed memory, not a hardened security product.
The full design contract — threat model, architecture, decision register, and build order — lives in CLAUDE.md. Read it before changing anything.
An agent's memory is a security surface. Tenet is event-sourced end to end: a single append-only, hash-chained event log is the only source of truth, and memory, the audit trail, and the agent's step history are all projections folded from that log. Nothing is authoritative except the log.
untrusted content ─► [ingest] ─► ╔═══════════════╗ ◄─ gate verdicts
agent lifecycle ──────────────► ║ EVENT LOG ║ ◄─ approver decisions
tool observations ──────────────► ║ append-only, ║
║ hash-chained ║
╚══════╤════════╝
fold/replay │
┌───────────────┬─────────────┴──────────────┐
▼ ▼ ▼
Context Store Audit View Step History
(retrieval) (who/what/why) (the agent loop)
- Event log (
src/tenet/events/) — the spine. Envelope with ULID ids and a SHA-256 hash chain, a closed event taxonomy, an append-onlyInMemoryEventLog, andreplay/rebuildfolds. Tamper-evident: mutate any past event andverify()raises. - Memory core on the log (
src/tenet/memory/) —MemoryCore.ingestappends amemory.raw.appendedevent (the source of truth) and folds it into the raw store and the context store. The context store is a pure projection (deterministic contextualizer, so no events of its own) and rebuilds identically from the log; retrieval is namespace-filter-first. - Scope grants (
src/tenet/scope/) — aScopeGrantis the sole source of an agent's authority for one task (namespaces, tools, action budget, expiry). The retriever enforces itsnamespaces: retrieval can never reach memory outside the grant, and no retrieved content can widen it. - Governance gate — contract (
src/tenet/gate/) — the pure-functionDefaultGate: grant check (tool membership, expiry, action budget) → policy → unmatched⇒DENY. Ships theGate/Policyprotocols andVerdict/GateDecision; the policy rules are authored separately (describe-first). - Agent loop + approver (
src/tenet/agent/,src/tenet/approver/) — the deterministicScriptedBrain(LLM-swappable), andAgentLoop: task → retrieve (as data) → propose → gate → approve/execute/block, every hop an event with an intact why-chain. Escalations fail closed; the approval surface never carries memory content. - Executor + sandboxed fs tools (
src/tenet/executor/) — a closed tool registry overfs.read/fs.write/fs.delete, jailed to a sandbox root (.., absolute-path and symlink escapes all rejected on the resolved path). Grant constraints (path_prefix) are re-checked at the executor — defense in depth; it does not trust that the gate was the only path to it.
pip install -e ".[dev]" # numpy + pytest
pytest # event log + memory core (all green)
python -m tenet.demo # memory-core walkthrough: ranking + scope isolationNo install? PYTHONPATH=src works too (the tests already put src/ on the path).
from tenet.events import InMemoryEventLog, Actor, taxonomy as T
log = InMemoryEventLog()
log.append(
namespace="proj",
actor=Actor(kind="user", id="alice"),
event_type=T.TASK_INITIATED,
payload={"description": "tidy the sandbox", "grant": {"tools": ["fs.read"]}},
correlation_id="task-1",
)
log.verify() # True — the hash chain holds- Event log ✅
- Memory core on the log (raw = event, context = projection) ✅
- ScopeGrant + retriever scope enforcement ✅
- Governance gate — contract ✅ (policy is Sai's, describe-first; loop wiring next)
- Agent loop + approver/escalate path ✅
- Executor + sandboxed fs tools ✅
- Headline demo — poisoned corpus, naive agent vs. Tenet agent, audit view as the receipt
- Then pgvector · 9. Then FastAPI
In scope for v1: prompt injection via memory, scope escalation, and unattributable actions. Out of scope: host/process/db compromise, a malicious principal, model-level jailbreaks of the agent's "Brain" (the gate exists because the Brain can be fooled), and DoS. Data/instruction separation reduces injection risk; it does not eliminate it. See CLAUDE.md §1.