Epistemic Kernel — Full Specification

Epistemic Kernel — Project Spec & Development Guide

Working title: Epistemic Kernel (a broker-mediated provenance system — the first buildable slice of a ground-up “AI OS”) Target platform: Linux (PC), single-machine MVP Language: Rust Audience: An implementing coding agent — this document defines what and why; implementation is left to that agent.


Table of Contents

  1. Core Concept
  2. MVP Definition
  3. Architecture Outline
  4. Data Model
  5. Protocol (Broker ⇄ Agent)
  6. Memory Subsystem
  7. Rules / Invariants
  8. Functional Requirements
  9. Non-Functional Requirements
  10. Roadmap / Phases
  11. Glossary
  12. Open Design Questions

1. Core Concept

Multi-agent LLM systems today have no structural distinction between fact and belief. Agent A summarizes something, Agent B treats the summary as ground truth, Agent C builds on B’s already-corrupted belief — and by the fourth hop nobody can trace where the error entered.

The Epistemic Kernel is a broker daemon that enforces one invariant everywhere:

A process may act on another process’s belief, but it can never receive that belief as if it were an attested fact.

This is the same shape as a traditional kernel’s job (mediate access to shared resources so processes can’t corrupt each other’s state) applied to a different substrate (truth, not memory/CPU). The mechanism is a real Linux privilege boundary plus a Rust type system that makes the fact/belief distinction impossible to accidentally erase.


2. MVP Definition

The MVP is not a full OS. It is:

  1. A broker daemon (single OS process, async runtime) that owns a Unix domain socket.
  2. A provenance type library (Rust crate) where Attested values can only be constructed inside the broker.
  3. A client SDK crate that agent processes use to talk to the broker over the socket — no other path to shared state exists.
  4. A pluggable attestor interface with one real backend for the MVP: filesystem facts (mtime, content hash, existence).
  5. A belief store with TTL-based expiry.
  6. A demo: 2–3 toy agent processes that publish beliefs, forward each other’s beliefs, and query the broker — demonstrating that (a) forged “attested” claims are rejected, (b) belief chains nest instead of flatten, (c) expired beliefs force re-derivation, (d) an audit trail can be walked to find where any given belief originated.

Explicitly out of scope for MVP: multi-machine distribution, process-level UID isolation between agents (single-process async tasks are acceptable for v1), a semantic filesystem, a scheduler/context-window economy, any GUI, any LLM integration itself (agents in the demo can be scripted/fake — the point is proving the broker’s guarantees, not proving an LLM behaves).


3. Architecture Outline

                 ┌────────────────────────────┐
                 │        Broker Daemon        │
                 │  (owns Unix socket, owns    │
                 │   the only Attested ctor)   │
                 │                              │
                 │  ┌────────────┐ ┌──────────┐│
                 │  │ Provenance │ │ Attestor ││
                 │  │   Store    │ │ Registry ││
                 │  │ (TTL sweep)│ │(pluggable)││
                 │  └────────────┘ └──────────┘│
                 └──────────────┬───────────────┘
                                │ Unix domain socket
                                │ (request/response protocol)
              ┌─────────────────┼─────────────────┐
              │                 │                 │
        ┌─────▼─────┐     ┌─────▼─────┐     ┌─────▼─────┐
        │  Agent A   │     │  Agent B   │     │  Agent C   │
        │ (client SDK)│    │(client SDK)│     │(client SDK)│
        └────────────┘     └────────────┘     └────────────┘

Components:

  • ek-provenance (crate/lib): defines Provenance, Tagged<T>, upgrade/downgrade functions, serialization.
  • ek-broker (binary): the daemon; owns the socket, the store, the attestor registry, TTL sweeper.
  • ek-sdk (crate/lib): what agent processes link against; wraps the socket protocol in an ergonomic async API.
  • ek-attestors (crate/lib): pluggable trait Attestor + a filesystem implementation for MVP.
  • ek-demo (binary, or a few): scripted fake agents exercising the system for the acceptance test.

4. Data Model

enum SourceTrust {
    UserControlled,  // e.g. local files the user owns, direct device sensors
    Untrusted,       // e.g. email bodies, web content, third-party messages
}

enum Provenance {
    Attested {
        source: SourceId,      // e.g. "file:/etc/hostname"
        checked_at: Instant,
    },
    Believed {
        by: AgentId,
        from: Box<Provenance>, // nesting = audit trail, never flattened
        confidence: f32,
        source_trust: SourceTrust, // orthogonal to confidence — see R10
    },
    Synthesized {
        by: AgentId,
        method: String,           // e.g. "image-gen:sdxl", "tool-authored"
        based_on: Vec<Box<Provenance>>, // inputs that informed the generation, if any
    },
}

struct Tagged<T> {
    value: T,
    provenance: Provenance,
}

Resolved design question (previously open in the future-directions doc): generated artifacts — images, audio, self-authored tools, any AI-produced content that isn’t a claim about the world — get their own Synthesized variant, distinct from both Attested and Believed. A synthesized value is never a fact and never someone’s belief about a fact; it’s a made thing. It can never silently convert into either of the other two variants.

Key rule: Provenance::Attested has no public constructor outside ek-broker. Every other crate can only ever build Believed or Synthesized, and building Believed always requires wrapping an existing Provenance (never fabricating one from nothing).


5. Protocol (Broker ⇄ Agent)

Minimum request set for MVP:

RequestBehavior
Attest(SourceId)Broker re-touches the real source (re-stat, re-hash) and returns a fresh Attested value. Never served from cache.
Publish(Tagged<Belief>)Agent submits a belief to the store. Broker validates the submitted Provenance — rejects if it claims Attested without having come from a real Attest call.
Query(BeliefId)Returns the current Tagged<T> for a belief, or “expired” if past TTL.
Trace(BeliefId)Walks the nested Provenance chain and returns the full audit trail.
Promote(BeliefId, reason)Moves a belief from the ephemeral working store into the retained store past its natural TTL. Logged with its own provenance (who promoted it, when, why).

Wire format: bincode or prost over the Unix socket; either is fine, pick one and be consistent. Framing: length-prefixed messages.


5a. Memory Subsystem

Agent memory is just the belief store, given durability and structure. Two tiers:

  • Working memory — beliefs actively in play. High-confidence, short TTL, cheap to re-derive if lost. This is the working_beliefs table already implied by the TTL sweep in Section 6/R5.
  • Retained memory — beliefs explicitly promoted to persist past their natural TTL, via the Promote request. Retained beliefs are not exempt from provenance tracking — they carry a visible staleness marker (last-attested timestamp, promoted-by, promotion reason) so nothing pretends to be fresher than it actually is.

Storage shape: two tables, not one:

  • working_beliefs — TTL-swept, ephemeral, matches existing Phase 4 design.
  • retained_beliefs — provenance chain preserved in full, plus promotion metadata (promoted_by: AgentId, promoted_at: Instant, reason: String, last_attested_at: Instant).

Hard rule: a retained belief can never upgrade to Provenance::Attested, no matter its age or how long it’s been trusted. “Believed for a long time” must stay visibly a belief — that’s precisely the pattern (old assumptions quietly calcifying into unexamined fact) the whole kernel exists to prevent.


6. Rules / Invariants (the non-negotiable “constitution”)

  • R1 — Sole constructor: Only ek-broker can construct Provenance::Attested. Enforced by Rust visibility (private constructor, pub(crate) at most), not by convention.
  • R2 — No silent stripping: Any code path that would discard a Provenance tag while keeping the value is a protocol violation and must not compile/must be rejected at the broker boundary.
  • R3 — No flattening: Believed.from must be the actual prior Provenance, boxed and nested — never replaced with a fresh unrelated tag. This nesting is the audit trail.
  • R4 — Mandatory revalidation path: Every Attested fact must be re-checkable via Attest; there is no such thing as a permanently cached attested fact.
  • R5 — TTL on beliefs: Every Believed value has an expiry. Expired beliefs are inaccessible via Query until re-derived or re-attested; the broker does not silently keep serving stale beliefs.
  • R6 — No direct cross-agent access: Agents never share a filesystem path, socket, or memory region directly. All state crosses the boundary through the broker’s protocol only.
  • R7 — Reject forged attestation: If an agent’s Publish claims a Provenance::Attested variant, the broker rejects it outright (agents cannot serialize their way around R1).
  • R8 — Traceable by construction: Trace must always be able to walk any belief back to a real Attested leaf (or explicitly report an untraceable/orphaned belief as an error condition, never silently).
  • R9 — No amnesty by age: A retained/promoted belief can never become Provenance::Attested regardless of how long it has persisted; retained beliefs must always expose their last-attested timestamp and promotion metadata, so age never quietly substitutes for verification.
  • R17 — Rate-bounded requests: The broker enforces a per-agent request-rate budget on all protocol calls (Attest, Publish, Query, etc.). A runaway or malfunctioning client is throttled/disconnected rather than allowed to hammer the store or an underlying attestor indefinitely — this holds even when nothing the client sent was individually invalid.
  • R18 — Crash-safe writes: Any single Publish/Promote/store-mutating operation is atomic — the broker must never leave the store in a state where a write is half-applied after an unclean shutdown. On restart, the broker must be able to determine, for any in-flight operation at crash time, that it either fully completed or never happened — never a silent partial or duplicate result.

7. Functional Requirements

  • FR1: Broker starts, binds a Unix socket with 0700 permissions owned by its own user.
  • FR2: Broker supports at least one real Attestor (filesystem: existence, mtime, content hash).
  • FR3: Agents can connect, Attest a fact, Publish a belief derived from it, and have another agent Query/Trace that belief.
  • FR4: Broker enforces R1–R9 and R17–R18 above at the protocol boundary (not just in the type system — a malicious/buggy client sending raw bytes must still be rejected).
  • FR5: TTL sweep runs periodically (e.g. every N seconds) and expires stale beliefs.
  • FR6: Demo suite proves: (a) a normal 2-hop belief chain works and traces correctly, (b) a forged “attested” claim from an agent is rejected, (c) an expired belief is inaccessible until re-derived, (d) Trace on a multi-hop belief shows every intermediate agent, (e) a promoted/retained belief still exposes its staleness and never silently upgrades to attested.

8. Non-Functional Requirements

  • NFR1: No unsafe in ek-provenance (the type-safety guarantee is the whole point; don’t undermine it for convenience).
  • NFR2: Broker must not panic on malformed/adversarial client input — return a protocol error instead.
  • NFR3: Single-machine, single-process broker is acceptable for MVP; design the socket protocol so a future multi-process/UID-isolated version doesn’t require a protocol rewrite.
  • NFR4: Reasonable test coverage on the rule-enforcement paths (R1–R9, R17–R18) specifically — these are the parts a code reviewer should trust least by default.
  • NFR5: Reference local-LLM inference backend must be llama.cpp compiled with Vulkan support, so the demo agents run on Nvidia, AMD, and Intel Arc hardware without vendor-specific toolchains. CUDA/ROCm can be used as optional accelerated paths for matching hardware, but Vulkan is the baseline — no one is excluded from running the demo because they don’t own an Nvidia card.
  • NFR6: Minimum viable hardware target for running the broker with real local-LLM demo agents (not just the broker alone, which needs far less): 8–12GB GPU VRAM, e.g. a used RTX 3060 12GB or equivalent, running quantized 7B–14B open-weight models at Q4/Q5.
  • NFR7: Per-agent request-rate limiting (R17) must be configurable but on-by-default with a sane budget out of the box — not something the demo relies on disabling to work.
  • NFR8: The persistent store (Phase 4 onward) must survive an unclean shutdown (kill -9, power loss) without corruption; acceptance for this is a test that kills the broker mid-write and confirms the store is either pre- or post-write on restart, never in between (R18).

9. Roadmap / Phases

  • Phase 0 (this doc): Spec, requirements, rules — done here.
  • Phase 1: ek-provenance crate — types, constructors, visibility rules, serialization. No networking yet.
  • Phase 2: ek-broker skeleton — socket, connection handling, in-memory (non-persistent) belief store, protocol enforcement of R1/R2/R7.
  • Phase 3: ek-attestors — trait + filesystem implementation; wire up real Attest calls.
  • Phase 4: Persistence + TTL — swap in-memory store for sled or rusqlite; background sweep task for R5; add retained_beliefs table and Promote request (R9).
  • Phase 5: ek-sdk — ergonomic async client wrapper agents actually use.
  • Phase 6: ek-demo — scripted agents; write the acceptance tests from FR6.
  • Phase 7 (stretch, post-MVP): process-level UID/cgroup isolation between agents; multi-machine transport; a second Attestor backend (e.g. a fake “sensor”).

10. Glossary

  • Attested fact: state whose provenance traces to a real, broker-verified source (file, sensor, direct process output).
  • Belief: state derived/inferred by an agent (a model), never directly ground truth.
  • Synthesized: state that is a generated artifact (image, audio, self-authored tool, etc.) — neither a fact nor an inference about the world, and never convertible into either.
  • Provenance: the tag carried by every value describing whether it’s attested, believed, or synthesized — and if believed, by whom, from what, and with what source trust level.
  • Broker: the single daemon process that is the only entity allowed to mint attested provenance and mediate all cross-agent state access.
  • Trace: walking a belief’s nested provenance chain back to its attested root(s).

11. Open Design Questions (for the implementing agent to flag back, not resolve unilaterally)

  • Wire format choice: bincode vs prost/protobuf — pick one, note tradeoffs, don’t block on it.
  • Exact TTL default and whether it’s global or per-fact-type configurable.
  • Whether Trace on an orphaned/untraceable belief should be an Err or a distinguished Orphaned variant.

This specification serves as the foundational architecture for Aurora’s provenance systems and trust boundaries. For more context on Aurora, see Aurora’s self-documentation. For future expansion ideas, hardware tiers, and security considerations beyond the MVP, see Future Directions & Hardware Tiers.