Skip to main content

Agent Evidence Layer — turns AI-agent runtime behavior into signed, tamper-evident, control-mapped audit evidence.

Project description

OpenWright — the Agent Evidence Layer

Turn the runtime behavior of AI agents into signed, tamper-evident, control-mapped audit evidence — verifiable by anyone, offline.

OpenWright sits on top of your existing OpenTelemetry instrumentation, forks a copy of your agent's runtime behavior, and turns it into signed, append-only, tamper-evident records mapped to specific regulatory controls. The evidence is verifiable by a third party without access to your data or infrastructure, and the ledger holds only hashes — never prompts or PII.

It ships five built-in, primary-source-cited framework crosswalks — plus a narrowed EU AI Act v1 review subset (eu-ai-act-v1) and deployer-profile variants of Art. 14 (in-the-loop / on-the-loop) and Art. 27 (FRIA-gated). You can also write your own:

Crosswalk Covers Controls
EU AI Act (Reg. 2024/1689) Art. 12, 13, 14, 26, 27, 73 (high-risk subset) 6
NIST AI RMF 1.0 Govern / Map / Measure / Manage subset 7
ISO/IEC 42001:2023 Annex A AI-management-system subset 6
GDPR (Reg. 2016/679) Art. 5, 22, 25, 30, 33, 35 (accountability + automated decisions) 8
SOC 2 Trust Services Criteria — Common Criteria + Processing Integrity 7

These crosswalks are maintainer-authored and cited, but not yet legally reviewed — they produce evidence, not a compliance determination.

OpenWright produces evidence that controls were exercised. It does NOT assert legal compliance, certification, or an audit opinion — those are for qualified auditors and counsel. Every artifact carries this boundary.

Install

pip install openwright-core

The distribution is openwright-core; it imports as openwright. Requires Python 3.10+.

Try it (one command)

openwright demo

Runs a complete, self-hosted, no-network demo: it instruments a sample high-risk agent, forks the telemetry into an evidence ledger, records human approvals and risk classifications, produces a signed report (JSON + PDF + OSCAL + SARIF) against the EU AI Act crosswalk, verifies it offline, and shows that tampering fails verification. It then opens an interactive page in your browser that walks through what happened and lets you verify the real signed report yourself — offline, in-browser (WebAssembly) — including a "Tamper" button to watch verification fail and a "Restore" button to watch it pass again. (Use openwright demo --no-browser for headless/CI.)

It also prints where the artifacts landed and a command to verify them yourself:

openwright verify <report.json> --pubkey <public_key.pem> --deep

Use it in your code

from datetime import timedelta
from openwright.ledger import FileLedgerBackend, Ledger
from openwright.sdk import EvidenceClient
from openwright.signing import InMemoryKeySource      # use FileKeySource in production
from openwright.crosswalk import evaluate
from openwright.crosswalk_loader import load_builtin
from openwright.report import build_report
from openwright.verify import verify_report

key = InMemoryKeySource()
ledger = Ledger(FileLedgerBackend("./ledger"), retention=timedelta(days=200))
client = EvidenceClient(ledger, agent_id="my-agent")

# Record the evidence telemetry can't infer — linked by task id.
with client.task("task-42", context_id="session-7"):
    approval = client.record_human_approval(reviewer="me@example.com", rationale="looks good")
    client.record_risk_classification("high", rationale="high-impact decision", fria="FRIA-1")
    client.record_decision(
        output="APPROVED",
        risk_classification="high",
        rationale="meets policy",
        approval_ref=approval.event_id,                # links the decision to the approval
        control="art-14-human-oversight",
    )

# Evaluate a crosswalk, build a signed report, verify it offline.
result = evaluate(load_builtin("eu-ai-act"), list(ledger.events()))
report = build_report(ledger, result, key, scope_description="my agent")
verdict = verify_report(report, trusted_public_key_raw=key.public_key_raw())

print({c["control_id"]: c["status"] for c in report["controls"]})
print("verified offline:", verdict.valid)

Collect from a live agent

Point your app's OTLP exporter at the collector; your existing backend keeps receiving telemetry unchanged while a copy is forked into the evidence ledger:

openwright collector --downstream http://your-existing-otlp-backend:4318

CLI

openwright demo                       Run the full end-to-end demo.
openwright collector --downstream URL Run the OTLP collector (gRPC+HTTP); fan out + fork to ledger.
openwright report  LEDGER --key K     Build a signed report (JSON/PDF/OSCAL/SARIF) from a ledger.
openwright verify  REPORT --pubkey K  Verify a signed report offline (--deep re-checks verdicts).
openwright gate    REPORT -r CONTROL  CI/CD gate: non-zero exit if a required control is unsatisfied.
openwright crosswalks                 List built-in crosswalks.
openwright connectors list            List installed connectors (sources/forwarders/exporters/storage).
openwright export  REPORT --to NAME   Export a report to a sink (GRC/CI) via an installed exporter.
openwright keygen  --out key.pem      Generate an Ed25519 signing key you control.
openwright version

Connectors

OpenWright exposes a small, versioned connector contract (openwright.connectors, v1.0): framework-capture sources, downstream forwarders, report exporters, and pluggable ledger/checkpoint storage backends. Connectors are independently installable openwright-<name> packages discovered via entry points — core never depends on a connector, so adding one needs zero core change. Resolve storage by URI (openwright collector --ledger-backend postgres://… --checkpoint-store s3://…) and see what's installed with openwright connectors list.

Run openwright --help for the full list.

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openwright_core-0.7.1.tar.gz (110.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openwright_core-0.7.1-py3-none-any.whl (138.9 kB view details)

Uploaded Python 3

File details

Details for the file openwright_core-0.7.1.tar.gz.

File metadata

  • Download URL: openwright_core-0.7.1.tar.gz
  • Upload date:
  • Size: 110.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openwright_core-0.7.1.tar.gz
Algorithm Hash digest
SHA256 9c2fa411319a824aa23730c34b233cca008c6b73de7682023da48c027a29a56a
MD5 133f9d889a0902418f017a5ac18cce87
BLAKE2b-256 7144c64ff413f7db815eb4442b06266d2b236401d52764e99b09d6f45314292f

See more details on using hashes here.

Provenance

The following attestation bundles were made for openwright_core-0.7.1.tar.gz:

Publisher: release.yml on allthingsN/openwright

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openwright_core-0.7.1-py3-none-any.whl.

File metadata

  • Download URL: openwright_core-0.7.1-py3-none-any.whl
  • Upload date:
  • Size: 138.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for openwright_core-0.7.1-py3-none-any.whl
Algorithm Hash digest
SHA256 4d18b590d13edd5efb350668fed521b5b53447207df52baeeb8bd9955f2b1b96
MD5 c2f887e291245adb8b3115c494ef5734
BLAKE2b-256 9adb25c2e8b72313590969d455cbf431e60b12dd039d7c614b2ca1fa7b47a7d4

See more details on using hashes here.

Provenance

The following attestation bundles were made for openwright_core-0.7.1-py3-none-any.whl:

Publisher: release.yml on allthingsN/openwright

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page