Skip to content

Rishikiran98/TENET

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TENET

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.

The one idea

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)

What's built

  • Event log (src/tenet/events/) — the spine. Envelope with ULID ids and a SHA-256 hash chain, a closed event taxonomy, an append-only InMemoryEventLog, and replay/rebuild folds. Tamper-evident: mutate any past event and verify() raises.
  • Memory core on the log (src/tenet/memory/) — MemoryCore.ingest appends a memory.raw.appended event (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/) — a ScopeGrant is the sole source of an agent's authority for one task (namespaces, tools, action budget, expiry). The retriever enforces its namespaces: retrieval can never reach memory outside the grant, and no retrieved content can widen it.
  • Governance gate — contract (src/tenet/gate/) — the pure-function DefaultGate: grant check (tool membership, expiry, action budget) → policy → unmatched⇒DENY. Ships the Gate/Policy protocols and Verdict/ GateDecision; the policy rules are authored separately (describe-first).
  • Agent loop + approver (src/tenet/agent/, src/tenet/approver/) — the deterministic ScriptedBrain (LLM-swappable), and AgentLoop: 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 over fs.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.

Run it

pip install -e ".[dev]"      # numpy + pytest
pytest                       # event log + memory core (all green)
python -m tenet.demo         # memory-core walkthrough: ranking + scope isolation

No 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

Build order (see CLAUDE.md §12)

  1. Event log
  2. Memory core on the log (raw = event, context = projection) ✅
  3. ScopeGrant + retriever scope enforcement
  4. Governance gate — contract ✅ (policy is Sai's, describe-first; loop wiring next)
  5. Agent loop + approver/escalate path
  6. Executor + sandboxed fs tools
  7. Headline demo — poisoned corpus, naive agent vs. Tenet agent, audit view as the receipt
  8. Then pgvector · 9. Then FastAPI

What this defends against (and what it doesn't)

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.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages