Example
A denial returns no data, and names its rule
from kognita import Envelope, decide, load_snapshot
evaluation = decide(
Envelope(principal="rm@bank.example", purpose="ELIGIBILITY_CHECK",
tool="check_eligibility", actor_location="AE",
subject_type="client", subject_id="1",
subjects={"instrument": "1"}),
load_snapshot(session),
attributes=pack.resolve_attributes(...),
rules=pack.rules(),
)
evaluation.outcome # DENY
for check in evaluation.basis():
print(check.regime, check.citation)
# HK_SFC SFC Code of Conduct para 5.5
# DIFC_DFSA DFSA COB 3; GEN 2
How a request moves
Authorise before discovery
An envelope describes an intent. It is evaluated before anything is fetched, so a refused request never touches the data it asked for.
Outcomes
Fail closed, by precedence
A single failing check among any number of passes still denies. Adding permissive rules cannot widen a policy set.
Guarantees
What the library promises
Every decision cites its rule
A check without a citation is an assertion, not a decision. The conformance kit enforces it.
Decisions are pure and replayable
decide() writes nothing and takes the instant as a parameter. "What would this have decided in March?" has an answer.
decide(envelope, snapshot,
as_of=datetime(2026, 3, 1, tzinfo=timezone.utc))
Evidence is tamper-evident
Each event carries the previous event's hash. Altering any payload breaks every hash after it.
$ kognita evidence verify --db store.db
BROKEN: evidence chain broken at sequence 2
$ kognita evidence export --db store.db -o audit.json
Approvals bind to what was reviewed
An approval is issued against an envelope hash covering the arguments, roles and checks. Changing any of them yields no matching approval.
Privacy
Evidence holds references, not content
An append-only log full of personal data collides with erasure rights, so payloads default to hashes and references. hashes_only strips content entirely while keeping the log provable.
Egress is guarded, not merely refused
A local-or-refuse rule confines a governed system to models running on the box. The guard adds redaction for everything else.
result = guard.send(text, call_the_model,
classification=Classification.C2,
destination="api.openai.com", destination_is_local=False)
result.decision # REDACT
# the provider saw: [TERM_1] ([EMAIL_1]) holds account [ACCOUNT_1]
# the caller got the real values back; the log records a hash, never content
PatternRedactor is a floor, not a guarantee. Regexes miss names in prose. Deployments handling real personal data should supply an NER-based redactor. The tests prove nothing unredacted escapes the guard, not detection recall.
Integration
Domain packs supply the domain
The core is domain-blind. A pack says what a request's attributes are and how to load the subjects it refers to. Policies are effective-dated rows; the evaluator for each rule_type is registered by the pack. A policy with no evaluator escalates rather than being skipped.
class MyPack:
name = "my-domain"
def load_subjects(self, envelope, session): ...
def resolve_attributes(self, envelope, subjects): ...
def rules(self): return build_registry(MY_EVALUATORS)
| Primitive | Meaning |
|---|---|
ATTRIBUTE_ALLOWLIST | Every named attribute must be in its allowlist |
ATTRIBUTE_DENYLIST | No named attribute may match its denylist |
REQUIRES_FLAG | Named attributes must all be truthy |
REQUIRES_HUMAN_APPROVAL | Mandate human review for matching tools or purposes |
PROHIBITED | An unconditional bar once the policy is engaged |
Conformance kit
Subclass ConformanceCase in your pack's test suite. The invariants (fail-closed, cited, evidenced) run against your rules, not just the bundled fixture.
from kognita.testing import ConformanceCase, Harness
class TestMyPack(ConformanceCase):
@pytest.fixture(autouse=True)
def _bind(self):
self.harness = Harness(pack=MyPack(), purposes=PURPOSES, seed=seed)
Layout
Small core, optional reach
| Package | What it is | Install |
|---|---|---|
kognita | The decision engine: decisions, evidence, retrieval, egress, tools. No network. | pip install kognita |
kognita.graph | Graphiti + Kuzu knowledge graph, with a deterministic system-of-record mirror | kognita[graph] |
kognita.adapters | Provider-backed embedders and clients | kognita[openai] and others |
kognita.testing | The conformance kit | included |
The core runs on pydantic, sqlmodel, numpy and python-dotenv. Import-linter contracts and a test that installs with no extras keep it that way.
Status
Where it stands
Kognita is alpha. Core packaging, governance, the evidence chain, retrieval, the egress guard, the tool runner, the broker, the conformance kit and adapters are in place.
Design records live in docs/decisions/, including the gap analysis that drives the roadmap.