Skip to main content

NomosGuard

LLM produces evidence. Deterministic machinery decides.

NomosGuard is a deterministic security reasoning core: an append-only evidence ledger, a rule engine that derives threat/access paths from that evidence, and a fail-closed policy gate. Language models may read events and write structured claims with cited evidence, and may later explain decisions in human language — but a model never crosses the decision boundary. Every claim without reproducible evidence is discarded; every decision is hash-chained; the gate defaults to deny.

The name: nomos (νόμος) — Greek for rational law, order derived from reason rather than brute force (physis) — plus guard, the fail-closed gate that enforces it. Together: reasoning that decides, evidence that must prove itself.

Why deterministic core + probabilistic edge

A language model's confidence is not evidence — it is an assertion. This project treats it as such:

  • The LLM edge (top): reads raw events, configuration, CVE records, logs; emits structured claims (entities, relations, vulnerabilities, tool calls), each citing the exact evidence fragment (log line hash, config path, CVE ID) that supports it.
  • The deterministic core: an append-only, SHA-256 hash-chained ledger stores every claim; a rule engine derives attack/access paths (MulVAL-style logical inference — pure logic, no randomness, no model); a policy gate decides ALLOW / ALERT / BLOCK, fail-closed.
  • The LLM edge (bottom): explains the decision, drafts remediation suggestions, and proposes next analysis steps. It narrates; it never decides. If the explanation contradicts the evidence chain, the chain wins.

This is the same separation that makes a court work: a lawyer (the model) presents evidence, but the verdict comes from the rules of law (the core), and the transcript is tamper-evident.

Status

Early development — see VISION.md for the architecture, scope, and first-release boundary. The core (evidence ledger, rule engine, policy gate) is implemented with 51 passing tests and a reproducible demo scenario, real log ingestion, and a measured benchmark corpus.

Components

Module What it does
nomosguard.ledger Append-only SHA-256 hash-chained evidence ledger; rejects unevidenced claims; persistent (atomic save, full-chain-verify load)
nomosguard.rules Forward-chaining rule engine with unification; tool-call / CVE / policy extractors
nomosguard.gate Fail-closed policy gate: ALLOW / ALERT / BLOCK with full derivation chains
nomosguard.ingest.toolcall_jsonl Real tool-call JSONL ingestion: each claim cites sha256 of the raw source line
nomosguard.mcp_server MCP session layer: 5 tools (evidence_ingest, assert_claim, derive_paths, decide, explain)
nomosguard.mcp_stdio JSON-RPC stdio server (python -m nomosguard.mcp_stdio)
nomosguard.benchmark Attack-scenario corpus with measured recall / false-positive / fail-closed results
nomosguard.facts_security Host/network/user/service/privilege facts (MulVAL vocabulary)
nomosguard.rules_security MulVAL-style rules: exploit, lateral movement, privilege escalation
nomosguard.policy_security Containment decisions: ISOLATE_HOST, REVOKE_ACCESS, ESCALATE
SKILL.md Agent behavioral contract: when to invoke the deterministic chain vs. narrate

Evidence production pipeline

The LLM edge is where hallucinations live — every model in the 16-model benchmark invented at least one claim. nomosguard.benchmark.model_compare.pipeline wraps model output in four stages, ordered by how much they can be trusted:

1. SAMPLE   N independent draws from the model
2. VOTE     keep a claim only if >= M draws produced it
            (one-off claims are likely hallucinations)
3. AUDIT    a second prompt asks the model to FLAG suspicious claims
            — it never deletes them (measured: deletion cost recall)
4. GROUND   deterministic: a claim survives only if its evidence
            field is a verbatim substring of the raw logs

Only stage 4 removes claims by hard rule. Stage 3 attaches suspicion as metadata (result.flagged); the claim survives so no correct evidence is ever silently lost. A first measured pass (step-5-preview-free, 4 scenarios) showed the pipeline trading −9 recall points for +20 precision points against single-pass extraction — the flag-not-delete audit design exists to close that recall gap.

from nomosguard.benchmark.model_compare.pipeline import run_pipeline

result = run_pipeline(model_fn, raw_logs, draws=3, min_votes=2)
# result.claims  — surviving claims, each with vote support
# result.flagged — suspicious claims, kept but marked
# result.report  — per-stage removals, for measurement

Benchmark (measured, not asserted)

Run with python -m nomosguard.benchmark.run_suite_main --output DIR. The corpus is committed and deterministic; the expected outcomes are hand-derived from the facts, not produced by the engine. Latest run:

metric value
scenarios 7
recall 2/2 = 100%
false positives 0
fail-closed on incomplete evidence OK
all scenarios passed yes

What the corpus does NOT cover (stated honestly): real-world logs, evidence tampering inside the ledger (that is the ledger's own test suite's job), and any scenario requiring an LLM to judge.

Ingestion (three evidence types, one discipline)

Three adapters, each with the same contract: every claim cites sha256:<hex> of the raw source line; malformed records are rejected with line number and reason (fail-closed); duplicate lines are counted, never re-appended.

Adapter Input (JSONL) Claim kind
ingest.toolcall_jsonl {"agent", "tool", "target", "args"?} tool_call
ingest.vuln_jsonl {"component", "cve": "CVE-YYYY-NNNN", "severity", "description"?} vulnerability
ingest.policy_jsonl {"subject", "action", "resource", "effect": "allow|deny"} policy_rule

Committed samples: examples/sample_toolcalls.jsonl, examples/sample_cves.jsonl, examples/sample_policies.jsonl.

Module What it does
nomosguard.ledger Append-only SHA-256 hash-chained evidence ledger; rejects unevidenced claims
nomosguard.rules Forward-chaining rule engine (MulVAL-style) with tool-call / CVE / policy extractors
nomosguard.gate Fail-closed policy gate: ALLOW / ALERT / BLOCK with full derivation chains
nomosguard.mcp_server MCP session layer: 5 tools (evidence_ingest, assert_claim, derive_paths, decide, explain)
nomosguard.mcp_stdio JSON-RPC stdio server (python -m nomosguard.mcp_stdio)
SKILL.md Agent behavioral contract: when to invoke the deterministic chain vs. narrate

Run it

pip install -e .
python -m nomosguard.demo    # committed scenario: derivation + BLOCK
pytest tests/                # 107 tests incl. security suite
python -m nomosguard.benchmark.run_suite_main          # tool-call corpus (11 scenarios)
python -m nomosguard.benchmark.security_main           # security corpus (5 scenarios)

Use it from an MCP client

{"command": "python", "args": ["-m", "nomosguard.mcp_stdio"]}

The server never calls a model. Agents load SKILL.md for the behavioral contract: assert claims with evidence, derive paths, read the gate decision, explain it — never decide it.

License

Apache-2.0

Metadata

Release files for nomosguard 0.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nomosguard 0.2.3
File Size Uploaded
nomosguard-0.2.3.tar.gz 80.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nomosguard 0.2.3
File Interpreter ABI Platform
nomosguard-0.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 155.9 kB

Release files / nomosguard-0.2.3.tar.gz

Download URL nomosguard-0.2.3.tar.gz
Size 80.4 kB
Tags Source
SHA-256 checksum
How to use checksums
d70f0e21b0bcdacd17f9fa8b934aa76be904d7cc6f0f3dc002299e4aca1ce64a
BLAKE2b-256 checksum
How to use checksums
f597023435a98366c60c383ca90eb28373f96de7dbcc66d96ce03d5bdab2ee31
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release files / nomosguard-0.2.3-py3-none-any.whl

Download URL nomosguard-0.2.3-py3-none-any.whl
Size 75.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9f9b00a1feb82a46fea302b761efba9eccb158dbc2764a02a01ba586a1fd11f9
BLAKE2b-256 checksum
How to use checksums
d0a66fb78b74405b50161c565c9fa70f451f4c578666c36f8247cd6fd7989755
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 9, 2026.

Transparency log

Release history Release notifications | RSS feed

0.7.5

2 release files

0.7.4

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.4

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.3 This release

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page